From dd151aec3f909d012afe67bf3052128d6e19171b Mon Sep 17 00:00:00 2001 From: brian Date: Mon, 7 Aug 2023 10:32:39 +0200 Subject: [PATCH] gan example Signed-off-by: brian --- .../src/test/java/net/brutex/gan/App.java | 606 ++++++------------ .../src/test/java/net/brutex/gan/App2.java | 343 ++++++++++ .../test/java/net/brutex/gan/App2Config.java | 176 +++++ .../keras/KerasSequentialModel.java | 440 +++++++------ .../main/java/net/brutex/ai/dnn/api/NN.java | 5 +- .../NeuralNetBaseBuilderConfiguration.java | 13 +- .../nn/conf/NeuralNetConfiguration.java | 7 + .../nn/conf/layers/ConvolutionLayer.java | 14 +- .../nn/conf/layers/Deconvolution2D.java | 23 +- .../nn/conf/layers/LayerConfiguration.java | 3 +- .../FeedForwardToCnnPreProcessor.java | 254 +++++--- .../nn/layers/AbstractLayer.java | 2 +- .../convolution/Deconvolution2DLayer.java | 22 +- .../nn/multilayer/MultiLayerNetwork.java | 2 +- .../BatchNormalizationParamInitializer.java | 5 + .../params/ConvolutionParamInitializer.java | 4 +- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 59821 bytes gradlew | 170 +++-- gradlew.bat | 14 +- 20 files changed, 1267 insertions(+), 838 deletions(-) create mode 100644 brutex-extended-tests/src/test/java/net/brutex/gan/App2.java create mode 100644 brutex-extended-tests/src/test/java/net/brutex/gan/App2Config.java diff --git a/brutex-extended-tests/src/test/java/net/brutex/gan/App.java b/brutex-extended-tests/src/test/java/net/brutex/gan/App.java index 696f9241b..dc5898413 100644 --- a/brutex-extended-tests/src/test/java/net/brutex/gan/App.java +++ b/brutex-extended-tests/src/test/java/net/brutex/gan/App.java @@ -1,473 +1,261 @@ -/* - * - * ****************************************************************************** - * * - * * This program and the accompanying materials are made available under the - * * terms of the Apache License, Version 2.0 which is available at - * * https://www.apache.org/licenses/LICENSE-2.0. - * * - * * See the NOTICE file distributed with this work for additional - * * information regarding copyright ownership. - * * Unless required by applicable law or agreed to in writing, software - * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * * License for the specific language governing permissions and limitations - * * under the License. - * * - * * SPDX-License-Identifier: Apache-2.0 - * ***************************************************************************** - * - */ - package net.brutex.gan; +import static net.brutex.ai.dnn.api.NN.dense; + import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; -import java.io.IOException; import java.util.Arrays; -import java.util.Random; -import java.util.UUID; -import javax.imageio.ImageIO; -import javax.swing.ImageIcon; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.WindowConstants; -import lombok.extern.slf4j.Slf4j; +import javax.swing.*; import org.apache.commons.lang3.ArrayUtils; -import org.datavec.api.split.FileSplit; -import org.datavec.image.loader.NativeImageLoader; -import org.datavec.image.recordreader.ImageRecordReader; -import org.datavec.image.transform.ColorConversionTransform; -import org.datavec.image.transform.ImageTransform; -import org.datavec.image.transform.PipelineImageTransform; -import org.datavec.image.transform.ResizeImageTransform; -import org.datavec.image.transform.ShowImageTransform; -import org.deeplearning4j.datasets.datavec.RecordReaderDataSetIterator; import org.deeplearning4j.datasets.iterator.impl.MnistDataSetIterator; import org.deeplearning4j.nn.conf.GradientNormalization; import org.deeplearning4j.nn.conf.NeuralNetConfiguration; -import org.deeplearning4j.nn.conf.distribution.Distribution; -import org.deeplearning4j.nn.conf.distribution.NormalDistribution; -import org.deeplearning4j.nn.conf.inputs.InputType; -import org.deeplearning4j.nn.conf.layers.ActivationLayer; -import org.deeplearning4j.nn.conf.layers.DenseLayer; -import org.deeplearning4j.nn.conf.layers.DropoutLayer; -import org.deeplearning4j.nn.conf.layers.LayerConfiguration; -import org.deeplearning4j.nn.conf.layers.OutputLayer; +import org.deeplearning4j.nn.conf.layers.*; import org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop; -import org.deeplearning4j.nn.conf.weightnoise.WeightNoise; import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; import org.deeplearning4j.nn.weights.WeightInit; -import org.deeplearning4j.nn.weights.WeightInitXavier; import org.deeplearning4j.optimize.listeners.PerformanceListener; -import org.deeplearning4j.optimize.listeners.ScoreToChartListener; import org.junit.jupiter.api.Test; import org.nd4j.linalg.activations.Activation; import org.nd4j.linalg.activations.impl.ActivationLReLU; -import org.nd4j.linalg.api.buffer.DataType; import org.nd4j.linalg.api.ndarray.INDArray; import org.nd4j.linalg.dataset.DataSet; -import org.nd4j.linalg.dataset.api.iterator.DataSetIterator; import org.nd4j.linalg.factory.Nd4j; import org.nd4j.linalg.learning.config.Adam; import org.nd4j.linalg.learning.config.IUpdater; -import org.nd4j.linalg.lossfunctions.LossFunctions.LossFunction; +import org.nd4j.linalg.lossfunctions.LossFunctions; -@Slf4j public class App { - private static final double LEARNING_RATE = 0.000002; - private static final double GRADIENT_THRESHOLD = 100.0; + private static final double LEARNING_RATE = 0.002; + private static final double GRADIENT_THRESHOLD = 100.0; + private static final IUpdater UPDATER = Adam.builder().learningRate(LEARNING_RATE).beta1(0.5).build(); + private static final int BATCHSIZE = 128; + private static JFrame frame; + private static JPanel panel; - private static final int X_DIM = 20 ; - private static final int Y_DIM = 20; - private static final int CHANNELS = 1; - private static final int batchSize = 1; - private static final int INPUT = 10; + private static LayerConfiguration[] genLayers() { + return new LayerConfiguration[] { + dense().nIn(100).nOut(256).weightInit(WeightInit.NORMAL).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + dense().nIn(256).nOut(512).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + dense().nIn(512).nOut(1024).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + dense().nIn(1024).nOut(784).activation(Activation.TANH).build() + }; + } - private static final int OUTPUT_PER_PANEL = 16; + /** + * Returns a network config that takes in a 10x10 random number and produces a 28x28 grayscale image. + * + * @return config + */ + private static NeuralNetConfiguration generator() { + NeuralNetConfiguration conf = NeuralNetConfiguration.builder() + .seed(42) + .updater(UPDATER) + .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) + .gradientNormalizationThreshold(GRADIENT_THRESHOLD) + .weightInit(WeightInit.XAVIER) + .activation(Activation.IDENTITY) + .layersFromArray(genLayers()) + .name("generator") + .build(); - private static final int ARRAY_SIZE_PER_SAMPLE = X_DIM*Y_DIM*CHANNELS; - private static final IUpdater UPDATER = Adam.builder().learningRate(LEARNING_RATE).beta1(0.5).build(); + return conf; + } - private static JFrame frame; - private static JFrame frame2; - private static JPanel panel; - private static JPanel panel2; + private static LayerConfiguration[] disLayers() { + return new LayerConfiguration[]{ + dense().nIn(784).nOut(1024).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + DropoutLayer.builder(1 - 0.5).build(), + dense().nIn(1024).nOut(512).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + DropoutLayer.builder(1 - 0.5).build(), + dense().nIn(512).nOut(256).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + DropoutLayer.builder(1 - 0.5).build(), + OutputLayer.builder(LossFunctions.LossFunction.XENT).nIn(256).nOut(1).activation(Activation.SIGMOID).build() + }; + } - private static final String OUTPUT_DIR = "C:/temp/output/"; + private static NeuralNetConfiguration discriminator() { + NeuralNetConfiguration conf = NeuralNetConfiguration.builder() + .seed(42) + .updater(UPDATER) + .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) + .gradientNormalizationThreshold(GRADIENT_THRESHOLD) + .weightInit(WeightInit.XAVIER) + .activation(Activation.IDENTITY) + .layersFromArray(disLayers()) + .name("discriminator") + .build(); - private static LayerConfiguration[] genLayers() { - return new LayerConfiguration[] { - DenseLayer.builder().nIn(INPUT).nOut(X_DIM*Y_DIM*CHANNELS).weightInit(WeightInit.NORMAL).build(), - ActivationLayer.builder(Activation.LEAKYRELU).build(), + return conf; + } - DenseLayer.builder().nIn(X_DIM*Y_DIM*CHANNELS).nOut(X_DIM*Y_DIM).build(), - ActivationLayer.builder(new ActivationLReLU(0.2)).build(), - DropoutLayer.builder(1 - 0.5).build(), - DenseLayer.builder().nIn(X_DIM*Y_DIM).nOut(X_DIM*Y_DIM).build(), - ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + private static NeuralNetConfiguration gan() { + LayerConfiguration[] genLayers = genLayers(); + LayerConfiguration[] disLayers = discriminator().getFlattenedLayerConfigurations().stream() + .map((layer) -> { + if (layer instanceof DenseLayer || layer instanceof OutputLayer) { + return FrozenLayerWithBackprop.builder(layer).build(); + } else { + return layer; + } + }).toArray(LayerConfiguration[]::new); + LayerConfiguration[] layers = ArrayUtils.addAll(genLayers, disLayers); - DenseLayer.builder().nIn(X_DIM*Y_DIM*CHANNELS).nOut(X_DIM*Y_DIM*CHANNELS).activation(Activation.TANH).build() - }; - } + NeuralNetConfiguration conf = NeuralNetConfiguration.builder() + .seed(42) + .updater(UPDATER) + .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) + .gradientNormalizationThreshold(GRADIENT_THRESHOLD) + .weightInit(WeightInit.XAVIER) + .activation(Activation.IDENTITY) + .layersFromArray(layers) + .name("GAN") + .build(); - /** - * Returns a network config that takes in a 10x10 random number and produces a 28x28 grayscale image. - * - * @return config - */ - private static NeuralNetConfiguration generator() { - NeuralNetConfiguration conf = NeuralNetConfiguration.builder() - .seed(42) - .updater(UPDATER) - .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) - .gradientNormalizationThreshold(GRADIENT_THRESHOLD) - //.weightInit(WeightInit.XAVIER) - .weightInit(WeightInit.XAVIER) - .activation(Activation.IDENTITY) - .layersFromArray(genLayers()) - .inputType(InputType.convolutional(X_DIM, Y_DIM, CHANNELS)) - // .inputPreProcessor("CNN1", new FeedForwardToCnnPreProcessor(Y_DIM, X_DIM, CHANNELS)) - .build(); - ((NeuralNetConfiguration) conf).init(); + return conf; + } - return conf; - } + @Test + public void runTest() throws Exception { + App.main(null); + } + public static void main(String... args) throws Exception { + Nd4j.getMemoryManager().setAutoGcWindow(15 * 1000); - private static LayerConfiguration[] disLayers() { - return new LayerConfiguration[]{ - DenseLayer.builder().name("1.Dense").nOut(X_DIM*Y_DIM*CHANNELS).build(), //input is set by setInputType on the network - ActivationLayer.builder(new ActivationLReLU(0.2)).build(), - DropoutLayer.builder(1 - 0.5).build(), - DenseLayer.builder().name("2.Dense").nIn(X_DIM * Y_DIM*CHANNELS).nOut(X_DIM*Y_DIM*CHANNELS*4).build(), //HxBxC - ActivationLayer.builder(new ActivationLReLU(0.2)).build(), - DropoutLayer.builder(1 - 0.5).build(), - DenseLayer.builder().name("3.Dense").nIn(X_DIM*Y_DIM*CHANNELS*4).nOut(X_DIM*Y_DIM*CHANNELS).build(), - ActivationLayer.builder(new ActivationLReLU(0.2)).build(), - DropoutLayer.builder(1 - 0.5).build(), - DenseLayer.builder().name("4.Dense").nIn(X_DIM*Y_DIM*CHANNELS).nOut(X_DIM*Y_DIM).build(), - ActivationLayer.builder(new ActivationLReLU(0.2)).build(), - DropoutLayer.builder(1 - 0.5).build(), + MnistDataSetIterator trainData = new MnistDataSetIterator(BATCHSIZE, true, 42); - OutputLayer.builder().name("dis-output").lossFunction(LossFunction.MCXENT).nIn(X_DIM*Y_DIM).nOut(1).activation(Activation.SIGMOID).build() - }; - } + MultiLayerNetwork gen = new MultiLayerNetwork(generator()); + MultiLayerNetwork dis = new MultiLayerNetwork(discriminator()); + MultiLayerNetwork gan = new MultiLayerNetwork(gan()); + gen.init(); + dis.init(); + gan.init(); - private static NeuralNetConfiguration discriminator() { + copyParams(gen, dis, gan); - NeuralNetConfiguration conf = - NeuralNetConfiguration.builder() - .seed(42) - .updater(UPDATER) - .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) - .gradientNormalizationThreshold(GRADIENT_THRESHOLD) - .weightInit(WeightInit.XAVIER) - //.weightNoise(new WeightNoise(new NormalDistribution(0.5, 0.5))) - .weightNoise(null) - // .weightInitFn(new WeightInitXavier()) - // .activationFn(new ActivationIdentity()) - .activation(Activation.IDENTITY) - .layersFromArray(disLayers()) - .inputType(InputType.convolutional(X_DIM, Y_DIM, CHANNELS)) - .build(); - ((NeuralNetConfiguration) conf).init(); + gen.addTrainingListeners(new PerformanceListener(10, true)); + dis.addTrainingListeners(new PerformanceListener(10, true)); + gan.addTrainingListeners(new PerformanceListener(10, true)); - return conf; - } + trainData.reset(); - private static NeuralNetConfiguration gan() { - LayerConfiguration[] genLayers = genLayers(); - LayerConfiguration[] disLayers = Arrays.stream(disLayers()) - .map((layer) -> { - if (layer instanceof DenseLayer || layer instanceof OutputLayer) { - return FrozenLayerWithBackprop.builder(layer).name("frozen-for-"+layer.getName()).build(); - } else { - return layer; - } - }).toArray(LayerConfiguration[]::new); - LayerConfiguration[] layers = ArrayUtils.addAll(genLayers, disLayers); + int j = 0; + for (int i = 0; i < 50; i++) { + while (trainData.hasNext()) { + j++; - NeuralNetConfiguration conf = NeuralNetConfiguration.builder() - .seed(42) - .updater( Adam.builder().learningRate(0.0002).beta1(0.5).build() ) - .gradientNormalization( GradientNormalization.RenormalizeL2PerLayer) - .gradientNormalizationThreshold( 100 ) - //.weightInitFn( new WeightInitXavier() ) //this is internal - .weightNoise(new WeightNoise(new NormalDistribution(0.5, 0.5))) - .weightInit( WeightInit.XAVIER) - //.activationFn( new ActivationIdentity()) //this is internal - .activation( Activation.IDENTITY ) - .layersFromArray( layers ) - .inputType( InputType.convolutional(X_DIM, Y_DIM, CHANNELS)) - .dataType(DataType.FLOAT) - .build(); -((NeuralNetConfiguration) conf).init(); - return conf; - } + // generate data + INDArray real = trainData.next().getFeatures().muli(2).subi(1); + int batchSize = (int) real.shape()[0]; + + INDArray fakeIn = Nd4j.rand(batchSize, 100); + INDArray fake = gan.activateSelectedLayers(0, gen.getLayers().length - 1, fakeIn); + + DataSet realSet = new DataSet(real, Nd4j.zeros(batchSize, 1)); + DataSet fakeSet = new DataSet(fake, Nd4j.ones(batchSize, 1)); + + DataSet data = DataSet.merge(Arrays.asList(realSet, fakeSet)); + + dis.fit(data); + dis.fit(data); + + // Update the discriminator in the GAN network + updateGan(gen, dis, gan); + + gan.fit(new DataSet(Nd4j.rand(batchSize, 100), Nd4j.zeros(batchSize, 1))); - @Test - public void runTest() throws Exception { - if(! log.isDebugEnabled()) { - log.info("Logging is not set to DEBUG"); - } - else { - log.info("Logging is set to DEBUG"); - } - main(); - } + if (j % 10 == 1) { + System.out.println("Epoch " + i +" Iteration " + j + " Visualizing..."); + INDArray[] samples = new INDArray[9]; + DataSet fakeSet2 = new DataSet(fakeIn, Nd4j.ones(batchSize, 1)); - public static void main(String... args) throws Exception { + for (int k = 0; k < 9; k++) { + INDArray input = fakeSet2.get(k).getFeatures(); + //samples[k] = gen.output(input, false); + samples[k] = gan.activateSelectedLayers(0, gen.getLayers().length - 1, input); - log.info("\u001B[32m Some \u001B[1m green \u001B[22m text \u001B[0m \u001B[7m Inverted\u001B[0m "); - Nd4j.getMemoryManager().setAutoGcWindow(500); - - //MnistDataSetIterator trainData = new MnistDataSetIterator(128, true, 45); - //FileSplit fileSplit = new FileSplit(new File("c:/users/brian/downloads/flowers"), NativeImageLoader.getALLOWED_FORMATS()); - FileSplit fileSplit = new FileSplit(new File("c:/users/brian/downloads/humans"), NativeImageLoader.getALLOWED_FORMATS()); - - - ImageTransform transform = new ColorConversionTransform(new Random(42), 7 ); - - ImageTransform transform2 = new ShowImageTransform("Tester", 30); - ImageTransform transform3 = new ResizeImageTransform(X_DIM, Y_DIM); - - ImageTransform tr = new PipelineImageTransform.Builder() - //.addImageTransform(transform) //convert to GREY SCALE - .addImageTransform(transform3) - //.addImageTransform(transform2) - .build(); - - ImageRecordReader imageRecordReader = new ImageRecordReader(X_DIM, Y_DIM, CHANNELS); - imageRecordReader.initialize(fileSplit, tr); - DataSetIterator trainData = new RecordReaderDataSetIterator(imageRecordReader, batchSize ); - - MultiLayerNetwork gen = new MultiLayerNetwork(generator()); - MultiLayerNetwork dis = new MultiLayerNetwork(discriminator()); - MultiLayerNetwork gan = new MultiLayerNetwork(gan()); - gen.init(); log.debug("Generator network: {}", gen); - dis.init(); log.debug("Discriminator network: {}", dis); - gan.init(); log.info("Complete GAN network: {}", gan); - - - copyParams(gen, dis, gan); - - //gen.addTrainingListeners(new PerformanceListener(15, true, "GEN")); - dis.addTrainingListeners(new PerformanceListener(10, true, "DIS")); - gan.addTrainingListeners(new PerformanceListener(10, true, "GAN")); - //gan.addTrainingListeners(new ScoreToChartListener("gan")); - //dis.setListeners(new ScoreToChartListener("dis")); - - //System.out.println(gan.toString()); - //gan.fit(Nd4j.rand(batchSize, CHANNELS, X_DIM, Y_DIM), Nd4j.zeros(batchSize, 1)); - - //gan.fit(new DataSet(trainData.next().getFeatures(), Nd4j.zeros(batchSize, 1))); - //trainData.reset(); - - int j = 0; - for (int i = 0; i < 51; i++) { //epoch - while (trainData.hasNext()) { - j++; - - DataSet next = trainData.next(); - // generate data - INDArray real = next.getFeatures();//.div(255f); - - //start next round if there are not enough images left to have a full batchsize dataset - if(real.length() < ARRAY_SIZE_PER_SAMPLE*batchSize) { - log.warn("Your total number of input images is not a multiple of {}, " - + "thus skipping {} images to make it fit", batchSize, real.length()/ARRAY_SIZE_PER_SAMPLE); - break; + } + visualize(samples); + } + } + trainData.reset(); + // Copy the GANs generator to gen. + //updateGen(gen, gan); } - //if(i%20 == 0) { - frame2 = visualize(new INDArray[]{real}, batchSize, - frame2 == null ? new JFrame() : frame2, true); //real has batchsize number of images - //} - real.divi(255f); - -// int batchSize = (int) real.shape()[0]; - - INDArray fakeIn = Nd4j.rand(batchSize, CHANNELS, X_DIM, Y_DIM); - //INDArray fakeIn = Nd4j.rand(new int[]{batchSize, X_DIM*Y_DIM}); //hack for MNIST only, use above otherwise - - - INDArray fake = gan.activateSelectedLayers(0, gen.getLayers().length - 1, fakeIn); - fake = fake.reshape(batchSize, CHANNELS, X_DIM, Y_DIM); - - //log.info("real has {} items.", real.length()); - DataSet realSet = new DataSet(real, Nd4j.zeros(batchSize, 1)); - DataSet fakeSet = new DataSet(fake, Nd4j.ones(batchSize, 1)); - - - DataSet data = DataSet.merge(Arrays.asList(realSet, fakeSet)); - - dis.fit(data); - //dis.fit(data); - - // Update the discriminator in the GAN network - updateGan(gen, dis, gan); - - //gan.fit(new DataSet(Nd4j.rand(batchSize, INPUT), Nd4j.zeros(batchSize, 1))); - gan.fit(new DataSet(Nd4j.rand(batchSize, CHANNELS, X_DIM, Y_DIM), Nd4j.ones(batchSize, 1))); - - //Visualize and reporting - if (j % 10 == 1) { - System.out.println("Epoch " + i + " Iteration " + j + " Visualizing..."); - INDArray[] samples = batchSize > OUTPUT_PER_PANEL ? new INDArray[OUTPUT_PER_PANEL] : new INDArray[batchSize]; - - - for (int k = 0; k < samples.length; k++) { - //INDArray input = fakeSet2.get(k).getFeatures(); - DataSet fakeSet2 = new DataSet(fakeIn, Nd4j.ones(batchSize, 1)); - INDArray input = fakeSet2.get(k).getFeatures(); - input = input.reshape(1,CHANNELS, X_DIM, Y_DIM); //batch size will be 1 here - - //samples[k] = gen.output(input, false); - samples[k] = gan.activateSelectedLayers(0, gen.getLayers().length - 1, input); - samples[k] = samples[k].reshape(1, CHANNELS, X_DIM, Y_DIM); - //samples[k] = - samples[k].addi(1f).divi(2f).muli(255f); - - } - frame = visualize(samples, 1, frame == null ? new JFrame() : frame, false); //each samples only has 1 image, thus batchElements=1 - } - } - if (trainData.resetSupported()) { - trainData.reset(); - } else { - log.error("Trainingdata {} does not support reset.", trainData.toString()); - } // Copy the GANs generator to gen. updateGen(gen, gan); + gen.save(new File("mnist-mlp-generator.dlj")); } - - - - } - - private static void copyParams(MultiLayerNetwork gen, MultiLayerNetwork dis, MultiLayerNetwork gan) { - int genLayerCount = gen.getLayers().length; - for (int i = 0; i < gan.getLayers().length; i++) { - if (i < genLayerCount) { - if(gan.getLayer(i).getParams() != null) - gan.getLayer(i).setParams(gen.getLayer(i).getParams()); - } else { - if(gan.getLayer(i).getParams() != null) - gan.getLayer(i ).setParams(dis.getLayer(i- genLayerCount).getParams()); - } - } - } - - private static void updateGen(MultiLayerNetwork gen, MultiLayerNetwork gan) { - for (int i = 0; i < gen.getLayers().length; i++) { - gen.getLayer(i).setParams(gan.getLayer(i).getParams()); - } - } - - private static void updateGan(MultiLayerNetwork gen, MultiLayerNetwork dis, MultiLayerNetwork gan) { - int genLayerCount = gen.getLayers().length; - for (int i = genLayerCount; i < gan.getLayers().length; i++) { - gan.getLayer(i).setParams(dis.getLayer(i - genLayerCount).getParams()); - } - } - - private static JFrame visualize(INDArray[] samples, int batchElements, JFrame frame, boolean isOrig) { - if (isOrig) { - frame.setTitle("Viz Original"); - } else { - frame.setTitle("Generated"); - } - - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - frame.setLayout(new BorderLayout()); - - JPanel panelx = new JPanel(); - - panelx.setLayout(new GridLayout(4, 4, 8, 8)); - for (INDArray sample : samples) { - for(int i = 0; i1) { - bi = new BufferedImage(X_DIM, Y_DIM, BufferedImage.TYPE_INT_RGB); //need to change here based on channels - } else { - bi = new BufferedImage(X_DIM, Y_DIM, BufferedImage.TYPE_BYTE_GRAY); //need to change here based on channels - } - final int imageSize = X_DIM * Y_DIM; - final int offset = batchElement * imageSize; - int pxl = offset * CHANNELS; //where to start in the INDArray - - //Image in NCHW - channels first format - for (int c = 0; c < CHANNELS; c++) { //step through the num channels for each pixel - for (int y = 0; y < Y_DIM; y++) { // step through the columns x - for (int x = 0; x < X_DIM; x++) { //step through the rows y - if(isOrig) log.trace("'{}.' Image (x,y,c): ({}, {}, {}) with INDArray with index {} and value '{}'", batchElement, x, y, c, pxl, tensor.getFloat(pxl)); - bi.getRaster().setSample(x, y, c, tensor.getFloat(pxl)); - pxl++; //next item in INDArray + private static void copyParams(MultiLayerNetwork gen, MultiLayerNetwork dis, MultiLayerNetwork gan) { + int genLayerCount = gen.getLayers().length; + for (int i = 0; i < gan.getLayers().length; i++) { + if (i < genLayerCount) { + gen.getLayer(i).setParams(gan.getLayer(i).getParams()); + } else { + dis.getLayer(i - genLayerCount).setParams(gan.getLayer(i).getParams()); + } } - } } - ImageIcon orig = new ImageIcon(bi); - Image imageScaled = orig.getImage().getScaledInstance((4 * X_DIM), (4 * Y_DIM), Image.SCALE_DEFAULT); - ImageIcon scaled = new ImageIcon(imageScaled); - if(! isOrig) saveImage(imageScaled, batchElement, isOrig); - return new JLabel(scaled); - } - - private static void saveImage(Image image, int batchElement, boolean isOrig) { - String outputDirectory = OUTPUT_DIR; // Set the output directory where the images will be saved - - try { - // Save the images to disk - saveImage(image, outputDirectory, UUID.randomUUID().toString()+".png"); - - log.debug("Images saved successfully."); - } catch (IOException e) { - log.error("Error saving the images: {}", e.getMessage()); + private static void updateGen(MultiLayerNetwork gen, MultiLayerNetwork gan) { + for (int i = 0; i < gen.getLayers().length; i++) { + gen.getLayer(i).setParams(gan.getLayer(i).getParams()); + } } -} - private static void saveImage(Image image, String outputDirectory, String fileName) throws IOException { - File directory = new File(outputDirectory); - if (!directory.exists()) { - directory.mkdir(); + + private static void updateGan(MultiLayerNetwork gen, MultiLayerNetwork dis, MultiLayerNetwork gan) { + int genLayerCount = gen.getLayers().length; + for (int i = genLayerCount; i < gan.getLayers().length; i++) { + gan.getLayer(i).setParams(dis.getLayer(i - genLayerCount).getParams()); + } + } + + private static void visualize(INDArray[] samples) { + if (frame == null) { + frame = new JFrame(); + frame.setTitle("Viz"); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.setLayout(new BorderLayout()); + + panel = new JPanel(); + + panel.setLayout(new GridLayout(samples.length / 3, 1, 8, 8)); + frame.add(panel, BorderLayout.CENTER); + frame.setVisible(true); } - File outputFile = new File(directory, fileName); - ImageIO.write(imageToBufferedImage(image), "png", outputFile); - } + panel.removeAll(); - public static BufferedImage imageToBufferedImage(Image image) { - if (image instanceof BufferedImage) { - return (BufferedImage) image; + for (INDArray sample : samples) { + panel.add(getImage(sample)); } - // Create a buffered image with the same dimensions and transparency as the original image - BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); - - // Draw the original image onto the buffered image - Graphics2D g2d = bufferedImage.createGraphics(); - g2d.drawImage(image, 0, 0, null); - g2d.dispose(); - - return bufferedImage; + frame.revalidate(); + frame.pack(); } + private static JLabel getImage(INDArray tensor) { + BufferedImage bi = new BufferedImage(28, 28, BufferedImage.TYPE_BYTE_GRAY); + for (int i = 0; i < 784; i++) { + int pixel = (int)(((tensor.getDouble(i) + 1) * 2) * 255); + bi.getRaster().setSample(i % 28, i / 28, 0, pixel); + } + ImageIcon orig = new ImageIcon(bi); + Image imageScaled = orig.getImage().getScaledInstance((8 * 28), (8 * 28), Image.SCALE_REPLICATE); + + ImageIcon scaled = new ImageIcon(imageScaled); + + return new JLabel(scaled); + } } \ No newline at end of file diff --git a/brutex-extended-tests/src/test/java/net/brutex/gan/App2.java b/brutex-extended-tests/src/test/java/net/brutex/gan/App2.java new file mode 100644 index 000000000..f9f7aba58 --- /dev/null +++ b/brutex-extended-tests/src/test/java/net/brutex/gan/App2.java @@ -0,0 +1,343 @@ +/* + * + * ****************************************************************************** + * * + * * This program and the accompanying materials are made available under the + * * terms of the Apache License, Version 2.0 which is available at + * * https://www.apache.org/licenses/LICENSE-2.0. + * * + * * See the NOTICE file distributed with this work for additional + * * information regarding copyright ownership. + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * * License for the specific language governing permissions and limitations + * * under the License. + * * + * * SPDX-License-Identifier: Apache-2.0 + * ***************************************************************************** + * + */ + +package net.brutex.gan; + + + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.List; +import javax.imageio.ImageIO; +import javax.swing.*; +import lombok.extern.slf4j.Slf4j; +import org.datavec.api.split.FileSplit; +import org.datavec.image.loader.NativeImageLoader; +import org.datavec.image.recordreader.ImageRecordReader; +import org.datavec.image.transform.*; +import org.deeplearning4j.datasets.datavec.RecordReaderDataSetIterator; +import org.deeplearning4j.datasets.iterator.impl.MnistDataSetIterator; +import org.deeplearning4j.nn.conf.GradientNormalization; +import org.deeplearning4j.nn.conf.NeuralNetConfiguration; +import org.deeplearning4j.nn.conf.layers.*; +import org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop; +import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; +import org.deeplearning4j.optimize.listeners.PerformanceListener; +import org.junit.jupiter.api.Test; +import org.nd4j.linalg.api.ndarray.INDArray; +import org.nd4j.linalg.dataset.DataSet; +import org.nd4j.linalg.dataset.api.iterator.DataSetIterator; +import org.nd4j.linalg.factory.Nd4j; + +@Slf4j +public class App2 { + + final int INPUT = CHANNELS*DIMENSIONS*DIMENSIONS; + static final float COLORSPACE = 255f; + static final int DIMENSIONS = 28; + static final int CHANNELS = 1; + final int ARRAY_SIZE_PER_SAMPLE = DIMENSIONS*DIMENSIONS*CHANNELS; + final int OUTPUT_PER_PANEL = 10; + + final boolean BIAS = true; + + static final int BATCHSIZE=128; + + private JFrame frame2, frame; + static final String OUTPUT_DIR = "d:/out/"; + + final static INDArray label_real = Nd4j.ones(BATCHSIZE, 1); + final static INDArray label_fake = Nd4j.zeros(BATCHSIZE, 1); + + @Test + void runTest() throws IOException { + Nd4j.getMemoryManager().setAutoGcWindow(15 * 1000); + + MnistDataSetIterator mnistIter = new MnistDataSetIterator(20, 200); + FileSplit fileSplit = new FileSplit(new File("c:/users/brian/downloads/humans2"), NativeImageLoader.getALLOWED_FORMATS()); + ImageTransform transform = new ColorConversionTransform(new Random(42), 7 ); + ImageTransform transform2 = new ShowImageTransform("Tester", 30); + ImageTransform transform3 = new ResizeImageTransform(DIMENSIONS, DIMENSIONS); + + ImageTransform tr = new PipelineImageTransform.Builder() + .addImageTransform(transform) //convert to GREY SCALE + .addImageTransform(transform3) + //.addImageTransform(transform2) + .build(); + + ImageRecordReader imageRecordReader = new ImageRecordReader(DIMENSIONS, DIMENSIONS, CHANNELS); + imageRecordReader.initialize(fileSplit, tr); + DataSetIterator trainData = new RecordReaderDataSetIterator(imageRecordReader, BATCHSIZE ); + trainData = new MnistDataSetIterator(BATCHSIZE, true, 42); + + MultiLayerNetwork dis = new MultiLayerNetwork(App2Config.discriminator()); + MultiLayerNetwork gen = new MultiLayerNetwork(App2Config.generator()); + + LayerConfiguration[] disLayers = App2Config.discriminator().getFlattenedLayerConfigurations().stream() + .map((layer) -> { + if (layer instanceof DenseLayer || layer instanceof OutputLayer) { + return FrozenLayerWithBackprop.builder(layer).name("frozen-for-"+layer.getName()).build(); + } else { + return layer; + } + }).toArray(LayerConfiguration[]::new); + + NeuralNetConfiguration netConfiguration = + NeuralNetConfiguration.builder() + .name("GAN") + .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) + .gradientNormalizationThreshold(100) + .updater(App2Config.UPDATER) + .innerConfigurations(new ArrayList<>(List.of(App2Config.generator()))) + .layersFromList(new ArrayList<>(Arrays.asList(disLayers))) + // .inputType(InputType.convolutional(DIMENSIONS, DIMENSIONS, CHANNELS)) + // .inputPreProcessor(4, new CnnToFeedForwardPreProcessor()) + //.inputPreProcessor(0, new CnnToFeedForwardPreProcessor()) + // .inputPreProcessor(2, new FeedForwardToCnnPreProcessor(DIMENSIONS, DIMENSIONS, CHANNELS)) + //.inputPreProcessor(2, new CnnToFeedForwardPreProcessor()) + //.dataType(DataType.FLOAT) + .build(); + + MultiLayerNetwork gan = new MultiLayerNetwork(netConfiguration ); + + dis.init(); log.debug("Discriminator network: {}", dis); + gen.init(); log.debug("Generator network: {}", gen); + gan.init(); log.debug("GAN network: {}", gan); + + + log.info("Generator Summary:\n{}", gen.summary()); + log.info("GAN Summary:\n{}", gan.summary()); + dis.addTrainingListeners(new PerformanceListener(10, true, "DIS")); + gen.addTrainingListeners(new PerformanceListener(10, true, "GEN")); + gan.addTrainingListeners(new PerformanceListener(10, true, "GAN")); + + int j = 0; + for (int i = 0; i < 51; i++) { //epoch + while (trainData.hasNext()) { + j++; + DataSet next = trainData.next(); + // generate data + INDArray real = next.getFeatures(); //.muli(2).subi(1);;//.div(255f); + + //start next round if there are not enough images left to have a full batchsize dataset + if(real.length() < ARRAY_SIZE_PER_SAMPLE*BATCHSIZE) { + log.warn("Your total number of input images is not a multiple of {}, " + + "thus skipping {} images to make it fit", BATCHSIZE, real.length()/ARRAY_SIZE_PER_SAMPLE); + break; + } + + //if(i%20 == 0) { + + // frame2 = visualize(new INDArray[]{real}, BATCHSIZE, + // frame2 == null ? new JFrame() : frame2, true); //real has batchsize number of images + //} + //real.divi(255f); + +// int batchSize = (int) real.shape()[0]; + + //INDArray fakeIn = Nd4j.rand(BATCHSIZE, CHANNELS, DIMENSIONS, DIMENSIONS); + //INDArray fakeIn = Nd4j.rand(new int[]{batchSize, X_DIM*Y_DIM}); //hack for MNIST only, use above otherwise + INDArray fakeIn = Nd4j.rand(BATCHSIZE, App2Config.INPUT); + + INDArray fake = gan.activateSelectedLayers(0, gen.getLayers().length - 1, fakeIn); + // when generator has TANH as activation - value range is -1 to 1 + // when generator has SIGMOID, then range is 0 to 1 + fake.addi(1f).divi(2f); + + DataSet realSet = new DataSet(real, label_real); + DataSet fakeSet = new DataSet(fake, label_fake); + + DataSet data = DataSet.merge(Arrays.asList(realSet, fakeSet)); + + dis.fit(data); + dis.fit(data); + // Update the discriminator in the GAN network + updateGan(gen, dis, gan); + + gan.fit(new DataSet(Nd4j.rand(BATCHSIZE, App2Config.INPUT), label_fake)); + + //Visualize and reporting + if (j % 10 == 1) { + System.out.println("Epoch " + i + " Iteration " + j + " Visualizing..."); + INDArray[] samples = BATCHSIZE > OUTPUT_PER_PANEL ? new INDArray[OUTPUT_PER_PANEL] : new INDArray[BATCHSIZE]; + + + for (int k = 0; k < samples.length; k++) { + DataSet fakeSet2 = new DataSet(fakeIn, label_fake); + INDArray input = fakeSet2.get(k).getFeatures(); + + //input = input.reshape(1,CHANNELS, DIMENSIONS, DIMENSIONS); //batch size will be 1 here for images + input = input.reshape(1, App2Config.INPUT); + + //samples[k] = gen.output(input, false); + samples[k] = gen.activateSelectedLayers(0, gen.getLayers().length - 1, input); + samples[k] = samples[k].reshape(1, CHANNELS, DIMENSIONS, DIMENSIONS); + //samples[k] = + //samples[k].muli(255f); + + } + frame = visualize(samples, 1, frame == null ? new JFrame() : frame, false); //each samples only has 1 image, thus batchElements=1 + } + } + + if (trainData.resetSupported()) { + trainData.reset(); + } else { + log.error("Trainingdata {} does not support reset.", trainData.toString()); + } + // Copy the GANs generator to gen. + updateGen(gen, gan); + log.info("Updated GAN's generator from gen."); + gen.save(new File("mnist-mlp-generator.dlj")); + } + } + + + + + + + + + + + + private static JFrame visualize(INDArray[] samples, int batchElements, JFrame frame, boolean isOrig) { + if (isOrig) { + frame.setTitle("Viz Original"); + } else { + frame.setTitle("Generated"); + } + + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.setLayout(new BorderLayout()); + + JPanel panelx = new JPanel(); + + panelx.setLayout(new GridLayout(4, 4, 8, 8)); + for (INDArray sample : samples) { + for(int i = 0; i1) { + bi = new BufferedImage(DIMENSIONS, DIMENSIONS, BufferedImage.TYPE_INT_RGB); //need to change here based on channels + } else { + bi = new BufferedImage(DIMENSIONS, DIMENSIONS, BufferedImage.TYPE_BYTE_GRAY); //need to change here based on channels + } + final int imageSize = DIMENSIONS * DIMENSIONS; + final int offset = batchElement * imageSize; + int pxl = offset * CHANNELS; //where to start in the INDArray + + //Image in NCHW - channels first format + for (int c = 0; c < CHANNELS; c++) { //step through the num channels for each pixel + for (int y = 0; y < DIMENSIONS; y++) { // step through the columns x + for (int x = 0; x < DIMENSIONS; x++) { //step through the rows y + float f_pxl = tensor.getFloat(pxl) * COLORSPACE; + if(isOrig) log.trace("'{}.' Image (x,y,c): ({}, {}, {}) with INDArray with index {} and value '{}'", batchElement, x, y, c, pxl, f_pxl); + bi.getRaster().setSample(x, y, c, f_pxl); + pxl++; //next item in INDArray + } + } + } + ImageIcon orig = new ImageIcon(bi); + Image imageScaled = orig.getImage().getScaledInstance((4 * DIMENSIONS), (4 * DIMENSIONS), Image.SCALE_DEFAULT); + ImageIcon scaled = new ImageIcon(imageScaled); + if(! isOrig) saveImage(imageScaled, batchElement, isOrig); + return new JLabel(scaled); + + } + + private static void saveImage(Image image, int batchElement, boolean isOrig) { + String outputDirectory = OUTPUT_DIR; // Set the output directory where the images will be saved + + try { + // Save the images to disk + saveImage(image, outputDirectory, UUID.randomUUID().toString()+".png"); + + log.debug("Images saved successfully."); + } catch (IOException e) { + log.error("Error saving the images: {}", e.getMessage()); + } + } + private static void saveImage(Image image, String outputDirectory, String fileName) throws IOException { + File directory = new File(outputDirectory); + if (!directory.exists()) { + directory.mkdir(); + } + + File outputFile = new File(directory, fileName); + ImageIO.write(imageToBufferedImage(image), "png", outputFile); + } + + public static BufferedImage imageToBufferedImage(Image image) { + if (image instanceof BufferedImage) { + return (BufferedImage) image; + } + + // Create a buffered image with the same dimensions and transparency as the original image + BufferedImage bufferedImage; + if (CHANNELS > 1) { + bufferedImage = + new BufferedImage( + image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); + } else { + bufferedImage = + new BufferedImage( + image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_BYTE_GRAY); + } + + // Draw the original image onto the buffered image + Graphics2D g2d = bufferedImage.createGraphics(); + g2d.drawImage(image, 0, 0, null); + g2d.dispose(); + + return bufferedImage; + } + private static void updateGen(MultiLayerNetwork gen, MultiLayerNetwork gan) { + for (int i = 0; i < gen.getLayers().length; i++) { + gen.getLayer(i).setParams(gan.getLayer(i).getParams()); + } + } + + private static void updateGan(MultiLayerNetwork gen, MultiLayerNetwork dis, MultiLayerNetwork gan) { + int genLayerCount = gen.getLayers().length; + for (int i = genLayerCount; i < gan.getLayers().length; i++) { + gan.getLayer(i).setParams(dis.getLayer(i - genLayerCount).getParams()); + } + } + +} diff --git a/brutex-extended-tests/src/test/java/net/brutex/gan/App2Config.java b/brutex-extended-tests/src/test/java/net/brutex/gan/App2Config.java new file mode 100644 index 000000000..607acd74b --- /dev/null +++ b/brutex-extended-tests/src/test/java/net/brutex/gan/App2Config.java @@ -0,0 +1,176 @@ +/* + * + * ****************************************************************************** + * * + * * This program and the accompanying materials are made available under the + * * terms of the Apache License, Version 2.0 which is available at + * * https://www.apache.org/licenses/LICENSE-2.0. + * * + * * See the NOTICE file distributed with this work for additional + * * information regarding copyright ownership. + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * * License for the specific language governing permissions and limitations + * * under the License. + * * + * * SPDX-License-Identifier: Apache-2.0 + * ***************************************************************************** + * + */ + +package net.brutex.gan; + +import static net.brutex.ai.dnn.api.NN.*; + +import org.deeplearning4j.nn.conf.GradientNormalization; +import org.deeplearning4j.nn.conf.NeuralNetConfiguration; +import org.deeplearning4j.nn.conf.layers.*; +import org.deeplearning4j.nn.weights.WeightInit; +import org.nd4j.linalg.activations.Activation; +import org.nd4j.linalg.activations.impl.ActivationLReLU; +import org.nd4j.linalg.learning.config.Adam; +import org.nd4j.linalg.learning.config.IUpdater; +import org.nd4j.linalg.lossfunctions.LossFunctions; + +public class App2Config { + + public static final int INPUT = 100; + public static final int X_DIM = 28; + public static final int y_DIM = 28; + public static final int CHANNELS = 1; + public static final IUpdater UPDATER = Adam.builder().learningRate(0.0002).beta1(0.5).build(); + + static LayerConfiguration[] genLayerConfig() { + return new LayerConfiguration[] { + /* + DenseLayer.builder().name("L-0").nIn(INPUT).nOut(INPUT + (INPUT / 2)).activation(Activation.RELU).build(), + ActivationLayer.builder().activation(Activation.RELU).build(), /* + Deconvolution2D.builder().name("L-Deconv-01").nIn(CHANNELS).nOut(CHANNELS) + .kernelSize(2,2) + .stride(1,1) + .padding(0,0) + .convolutionMode(ConvolutionMode.Truncate) + .activation(Activation.RELU) + .hasBias(BIAS).build(), + //BatchNormalization.builder().nOut(CHANNELS).build(), + Deconvolution2D.builder().name("L-Deconv-02").nIn(CHANNELS).nOut(CHANNELS) + .kernelSize(2,2) + .stride(2,2) + .padding(0,0) + .convolutionMode(ConvolutionMode.Truncate) + .activation(Activation.RELU) + .hasBias(BIAS).build(), + //BatchNormalization.builder().name("L-batch").nOut(CHANNELS).build(), + + + DenseLayer.builder().name("L-x").nIn(INPUT + (INPUT / 2)).nOut(2 * INPUT).build(), + ActivationLayer.builder().activation(Activation.RELU).dropOut(0.2).build(), + DenseLayer.builder().name("L-x").nIn(2 * INPUT).nOut(3 * INPUT).build(), + ActivationLayer.builder().activation(Activation.RELU).dropOut(0.2).build(), + DenseLayer.builder().name("L-x").nIn(3 * INPUT).nOut(2 * INPUT).build(), + ActivationLayer.builder().activation(Activation.RELU).dropOut(0.2).build(), + // DropoutLayer.builder(0.001).build(), + DenseLayer.builder().nIn(2 * INPUT).nOut(INPUT).activation(Activation.TANH).build() */ + + dense().nIn(INPUT).nOut(256).weightInit(WeightInit.NORMAL).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + dense().nIn(256).nOut(512).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + dense().nIn(512).nOut(1024).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + dense().nIn(1024).nOut(784).activation(Activation.TANH).build(), + + }; + } + + static LayerConfiguration[] disLayerConfig() { + return new LayerConfiguration[] {/* + Convolution2D.builder().nIn(CHANNELS).kernelSize(2,2).padding(1,1).stride(1,1).nOut(CHANNELS) + .build(), + Convolution2D.builder().nIn(CHANNELS).kernelSize(3,3).padding(1,1).stride(2,2).nOut(CHANNELS) + .build(), + ActivationLayer.builder().activation(Activation.LEAKYRELU).build(), + BatchNormalization.builder().build(), + OutputLayer.builder().nOut(1).lossFunction(LossFunctions.LossFunction.MCXENT) + .activation(Activation.SIGMOID) + .build() + + + dense().name("L-dense").nIn(INPUT).nOut(INPUT).build(), + ActivationLayer.builder().activation(Activation.RELU).build(), + DropoutLayer.builder(0.5).build(), + + DenseLayer.builder().nIn(INPUT).nOut(INPUT/2).build(), + ActivationLayer.builder().activation(Activation.RELU).build(), + DropoutLayer.builder(0.5).build(), + + DenseLayer.builder().nIn(INPUT/2).nOut(INPUT/4).build(), + ActivationLayer.builder().activation(Activation.RELU).build(), + DropoutLayer.builder(0.5).build(), + + OutputLayer.builder().nIn(INPUT/4).nOut(1).lossFunction(LossFunctions.LossFunction.XENT) + .activation(Activation.SIGMOID) + .build() */ + dense().nIn(784).nOut(1024).hasBias(true).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + DropoutLayer.builder(1 - 0.5).build(), + dense().nIn(1024).nOut(512).hasBias(true).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + DropoutLayer.builder(1 - 0.5).build(), + dense().nIn(512).nOut(256).hasBias(true).build(), + ActivationLayer.builder(new ActivationLReLU(0.2)).build(), + DropoutLayer.builder(1 - 0.5).build(), + OutputLayer.builder(LossFunctions.LossFunction.XENT).nIn(256).nOut(1).activation(Activation.SIGMOID).build() + }; + } + + + static NeuralNetConfiguration generator() { + NeuralNetConfiguration conf = + NeuralNetConfiguration.builder() + .name("generator") + .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) + .gradientNormalizationThreshold(100) + .seed(42) + .updater(UPDATER) + .weightInit(WeightInit.XAVIER) + //.weightNoise(new WeightNoise(new NormalDistribution(0.5, 0.5))) + .weightNoise(null) + // .weightInitFn(new WeightInitXavier()) + // .activationFn(new ActivationIdentity()) + .activation(Activation.IDENTITY) + .layersFromArray(App2Config.genLayerConfig()) + // .inputType(InputType.convolutional(DIMENSIONS, DIMENSIONS, CHANNELS)) + //.inputPreProcessor(0, new CnnToFeedForwardPreProcessor()) + //.inputPreProcessor(2, new FeedForwardToCnnPreProcessor(DIMENSIONS, DIMENSIONS, CHANNELS)) + //.inputPreProcessor(4, new CnnToFeedForwardPreProcessor()) + + .build(); + conf.init(); + return conf; + } + + static NeuralNetConfiguration discriminator() { + NeuralNetConfiguration conf = + NeuralNetConfiguration.builder() + .name("discriminator") + .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer) + .gradientNormalizationThreshold(100) + .seed(42) + .updater(UPDATER) + .weightInit(WeightInit.XAVIER) + // .weightNoise(new WeightNoise(new NormalDistribution(0.5, 0.5))) + .weightNoise(null) + // .weightInitFn(new WeightInitXavier()) + // .activationFn(new ActivationIdentity()) + .activation(Activation.IDENTITY) + .layersFromArray(disLayerConfig()) + //.inputPreProcessor(0, new FeedForwardToCnnPreProcessor(DIMENSIONS, DIMENSIONS, CHANNELS)) + //.inputPreProcessor(0, new CnnToFeedForwardPreProcessor()) + //.dataType(DataType.FLOAT) + .build(); + conf.init(); + return conf; + } +} diff --git a/cavis-dnn/cavis-dnn-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java b/cavis-dnn/cavis-dnn-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java index af22b0a1b..a9a885b74 100644 --- a/cavis-dnn/cavis-dnn-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java +++ b/cavis-dnn/cavis-dnn-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java @@ -43,223 +43,255 @@ import static org.deeplearning4j.nn.modelimport.keras.utils.KerasModelUtils.impo @Slf4j public class KerasSequentialModel extends KerasModel { - /** - * (Recommended) Builder-pattern constructor for Sequential model. - * - * @param modelBuilder builder object - * @throws IOException I/O exception - * @throws InvalidKerasConfigurationException Invalid Keras configuration - * @throws UnsupportedKerasConfigurationException Unsupported Keras configuration - */ - public KerasSequentialModel(KerasModelBuilder modelBuilder) - throws UnsupportedKerasConfigurationException, IOException, InvalidKerasConfigurationException { - this(modelBuilder.getModelJson(), modelBuilder.getModelYaml(), modelBuilder.getWeightsArchive(), - modelBuilder.getWeightsRoot(), modelBuilder.getTrainingJson(), modelBuilder.getTrainingArchive(), - modelBuilder.isEnforceTrainingConfig(), modelBuilder.getInputShape()); + /** + * (Recommended) Builder-pattern constructor for Sequential model. + * + * @param modelBuilder builder object + * @throws IOException I/O exception + * @throws InvalidKerasConfigurationException Invalid Keras configuration + * @throws UnsupportedKerasConfigurationException Unsupported Keras configuration + */ + public KerasSequentialModel(KerasModelBuilder modelBuilder) + throws UnsupportedKerasConfigurationException, + IOException, + InvalidKerasConfigurationException { + this( + modelBuilder.getModelJson(), + modelBuilder.getModelYaml(), + modelBuilder.getWeightsArchive(), + modelBuilder.getWeightsRoot(), + modelBuilder.getTrainingJson(), + modelBuilder.getTrainingArchive(), + modelBuilder.isEnforceTrainingConfig(), + modelBuilder.getInputShape()); + } + + /** + * (Not recommended) Constructor for Sequential model from model configuration (JSON or YAML), + * training configuration (JSON), weights, and "training mode" boolean indicator. When built in + * training mode, certain unsupported configurations (e.g., unknown regularizers) will throw + * Exceptions. When enforceTrainingConfig=false, these will generate warnings but will be + * otherwise ignored. + * + * @param modelJson model configuration JSON string + * @param modelYaml model configuration YAML string + * @param trainingJson training configuration JSON string + * @throws IOException I/O exception + */ + public KerasSequentialModel( + String modelJson, + String modelYaml, + Hdf5Archive weightsArchive, + String weightsRoot, + String trainingJson, + Hdf5Archive trainingArchive, + boolean enforceTrainingConfig, + int[] inputShape) + throws IOException, + InvalidKerasConfigurationException, + UnsupportedKerasConfigurationException { + + Map modelConfig = KerasModelUtils.parseModelConfig(modelJson, modelYaml); + this.kerasMajorVersion = KerasModelUtils.determineKerasMajorVersion(modelConfig, config); + this.kerasBackend = KerasModelUtils.determineKerasBackend(modelConfig, config); + this.enforceTrainingConfig = enforceTrainingConfig; + + /* Determine model configuration type. */ + if (!modelConfig.containsKey(config.getFieldClassName())) + throw new InvalidKerasConfigurationException( + "Could not determine Keras model class (no " + + config.getFieldClassName() + + " field found)"); + this.className = (String) modelConfig.get(config.getFieldClassName()); + if (!this.className.equals(config.getFieldClassNameSequential())) + throw new InvalidKerasConfigurationException( + "Model class name must be " + + config.getFieldClassNameSequential() + + " (found " + + this.className + + ")"); + + /* Process layer configurations. */ + if (!modelConfig.containsKey(config.getModelFieldConfig())) + throw new InvalidKerasConfigurationException( + "Could not find layer configurations (no " + + config.getModelFieldConfig() + + " field found)"); + + // Prior to Keras 2.2.3 the "config" of a Sequential model was a list of layer configurations. + // For consistency + // "config" is now an object containing a "name" and "layers", the latter contain the same data + // as before. + // This change only affects Sequential models. + List layerList; + try { + layerList = (List) modelConfig.get(config.getModelFieldConfig()); + } catch (Exception e) { + HashMap layerMap = (HashMap) modelConfig.get(config.getModelFieldConfig()); + layerList = (List) layerMap.get("layers"); } - /** - * (Not recommended) Constructor for Sequential model from model configuration - * (JSON or YAML), training configuration (JSON), weights, and "training mode" - * boolean indicator. When built in training mode, certain unsupported configurations - * (e.g., unknown regularizers) will throw Exceptions. When enforceTrainingConfig=false, these - * will generate warnings but will be otherwise ignored. - * - * @param modelJson model configuration JSON string - * @param modelYaml model configuration YAML string - * @param trainingJson training configuration JSON string - * @throws IOException I/O exception - */ - public KerasSequentialModel(String modelJson, String modelYaml, Hdf5Archive weightsArchive, String weightsRoot, - String trainingJson, Hdf5Archive trainingArchive, boolean enforceTrainingConfig, - int[] inputShape) - throws IOException, InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { + Pair, List> layerPair = prepareLayers(layerList); + this.layers = layerPair.getFirst(); + this.layersOrdered = layerPair.getSecond(); - Map modelConfig = KerasModelUtils.parseModelConfig(modelJson, modelYaml); - this.kerasMajorVersion = KerasModelUtils.determineKerasMajorVersion(modelConfig, config); - this.kerasBackend = KerasModelUtils.determineKerasBackend(modelConfig, config); - this.enforceTrainingConfig = enforceTrainingConfig; + KerasLayer inputLayer; + if (this.layersOrdered.get(0) instanceof KerasInput) { + inputLayer = this.layersOrdered.get(0); + } else { + /* Add placeholder input layer and update lists of input and output layers. */ + int[] firstLayerInputShape = this.layersOrdered.get(0).getInputShape(); + Preconditions.checkState( + ArrayUtil.prod(firstLayerInputShape) > 0, "Input shape must not be zero!"); + inputLayer = new KerasInput("input1", firstLayerInputShape); + inputLayer.setDimOrder(this.layersOrdered.get(0).getDimOrder()); + this.layers.put(inputLayer.getName(), inputLayer); + this.layersOrdered.add(0, inputLayer); + } + this.inputLayerNames = new ArrayList<>(Collections.singletonList(inputLayer.getName())); + this.outputLayerNames = + new ArrayList<>( + Collections.singletonList( + this.layersOrdered.get(this.layersOrdered.size() - 1).getName())); - /* Determine model configuration type. */ - if (!modelConfig.containsKey(config.getFieldClassName())) - throw new InvalidKerasConfigurationException( - "Could not determine Keras model class (no " + config.getFieldClassName() + " field found)"); - this.className = (String) modelConfig.get(config.getFieldClassName()); - if (!this.className.equals(config.getFieldClassNameSequential())) - throw new InvalidKerasConfigurationException("Model class name must be " + config.getFieldClassNameSequential() - + " (found " + this.className + ")"); - - /* Process layer configurations. */ - if (!modelConfig.containsKey(config.getModelFieldConfig())) - throw new InvalidKerasConfigurationException( - "Could not find layer configurations (no " + config.getModelFieldConfig() + " field found)"); - - // Prior to Keras 2.2.3 the "config" of a Sequential model was a list of layer configurations. For consistency - // "config" is now an object containing a "name" and "layers", the latter contain the same data as before. - // This change only affects Sequential models. - List layerList; - try { - layerList = (List) modelConfig.get(config.getModelFieldConfig()); - } catch (Exception e) { - HashMap layerMap = (HashMap) modelConfig.get(config.getModelFieldConfig()); - layerList = (List) layerMap.get("layers"); - } - - Pair, List> layerPair = - prepareLayers(layerList); - this.layers = layerPair.getFirst(); - this.layersOrdered = layerPair.getSecond(); - - KerasLayer inputLayer; - if (this.layersOrdered.get(0) instanceof KerasInput) { - inputLayer = this.layersOrdered.get(0); - } else { - /* Add placeholder input layer and update lists of input and output layers. */ - int[] firstLayerInputShape = this.layersOrdered.get(0).getInputShape(); - Preconditions.checkState(ArrayUtil.prod(firstLayerInputShape) > 0,"Input shape must not be zero!"); - inputLayer = new KerasInput("input1", firstLayerInputShape); - inputLayer.setDimOrder(this.layersOrdered.get(0).getDimOrder()); - this.layers.put(inputLayer.getName(), inputLayer); - this.layersOrdered.add(0, inputLayer); - } - this.inputLayerNames = new ArrayList<>(Collections.singletonList(inputLayer.getName())); - this.outputLayerNames = new ArrayList<>( - Collections.singletonList(this.layersOrdered.get(this.layersOrdered.size() - 1).getName())); - - /* Update each layer's inbound layer list to include (only) previous layer. */ - KerasLayer prevLayer = null; - for (KerasLayer layer : this.layersOrdered) { - if (prevLayer != null) - layer.setInboundLayerNames(Collections.singletonList(prevLayer.getName())); - prevLayer = layer; - } - - /* Import training configuration. */ - if (enforceTrainingConfig) { - if (trainingJson != null) - importTrainingConfiguration(trainingJson); - else log.warn("If enforceTrainingConfig is true, a training " + - "configuration object has to be provided. Usually the only practical way to do this is to store" + - " your keras model with `model.save('model_path.h5'. If you store model config and weights" + - " separately no training configuration is attached."); - } - - this.outputTypes = inferOutputTypes(inputShape); - - if (weightsArchive != null) - importWeights(weightsArchive, weightsRoot, layers, kerasMajorVersion, kerasBackend); + /* Update each layer's inbound layer list to include (only) previous layer. */ + KerasLayer prevLayer = null; + for (KerasLayer layer : this.layersOrdered) { + if (prevLayer != null) + layer.setInboundLayerNames(Collections.singletonList(prevLayer.getName())); + prevLayer = layer; } - /** - * Default constructor - */ - public KerasSequentialModel() { - super(); + /* Import training configuration. */ + if (enforceTrainingConfig) { + if (trainingJson != null) importTrainingConfiguration(trainingJson); + else + log.warn( + "If enforceTrainingConfig is true, a training " + + "configuration object has to be provided. Usually the only practical way to do this is to store" + + " your keras model with `model.save('model_path.h5'. If you store model config and weights" + + " separately no training configuration is attached."); } - /** - * Configure a NeuralNetConfiguration from this Keras Sequential model configuration. - * - * @return NeuralNetConfiguration - */ - public NeuralNetConfiguration getNeuralNetConfiguration() - throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { - if (!this.className.equals(config.getFieldClassNameSequential())) - throw new InvalidKerasConfigurationException( - "Keras model class name " + this.className + " incompatible with MultiLayerNetwork"); - if (this.inputLayerNames.size() != 1) - throw new InvalidKerasConfigurationException( - "MultiLayerNetwork expects only 1 input (found " + this.inputLayerNames.size() + ")"); - if (this.outputLayerNames.size() != 1) - throw new InvalidKerasConfigurationException( - "MultiLayerNetwork expects only 1 output (found " + this.outputLayerNames.size() + ")"); + this.outputTypes = inferOutputTypes(inputShape); - NeuralNetConfiguration.NeuralNetConfigurationBuilder modelBuilder = NeuralNetConfiguration.builder(); + if (weightsArchive != null) + importWeights(weightsArchive, weightsRoot, layers, kerasMajorVersion, kerasBackend); + } - if (optimizer != null) { - modelBuilder.updater(optimizer); + /** Default constructor */ + public KerasSequentialModel() { + super(); + } + + /** + * Configure a NeuralNetConfiguration from this Keras Sequential model configuration. + * + * @return NeuralNetConfiguration + */ + public NeuralNetConfiguration getNeuralNetConfiguration() + throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { + if (!this.className.equals(config.getFieldClassNameSequential())) + throw new InvalidKerasConfigurationException( + "Keras model class name " + this.className + " incompatible with MultiLayerNetwork"); + if (this.inputLayerNames.size() != 1) + throw new InvalidKerasConfigurationException( + "MultiLayerNetwork expects only 1 input (found " + this.inputLayerNames.size() + ")"); + if (this.outputLayerNames.size() != 1) + throw new InvalidKerasConfigurationException( + "MultiLayerNetwork expects only 1 output (found " + this.outputLayerNames.size() + ")"); + + NeuralNetConfiguration.NeuralNetConfigurationBuilder modelBuilder = + NeuralNetConfiguration.builder(); + + if (optimizer != null) { + modelBuilder.updater(optimizer); + } + + // don't forcibly override for keras import + modelBuilder.overrideNinUponBuild(false); + /* Add layers one at a time. */ + KerasLayer prevLayer = null; + int layerIndex = 0; + for (KerasLayer layer : this.layersOrdered) { + if (layer.isLayer()) { + int nbInbound = layer.getInboundLayerNames().size(); + if (nbInbound != 1) + throw new InvalidKerasConfigurationException( + "Layers in NeuralNetConfiguration must have exactly one inbound layer (found " + + nbInbound + + " for layer " + + layer.getName() + + ")"); + if (prevLayer != null) { + InputType[] inputTypes = new InputType[1]; + InputPreProcessor preprocessor; + if (prevLayer.isInputPreProcessor()) { + inputTypes[0] = this.outputTypes.get(prevLayer.getInboundLayerNames().get(0)); + preprocessor = prevLayer.getInputPreprocessor(inputTypes); + InputType outputType = preprocessor.getOutputType(inputTypes[0]); + layer.getLayer().setNIn(outputType, modelBuilder.isOverrideNinUponBuild()); + } else { + inputTypes[0] = this.outputTypes.get(prevLayer.getName()); + preprocessor = layer.getInputPreprocessor(inputTypes); + if (preprocessor != null) { + InputType outputType = preprocessor.getOutputType(inputTypes[0]); + layer.getLayer().setNIn(outputType, modelBuilder.isOverrideNinUponBuild()); + } else layer.getLayer().setNIn(inputTypes[0], modelBuilder.isOverrideNinUponBuild()); + } + if (preprocessor != null) { + + Map map = new HashMap<>(); + map.put(layerIndex, preprocessor); + modelBuilder.inputPreProcessors(map); + } } - - //don't forcibly override for keras import - modelBuilder.overrideNinUponBuild(false); - /* Add layers one at a time. */ - KerasLayer prevLayer = null; - int layerIndex = 0; - for (KerasLayer layer : this.layersOrdered) { - if (layer.isLayer()) { - int nbInbound = layer.getInboundLayerNames().size(); - if (nbInbound != 1) - throw new InvalidKerasConfigurationException( - "Layers in NeuralNetConfiguration must have exactly one inbound layer (found " - + nbInbound + " for layer " + layer.getName() + ")"); - if (prevLayer != null) { - InputType[] inputTypes = new InputType[1]; - InputPreProcessor preprocessor; - if (prevLayer.isInputPreProcessor()) { - inputTypes[0] = this.outputTypes.get(prevLayer.getInboundLayerNames().get(0)); - preprocessor = prevLayer.getInputPreprocessor(inputTypes); - InputType outputType = preprocessor.getOutputType(inputTypes[0]); - layer.getLayer().setNIn(outputType,modelBuilder.isOverrideNinUponBuild()); - } else { - inputTypes[0] = this.outputTypes.get(prevLayer.getName()); - preprocessor = layer.getInputPreprocessor(inputTypes); - if(preprocessor != null) { - InputType outputType = preprocessor.getOutputType(inputTypes[0]); - layer.getLayer().setNIn(outputType,modelBuilder.isOverrideNinUponBuild()); - } - else - layer.getLayer().setNIn(inputTypes[0],modelBuilder.isOverrideNinUponBuild()); - - } - if (preprocessor != null) - modelBuilder.inputPreProcessor(layerIndex, preprocessor); - - - } - - modelBuilder.layer(layerIndex++, layer.getLayer()); - } else if (layer.getVertex() != null) - throw new InvalidKerasConfigurationException("Cannot add vertex to NeuralNetConfiguration (class name " - + layer.getClassName() + ", layer name " + layer.getName() + ")"); - prevLayer = layer; - } - - /* Whether to use standard backprop (or BPTT) or truncated BPTT. */ - if (this.useTruncatedBPTT && this.truncatedBPTT > 0) - modelBuilder.backpropType(BackpropType.TruncatedBPTT) - .tbpttFwdLength(truncatedBPTT) - .tbpttBackLength(truncatedBPTT); - else - modelBuilder.backpropType(BackpropType.Standard); - - NeuralNetConfiguration build = modelBuilder.build(); - - - return build; + modelBuilder.layer(layerIndex++, layer.getLayer()); + } else if (layer.getVertex() != null) + throw new InvalidKerasConfigurationException( + "Cannot add vertex to NeuralNetConfiguration (class name " + + layer.getClassName() + + ", layer name " + + layer.getName() + + ")"); + prevLayer = layer; } - /** - * Build a MultiLayerNetwork from this Keras Sequential model configuration. - * - * @return MultiLayerNetwork - */ - public MultiLayerNetwork getMultiLayerNetwork() - throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { - return getMultiLayerNetwork(true); - } + /* Whether to use standard backprop (or BPTT) or truncated BPTT. */ + if (this.useTruncatedBPTT && this.truncatedBPTT > 0) + modelBuilder + .backpropType(BackpropType.TruncatedBPTT) + .tbpttFwdLength(truncatedBPTT) + .tbpttBackLength(truncatedBPTT); + else modelBuilder.backpropType(BackpropType.Standard); - /** - * Build a MultiLayerNetwork from this Keras Sequential model configuration and import weights. - * - * @return MultiLayerNetwork - */ - public MultiLayerNetwork getMultiLayerNetwork(boolean importWeights) - throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { - MultiLayerNetwork model = new MultiLayerNetwork(getNeuralNetConfiguration()); - model.init(); - if (importWeights) - model = (MultiLayerNetwork) KerasModelUtils.copyWeightsToModel(model, this.layers); - return model; - } + NeuralNetConfiguration build = modelBuilder.build(); + + return build; + } + + /** + * Build a MultiLayerNetwork from this Keras Sequential model configuration. + * + * @return MultiLayerNetwork + */ + public MultiLayerNetwork getMultiLayerNetwork() + throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { + return getMultiLayerNetwork(true); + } + + /** + * Build a MultiLayerNetwork from this Keras Sequential model configuration and import weights. + * + * @return MultiLayerNetwork + */ + public MultiLayerNetwork getMultiLayerNetwork(boolean importWeights) + throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { + MultiLayerNetwork model = new MultiLayerNetwork(getNeuralNetConfiguration()); + model.init(); + if (importWeights) + model = (MultiLayerNetwork) KerasModelUtils.copyWeightsToModel(model, this.layers); + return model; + } } diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/net/brutex/ai/dnn/api/NN.java b/cavis-dnn/cavis-dnn-nn/src/main/java/net/brutex/ai/dnn/api/NN.java index 06e73dcf9..683a83083 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/net/brutex/ai/dnn/api/NN.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/net/brutex/ai/dnn/api/NN.java @@ -23,6 +23,7 @@ package net.brutex.ai.dnn.api; import org.deeplearning4j.nn.conf.NeuralNetConfiguration; import org.deeplearning4j.nn.conf.NeuralNetConfiguration.NeuralNetConfigurationBuilder; +import org.deeplearning4j.nn.conf.layers.DenseLayer; /** * A fluent API to configure and create artificial neural networks @@ -30,9 +31,11 @@ import org.deeplearning4j.nn.conf.NeuralNetConfiguration.NeuralNetConfigurationB public class NN { - public static NeuralNetConfigurationBuilder net() { + public static NeuralNetConfigurationBuilder nn() { return NeuralNetConfiguration.builder(); } + public static DenseLayer.DenseLayerBuilder dense() { return DenseLayer.builder(); } + } diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetBaseBuilderConfiguration.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetBaseBuilderConfiguration.java index b69eb174f..ae4a8604b 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetBaseBuilderConfiguration.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetBaseBuilderConfiguration.java @@ -152,7 +152,7 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor @Getter @Setter @NonNull @lombok.Builder.Default protected BackpropType backpropType = BackpropType.Standard; - @Getter @lombok.Builder.Default + @Getter @Setter @Singular protected Map inputPreProcessors = new HashMap<>(); /** * When doing truncated BPTT: how many steps of forward pass should we do before doing (truncated) @@ -524,12 +524,11 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor * @param processor what to use to preProcess the data. * @return builder pattern */ - public B inputPreProcessor(@NonNull Integer layer, @NonNull InputPreProcessor processor) { - if(inputPreProcessors$value==null) inputPreProcessors$value=new LinkedHashMap<>(); - inputPreProcessors$value.put(layer, processor); - inputPreProcessors$set = true; - return self(); - } + //public B inputPreProcessor(@NonNull Integer layer, @NonNull InputPreProcessor processor) { + // inputPreProcessors$value.put(layer, processor); + // inputPreProcessors$set = true; + // return self(); + // } /** * Set layer at index diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetConfiguration.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetConfiguration.java index fcdb56125..48dd1f370 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetConfiguration.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/NeuralNetConfiguration.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import lombok.*; import lombok.experimental.SuperBuilder; @@ -317,6 +318,7 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration { @NonNull InputPreProcessor inputPreProcessor = l.getPreProcessorForInputType(currentInputType); if (inputPreProcessor != null) { + inputPreProcessors = new HashMap<>(inputPreProcessors); inputPreProcessors.put(i, inputPreProcessor); } } @@ -538,6 +540,11 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration { obj.getClass().getSimpleName()); } }); + // make sure the indexes are sequenced properly + AtomicInteger i = new AtomicInteger(); + ret.forEach(obj -> { + obj.setIndex(i.getAndIncrement()); + }); return ret; } diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/ConvolutionLayer.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/ConvolutionLayer.java index 0e76f5776..5908bc966 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/ConvolutionLayer.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/ConvolutionLayer.java @@ -219,7 +219,7 @@ public class ConvolutionLayer extends FeedForwardLayer { throw new IllegalStateException( "Invalid input for Convolution layer (layer name=\"" + getName() - + "\"): Expected CNN input, got " + + "\" at index '"+getIndex()+"') : Expected CNN input, got " + inputType); } @@ -372,7 +372,8 @@ public class ConvolutionLayer extends FeedForwardLayer { * @param kernelSize kernel size */ public B kernelSize(int... kernelSize) { - this.kernelSize$value = ValidationUtils.validate3NonNegative(kernelSize, "kernelSize"); + //this.kernelSize$value = ValidationUtils.validate3NonNegative(kernelSize, "kernelSize"); + this.kernelSize$value = kernelSize; this.kernelSize$set = true; return self(); } @@ -383,7 +384,8 @@ public class ConvolutionLayer extends FeedForwardLayer { * @param stride kernel size */ public B stride(int... stride) { - this.stride$value = ValidationUtils.validate3NonNegative(stride, "stride"); + //this.stride$value = ValidationUtils.validate3NonNegative(stride, "stride"); + this.stride$value = stride; this.stride$set = true; return self(); } @@ -394,7 +396,8 @@ public class ConvolutionLayer extends FeedForwardLayer { * @param padding kernel size */ public B padding(int... padding) { - this.padding$value = ValidationUtils.validate3NonNegative(padding, "padding"); + //this.padding$value = ValidationUtils.validate3NonNegative(padding, "padding"); + this.padding$value = padding; this.padding$set = true; return self(); } @@ -404,7 +407,8 @@ public class ConvolutionLayer extends FeedForwardLayer { * @param dilation kernel size */ public B dilation(int... dilation) { - this.dilation$value = ValidationUtils.validate3NonNegative(dilation, "dilation"); + //this.dilation$value = ValidationUtils.validate3NonNegative(dilation, "dilation"); + this.dilation$value = dilation; this.dilation$set = true; return self(); } diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/Deconvolution2D.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/Deconvolution2D.java index 62fab4f7f..c8374c646 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/Deconvolution2D.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/Deconvolution2D.java @@ -20,14 +20,19 @@ package org.deeplearning4j.nn.conf.layers; +import java.util.Arrays; import java.util.Collection; import java.util.Map; +import java.util.stream.IntStream; + import lombok.*; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; +import lombok.extern.slf4j.Slf4j; import org.deeplearning4j.nn.api.Layer; import org.deeplearning4j.nn.api.ParamInitializer; import org.deeplearning4j.nn.conf.CNN2DFormat; +import org.deeplearning4j.nn.conf.ConvolutionMode; import org.deeplearning4j.nn.conf.NeuralNetConfiguration; import org.deeplearning4j.nn.conf.inputs.InputType; import org.deeplearning4j.nn.layers.convolution.Deconvolution2DLayer; @@ -84,6 +89,8 @@ public class Deconvolution2D extends ConvolutionLayer { boolean initializeParams, DataType networkDataType) { setNetConfiguration(conf); + + LayerValidation.assertNInNOutSet("Deconvolution2D", getName(), layerIndex, getNIn(), getNOut()); LayerConfiguration lconf = conf.getFlattenedLayerConfigurations().get(layerIndex); runInheritance(); @@ -127,11 +134,25 @@ public class Deconvolution2D extends ConvolutionLayer { getName(), Deconvolution2DLayer.class); } - +@Slf4j private static final class Deconvolution2DBuilderImpl extends Deconvolution2DBuilder { public Deconvolution2D build() { Deconvolution2D l = new Deconvolution2D(this); + if( l.getConvolutionMode() == ConvolutionMode.Same + && IntStream.of(l.getPadding()).sum() != 0) { + log.warn("Invalid input for layer '{}'. " + + "You cannot have a padding of {} when Convolution Mode is set to 'Same'." + + " Padding will be ignored." + , l.getName(), l.getPadding()); + } + /* strides * (input_size-1) + kernel_size - 2*padding */ + //TODO: This is wrong, also depends on convolutionMode, etc ... + /*l.nOut = l.getStride()[0] * (l.getNIn()-1) + + IntStream.of(l.getKernelSize()).reduce(1, (a,b) -> a*b) + - 2L * IntStream.of(l.getPadding()).sum(); + */ + //l.nOut =264; l.initializeConstraints(); return l; } diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/LayerConfiguration.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/LayerConfiguration.java index 5c04fa32c..11a1b6f30 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/LayerConfiguration.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/layers/LayerConfiguration.java @@ -62,6 +62,7 @@ public abstract class LayerConfiguration implements ILayerConfiguration, Serializable, Cloneable { // ITrainableLayerConfiguration @Getter @Setter protected String name; + @Getter @Setter private int index; @Getter @Setter protected List allParamConstraints; @Getter @Setter protected List weightConstraints; @Getter @Setter protected List biasConstraints; @@ -72,6 +73,7 @@ public abstract class LayerConfiguration /** The type of the layer, basically defines the base class and its properties */ @Builder.Default @Getter @Setter @NonNull private LayerType type = LayerType.UNKNOWN; + /** * Number of parameters this layer has a result of its configuration * @return number or parameters @@ -80,7 +82,6 @@ public abstract class LayerConfiguration return initializer().numParams(this); } - /** * A reference to the neural net configuration. This field is excluded from json serialization as * well as from equals check to avoid circular referenced. diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/preprocessor/FeedForwardToCnnPreProcessor.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/preprocessor/FeedForwardToCnnPreProcessor.java index 810ae513a..1bf3c6392 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/preprocessor/FeedForwardToCnnPreProcessor.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/conf/preprocessor/FeedForwardToCnnPreProcessor.java @@ -37,122 +37,166 @@ import org.nd4j.linalg.api.shape.Shape; @Data @EqualsAndHashCode(exclude = {"shape"}) public class FeedForwardToCnnPreProcessor implements InputPreProcessor { - private long inputHeight; - private long inputWidth; - private long numChannels; + private long inputHeight; + private long inputWidth; + private long numChannels; - @Getter(AccessLevel.NONE) - @Setter(AccessLevel.NONE) - private long[] shape; + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private long[] shape; - /** - * Reshape to a channels x rows x columns tensor - * - * @param inputHeight the columns - * @param inputWidth the rows - * @param numChannels the channels - */ - @JsonCreator - public FeedForwardToCnnPreProcessor(@JsonProperty("inputHeight") long inputHeight, - @JsonProperty("inputWidth") long inputWidth, @JsonProperty("numChannels") long numChannels) { - this.inputHeight = inputHeight; - this.inputWidth = inputWidth; - this.numChannels = numChannels; + /** + * Reshape to a channels x rows x columns tensor + * + * @param inputHeight the columns + * @param inputWidth the rows + * @param numChannels the channels + */ + @JsonCreator + public FeedForwardToCnnPreProcessor( + @JsonProperty("inputHeight") long inputHeight, + @JsonProperty("inputWidth") long inputWidth, + @JsonProperty("numChannels") long numChannels) { + this.inputHeight = inputHeight; + this.inputWidth = inputWidth; + this.numChannels = numChannels; + } + /** + * Reshape to a channels x rows x columns tensor + * + * @param inputHeight the columns + * @param inputWidth the rows + */ + public FeedForwardToCnnPreProcessor(long inputWidth, long inputHeight) { + this.inputHeight = inputHeight; + this.inputWidth = inputWidth; + this.numChannels = 1; + } + + @Override + public INDArray preProcess(INDArray input, int miniBatchSize, LayerWorkspaceMgr workspaceMgr) { + this.shape = input.shape(); + if (input.rank() == 4) return workspaceMgr.leverageTo(ArrayType.ACTIVATIONS, input); + + if (input.columns() != inputWidth * inputHeight * numChannels) + throw new IllegalArgumentException( + "Invalid input: expect output columns must be equal to rows " + + inputHeight + + " x columns " + + inputWidth + + " x channels " + + numChannels + + " but was instead " + + Arrays.toString(input.shape())); + + if (input.ordering() != 'c' || !Shape.hasDefaultStridesForShape(input)) + input = workspaceMgr.dup(ArrayType.ACTIVATIONS, input, 'c'); + + return workspaceMgr.leverageTo( + ArrayType.ACTIVATIONS, + input.reshape('c', input.size(0), numChannels, inputHeight, inputWidth)); + } + + @Override + // return 4 dimensions + public INDArray backprop(INDArray epsilons, int miniBatchSize, LayerWorkspaceMgr workspaceMgr) { + if (epsilons.ordering() != 'c' || !Shape.hasDefaultStridesForShape(epsilons)) + epsilons = workspaceMgr.dup(ArrayType.ACTIVATION_GRAD, epsilons, 'c'); + + if (shape == null || ArrayUtil.prod(shape) != epsilons.length()) { + if (epsilons.rank() == 2) + return workspaceMgr.leverageTo(ArrayType.ACTIVATION_GRAD, epsilons); // should never happen + + return epsilons.reshape('c', epsilons.size(0), numChannels, inputHeight, inputWidth); } - public FeedForwardToCnnPreProcessor(long inputWidth, long inputHeight) { - this.inputHeight = inputHeight; - this.inputWidth = inputWidth; - this.numChannels = 1; + return workspaceMgr.leverageTo(ArrayType.ACTIVATION_GRAD, epsilons.reshape('c', shape)); + } + + @Override + public FeedForwardToCnnPreProcessor clone() { + try { + FeedForwardToCnnPreProcessor clone = (FeedForwardToCnnPreProcessor) super.clone(); + if (clone.shape != null) clone.shape = clone.shape.clone(); + return clone; + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); } + } - @Override - public INDArray preProcess(INDArray input, int miniBatchSize, LayerWorkspaceMgr workspaceMgr) { - this.shape = input.shape(); - if (input.rank() == 4) - return workspaceMgr.leverageTo(ArrayType.ACTIVATIONS, input); + @Override + public InputType getOutputType(InputType inputType) { - if (input.columns() != inputWidth * inputHeight * numChannels) - throw new IllegalArgumentException("Invalid input: expect output columns must be equal to rows " - + inputHeight + " x columns " + inputWidth + " x channels " + numChannels - + " but was instead " + Arrays.toString(input.shape())); - - if (input.ordering() != 'c' || !Shape.hasDefaultStridesForShape(input)) - input = workspaceMgr.dup(ArrayType.ACTIVATIONS, input, 'c'); - - return workspaceMgr.leverageTo(ArrayType.ACTIVATIONS, - input.reshape('c', input.size(0), numChannels, inputHeight, inputWidth)); - } - - @Override - // return 4 dimensions - public INDArray backprop(INDArray epsilons, int miniBatchSize, LayerWorkspaceMgr workspaceMgr) { - if (epsilons.ordering() != 'c' || !Shape.hasDefaultStridesForShape(epsilons)) - epsilons = workspaceMgr.dup(ArrayType.ACTIVATION_GRAD, epsilons, 'c'); - - if (shape == null || ArrayUtil.prod(shape) != epsilons.length()) { - if (epsilons.rank() == 2) - return workspaceMgr.leverageTo(ArrayType.ACTIVATION_GRAD, epsilons); //should never happen - - return epsilons.reshape('c', epsilons.size(0), numChannels, inputHeight, inputWidth); + switch (inputType.getType()) { + case FF: + InputType.InputTypeFeedForward c = (InputType.InputTypeFeedForward) inputType; + val expSize = inputHeight * inputWidth * numChannels; + if (c.getSize() != expSize) { + throw new IllegalStateException( + "Invalid input: expected FeedForward input of size " + + expSize + + " = (d=" + + numChannels + + " * w=" + + inputWidth + + " * h=" + + inputHeight + + "), got " + + inputType); } + return InputType.convolutional(inputHeight, inputWidth, numChannels); + case CNN: + InputType.InputTypeConvolutional c2 = (InputType.InputTypeConvolutional) inputType; - return workspaceMgr.leverageTo(ArrayType.ACTIVATION_GRAD, epsilons.reshape('c', shape)); - } - - - @Override - public FeedForwardToCnnPreProcessor clone() { - try { - FeedForwardToCnnPreProcessor clone = (FeedForwardToCnnPreProcessor) super.clone(); - if (clone.shape != null) - clone.shape = clone.shape.clone(); - return clone; - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); + if (c2.getChannels() != numChannels + || c2.getHeight() != inputHeight + || c2.getWidth() != inputWidth) { + throw new IllegalStateException( + "Invalid input: Got CNN input type with (d,w,h)=(" + + c2.getChannels() + + "," + + c2.getWidth() + + "," + + c2.getHeight() + + ") but expected (" + + numChannels + + "," + + inputHeight + + "," + + inputWidth + + ")"); } - } - - @Override - public InputType getOutputType(InputType inputType) { - - switch (inputType.getType()) { - case FF: - InputType.InputTypeFeedForward c = (InputType.InputTypeFeedForward) inputType; - val expSize = inputHeight * inputWidth * numChannels; - if (c.getSize() != expSize) { - throw new IllegalStateException("Invalid input: expected FeedForward input of size " + expSize - + " = (d=" + numChannels + " * w=" + inputWidth + " * h=" + inputHeight + "), got " - + inputType); - } - return InputType.convolutional(inputHeight, inputWidth, numChannels); - case CNN: - InputType.InputTypeConvolutional c2 = (InputType.InputTypeConvolutional) inputType; - - if (c2.getChannels() != numChannels || c2.getHeight() != inputHeight || c2.getWidth() != inputWidth) { - throw new IllegalStateException("Invalid input: Got CNN input type with (d,w,h)=(" + c2.getChannels() - + "," + c2.getWidth() + "," + c2.getHeight() + ") but expected (" + numChannels - + "," + inputHeight + "," + inputWidth + ")"); - } - return c2; - case CNNFlat: - InputType.InputTypeConvolutionalFlat c3 = (InputType.InputTypeConvolutionalFlat) inputType; - if (c3.getDepth() != numChannels || c3.getHeight() != inputHeight || c3.getWidth() != inputWidth) { - throw new IllegalStateException("Invalid input: Got CNN input type with (d,w,h)=(" + c3.getDepth() - + "," + c3.getWidth() + "," + c3.getHeight() + ") but expected (" + numChannels - + "," + inputHeight + "," + inputWidth + ")"); - } - return c3.getUnflattenedType(); - default: - throw new IllegalStateException("Invalid input type: got " + inputType); + return c2; + case CNNFlat: + InputType.InputTypeConvolutionalFlat c3 = (InputType.InputTypeConvolutionalFlat) inputType; + if (c3.getDepth() != numChannels + || c3.getHeight() != inputHeight + || c3.getWidth() != inputWidth) { + throw new IllegalStateException( + "Invalid input: Got CNN input type with (d,w,h)=(" + + c3.getDepth() + + "," + + c3.getWidth() + + "," + + c3.getHeight() + + ") but expected (" + + numChannels + + "," + + inputHeight + + "," + + inputWidth + + ")"); } + return c3.getUnflattenedType(); + default: + throw new IllegalStateException("Invalid input type: got " + inputType); } + } - @Override - public Pair feedForwardMaskArray(INDArray maskArray, MaskState currentMaskState, - int minibatchSize) { - //Pass-through, unmodified (assuming here that it's a 1d mask array - one value per example) - return new Pair<>(maskArray, currentMaskState); - } - + @Override + public Pair feedForwardMaskArray( + INDArray maskArray, MaskState currentMaskState, int minibatchSize) { + // Pass-through, unmodified (assuming here that it's a 1d mask array - one value per example) + return new Pair<>(maskArray, currentMaskState); + } } diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/AbstractLayer.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/AbstractLayer.java index 006b87250..707d995d9 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/AbstractLayer.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/AbstractLayer.java @@ -369,7 +369,7 @@ public abstract class AbstractLayer impl protected String layerId() { String name = this.layerConfiguration.getName(); - return "(layer name: " + return "(network: " + getNetConfiguration().getName() + " layer name: " + (name == null ? "\"\"" : name) + ", layer index: " + index diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/convolution/Deconvolution2DLayer.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/convolution/Deconvolution2DLayer.java index 0761a1189..3b3032151 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/convolution/Deconvolution2DLayer.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/layers/convolution/Deconvolution2DLayer.java @@ -101,8 +101,8 @@ public class Deconvolution2DLayer extends ConvolutionLayer { int[] args = new int[] { (int)kH, (int)kW, strides[0], strides[1], - pad[0], pad[1], dilation[0], dilation[1], sameMode, - nchw ? 0 : 1 //0 = NCHW; 1 = NHWC + pad[0], pad[1], dilation[0], dilation[1], sameMode //, + //nchw ? 0 : 1 //0 = NCHW; 1 = NHWC }; INDArray delta; @@ -224,8 +224,8 @@ public class Deconvolution2DLayer extends ConvolutionLayer { int[] args = new int[] { kH, kW, strides[0], strides[1], - pad[0], pad[1], dilation[0], dilation[1], sameMode, - nchw ? 0 : 1 //0 = NCHW; 1 = NHWC + pad[0], pad[1], dilation[0], dilation[1], sameMode //, + //nchw ? 0 : 1 //0 = NCHW; 1 = NHWC }; //DL4J Deconv weights: [inputDepth, outputDepth, kH, kW] @@ -238,6 +238,20 @@ public class Deconvolution2DLayer extends ConvolutionLayer { } else { opInputs = new INDArray[]{input, weights}; } + /** + * 2D deconvolution implementation + * + * IntArgs: + * 0: kernel height + * 1: kernel width + * 2: stride height + * 3: stride width + * 4: padding height + * 5: padding width + * 6: dilation height + * 7: dilation width + * 8: same mode: 0 false, 1 true + */ CustomOp op = DynamicCustomOp.builder("deconv2d") .addInputs(opInputs) .addIntegerArguments(args) diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/multilayer/MultiLayerNetwork.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/multilayer/MultiLayerNetwork.java index 7cc08a62d..9ce05fb9f 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/multilayer/MultiLayerNetwork.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/multilayer/MultiLayerNetwork.java @@ -773,7 +773,7 @@ public class MultiLayerNetwork extends ArtificialNeuralNetwork LayerConfiguration lc = getNetConfiguration().getFlattenedLayerConfigurations().get(i); layers[i] = lc.instantiate( - lc.getNetConfiguration(), + this.getNetConfiguration(), trainingListeners, i, paramsView, diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/BatchNormalizationParamInitializer.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/BatchNormalizationParamInitializer.java index 3538960d1..8769b3e39 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/BatchNormalizationParamInitializer.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/BatchNormalizationParamInitializer.java @@ -101,8 +101,10 @@ public class BatchNormalizationParamInitializer extends AbstractParamInitializer params.put(GAMMA, createGamma(conf, gammaView, initializeParams)); conf.getNetConfiguration().addNetWideVariable(GAMMA); + conf.addVariable(GAMMA); params.put(BETA, createBeta(conf, betaView, initializeParams)); conf.getNetConfiguration().addNetWideVariable(BETA); + conf.addVariable(BETA); meanOffset = 2 * nOut; } @@ -125,12 +127,15 @@ public class BatchNormalizationParamInitializer extends AbstractParamInitializer params.put(GLOBAL_MEAN, globalMeanView); conf.getNetConfiguration().addNetWideVariable(GLOBAL_MEAN); + conf.addVariable(GLOBAL_MEAN); if(layer.isUseLogStd()){ params.put(GLOBAL_LOG_STD, globalVarView); conf.getNetConfiguration().addNetWideVariable(GLOBAL_LOG_STD); + conf.addVariable(GLOBAL_LOG_STD); } else { params.put(GLOBAL_VAR, globalVarView); conf.getNetConfiguration().addNetWideVariable(GLOBAL_VAR); + conf.addVariable(GLOBAL_VAR); } return params; diff --git a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/ConvolutionParamInitializer.java b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/ConvolutionParamInitializer.java index a0d9bea82..9ad41df57 100644 --- a/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/ConvolutionParamInitializer.java +++ b/cavis-dnn/cavis-dnn-nn/src/main/java/org/deeplearning4j/nn/params/ConvolutionParamInitializer.java @@ -114,11 +114,13 @@ public class ConvolutionParamInitializer extends AbstractParamInitializer { params.put(WEIGHT_KEY, createWeightMatrix(conf, weightView, initializeParams)); conf.getNetConfiguration().addNetWideVariable(WEIGHT_KEY); conf.getNetConfiguration().addNetWideVariable(BIAS_KEY); - conf.getNetConfiguration().addNetWideVariable(BIAS_KEY); + conf.addVariable(WEIGHT_KEY); + conf.addVariable(BIAS_KEY); } else { INDArray weightView = paramsView; params.put(WEIGHT_KEY, createWeightMatrix(conf, weightView, initializeParams)); conf.getNetConfiguration().addNetWideVariable(WEIGHT_KEY); + conf.addVariable(WEIGHT_KEY); } return params; diff --git a/gradle.properties b/gradle.properties index ef0384eee..c6ceae50d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,7 +34,7 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true #for whatever reason we had to add MaxMetaspace and file encoding = utf8, gradle crashed otherwise org.gradle.jvmargs=-Xmx8192m -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:ErrorFile=/var/log/java/hs_err_pid%p.log - +#-DsocksProxyHost=sshtunnel -DsocksProxyPort=8888 -Djava.net.preferIPv4Stack=true # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832f090a2944b7473328c07c9755baa3196..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 9308 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 delta 10197 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 '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -APP_HOME=$(cd "${APP_HOME:-./}" && pwd -P) || exit +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" APP_BASE_NAME=${0##*/} @@ -91,15 +91,15 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum -warn() { - echo "$*" +warn () { + echo "$*" } >&2 -die() { - echo - echo "$*" - echo - exit 1 +die () { + echo + echo "$*" + echo + exit 1 } >&2 # OS specific support (must be 'true' or 'false'). @@ -107,52 +107,51 @@ cygwin=false msys=false darwin=false nonstop=false -case "$(uname)" in #( -CYGWIN*) cygwin=true ;; #( -Darwin*) darwin=true ;; #( -MSYS* | MINGW*) msys=true ;; #( -NONSTOP*) nonstop=true ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ]; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi + fi else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop"; then - case $MAX_FD in #( - max*) - MAX_FD=$(ulimit -H -n) || - warn "Could not query maximum file descriptor limit" - ;; - esac - case $MAX_FD in #( - '' | soft) : ;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - ;; - esac +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi # Collect all arguments for the java command, stacking in reverse order: @@ -164,36 +163,34 @@ fi # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys"; then - APP_HOME=$(cygpath --path --mixed "$APP_HOME") - CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - JAVACMD=$(cygpath --unix "$JAVACMD") + JAVACMD=$( cygpath --unix "$JAVACMD" ) - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg; do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) - t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] - ;; #( - *) false ;; - esac - then - arg=$(cygpath --path --ignore --mixed "$arg") - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done fi # Collect all arguments for the java command; @@ -203,15 +200,10 @@ fi # * put everything else in single quotes, so that it's not re-expanded. set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1; then - die "xargs is not available" -fi + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" # Use "xargs" to parse quoted args. # @@ -233,10 +225,10 @@ fi # eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' -)" '"$@"' + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f127cfd49..107acd32c 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%"=="" @echo off +@if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. +if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,15 +75,13 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd +if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal