Skip to content

← machine_learning package

ConvexModel

A flexible convex optimization based machine learning model.

This node is configured by specifying a smooth training cost function of parameters w (weights), optionally b (a bias or intercept), and the provided input data D, by wiring a graph with these placeholders into the cost port. For non-smooth costs, see below for more details. In either case, D may be any numeric data structure (typically a Packet or list thereof), and the cost may use any formula that is differentiable with respect to w and b, and may include smooth regularization terms (e.g., l2 norms). b is purely a convenience argument, and can be omitted if not needed. The w parameter can also have any structure (packets/arrays, lists/dictionaries thereof), and in general you can wire in an initial value (e.g., a zero-initialized array via the weights port). If an initial value is not provided, this defaults to a single zero-initialized training instance, which is often sufficient (more precisely, it defaults to the same data structure as your training data, but with any instance axis dropped and only a single zero- initialized instance retained). For the node to be able to to make predictions on new data, a prediction function (a mapping of weights, optional bias, and data) needs to be defined, and you can wire in a graph with the appropriate placeholders for this into the "pred" input. However, oftentimes, this is redundant and will have the same form as what is wired as predictions into the "Loss" node in your cost function (e.g., SigmoidBinaryCrossEntropyLoss), with the loss replaced by the appropriate link function (e.g., Sigmoid, Softmax, or Sign for classification, or no link for regression). If this is so, and you are using a Loss node in your cost function, you can leave the pred input unspecified, in which case it will be inferred to be the subgraph of your cost as just described. For non-smooth optimization, you may provide additional non-smooth cost-function terms in the form of one or more graphs with placeholders w and step_size, which may implement or invoke proximal operators corresponding to the desired penalties (e.g., the Sparse Penalty node to impose a sparsity-promoting l1 norm on the weights, etc.) - in most cases, this is simply a graph where those two placeholders are wired into the data and step_size inputs of one of the chosen Penalty node, which in turn is wired into one of the prox1..N ports. Additionally or alternatively you can also specify a graph invoking one or more constraint projections (e.g., using the Non-negative Constraint node) as a function of the weights into the constraint port. If you wish to specify multiple constraints and/or proximal operators, the following consideration applies: this node may not offer a solver that natively supports more than one such term, in which case a "meta-term" is constructed that is simply the successive application of your prox operators followed by the constraint; this is benign if the operators act on separate parts of your weights, and under some conditions this will also still converge if your operators overlap on some weights, but in general you will get a warning. If you know what you are doing, you can also simply chain or otherwise compose multiple proximal operators in a single graph and wire that into the prox1 port, and thereby avoid the warning. The node will by default use a smooth solver if there are no non-smooth terms, and otherwise default to the proximal gradient descent (PGD) algorithm to minimize the cost function, but other solvers could be used as well. Once weights have been optimized, the node can be used to make predictions on new data (where it will generally match the data types of the input data, e.g., Packet or a list thereof). Note also that you can configure what data the node should train on using the train_on property. For how to pass training data into the node, see documentation in the other machine learning nodes, which are somewhat more beginner-oriented than this node. More Info... Version 0.3.0

Ports/Properties

data

Data to process.

  • verbose name: Data
  • default value: None
  • port type: DataPort
  • value type: AnyNumeric (can be None)
  • data direction: INOUT

weights

Initial/final weights. If not set, will be initialized to a packet equivalent to a single all-zeroes training-data instance.

  • verbose name: Weights
  • default value: None
  • port type: DataPort
  • value type: AnyNumeric (can be None)
  • data direction: INOUT

cost

Smooth part of training cost function.

  • verbose name: Smooth Cost
  • default value: None
  • port type: GraphPort
  • value type: Graph

cost__signature

