Network class hidden/undocumented properties

I have 2 network objects. net1 is defined by calling "fitnet", net2 by calling "network". Then net2 is set to be identical to net1, and it actually is.
If i call "isequal" on every single visible property (they are 37) of them I get true but if I call isequal(net1,net2) I get false.
How is that possibile? Are there any hidden/undocumented properties in network class? If yes, how can I retrieve them?
Here's some code
Define networks
net2 = distdelaynet({[1,2,3],[0,1],[0,1]},[10,5]);
net1 = network(1,3,[true;true;true],[true;false;false],[false,false,false;true,false,false;false,true,false],[false,false,true]);
net1.inputs{1,1}.processFcns = {'removeconstantrows','mapminmax'};
net1.outputs{1,3}.processFcns = {'removeconstantrows','mapminmax'};
net1.layers{1,1}.name = 'Hidden 1';
net1.layers{1,1}.size = 10;
net1.layers{1,1}.transferFcn = 'tansig';
net1.layers{1,1}.initFcn = 'initnw';
net1.layers{2,1}.name = 'Hidden 2';
net1.layers{2,1}.size = 5;
net1.layers{2,1}.transferFcn = 'tansig';
net1.layers{2,1}.initFcn = 'initnw';
net1.layers{3,1}.name = 'Output';
net1.layers{3,1}.initFcn = 'initnw';
net1.inputWeights{1,1}.delays = [1,2,3];
net1.inputWeights{1,1}.learnFcn = 'learngdm';
net1.inputWeights{1,1}.learnParam = nnetParam('learngdm');
net1.inputWeights{1,1}.initFcn = '';
net1.layerWeights{1,1}.learnFcn = 'learngdm';
net1.layerWeights{1,1}.initFcn = '';
net1.layerWeights{2,1}.delays = [0,1];
net1.layerWeights{2,1}.learnFcn = 'learngdm';
net1.layerWeights{2,1}.initFcn = '';
net1.layerWeights{2,2}.learnFcn = 'learngdm';
net1.layerWeights{2,2}.initFcn = '';
net1.layerWeights{3,2}.delays = [0,1];
net1.layerWeights{3,2}.learnFcn = 'learngdm';
net1.layerWeights{3,2}.initFcn = '';
net1.layerWeights{3,3}.learnFcn = 'learngdm';
net1.layerWeights{3,3}.initFcn = '';
net1.biases{1,1}.learnFcn = 'learngdm';
net1.biases{2,1}.learnFcn = 'learngdm';
net1.biases{3,1}.learnFcn = 'learngdm';
net2.name = net1.name;
net1.adaptFcn = 'adaptwb';
net1.divideFcn = net2.divideFcn;
net1.divideParam = net2.divideParam;
net1.divideMode = net2.divideMode;
net1.plotFcns = net2.plotFcns;
net1.plotParams = net2.plotParams;
net1.trainFcn = net2.trainFcn;
net1.trainParam = net2.trainParam;
net1.LW = net2.LW;
net1.b = net2.b;
Then checking every property
isequal(net1.name,net2.name)
isequal(net1.userdata,net2.userdata)
isequal(net1.numInputs,net2.numInputs)
isequal(net1.numLayers,net2.numLayers)
isequal(net1.numOutputs,net2.numOutputs)
isequal(net1.numInputDelays,net2.numInputDelays)
isequal(net1.numLayerDelays,net2.numLayerDelays)
isequal(net1.numFeedbackDelays,net2.numFeedbackDelays)
isequal(net1.numWeightElements,net2.numWeightElements)
isequal(net1.sampleTime,net2.sampleTime)
isequal(net1.biasConnect,net2.biasConnect)
isequal(net1.inputConnect,net2.inputConnect)
isequal(net1.layerConnect,net2.layerConnect)
isequal(net1.outputConnect,net2.outputConnect)
isequal(net1.output,net2.output)
isequal(net1.inputs,net2.inputs)
isequal(net1.layers,net2.layers)
isequal(net1.outputs,net2.outputs)
isequal(net1.biases,net2.biases)
isequal(net1.inputWeights,net2.inputWeights)
isequal(net1.layerWeights,net2.layerWeights)
isequal(net1.adaptFcn,net2.adaptFcn)
isequal(net1.adaptParam,net2.adaptParam)
isequal(net1.derivFcn,net2.derivFcn)
isequal(net1.divideFcn,net2.divideFcn)
isequal(net1.divideParam,net2.divideParam)
isequal(net1.divideMode,net2.divideMode)
isequal(net1.initFcn,net2.initFcn)
isequal(net1.performFcn,net2.performFcn)
isequal(net1.performParam,net2.performParam)
isequal(net1.plotFcns,net2.plotFcns)
isequal(net1.plotParams,net2.plotParams)
isequal(net1.trainFcn,net2.trainFcn)
isequal(net1.trainParam,net2.trainParam)
isequal(net1.IW,net2.IW)
isequal(net1.LW,net2.LW)
isequal(net1.b,net2.b)
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
ans =
1
They look identical, but...
isequal(net1,net2)
ans =
0
Thank you

