Actual source code: regressor.c
1: #include <petsc/private/regressorimpl.h>
3: PetscBool PetscRegressorRegisterAllCalled = PETSC_FALSE;
4: PetscFunctionList PetscRegressorList = NULL;
6: PetscClassId PETSCREGRESSOR_CLASSID;
8: /* Logging support */
9: PetscLogEvent PetscRegressor_SetUp, PetscRegressor_Fit, PetscRegressor_Predict;
11: /*@C
12: PetscRegressorRegister - Adds a method to the `PetscRegressor` package.
14: Not collective
16: Input Parameters:
17: + sname - name of a new user-defined regressor
18: - function - routine to create method context
20: Notes:
21: `PetscRegressorRegister()` may be called multiple times to add several user-defined regressors.
23: Example Usage:
24: .vb
25: PetscRegressorRegister("my_regressor",MyRegressorCreate);
26: .ve
28: Then, your regressor can be chosen with the procedural interface via
29: .vb
30: PetscRegressorSetType(regressor,"my_regressor")
31: .ve
32: or at runtime via the option
33: .vb
34: -regressor_type my_regressor
35: .ve
37: Level: advanced
39: .seealso: `PetscRegressorRegisterAll()`
40: @*/
41: PetscErrorCode PetscRegressorRegister(const char sname[], PetscErrorCode (*function)(PetscRegressor))
42: {
43: PetscFunctionBegin;
44: PetscCall(PetscRegressorInitializePackage());
45: PetscCall(PetscFunctionListAdd(&PetscRegressorList, sname, function));
46: PetscFunctionReturn(PETSC_SUCCESS);
47: }
49: /*@
50: PetscRegressorCreate - Creates a `PetscRegressor` object.
52: Collective
54: Input Parameter:
55: . comm - the MPI communicator that will share the `PetscRegressor` object
57: Output Parameter:
58: . newregressor - the new `PetscRegressor` object
60: Level: beginner
62: .seealso: `PetscRegressorFit()`, `PetscRegressorPredict()`, `PetscRegressor`
63: @*/
64: PetscErrorCode PetscRegressorCreate(MPI_Comm comm, PetscRegressor *newregressor)
65: {
66: PetscRegressor regressor;
68: PetscFunctionBegin;
69: PetscAssertPointer(newregressor, 2);
70: *newregressor = NULL;
71: PetscCall(PetscRegressorInitializePackage());
73: PetscCall(PetscHeaderCreate(regressor, PETSCREGRESSOR_CLASSID, "PetscRegressor", "Regressor", "PetscRegressor", comm, PetscRegressorDestroy, PetscRegressorView));
75: regressor->setupcalled = PETSC_FALSE;
76: regressor->fitcalled = PETSC_FALSE;
77: regressor->data = NULL;
78: regressor->training = NULL;
79: regressor->target = NULL;
80: PetscObjectParameterSetDefault(regressor, regularizer_weight, 1.0); // Default to regularizer weight of 1.0, usually the default in SciKit-learn
82: *newregressor = regressor;
83: PetscFunctionReturn(PETSC_SUCCESS);
84: }
86: /*@
87: PetscRegressorView - Prints information about the `PetscRegressor` object
89: Collective
91: Input Parameters:
92: + regressor - the `PetscRegressor` context
93: - viewer - a `PetscViewer` context
95: Options Database Key:
96: . -regressor_view - Calls `PetscRegressorView()` at the end of `PetscRegressorFit()`
98: Level: beginner
100: Notes:
101: The available visualization contexts include
102: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
103: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
104: output where only the first processor opens
105: the file. All other processors send their
106: data to the first processor to print.
108: .seealso: [](ch_regressor), `PetscRegressor`, `PetscViewerASCIIOpen()`
109: @*/
110: PetscErrorCode PetscRegressorView(PetscRegressor regressor, PetscViewer viewer)
111: {
112: PetscBool isascii, isstring;
113: PetscRegressorType type;
115: PetscFunctionBegin;
117: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)regressor)->comm, &viewer));
119: PetscCheckSameComm(regressor, 1, viewer, 2);
121: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
122: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
123: if (isascii) {
124: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)regressor, viewer));
126: PetscCall(PetscViewerASCIIPushTab(viewer));
127: PetscTryTypeMethod(regressor, view, viewer);
128: if (regressor->tao) PetscCall(TaoView(regressor->tao, viewer));
129: PetscCall(PetscViewerASCIIPopTab(viewer));
130: } else if (isstring) {
131: PetscCall(PetscRegressorGetType(regressor, &type));
132: PetscCall(PetscViewerStringSPrintf(viewer, " PetscRegressorType: %-7.7s", type));
133: }
134: PetscFunctionReturn(PETSC_SUCCESS);
135: }
137: /*@
138: PetscRegressorViewFromOptions - View a `PetscRegressor` object based on values in the options database
140: Collective
142: Input Parameters:
143: + A - the `PetscRegressor` context
144: . obj - Optional object that provides the prefix for the options database
145: - name - command line option
147: Level: intermediate
149: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorView`, `PetscObjectViewFromOptions()`, `PetscRegressorCreate()`
150: @*/
151: PetscErrorCode PetscRegressorViewFromOptions(PetscRegressor A, PetscObject obj, const char name[])
152: {
153: PetscFunctionBegin;
155: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
156: PetscFunctionReturn(PETSC_SUCCESS);
157: }
159: /*@
160: PetscRegressorSetFromOptions - Sets `PetscRegressor` options from the options database.
162: Collective
164: Input Parameter:
165: . regressor - the `PetscRegressor` context
167: Options Database Keys:
168: . -regressor_type <type> - the particular type of regressor to be used; see `PetscRegressorType` for complete list
170: Level: beginner
172: Note:
173: This routine must be called before `PetscRegressorSetUp()` (or `PetscRegressorFit()`, which calls
174: the former) if the user is to be allowed to set the regressor type.
176: .seealso: `PetscRegressor`, `PetscRegressorCreate()`
177: @*/
178: PetscErrorCode PetscRegressorSetFromOptions(PetscRegressor regressor)
179: {
180: PetscBool flg;
181: PetscRegressorType default_type = PETSCREGRESSORLINEAR;
182: char type[256];
184: PetscFunctionBegin;
186: if (((PetscObject)regressor)->type_name) default_type = ((PetscObject)regressor)->type_name;
187: PetscObjectOptionsBegin((PetscObject)regressor);
188: /* Check for type from options */
189: PetscCall(PetscOptionsFList("-regressor_type", "PetscRegressor type", "PetscRegressorSetType", PetscRegressorList, default_type, type, 256, &flg));
190: if (flg) {
191: PetscCall(PetscRegressorSetType(regressor, type));
192: } else if (!((PetscObject)regressor)->type_name) {
193: PetscCall(PetscRegressorSetType(regressor, default_type));
194: }
195: PetscCall(PetscOptionsReal("-regressor_regularizer_weight", "Weight for the regularizer", "PetscRegressorSetRegularizerWeight", regressor->regularizer_weight, ®ressor->regularizer_weight, &flg));
196: if (flg) PetscCall(PetscRegressorSetRegularizerWeight(regressor, regressor->regularizer_weight));
197: // The above is a little superfluous, because we have already set regressor->regularizer_weight above, but we also need to set the flag indicating that the user has set the weight!
198: PetscTryTypeMethod(regressor, setfromoptions, PetscOptionsObject);
199: PetscOptionsEnd();
200: PetscFunctionReturn(PETSC_SUCCESS);
201: }
203: /*@
204: PetscRegressorSetUp - Sets up the internal data structures for the later use of a regressor.
206: Collective
208: Input Parameter:
209: . regressor - the `PetscRegressor` context
211: Notes:
212: For basic use of the `PetscRegressor` solvers the user need not to explicitly call
213: `PetscRegressorSetUp()`, since these actions will automatically occur during
214: the call to `PetscRegressorFit()`. However, if one wishes to control this
215: phase separately, `PetscRegressorSetUp()` should be called after `PetscRegressorCreate()`,
216: `PetscRegressorSetUp()`, and optional routines of the form `PetscRegressorSetXXX()`,
217: but before `PetscRegressorFit()`.
219: Level: advanced
221: .seealso: `PetscRegressorCreate()`, `PetscRegressorFit()`, `PetscRegressorDestroy()`
222: @*/
223: PetscErrorCode PetscRegressorSetUp(PetscRegressor regressor)
224: {
225: PetscFunctionBegin;
227: if (regressor->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
228: PetscCall(PetscLogEventBegin(PetscRegressor_SetUp, regressor, 0, 0, 0));
229: //TODO is there some mat vec etc that must be set, like TaoSolution?
230: PetscTryTypeMethod(regressor, setup);
231: regressor->setupcalled = PETSC_TRUE;
232: PetscCall(PetscLogEventEnd(PetscRegressor_SetUp, regressor, 0, 0, 0));
233: PetscFunctionReturn(PETSC_SUCCESS);
234: }
236: /* NOTE: I've decided to make this take X and y, like the Scikit-learn Fit routines do.
237: * Am I overlooking some reason that X should be set in a separate function call, a la KSPSetOperators()?. */
238: /*@
239: PetscRegressorFit - Fit, or train, a regressor from a training dataset
241: Collective
243: Input Parameters:
244: + regressor - the `PetscRegressor` context
245: . X - matrix of training data (of dimension [number of samples] x [number of features])
246: - y - vector of target values from the training dataset
248: Level: beginner
250: .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorDestroy()`, `PetscRegressorPredict()`
251: @*/
252: PetscErrorCode PetscRegressorFit(PetscRegressor regressor, Mat X, Vec y)
253: {
254: PetscFunctionBegin;
259: if (X) {
260: PetscCall(PetscObjectReference((PetscObject)X));
261: PetscCall(MatDestroy(®ressor->training));
262: regressor->training = X;
263: }
264: if (y) {
265: PetscCall(PetscObjectReference((PetscObject)y));
266: PetscCall(VecDestroy(®ressor->target));
267: regressor->target = y;
268: }
269: PetscCall(PetscRegressorSetUp(regressor));
271: PetscCall(PetscLogEventBegin(PetscRegressor_Fit, regressor, X, y, 0));
272: PetscUseTypeMethod(regressor, fit);
273: PetscCall(PetscLogEventEnd(PetscRegressor_Fit, regressor, X, y, 0));
274: //TODO print convergence data
275: PetscCall(PetscRegressorViewFromOptions(regressor, NULL, "-regressor_view"));
276: regressor->fitcalled = PETSC_TRUE;
277: PetscFunctionReturn(PETSC_SUCCESS);
278: }
280: /*@
281: PetscRegressorPredict - Compute predictions (that is, perform inference) using a fitted regression model.
283: Collective
285: Input Parameters:
286: + regressor - the `PetscRegressor` context (for which `PetscRegressorFit()` must have been called)
287: - X - data matrix of unlabeled observations
289: Output Parameter:
290: . y - vector of predicted labels
292: Level: beginner
294: .seealso: `PetscRegressorFit()`, `PetscRegressorDestroy()`
295: @*/
296: PetscErrorCode PetscRegressorPredict(PetscRegressor regressor, Mat X, Vec y)
297: {
298: PetscFunctionBegin;
302: PetscCheck(regressor->fitcalled == PETSC_TRUE, ((PetscObject)regressor)->comm, PETSC_ERR_ARG_WRONGSTATE, "PetscRegressorFit() must be called before PetscRegressorPredict()");
303: PetscCall(PetscLogEventBegin(PetscRegressor_Predict, regressor, X, y, 0));
304: PetscTryTypeMethod(regressor, predict, X, y);
305: PetscCall(PetscLogEventEnd(PetscRegressor_Predict, regressor, X, y, 0));
306: PetscFunctionReturn(PETSC_SUCCESS);
307: }
309: /*@
310: PetscRegressorReset - Resets a `PetscRegressor` context by removing any allocated `Vec` and `Mat`. Any options set in the object remain.
312: Collective
314: Input Parameter:
315: . regressor - context obtained from `PetscRegressorCreate()`
317: Level: intermediate
319: .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorFit()`, `PetscRegressorPredict()`, `PetscRegressorDestroy()`
320: @*/
321: PetscErrorCode PetscRegressorReset(PetscRegressor regressor)
322: {
323: PetscFunctionBegin;
325: if (regressor->ops->reset) PetscTryTypeMethod(regressor, reset);
326: PetscCall(MatDestroy(®ressor->training));
327: PetscCall(VecDestroy(®ressor->target));
328: PetscCall(TaoDestroy(®ressor->tao));
329: regressor->setupcalled = PETSC_FALSE;
330: regressor->fitcalled = PETSC_FALSE;
331: PetscFunctionReturn(PETSC_SUCCESS);
332: }
334: /*@C
335: PetscRegressorDestroy - Destroys the regressor context that was created with `PetscRegressorCreate()`.
337: Collective
339: Input Parameter:
340: . regressor - the `PetscRegressor` context
342: Level: beginner
344: .seealso: `PetscRegressorCreate()`, `PetscRegressorSetUp()`, `PetscRegressorReset()`, `PetscRegressor`
345: @*/
346: PetscErrorCode PetscRegressorDestroy(PetscRegressor *regressor)
347: {
348: PetscFunctionBegin;
349: if (!*regressor) PetscFunctionReturn(PETSC_SUCCESS);
351: if (--((PetscObject)*regressor)->refct > 0) {
352: *regressor = NULL;
353: PetscFunctionReturn(PETSC_SUCCESS);
354: }
356: PetscCall(PetscRegressorReset(*regressor));
357: PetscTryTypeMethod(*regressor, destroy);
359: PetscCall(PetscHeaderDestroy(regressor));
360: PetscFunctionReturn(PETSC_SUCCESS);
361: }
363: /*@C
364: PetscRegressorSetType - Sets the type for the regressor.
366: Collective
368: Input Parameters:
369: + regressor - the `PetscRegressor` context
370: - type - a known regression method
372: Options Database Key:
373: . -regressor_type <type> - Sets the type of regressor; use -help for a list of available types
375: Level: intermediate
377: Notes:
378: See "include/petscregressor.h" for available methods (for instance)
379: . `PETSCREGRESSORLINEAR` - Regression model that is linear in its coefficients; supports ordinary least squares as well as regularized variants
381: Normally, it is best to use the `PetscRegressorSetFromOptions()` command and then
382: set the `PetscRegressor` type from the options database rather than by using
383: this routine, as this provides maximum flexibility.
384: The `PetscRegressorSetType()` routine is provided for those situations where it
385: is necessary to set the nonlinear solver independently of the command
386: line or options database.
388: .seealso: `PetscRegressorType`
389: @*/
390: PetscErrorCode PetscRegressorSetType(PetscRegressor regressor, PetscRegressorType type)
391: {
392: PetscErrorCode (*r)(PetscRegressor);
393: PetscBool match;
395: PetscFunctionBegin;
397: PetscAssertPointer(type, 2);
399: PetscCall(PetscObjectTypeCompare((PetscObject)regressor, type, &match));
400: if (match) PetscFunctionReturn(PETSC_SUCCESS);
402: PetscCall(PetscFunctionListFind(PetscRegressorList, type, &r));
403: PetscCheck(r, PetscObjectComm((PetscObject)regressor), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PetscRegressor type %s", type);
405: /* Destroy the existing solver information */
406: PetscTryTypeMethod(regressor, destroy);
407: PetscCall(TaoDestroy(®ressor->tao));
408: regressor->ops->setup = NULL;
409: regressor->ops->setfromoptions = NULL;
410: regressor->ops->settraining = NULL;
411: regressor->ops->fit = NULL;
412: regressor->ops->predict = NULL;
413: regressor->ops->destroy = NULL;
414: regressor->ops->reset = NULL;
415: regressor->ops->view = NULL;
417: /* Call the PetscRegressorCreate_XXX routine for this particular regressor */
418: regressor->setupcalled = PETSC_FALSE;
419: PetscCall((*r)(regressor));
420: PetscCall(PetscObjectChangeTypeName((PetscObject)regressor, type));
421: PetscFunctionReturn(PETSC_SUCCESS);
422: }
424: /*@
425: PetscRegressorGetType - Gets the current `PetscRegressorType` being used in the `PetscRegressor` object
427: Not Collective
429: Input Parameter:
430: . regressor - the `PetscRegressor` solver context
432: Output Parameter:
433: . type - the `PetscRegressorType`
435: Level: intermediate
437: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorType`, `PetscRegressorSetType()`
438: @*/
439: PetscErrorCode PetscRegressorGetType(PetscRegressor regressor, PetscRegressorType *type)
440: {
441: PetscFunctionBegin;
443: PetscAssertPointer(type, 2);
444: *type = ((PetscObject)regressor)->type_name;
445: PetscFunctionReturn(PETSC_SUCCESS);
446: }
448: /*@
449: PetscRegressorSetRegularizerWeight - Sets the weight to be used for the regularizer for a `PetscRegressor` context
451: Logically Collective
453: Input Parameters:
454: + regressor - the `PetscRegressor` context
455: - weight - the regularizer weight
457: Options Database Key:
458: . regressor_regularizer_weight <weight> - sets the regularizer's weight
460: Level: beginner
462: .seealso: `PetscRegressorSetType`
463: @*/
464: PetscErrorCode PetscRegressorSetRegularizerWeight(PetscRegressor regressor, PetscReal weight)
465: {
466: PetscFunctionBegin;
469: regressor->regularizer_weight = weight;
470: PetscFunctionReturn(PETSC_SUCCESS);
471: }
473: /*@
474: PetscRegressorGetTao - Returns the `Tao` context for a `PetscRegressor` object.
476: Not Collective, but if the `PetscRegressor` is parallel, then the `Tao` object is parallel
478: Input Parameter:
479: . regressor - the regressor context
481: Output Parameter:
482: . tao - the `Tao` context
484: Level: beginner
486: Notes:
487: The `Tao` object will be created if it does not yet exist.
489: The user can directly manipulate the `Tao` context to set various
490: options, etc. Likewise, the user can then extract and manipulate the
491: child contexts such as `KSP` or `TaoLineSearch`as well.
493: Depending on the type of the regressor and the options that are set, the regressor may use not use a `Tao` object.
495: .seealso: `PetscRegressorLinearGetKSP()`
496: @*/
497: PetscErrorCode PetscRegressorGetTao(PetscRegressor regressor, Tao *tao)
498: {
499: PetscFunctionBegin;
501: PetscAssertPointer(tao, 2);
502: // Analogous to how SNESGetKSP() operates, this routine should create the Tao if it doesn't exist.
503: if (!regressor->tao) {
504: PetscCall(TaoCreate(PetscObjectComm((PetscObject)regressor), ®ressor->tao));
505: PetscCall(PetscObjectIncrementTabLevel((PetscObject)regressor->tao, (PetscObject)regressor, 1));
506: PetscCall(PetscObjectSetOptions((PetscObject)regressor->tao, ((PetscObject)regressor)->options));
507: }
508: *tao = regressor->tao;
509: PetscFunctionReturn(PETSC_SUCCESS);
510: }
512: /*@
513: PetscRegressorSetOptionsPrefix - Sets the prefix used for searching for all
514: PetscRegressor options in the database.
516: Logically Collective
518: Input Parameters:
519: + regressor - the `PetscRegressor` context
520: - p - the prefix string to prepend to all PetscRegressor option requests
522: Level: advanced
524: Notes:
525: A hyphen (-) must NOT be given at the beginning of the prefix name.
526: The first character of all runtime options is AUTOMATICALLY the hyphen.
528: For example, to distinguish between the runtime options for two
529: different PetscRegressor solvers, one could call
530: .vb
531: PetscRegressorSetOptionsPrefix(regressor1,"sys1_")
532: PetscRegressorSetOptionsPrefix(regressor2,"sys2_")
533: .ve
535: This would enable use of different options for each system, such as
536: .vb
537: -sys1_regressor_method linear -sys1_regressor_regularizer_weight 1.2
538: -sys2_regressor_method linear -sys2_regressor_regularizer_weight 1.1
539: .ve
541: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorAppendOptionsPrefix()`, `PetscRegressorGetOptionsPrefix()`
542: @*/
543: PetscErrorCode PetscRegressorSetOptionsPrefix(PetscRegressor regressor, const char p[])
544: {
545: PetscFunctionBegin;
547: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)regressor, p));
548: PetscFunctionReturn(PETSC_SUCCESS);
549: }
551: /*@
552: PetscRegressorAppendOptionsPrefix - Appends to the prefix used for searching for all PetscRegressor options in the database.
554: Logically Collective
556: Input Parameters:
557: + regressor - the `PetscRegressor` solver context
558: - p - the prefix string to prepend to all `PetscRegressor` option requests
560: Level: advanced
562: Note:
563: A hyphen (-) must NOT be given at the beginning of the prefix name.
564: The first character of all runtime options is automatically the hyphen.
566: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorSetOptionsPrefix()`, `PetscRegressorGetOptionsPrefix()`
567: @*/
568: PetscErrorCode PetscRegressorAppendOptionsPrefix(PetscRegressor regressor, const char p[])
569: {
570: PetscFunctionBegin;
572: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)regressor, p));
573: PetscFunctionReturn(PETSC_SUCCESS);
574: }
576: /*@
577: PetscRegressorGetOptionsPrefix - Gets the prefix used for searching for all
578: PetscRegressor options in the database
580: Not Collective
582: Input Parameter:
583: . regressor - the `PetscRegressor` context
585: Output Parameter:
586: . p - pointer to the prefix string used is returned
588: Fortran Notes:
589: Pass in a string 'prefix' of sufficient length to hold the prefix.
591: Level: advanced
593: .seealso: [](ch_regressor), `PetscRegressor`, `PetscRegressorSetFromOptions()`, `PetscRegressorSetOptionsPrefix()`, `PetscRegressorAppendOptionsPrefix()`
594: @*/
595: PetscErrorCode PetscRegressorGetOptionsPrefix(PetscRegressor regressor, const char *p[])
596: {
597: PetscFunctionBegin;
599: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)regressor, p));
600: PetscFunctionReturn(PETSC_SUCCESS);
601: }