[help please!] Error with custom training loop: Value to differentiate is not traced.

1 visualización (últimos 30 días)
Hi!
I am using MATLAB to code a neural network with custom loss fuction these days.
I run the code and get this error: Value to differentiate is not traced. It must be a traced real dlarray scalar. Use dlgradient
inside a function called by dlfeval to trace the variables.
Here's my code:
% Generate data
sampleSize = 1000;
x = -2 + (2+2)*rand(1000,1);
e = randn(sampleSize,1);
y = (x.^2-1<=0).*(x+e) + (x.^2-1>0).*(-x+e);
data = table();
data = addvars(data, y); data = addvars(data, x);
% Define network
layers = [
featureInputLayer(1)
tanhLayer()
fullyConnectedLayer(10)
tanhLayer()
fullyConnectedLayer(10)
tanhLayer()
fullyConnectedLayer(1)];
net = dlnetwork(layers);
% hyper parameters
numEpoch = 100;
learnRate = 0.0002;
gradientDecayFactor = 0.5;
squaredGradientDecayFactor = 0.999;
trailingAvg = [];
trailingAvgSqD = [];
% Training
iteration = 0;
start = tic;
for i = 1:numEpoch
fprintf('The %.dth epoch.\n', i);
iteration = iteration + 1;
% Do NOT use batch
X = dlarray(data{:,'x'},'BC');
if canUseGPU
X = gpuArray(X);
end
% get loss and gradients
[loss,gradients] = dlfeval(@modelLoss, net, X, data);
% update parameters
[net,trailingAvg,trailingAvgSqD] = adamupdate(net, gradients, ...
trailingAvg, trailingAvgSqD, iteration, ...
learnRate, gradientDecayFactor, squaredGradientDecayFactor);
end
The 'modelLoss' function looks like:
function [loss,gradients,state] = modelLoss(net, X, data)
% get output of network
output = forward(net, X);
% !!! where the problem is !!!
f = extractdata(output)';
% get sub sample according to wether f larger than 0
% get SSE of each OLS regression in each subsample
if height(data(f<=0,:))<5 || height(data(f>0,:))<5
mdl = fitlme(data, 'y ~ x');
loss = mdl.SSE;
else
mdl1 = fitlme(data(f<=0, :), 'y ~ x ');
mdl2 = fitlme(data(f>0, :), 'y ~ x ');
loss = mdl1.SSE + mdl2.SSE;
end
% return loss
gradients = dlgradient(dlarray(loss), net.Learnables);
end
I've read another answer, which states that I should not use the "extractdata" function, since the gradient information will be erased.
But it seems that I must use this function because the object 'dlarray' do not support the function 'find'!
Could someone help me please!!!
Thank you so much!!!

Respuestas (1)

sanidhyak
sanidhyak el 19 de Feb. de 2025
Editada: sanidhyak el 3 de Mzo. de 2025
I understand that you are encountering the error "Value to differentiate is not traced" while training your custom neural network in MATLAB. I too faced the same issue when reproducing the provided code. This issue arises because gradient tracking is broken inside the modelLoss function due to the use of extractdata and fitlme” functions.
To resolve this, the following workarounds are needed in the provided code:
  • Remove extractdata” function to maintain gradient tracking.
  • Replace fitlme with a custom regression function compatible with dlarray.
  • Use element-wise operations (.* instead of *) so that dlarray is compatibility.
Kindly refer to the following corrected code:
% Training loop modifications
for i = 1:numEpoch
fprintf('The %.dth epoch.\n', i);
iteration = iteration + 1;
% Convert both X and Y to dlarrays
X = dlarray(data{:,'x'},'BC');
Y = dlarray(data{:,'y'},'BC');
if canUseGPU
X = gpuArray(X);
Y = gpuArray(Y);
end
% Get loss and gradients
[loss,gradients] = dlfeval(@modelLoss, net, X, Y);
% Update parameters
[net,trailingAvg,trailingAvgSqD] = adamupdate(net, gradients, ...
trailingAvg, trailingAvgSqD, iteration, ...
learnRate, gradientDecayFactor, squaredGradientDecayFactor);
end
The corrected "modelLoss" function:
function [loss,gradients] = modelLoss(net, X, Y)
% Get network output
output = forward(net, X);
% Create masks while maintaining gradient tracking
mask_neg = output <= 0;
mask_pos = output > 0;
% Count samples in each group
n_neg = sum(mask_neg, 'all');
n_pos = sum(mask_pos, 'all');
% Initialize loss
loss = dlarray(0);
if n_neg >= 5 && n_pos >= 5
% Split data using masks while preserving gradients
X_neg = X .* mask_neg;
Y_neg = Y .* mask_neg;
X_pos = X .* mask_pos;
Y_pos = Y .* mask_pos;
% Calculate regression for each group
beta_neg = calculateBeta(X_neg(mask_neg), Y_neg(mask_neg));
pred_neg = X_neg .* beta_neg;
loss_neg = sum((Y_neg - pred_neg).^2, 'all');
beta_pos = calculateBeta(X_pos(mask_pos), Y_pos(mask_pos));
pred_pos = X_pos .* beta_pos;
loss_pos = sum((Y_pos - pred_pos).^2, 'all');
loss = loss_neg + loss_pos;
else
% Single regression if groups are too small
beta = calculateBeta(X, Y);
pred = X .* beta;
loss = sum((Y - pred).^2, 'all');
end
gradients = dlgradient(loss, net.Learnables);
end
Helper function:
function beta = calculateBeta(X, Y)
XX = sum(X .* X, 'all');
XY = sum(X .* Y, 'all');
beta = XY ./ XX;
end
This implementation solves the error, and gradient tracking will be maintained throughout the training loop.
For further reference, please check the following MATLAB documentations on “dlarray” and “dlradient”:
I hope this helps!
(As can be seen in the screenshot below, the error has been resolved, and training is proceeding)

Categorías

Más información sobre Custom Training Using Automatic Differentiation en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by