6 comentarios

Steven Lord
Steven Lord el 28 de Abr. de 2016
I'm curious why you're testing the two objects for equality. How are you using the output of isequal on net1 and net2?
Roberto
Roberto el 28 de Abr. de 2016
It's only a test. I have this function (as part of a bigger and more complex algorithm) that generate neural networks and set them with my parameters. Now, I'm about to replace this function with a new one that is more flexible and general. It uses network() instead of distdelaynet() for example. The first function is well tested so i wanted to see if at least in some selected cases the new one gives the exact output of the old one in order to avoid anomalies or unexpected behaviours in a more vast scenario. You may call it "accurate testing" or "obsessive compulsive disorder" -.-
Steven Lord
Steven Lord el 28 de Abr. de 2016
So for that you don't necessarily need the networks to be equal, you need the outputs of the networks to be equal (or very close, to account for floating-point differences.)
You should consider writing some unit tests for this function; that way if it passes the tests you can be more confident that it's behaving as expected. You can use the MATLAB unit testing framework to create test functions or classes for this purpose.
Roberto
Roberto el 28 de Abr. de 2016
Yes, checking the exact output of the function (in selected cases) is my first line test. If it's not viable or if it fails my second line is to check that the network's output is the same of the network produced by the other function. Despite the randomness in neural networks initialization and training it's viable by initializing the rng.
Greg Heath
Greg Heath el 29 de Abr. de 2016
It looks like the problem is version dependent:
Using 2014a
>> net1 = fitnet; net2 = fitnet; isequal( net1, net2 )
ans = 1
>> net2 = net1; isequal( net1, net2 )
ans = 1
Hope this helps.
Greg
Roberto
Roberto el 29 de Abr. de 2016
Thank you Greg. I'm using 2014a and I have exactly your result, but the problem is "reproducing" the output of fitnet() by calling network() and then setting the net properly. In this case I have 2 network objects that are not equal despite every property of them are identical. (in the sense of isequal())

Iniciar sesión para comentar.

Respuestas (1)

Walter Roberson
Walter Roberson el 28 de Abr. de 2016
The following properties differ:
'inputWeights' 'divideParam' 'plotParams' 'trainParam' 'revert'
The revert property is outright different. The other four are more difficult to explain. If you use
s1 = struct(net1);
s2 = struct(net2);
then even through net1.divideParam and net2.divideParam appear identical, s1.divideParam will be class nnetParam but s2.divideParam will be a struct with the same essential content. Likewise for plotParams and trainParam. For inputWeights, the difference is in inputWeights{1}.learnparam . I have no explanation for this difference. I poked into the code a bit but nothing was obvious.
The revert property is actually a method: see http://www.mathworks.com/help/nnet/ref/revert.html . None the less, there has to be something there that causes this to be different. Ah, as well as being a method, revert is a hidden property.
The initial divideParam, plotParams, trainParam for net1 are represented with a struct with no field, and if you struct(net1) after the first assignment to it, you will get struct for those fields, just like you do afterwards with net2. This suggests that there is some kind of built-in behavior that struct() should convert those parameters to structures, but that the behavior is getting overwritten by the assignment of the net2 parameters to net1 .
I think I am about out of time to follow this any further.

6 comentarios

Thank you for your answer, it's helpful. So, let's summarize:
1. net1.revert and net2.revert are different 2. the other four properties have "something different" that make them return different outputs from struct, but this "something" is not detected by isequal.
There's an easy fix for the first point:
s = rng;
net1 = init(net1);
rng(s);
net2 = init(net2);
isequal(net1.revert,net2.revert)
ans =
1
but still
isequal(net1,net2)
ans =
0
So the other properties are different "in some way" not detected by isequal or there's some other hidden property...any ideas?
Walter Roberson
Walter Roberson el 28 de Abr. de 2016
revert is the only hidden property.
Roberto
Roberto el 28 de Abr. de 2016
Thank you Walter. Well, if revert is the only hidden property then we have 2 objects, they're different, but their properties are identical...
Maybe the problem is "isequal"? Other ways to check equality?
Walter Roberson
Walter Roberson el 29 de Abr. de 2016
isequal compares by value, not by data type. eq() includes datatype
Roberto
Roberto el 29 de Abr. de 2016
I'm out of options
Walter Roberson
Walter Roberson el 29 de Abr. de 2016
Sorry, the details of class construction is something I have never investigated before.
It appears that it is built on old style classes.

Iniciar sesión para comentar.

Categorías

Más información sobre Deep Learning Toolbox en Centro de ayuda y File Exchange.

Preguntada:

el 28 de Abr. de 2016

Comentada:

el 29 de Abr. de 2016

Community Treasure Hunt

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

Start Hunting!

Translated by