Gradient Origin Network
Gradient Origin Network
Data gathering and processing
mnist=ResourceObject["MNIST"];images=Keys@ResourceData[mnist,"TrainingData"];
For testing, we’ll only work with a small number of images.
samples=RandomChoice[images,5]
,
,
,
,
{width,height}=ImageDimensions@RandomChoice@images;
We create a long list of {i,j} pixel coordinates. Hopefully this pixel ordering is consistent with the built-in function ImageData.
indices = Tuples[{Range[width],Range[height]}];
Creating the input space
We first define a desired latent space dimension. We pick 32 here as in the original paper.
latentSpaceSize=32;
The latent space is a scaled version of the pixel space, concatenated with the latent space.I picked as a scale factor for various reasons.
π
2
input[c_,l_]:=c~Join~l
π
2
input[c_]:=input[c,ConstantArray[0,latentSpaceSize]]
SIREN showcase
testimage=RandomChoice@images
A SIREN is basically a MLP with sine activation functions:
siren=NetInitialize@NetChain[{width,Sin,width,Sin,width,1},"Input"2]
NetChain
Here we don’t use the latent space yet, so we can train the network straight away. We still have to scale both the input and the output, though.
trainedNet=NetTrainsiren,indicesPartition[Flatten[2#-1&/@ImageData[testimage]],1];
π
2
We then reconstruct the image, comparing the reconstruction with the original :
testimageImage(#+1)2&@PartitiontrainedNet/@indices,width
π
2
If the two images look similar, then the pixel ordering is consistent with ImageData and there was sufficient training.
Building the initial network
We’ll use the same network structure as in the paper : four hidden layers with 256 features each.
net=NetChain[256//{#,Sin,#,Sin,#,Sin,#,Sin,1}&,"Input"2+latentSpaceSize]//NetInitialize
NetChain
Training
This part is quite messy and difficult to explain, but it seems to work.
G=Table[net[input[c],NetPortGradient["Input"]][[3;;]],{c,indices}];F=Flatten@Table[net[input[c]],{c,indices}];d=Table[F-Flatten[2#-1&/@ImageData[img]],{img,samples}];dG=d.G;
trainedNet=NetTrain[net,(Flatten[Outer[input[#2,#1]&,dG,indices,1,1],1]Partition[Flatten@Table[Flatten[2#-1&/@ImageData[img]],{img,samples}],1])]
NetChain
Table[Image[(#+1)/2&@Partition[trainedNet/@(input[#,dG[[i]]]&/@indices),width]],{i,Range@Length@samples}]
,
,
,
,
Image[(#+1)/2&@Partition[trainedNet/@(input[#,(dG[[1]]+dG[[2]])/2]&/@indices),width]]