rvfl

1from .regressor import RVFLRegressor
2from .classifier import RVFLClassifier
3
4__all__ = ["RVFLRegressor", "RVFLClassifier"]
class RVFLRegressor(rvfl.base._RVFLBase, sklearn.base.RegressorMixin):
 7class RVFLRegressor(_RVFLBase, RegressorMixin):
 8    """
 9    Random Vector Functional Link Regressor.
10
11    Fits a single-hidden-layer network with random, fixed weights by solving
12    a ridge regression problem in closed form.  Supports single- and
13    multi-output regression.
14
15    Inherits all parameters from :class:`_RVFLBase`.
16
17    Examples
18    --------
19    >>> from rvfl import RVFLRegressor
20    >>> model = RVFLRegressor(n_nodes=200, alpha=1e-2)
21    >>> model.fit(X_train, y_train)
22    RVFLRegressor(alpha=0.01, n_nodes=200)
23    >>> y_pred = model.predict(X_test)
24    """
25
26    def fit(self, X, Y):
27        """
28        Fit the RVFL regressor.
29
30        Parameters
31        ----------
32        X : array-like of shape (n_samples, n_features)
33            Training inputs.
34        Y : array-like of shape (n_samples,) or (n_samples, n_targets)
35            Training targets.  1-D arrays are treated as single-output.
36
37        Returns
38        -------
39        self : RVFLRegressor
40            Fitted estimator.
41        """
42        Y = np.array(Y) if np.ndim(Y) == 2 else np.array(Y)[:, None]
43        self._fit_hidden(X, Y)
44        return self
45
46    def predict(self, X):
47        """
48        Predict target values for ``X``.
49
50        Parameters
51        ----------
52        X : array-like of shape (n_samples, n_features)
53            Input samples.
54
55        Returns
56        -------
57        y : ndarray of shape (n_samples,) or (n_samples, n_targets)
58            Predicted values.  The trailing dimension is squeezed away for
59            single-output problems.
60        """
61        return self._predict_raw(X).squeeze()

Random Vector Functional Link Regressor.

Fits a single-hidden-layer network with random, fixed weights by solving a ridge regression problem in closed form. Supports single- and multi-output regression.

Inherits all parameters from _RVFLBase.

Examples

>>> from rvfl import RVFLRegressor
>>> model = RVFLRegressor(n_nodes=200, alpha=1e-2)
>>> model.fit(X_train, y_train)
RVFLRegressor(alpha=0.01, n_nodes=200)
>>> y_pred = model.predict(X_test)
def fit(self, X, Y):
26    def fit(self, X, Y):
27        """
28        Fit the RVFL regressor.
29
30        Parameters
31        ----------
32        X : array-like of shape (n_samples, n_features)
33            Training inputs.
34        Y : array-like of shape (n_samples,) or (n_samples, n_targets)
35            Training targets.  1-D arrays are treated as single-output.
36
37        Returns
38        -------
39        self : RVFLRegressor
40            Fitted estimator.
41        """
42        Y = np.array(Y) if np.ndim(Y) == 2 else np.array(Y)[:, None]
43        self._fit_hidden(X, Y)
44        return self

Fit the RVFL regressor.

Parameters

X : array-like of shape (n_samples, n_features) Training inputs. Y : array-like of shape (n_samples,) or (n_samples, n_targets) Training targets. 1-D arrays are treated as single-output.

Returns

self : RVFLRegressor Fitted estimator.

def predict(self, X):
46    def predict(self, X):
47        """
48        Predict target values for ``X``.
49
50        Parameters
51        ----------
52        X : array-like of shape (n_samples, n_features)
53            Input samples.
54
55        Returns
56        -------
57        y : ndarray of shape (n_samples,) or (n_samples, n_targets)
58            Predicted values.  The trailing dimension is squeezed away for
59            single-output problems.
60        """
61        return self._predict_raw(X).squeeze()

Predict target values for X.

Parameters

X : array-like of shape (n_samples, n_features) Input samples.

Returns

y : ndarray of shape (n_samples,) or (n_samples, n_targets) Predicted values. The trailing dimension is squeezed away for single-output problems.