Argument names of the smooth terms of the training cost function. The first argument is a data structure of weights (usually an array), the second is an optional bias or intercept term (usually a scalar), and the third is the input data (basically what is passed in as the data to the ConvexModel node). Your cost function is then built as follows: you start with one Placeholder node for each of the listed names (whose set slotname must match the respective name); dependent on these placeholders you build out whatever expression represents the smooth component of your cost function. In formulating the cost, it is recommended to use one of the predefined Loss nodes (except MeaureLoss, which is not allowed in this context) to evaluate a loss function in terms of the input data (D). This allows ConvexModel to reuse a portion of your graph as the prediction function (namely the exact portion that is wired into the predictions port of the Loss node). This is however optional and you can always specify the prediction function separately yourself. To then pass your cost function to the ConvexModel node, you wire its final node (which outputs the scalar cost given the arguments) into the "cost" input port of ConvexModel. In graphical UIs, the edge connecting your cost function to the ConvexModel node will be drawn in dotted style to indicate that this is not a normal forward data flow but that a graph (i.e., your cost function) is running under the control of the ConvexModel node. The latter will, among others, take derivatives of your cost in order to optimize the weights. Your graph may also contain additional placeholders for hyper-parameters with names of your choosing (e.g., alpha or gamma); the values for such parameters must then be specified via the hyper_params dictionary input of the ConvexModel node; such hyper-parameters can be used to govern the strength of a smooth regularization term, for example the squared l2 norm of the weights or a Tikhonov operator.

  • verbose name: Smooth Cost [Signature]
  • default value: (w,b,D)
  • port type: Port
  • value type: object (can be None)

pred

Optional prediction function. If not set, will be initialized to a GLM-type prediction function.

  • verbose name: Prediction Function
  • default value: None
  • port type: GraphPort
  • value type: Graph

pred__signature

Argument names of an optional prediction function graph. The arguments are the same as for the cost graph, except that the prediction function is only evaluated at prediction time (after optimization is done), and that the expected output is an array (or packet) of predictions for each observation (instance) in the data. If you do not specify a prediction function, the node will attempt to infer one from the cost function, by taking the subgraph of the cost function that wired into a Loss node (e.g., SquaredLoss), if present, and replacing the loss with the appropriate link function (e.g., Sigmoid, Softmax, or Sign for classification, or no link for regression). Note that this will only work if the cost function actually uses such a Loss node; otherwise you will have to wire in a graph that represents the prediction function here, following a recipe analogous to the one described in the previous sentence.

  • verbose name: Prediction Function [Signature]
  • default value: (w,b,D)
  • port type: Port
  • value type: object (can be None)

prox1

Optional proximal operator.

  • verbose name: Prox1
  • default value: None
  • port type: GraphPort
  • value type: Graph

prox1__signature

Arguments to first proximal operator. Similarly to the cost function, this is an optional graph starting with some Placeholder nodes (in this case one with slotname set to w and another with slotname set to step), and followed by one or more nodes that implement the operation of a proximal operator applied to w with step size step. The output of this operation is then wired into the "prox1" port of the ConvexModel node. Proximal operators represent non-smooth penalties applied to the weights, and the easiest way to specify these operators is to use one of the Penalty nodes in NeuroPype, which implement a wide range of (flexibly configurable) proximal operators, and which have a "data" input (into which the "w" Placeholder is wired) and a "step_size" input (into which the "step" Placeholder is to be wired). Your graph may also contain additional placeholders for hyper-parameters with names of your choosing (e.g., alpha or gamma); the values for such parameters must then be specified via the hyper_params dictionary input of the ConvexModel node.

  • verbose name: Prox1 [Signature]
  • default value: (w,step)
  • port type: Port
  • value type: object (can be None)

prox2

Optional second proximal operator.

  • verbose name: Prox2
  • default value: None
  • port type: GraphPort
  • value type: Graph

prox2__signature

