I'm reworking some of the GANs I originally made in TensorFlow2 to see if I can improve performance in Mathematica, and have been stuck on how to create a custom Minibatch Standard Deviation Layer. I'm trying to implement it to stabilize the training process and reduce instances of Mode Collapse. (More information on its purpose (with Python) can be found here.) Basically it takes the mean of the samples and figures out the standard deviation within each batch. The generator is penalized if the standard deviation is too low.
I thought the new FunctionLayer
in 12.2 would be useful for this purpose but this is as far as I've gotten so far. Some how I need to thread that minibatch
layer back into the network.
discriminator = NetGraph[{
ConvolutionLayer[16, 5, "Stride" -> 3, "Input" -> {3, 4000}],
ElementwiseLayer["ELU"],
ConvolutionLayer[32, 3, "Stride" -> 1],
ElementwiseLayer["ELU"],
ConvolutionLayer[64, 2, "Stride" -> 1],
ElementwiseLayer["ELU"],
minibatch,
FlattenLayer[],
100,
Ramp,
1,
Tanh,
SequenceLastLayer[]
},
{1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13,
6 -> 7}
]
minibatch = NetChain[{
AggregationLayer[Mean, {2}],
FunctionLayer[StandardDeviation]
}]
GAN = NetInitialize@NetGANOperator[{generator, discriminator}]
BATCHSIZE = 64;
noise := RandomVariate[NormalDistribution[0, 0.2], 400]
trained = NetTrain[
GAN,
<|"Sample" -> RandomSample[trainingData, BATCHSIZE],
"Latent" -> Table[noise, BATCHSIZE]|>,
BatchSize -> BATCHSIZE
]
The Wolfram framework always seems to apply the whole net to one example. How can I apply a function to all samples in the round and then append it to the array? Even if it's just a reference, I'm pretty sure I can follow it through.
Updated 2020-12-18 Along with the bounty I have also added a 3 samples of the training data that can be seen on a public gist of the shape {3,300}.
Updated 2021-01-02 Corrected code.
Syntax::bktmcp: Expression "NetGraph[<<1>>" has no closing "]".
$\endgroup$