class RVFLClassifier(rvfl.base._RVFLBase, sklearn.base.ClassifierMixin):
  8class RVFLClassifier(_RVFLBase, ClassifierMixin):
  9    """
 10    Random Vector Functional Link Classifier.
 11
 12    Solves the regularized normal equation directly on a one-hot encoded
 13    response matrix of shape ``(n_samples, n_classes)`` — no separate
 14    regressors, no loops over classes.  All computation is pure matrix
 15    algebra, identical to what the RVFL regressor does internally except
 16    that the right-hand side ``Y`` is now a 2-D one-hot matrix instead of
 17    a 1-D (or single-column) target vector.
 18
 19    The closed-form solution is:
 20
 21    .. math::
 22
 23        \\beta = (H^\\top H + \\alpha I)^{-1} H^\\top Y
 24
 25    where :math:`H` is the hidden-feature matrix (random projections +
 26    optional direct link) built by :class:`_RVFLBase`.
 27
 28    Raw per-class scores ``H @ beta`` are converted to calibrated
 29    probabilities with the element-wise sigmoid (``expit``) followed by
 30    row-normalisation, so every row sums to 1.
 31
 32    Inherits all parameters from :class:`_RVFLBase`.
 33
 34    Attributes
 35    ----------
 36    classes_ : ndarray of shape (n_classes,)
 37        Unique class labels seen during ``fit``, in sorted order.
 38    n_classes_ : int
 39        Number of unique classes.
 40
 41    Examples
 42    --------
 43    >>> from rvfl import RVFLClassifier
 44    >>> clf = RVFLClassifier(n_nodes=200, activation='relu')
 45    >>> clf.fit(X_train, y_train)
 46    RVFLClassifier(activation='relu', n_nodes=200)
 47    >>> clf.predict(X_test)
 48    array([...])
 49    >>> clf.predict_proba(X_test)
 50    array([[...]])
 51    """
 52
 53    def __init__(
 54        self,
 55        n_nodes=200,
 56        activation="relu",
 57        scale=1.0,
 58        alpha=1e-4,
 59        direct_link=True,
 60        random_state=42,
 61    ):
 62        super().__init__(
 63            n_nodes=n_nodes,
 64            activation=activation,
 65            scale=scale,
 66            alpha=alpha,
 67            direct_link=direct_link,
 68            random_state=random_state,
 69        )
 70
 71    # ------------------------------------------------------------------
 72    # Internal helper
 73    # ------------------------------------------------------------------
 74
 75    @staticmethod
 76    def _one_hot(y_idx, n_classes):
 77        """
 78        Build a one-hot matrix from integer class indices.
 79
 80        Parameters
 81        ----------
 82        y_idx : ndarray of shape (n_samples,)
 83            Integer class indices in ``{0, ..., n_classes-1}``.
 84        n_classes : int
 85
 86        Returns
 87        -------
 88        Y : ndarray of shape (n_samples, n_classes), dtype float64
 89        """
 90        Y = np.zeros((len(y_idx), n_classes), dtype=float)
 91        Y[np.arange(len(y_idx)), y_idx] = 1.0
 92        return Y
 93
 94    # ------------------------------------------------------------------
 95    # Public API
 96    # ------------------------------------------------------------------
 97
 98    def fit(self, X, y):
 99        """
100        Fit the RVFL classifier.
101
102        Builds the hidden-feature matrix ``H`` via :class:`_RVFLBase`,
103        one-hot encodes ``y`` into ``Y`` of shape
104        ``(n_samples, n_classes)``, then solves the single ridge system
105
106        .. math::
107
108            \\beta = (H^\\top H + \\alpha I)^{-1} H^\\top Y
109
110        to obtain the weight matrix ``beta_`` of shape
111        ``(n_hidden_features, n_classes)``.
112
113        Parameters
114        ----------
115        X : array-like of shape (n_samples, n_features)
116            Training inputs.
117        y : array-like of shape (n_samples,)
118            Class labels (integers, strings, or any type sortable by
119            ``numpy.unique``).
120
121        Returns
122        -------
123        self : RVFLClassifier
124            Fitted estimator.
125        """
126        self.classes_ = np.unique(y)
127        self.n_classes_ = len(self.classes_)
128
129        # Map arbitrary labels → contiguous integers 0 … n_classes-1
130        label_to_idx = {lbl: i for i, lbl in enumerate(self.classes_)}
131        y_idx = np.array([label_to_idx[lbl] for lbl in y])
132
133        # One-hot response matrix  (n_samples × n_classes)
134        Y = self._one_hot(y_idx, self.n_classes_)
135
136        # Delegate to _RVFLBase: builds H and solves the normal equation
137        # for a multi-column right-hand side — identical path to regression.
138        self._fit_hidden(X, Y)
139        return self
140
141    def predict_proba(self, X):
142        """
143        Predict class probabilities for ``X``.
144
145        Raw scores ``H @ beta_`` (shape ``(n_samples, n_classes)``) are
146        passed through the element-wise sigmoid and then row-normalised:
147
148        .. math::
149
150            p_{ij} = \\frac{\\sigma(s_{ij})}{\\sum_k \\sigma(s_{ik})}
151
152        Parameters
153        ----------
154        X : array-like of shape (n_samples, n_features)
155            Input samples.
156
157        Returns
158        -------
159        proba : ndarray of shape (n_samples, n_classes)
160            Estimated class probabilities.  Rows sum to 1.
161        """
162        scores = self._predict_raw(X)  # (n_samples, n_classes)
163        proba = expit(scores)  # element-wise sigmoid
164        row_sums = proba.sum(axis=1, keepdims=True)
165        row_sums = np.where(row_sums < 1e-10, 1e-10, row_sums)
166        return proba / row_sums
167
168    def predict(self, X):
169        """
170        Predict class labels for ``X``.
171
172        Parameters
173        ----------
174        X : array-like of shape (n_samples, n_features)
175            Input samples.
176
177        Returns
178        -------
179        labels : ndarray of shape (n_samples,)
180            Predicted class labels in the same encoding seen during ``fit``.
181        """
182        return self.classes_[self.predict_proba(X).argmax(axis=1)]
183
184    def decision_function(self, X):
185        """
186        Raw per-class scores before sigmoid.
187
188        For binary problems returns a 1-D array (score for the positive
189        class); for multiclass returns a 2-D array of shape
190        ``(n_samples, n_classes)``.
191
192        Parameters
193        ----------
194        X : array-like of shape (n_samples, n_features)
195            Input samples.
196
197        Returns
198        -------
199        scores : ndarray of shape (n_samples,) or (n_samples, n_classes)
200        """
201        scores = self._predict_raw(X)
202        if self.n_classes_ == 2:
203            return scores[:, 1]
204        return scores