Arguments to the second proximal operator, if any. See documentation of prox1 for more details. Note that most of the available solvers do not natively support more than one proximal operator. In such cases, the operators will be applied in a round-robin fashion (i.e., the first operator is applied to the weights, then the second operator is applied to the result, and so on), which is a sensible strategy if the operators are in some sense orthogonal, for example by acting on different parts of the weights or orthogonal projections of the weights; if the operators are in "tension", the result can be suboptimal, and you may need to implement a single proximal operator that combines the effects of the individual operators, for example by alternating between them in a loop.

  • verbose name: Prox2 [Signature]
  • default value: (w,step)
  • port type: Port
  • value type: object (can be None)

prox3

Optional third proximal operator.

  • verbose name: Prox3
  • default value: None
  • port type: GraphPort
  • value type: Graph

prox3__signature

Arguments to the third proximal operator, if any. See documentation of prox1 for the general structure and prox2 for more details on having more than one prox operator.

  • verbose name: Prox3 [Signature]
  • default value: (w,step)
  • port type: Port
  • value type: object (can be None)

constraint

Optional constraint(s).

  • verbose name: Constraint
  • default value: None
  • port type: GraphPort
  • value type: Graph

constraint__signature

Arguments to constraint projection(s). A constraint projection is a simple graph of (typically) a single placeholder, with slotname set by convention to w, followed by some operation that constrains w to a convex set (e.g., the set of non-negative numbers). NeuroPype ships with a number of such nodes, which generally end in Constraint, and which implement a number of customary convex contraints. The output of the constraint projection is then wired into the "constraint" port of the ConvexModel node.

  • verbose name: Constraint [Signature]
  • default value: (w)
  • port type: Port
  • value type: object (can be None)

hyper_params

Hyper-parameters for the custom wired-in graphs. This is a dictionary of arbitrary key-value pairs that can be used to configure the cost function and proximal operators. The respective graphs may then declare and use placeholders named the same as in the dictionary keys.

  • verbose name: Hyper Params
  • default value: {}
  • port type: DictPort
  • value type: dict (can be None)

max_iter

Maximum number of iterations.

  • verbose name: Max Iter
  • default value: 500
  • port type: IntPort
  • value type: int (can be None)

abstol

Absolute convergence tolerance. If weights change less than this (after normalization by step size), the optimization terminates. Note that this depends on the data scale.

  • verbose name: Abstol
  • default value: 0.001
  • port type: FloatPort
  • value type: float (can be None)

hessian_rank

Maximum rank of the Hessian approximation, if using a quasi-Newton (L-BFGS) method. This is typically only available if none of the prox and constraint argument are specified, and is ignored otherwise. The value is a trade-off between accuracy, memory usage, and performance, and a typical values are 6-10.

  • verbose name: Hessian Rank
  • default value: 10
  • port type: IntPort
  • value type: int (can be None)

stepsize

Optional step size. If unspecified, the step size is adapted automatically using a line search.

  • verbose name: Stepsize
  • default value: None
  • port type: FloatPort
  • value type: float (can be None)

max_backtrack

Maximum number of line search steps per iteration. A typical value is 15, but some solvers, such as L-BFGS can benefit from as many as 30. Only used if step size is left to automatic.

  • verbose name: Max Backtrack
  • default value: None
  • port type: IntPort
  • value type: int (can be None)

backtrack_factor

Backtracking line search factor. Only used if stepsize is 0. The default depends on the chosen algorithm, and is 0.5 for PGD and 0.8 for Jaxopt-based LBFGS.

  • verbose name: Backtrack Factor
  • default value: None
  • port type: FloatPort
  • value type: float (can be None)

increase_factor

Line search increase factor. Only used if stepsize is 0. The default depends on the chosen algorithm, and is 1.5 (jaxopt) or 2.0 (optax) depending on the LBFGS variant.

  • verbose name: Increase Factor
  • default value: None
  • port type: FloatPort
  • value type: float (can be None)

use_jit

