Complex-Valued Neural Networks
R2026bComplex numbers are a useful and natural way of expressing data in many scientific and engineering domains, such as wireless communications or quantum mechanics. To model data in these domains, build and train neural networks with complex-valued inputs, outputs, and learnable parameters.
Since R2024a, the trainnet function, the
dlgradient function, the automatic differentiation framework, and many
layers, solvers, and metrics support complex numbers. You can build and train a complex-valued
neural network in the same way you would build and train a real-valued neural network.
For an example showing how to train a simple complex-valued neural network, see Denoise Complex-Valued Signal Using Multilayer Perceptron.
For an example showing how to train a complex-valued neural network for a wireless communication application, see Complex-Valued Neural Network for Digital Predistortion Design-Offline Training (Communications Toolbox).
For an example showing how to train a complex-valued physics-informed neural network to solve a quantum mechanics problem, see Train Complex-Valued Physics-Informed Neural Network.
An alternative approach is to split the data into real and imaginary parts and treat them as two separate real-valued input channels. Use this approach in these circumstances:
You are using a release that is older than R2024a.
Your solver or network architecture does not support complex numbers.
The next steps in your workflow do not support complex-valued neural networks. For example, formal verification, compression, and code generation do not support complex-valued neural networks.
For more information, see Split Input Data Into Real and Imaginary Components. For an example of this approach, see Train Network with Complex-Valued Data.
Supported Layers
There are two types of layers that support complex-valued input and output data:
Layers that do not have learnables and use the same algorithm for both real and complex values, and that therefore support both real and complex input data; for example,
additionLayerDedicated complex layers that have learnables or that require a specific, complex algorithm; for example,
complexConvolution1dLayer
Since R2024a, unless otherwise indicated, these layers support complex-valued data.
Input Layers
| An input layer inputs unformatted data or data with a custom format into a neural network. | |
| An image input layer inputs 2-D images to a neural network and applies data normalization. | |
| A 3-D image input layer inputs 3-D images or volumes to a neural network and applies data normalization. | |
| A sequence input layer inputs sequence data to a neural network and applies data normalization. | |
| A feature input layer inputs feature data to a neural network and applies data normalization. Use this layer when you have a data set of numeric scalars representing features (data without spatial or time dimensions). |
Convolution and Fully Connected Layers
| A complex fully connected layer multiplies the input by a complex weight matrix and then adds a complex bias vector. |
| A complex 1-D convolutional layer applies sliding complex convolutional filters to 1-D input. |
| A complex 2-D convolutional layer applies sliding complex convolutional filters to 2-D input. |
Sequence Layers
| A flatten layer collapses the spatial dimensions of the input into the channel dimension. |
Activation Layers
| A hyperbolic tangent (tanh) activation layer applies the tanh function on the layer inputs. | |
| A function layer applies a specified function to the layer input. | |
| A complex ReLU layer performs a threshold operation to the real and imaginary parts of the input, where any value less than zero is set to zero. |
| A zReLU layer performs a threshold operation to complex inputs, where any value with negative real or imaginary part is set to zero. |
Utility Layers
| A dropout layer randomly sets input elements to zero with a given probability. | |
| A scaling layer linearly scales and offsets the input data. | |
| A 2-D crop layer applies 2-D cropping to the input. | |
| A 3-D crop layer crops a 3-D volume to the size of the input feature map. | |
| A complex-to-real layer converts complex-valued data to real-valued data by splitting the data in a specified dimension. |
| A real-to-complex layer converts real-valued data to complex-valued data by merging the data in a specified dimension. |
Pooling Layers
| A 1-D global average pooling layer performs downsampling by outputting the average of the time or spatial dimensions of the input. | |
| A 2-D global average pooling layer performs downsampling by computing the mean of the height and width dimensions of the input. | |
| A 3-D global average pooling layer performs downsampling by computing the mean of the height, width, and depth dimensions of the input. |
Combination Layers
| An addition layer adds inputs from multiple neural network layers element-wise. | |
| A multiplication layer multiplies inputs from multiple neural network layers element-wise. | |
| A concatenation layer takes inputs and concatenates them along a specified dimension. The inputs must have the same size in all dimensions except the concatenation dimension. | |
| A depth concatenation layer takes inputs that have the same height and width and concatenates them along the channel dimension. |
Supported Solvers
To choose a solver, specify the solverName argument of the
function.trainingOptions
There are two types of solvers in Deep Learning Toolbox™: stochastic solvers and batch solvers. Only stochastic solvers support complex-valued gradients.
| Solver | Description | Syntax |
|---|---|---|
| SGDM | Stochastic gradient descent with momentum | trainingOptions("sgdm",...) |
| RMSProp | Root mean square propagation | trainingOptions("rmsprop",...) |
| Adam | Adaptive moment estimation | trainingOptions("adam",...) |
Supported Metrics and Loss Functions
Since R2026a, these built-in metrics support complex-valued network outputs:
"mae"/"mean-absolute-error"/"l1loss"— Mean absolute error for regression tasks"mse"/"mean-squared-error"/"l2loss"— Mean squared error for regression tasks
You can also define custom metrics that support complex-valued network outputs. To learn more about defining custom metrics, see Define Custom Metric Function.
Supported Functions
Every function listed in MATLAB Functions with dlarray Support supports complex-valued
dlarray inputs, provided the underlying function supports
complex-valued inputs.
Additionally, these functions support complex-valued dlarray objects as
inputs:
| Compute gradients for custom training loops using automatic differentiation | |
| Sum all weighted input data and apply a bias |
| L1 loss for regression tasks |
| L2 loss for regression tasks |
Choose Complex Activation Layer
Choosing activation layers can affect the performance of a neural network. For an example showing how to choose an activation layer, see Compare Activation Layers.
Creating an equivalent complex-valued layer for a real-valued activation layer might not be straightforward. For example, the original layer might have more than one complex equivalent, as is the case for the ReLU layer. The algorithm of the ReLU operation cannot be applied directly to complex numbers because it assumes that the data is ordered. Instead, there are several different complex algorithms for ReLU. Deep Learning Toolbox contains two built-in complex ReLU layers:
zReLU — A
object performs a threshold operation to complex inputs, where the layer sets any value with a negative real or imaginary part to zero. For example,zreluLayer-1 + 2iresults in0, because the real part is negative.1 - 2iresults in0, because the imaginary part is negative.1 + 2iresults in1 + 2i, because both the real and the imaginary part are positive.Complex ReLU — A
object performs a threshold operation on the real and imaginary parts of the input separately, where the layer sets any negative value to zero. For example,complexReluLayer-1 + 2iresults in0 + 2i.1 - 2iresults in1 + 0i.
Even if you can apply a layer to complex numbers, it might still behave differently than when you apply it to real numbers. For example, the swish operation is defined as . For complex numbers, this function oscillates and has poles, where the denominator is equal to zero and the function diverges.
Create Custom Complex Layer
To create a custom layer that supports complex-valued input data, follow the same process as you would to create a custom layer that supports only real-valued data, but specify only operations that support complex numbers. To learn how to create custom layers, see Define Custom Deep Learning Layers.
For example, to create a complex-valued swish activation layer that applies the swish activation function separately to the real and imaginary parts of the input, use this code.
classdef complexSwishLayer < nnet.layer.Layer & nnet.layer.Acceleratable % complexSwishLayer Complex-valued swish activation layer % % A complex swish layer applies the swish activation function % separately to the real and imaginary parts of the input: % % complexSwish(a + ib) = swish(a) + i*swish(b), % % where swish(x) = x / (1 + exp(-x)). methods function layer = complexSwishLayer(args) arguments args.Name = ""; end layer.Name = args.Name; layer.Description = "Complex Swish"; end function Z = predict(~, X) Z = complex(swish(real(X)),swish(imag(X))); end end end function Y = swish(X) Y = X ./ (1 + exp(-X)); end
Define Complex Backward Function
Note
Defining the backward function is optional and rarely needed. If you do not
specify a backward function, and the layer forward functions support objects, then the
software determines the complex backward function using automatic differentiation.
For a list of functions that support dlarraydlarray objects, see List of Functions with dlarray Support.
Define a custom backward function when you want to:
Use a specific algorithm to compute the derivatives.
Use operations in the forward functions that do not support
dlarrayobjects.Customize the backward function at points where the derivative is not defined. For example, the ReLU operation has a discontinuity at x=0. By default, the software sets the gradient to 0 at the discontinuity. To choose a different value, create a custom ReLU layer and use a custom backward function.
The definition of the gradient for the backward function is different for complex-valued layers than for real-valued layers.
When training a neural network, compute the complex gradients by using the conjugate Wirtinger derivative. This derivative points in the direction of the steepest ascent in the complex plane:
The function returns
twice the value of the conjugate Wirtinger derivative. However, the loss must be real,
so . MATLAB® computes the nonconjugate Wirtinger derivative during backpropagation and
applies a complex conjugate at the end. Therefore, to implement a custom complex
backward function, implement the nonconjugate Wirtinger derivative of the loss
function:dlgradient
For more information on how to implement custom backward functions, see Backward Function.
Resolve Unintended Complex Gradients
Backpropagation can cause complex gradients to flow into layers that do not support
complex numbers. In that situation, you might see an error message like this:
Encountered complex value when computing gradient with respect to an output
of fullyConnectedLayer. Convert all outputs of fullyConnectedLayer to
real.
To resolve this error, add calls to the real function before the
layer that returns complex gradients.
If complex gradients propagate back into a layer from a complex layer, add a function layer before the complex layer:
layers = [
featureInputLayer(10)
fullyConnectedLayer(10)
functionLayer(@real) % add function layer
complexReluLayer
complexToRealLayer];If complex gradients propagate inside a custom loss function, add a call to the
real function in the loss
function:
function [loss,grad] = customLoss(X) loss = imag(sigmoid(X)); loss = real(loss); % add call to real loss = sum(loss,"all") grad = dlgradient(loss,X); end
Split Input Data Into Real and Imaginary Components
If you cannot use a complex-valued neural network, then an alternative approach is to split the data into real and imaginary parts and treat them as two separate real-valued input channels.
Before R2024a, split the data into real and imaginary parts before giving it to the
neural network by using the real and imag
functions.
In R2024a, if a network starts with one of these input layers, set the
SplitComplexInputs name-value argument to true:
After R2024b, add a layer after the input
layer instead.complexToRealLayer
After R2024b, if most of a neural network supports complex-valued data, and only a
subsection of the network does not, then you can wrap that subsection in and complexToRealLayer objects. For
example:realToComplexLayer
layers = [... inputLayer(inputSize), ... layerThatSupportsComplex1, ... layerThatSupportsComplex2, ... % more layers complexToRealLayer, ... layerThatDoesNotSupportComplex, ... realToComplexLayer, ... % more layers ];
See Also
| complexFullyConnectedLayer | complexConvolution1dLayer | complexConvolution2dLayer | complexReluLayer | zreluLayer | complexToRealLayerrealToComplexLayer