Random Vector Functional Link Classifier.

Solves the regularized normal equation directly on a one-hot encoded response matrix of shape (n_samples, n_classes) — no separate regressors, no loops over classes. All computation is pure matrix algebra, identical to what the RVFL regressor does internally except that the right-hand side Y is now a 2-D one-hot matrix instead of a 1-D (or single-column) target vector.

The closed-form solution is:

$$\beta = (H^\top H + \alpha I)^{-1} H^\top Y$$

where \( H \) is the hidden-feature matrix (random projections + optional direct link) built by _RVFLBase.

Raw per-class scores H @ beta are converted to calibrated probabilities with the element-wise sigmoid (expit) followed by row-normalisation, so every row sums to 1.

Inherits all parameters from _RVFLBase.

Attributes

classes_ : ndarray of shape (n_classes,) Unique class labels seen during fit, in sorted order. n_classes_ : int Number of unique classes.

Examples

>>> from rvfl import RVFLClassifier
>>> clf = RVFLClassifier(n_nodes=200, activation='relu')
>>> clf.fit(X_train, y_train)
RVFLClassifier(activation='relu', n_nodes=200)
>>> clf.predict(X_test)
array([...])
>>> clf.predict_proba(X_test)
array([[...]])
def fit(self, X, y):
 98    def fit(self, X, y):
 99        """
100        Fit the RVFL classifier.
101
102        Builds the hidden-feature matrix ``H`` via :class:`_RVFLBase`,
103        one-hot encodes ``y`` into ``Y`` of shape
104        ``(n_samples, n_classes)``, then solves the single ridge system
105
106        .. math::
107
108            \\beta = (H^\\top H + \\alpha I)^{-1} H^\\top Y
109
110        to obtain the weight matrix ``beta_`` of shape
111        ``(n_hidden_features, n_classes)``.
112
113        Parameters
114        ----------
115        X : array-like of shape (n_samples, n_features)
116            Training inputs.
117        y : array-like of shape (n_samples,)
118            Class labels (integers, strings, or any type sortable by
119            ``numpy.unique``).
120
121        Returns
122        -------
123        self : RVFLClassifier
124            Fitted estimator.
125        """
126        self.classes_ = np.unique(y)
127        self.n_classes_ = len(self.classes_)
128
129        # Map arbitrary labels → contiguous integers 0 … n_classes-1
130        label_to_idx = {lbl: i for i, lbl in enumerate(self.classes_)}
131        y_idx = np.array([label_to_idx[lbl] for lbl in y])
132
133        # One-hot response matrix  (n_samples × n_classes)
134        Y = self._one_hot(y_idx, self.n_classes_)
135
136        # Delegate to _RVFLBase: builds H and solves the normal equation
137        # for a multi-column right-hand side — identical path to regression.
138        self._fit_hidden(X, Y)
139        return self