If enabled, attempt to use JIT compilation for the inner loop. This incurs a one-time compilation cost, but the actual solving will be greatly accelerated if using the GPU.

  • verbose name: Use Jit
  • default value: auto
  • port type: EnumPort
  • value type: str (can be None)

unroll

Whether to unroll the optimization loop. Not supported by all solvers; this could be useful for very rough solves that are set to terminate after just a few iterations but is otherwise usually not recommended.

  • verbose name: Unroll
  • default value: auto
  • port type: EnumPort
  • value type: str (can be None)

solver

Solver to use. PGD is the basic (unaccelerated) proximal gradient descent and APGD is the Nesterov accelerated version. Both are first-order methods and require the cost function to be differentiable (smooth). APGD typically converges in fewer iterations than PGD at a modest per-iteration overhead. LBFGS is an efficient quasi-Newton method that can be used with twice differentiable cost functions, but supports neither proximal operators nor constraints. The jaxopt variants of these solvers are the legacy implementations that use the (now deprecated) jaxopt package; in the long term, these will be phased out.

  • verbose name: Solver To Use
  • default value: auto
  • port type: ComboPort
  • value type: str (can be None)

linesearch_type

Type of line search to use (if stepsize is not given). Note that the set of implemented line-search modes may depend on the solver and is subject to change.

  • verbose name: Linesearch Type
  • default value: auto
  • port type: ComboPort
  • value type: str (can be None)

verbosity

Verbosity level. 0: no output, 1: per-iteration summary. Note that JIT will be disabled if verbosity is used.

  • verbose name: Verbosity
  • default value: 0
  • port type: IntPort
  • value type: int (can be None)

canonicalize_output_axes

Whether to canonicalize the output axes of the model to match the expected output axes of other machine-learning nodes. This can be turned off if your model emits a handcrafted feature or statistic axis to describe its predictions that you'd like to retain. Note though that some downstream nodes, like MeasureLoss might not work as expected. If your model is highly custom, you may be required to do this step explicitly in your prediction function.

  • verbose name: Canonicalize Output Axes
  • default value: True
  • port type: BoolPort
  • value type: bool (can be None)

train_on

Update the model on the specified data. Note that generally the model will output predictions on any data that it receives whether it is training on it or not. In the "initial offline" mode, and only if the model is not already trained, the model is trained on the first non-streaming packet that it receives, which should thus be the training set, while subsequent data are test data. In the "successive offline" mode, the model is trained on any non-streaming packet that it receives, whether it is already pretrained or not (in such case it will be further fine-tuned given the new training data). In both scenarios, ny streaming data is taken as test-only data; this is a typical scenario for real-time processing when the model is first trained or fine-tuned on some pre-recorded data, but it can also be used to just train a model on multiple successive datasets. The last mode, "offline and streaming" will train on any data that has label information, whether it is offline or streaming. This can be used for either real-time training or fine-tuning, i.e., while data is being collected. Note however that this is dangerous if you also intend to test performance on streaming data -- in such case the model will update (i.e. train) on your test data, unless the test labels are withheld from the node.

  • verbose name: Train On
  • default value: initial offline
  • port type: EnumPort
  • value type: str (can be None)

dont_reset_model

Do not reset the model when the preceding graph is changed. Normally, when certain parameters of preceding nodes are being changed, the model will be reset. If this is enabled, the model will persist, but there is a chance that the model is incompatible when input data format to this node has changed.

  • verbose name: Do Not Reset Model
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

no_compile_in_debug

Do not compile the model when running in debug mode.

  • verbose name: No Compile In Debug
  • default value: True
  • port type: BoolPort
  • value type: bool (can be None)

set_breakpoint

Set a breakpoint on this node. If this is enabled, your debugger (if one is attached) will trigger a breakpoint.

  • verbose name: Set Breakpoint (Debug Only)
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

metadata

User-definable meta-data associated with the node. Usually reserved for technical purposes.

  • verbose name: Metadata
  • default value: {}
  • port type: DictPort
  • value type: dict (can be None)