class_docstr: Multi-layer Perceptron for regression.
  
  This model is still work in progress. Here are some features that still need implementing:
  
  - `learn_one` and `predict_one` just cast the input `dict` to a single row dataframe and then
      call `learn_many` and `predict_many` respectively. This is very inefficient.
  - Not all of the optimizers in the `optim` module can be used as they are not all vectorised.
  - Emerging and disappearing features are not supported. Each instance/batch has to have the
      same features.
  - The gradient haven't been numerically checked.
  
  Parameters
  ----------
  hidden_dims
      The dimensions of the hidden layers. For example, specifying `(10, 20)` means that there
      are two hidden layers with 10 and 20 neurons, respectively. Note that the number of layers
      the network contains is equal to the number of hidden layers plus two (to account for the
      input and output layers).
  activations
      The activation functions to use at each layer, including the input and output layers.
      Therefore you need to specify three activation if you specify one hidden layer.
  loss
      Loss function. Defaults to `optim.losses.Squared`.
  optimizer
      Optimizer. Defaults to `optim.SGD` with the learning rate set to `0.01`.
  seed
      Random number generation seed. Set this for reproducibility.
  
  Examples
  --------
  
  >>> from river import datasets
  >>> from river import evaluate
  >>> from river import neural_net as nn
  >>> from river import optim
  >>> from river import preprocessing as pp
  >>> from river import metrics
  
  >>> model = (
  ...     pp.StandardScaler() |
  ...     nn.MLPRegressor(
  ...         hidden_dims=(5,),
  ...         activations=(
  ...             nn.activations.ReLU,
  ...             nn.activations.ReLU,
  ...             nn.activations.Identity
  ...         ),
  ...         optimizer=optim.SGD(1e-3),
  ...         seed=42
  ...     )
  ... )
  
  >>> dataset = datasets.TrumpApproval()
  
  >>> metric = metrics.MAE()
  
  >>> evaluate.progressive_val_score(dataset, model, metric)
  MAE: 1.580578
  
  You can also use this to process mini-batches of data.
  
  >>> model = (
  ...     pp.StandardScaler() |
  ...     nn.MLPRegressor(
  ...         hidden_dims=(10,),
  ...         activations=(
  ...             nn.activations.ReLU,
  ...             nn.activations.ReLU,
  ...             nn.activations.ReLU
  ...         ),
  ...         optimizer=optim.SGD(1e-4),
  ...         seed=42
  ...     )
  ... )
  
  >>> dataset = datasets.TrumpApproval()
  >>> batch_size = 32
  
  >>> for epoch in range(10):
  ...     for xb in pd.read_csv(dataset.path, chunksize=batch_size):
  ...         yb = xb.pop('five_thirty_eight')
  ...         y_pred = model.predict_many(xb)
  ...         model.learn_many(xb, yb)
  
  >>> model.predict_many(xb)
        five_thirty_eight
  992           39.405231
  993           46.447481
  994           42.121865
  995           40.251148
  996           40.836378
  997           40.893153
  998           40.949927
  999           48.416504
  1000          42.077830
code: def __init__(
      self,
      hidden_dims,
      activations,
      loss: optim.losses.Loss | None = None,
      optimizer: optim.base.Optimizer | None = None,
      seed: int | None = None,
  ):
      super().__init__(
          hidden_dims=hidden_dims,
          activations=activations,
          loss=loss or optim.losses.Squared(),
          optimizer=optimizer or optim.SGD(0.01),
          seed=seed,
      )
  
imports: from __future__ import annotations
  import collections
  import copy
  import functools
  import numpy
  import pandas
  from river import base, optim
label_desc: Use image node_id 1 to create a new MLPRegressor object from inherited base classes: base, MLP with example: obj = MLPRegressor(hidden_dims, activations, loss, optimizer, seed)