Fit the RVFL classifier.

Builds the hidden-feature matrix H via _RVFLBase, one-hot encodes y into Y of shape (n_samples, n_classes), then solves the single ridge system

$$\beta = (H^\top H + \alpha I)^{-1} H^\top Y$$

to obtain the weight matrix beta_ of shape (n_hidden_features, n_classes).

Parameters

X : array-like of shape (n_samples, n_features) Training inputs. y : array-like of shape (n_samples,) Class labels (integers, strings, or any type sortable by numpy.unique).

Returns

self : RVFLClassifier Fitted estimator.

def predict_proba(self, X):
141    def predict_proba(self, X):
142        """
143        Predict class probabilities for ``X``.
144
145        Raw scores ``H @ beta_`` (shape ``(n_samples, n_classes)``) are
146        passed through the element-wise sigmoid and then row-normalised:
147
148        .. math::
149
150            p_{ij} = \\frac{\\sigma(s_{ij})}{\\sum_k \\sigma(s_{ik})}
151
152        Parameters
153        ----------
154        X : array-like of shape (n_samples, n_features)
155            Input samples.
156
157        Returns
158        -------
159        proba : ndarray of shape (n_samples, n_classes)
160            Estimated class probabilities.  Rows sum to 1.
161        """
162        scores = self._predict_raw(X)  # (n_samples, n_classes)
163        proba = expit(scores)  # element-wise sigmoid
164        row_sums = proba.sum(axis=1, keepdims=True)
165        row_sums = np.where(row_sums < 1e-10, 1e-10, row_sums)
166        return proba / row_sums

Predict class probabilities for X.

Raw scores H @ beta_ (shape (n_samples, n_classes)) are passed through the element-wise sigmoid and then row-normalised:

$$p_{ij} = \frac{\sigma(s_{ij})}{\sum_k \sigma(s_{ik})}$$

Parameters

X : array-like of shape (n_samples, n_features) Input samples.

Returns

proba : ndarray of shape (n_samples, n_classes) Estimated class probabilities. Rows sum to 1.

def predict(self, X):
168    def predict(self, X):
169        """
170        Predict class labels for ``X``.
171
172        Parameters
173        ----------
174        X : array-like of shape (n_samples, n_features)
175            Input samples.
176
177        Returns
178        -------
179        labels : ndarray of shape (n_samples,)
180            Predicted class labels in the same encoding seen during ``fit``.
181        """
182        return self.classes_[self.predict_proba(X).argmax(axis=1)]

Predict class labels for X.

Parameters

X : array-like of shape (n_samples, n_features) Input samples.

Returns

labels : ndarray of shape (n_samples,) Predicted class labels in the same encoding seen during fit.