diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasModel.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasModel.java index 3eff2864a553..b054ba8a176d 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasModel.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasModel.java @@ -153,7 +153,7 @@ protected KerasModel(String modelJson, String modelYaml, Hdf5Archive weightsArch prepareLayers((List) layerLists.get((config.getModelFieldLayers()))); /* Import training configuration. */ - if (trainingJson != null) + if (trainingJson != null && enforceTrainingConfig) importTrainingConfiguration(trainingJson); /* Infer output types for each layer. */ diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java index 4b5c5faa4843..37e77177eb0d 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/KerasSequentialModel.java @@ -118,7 +118,7 @@ public KerasSequentialModel(String modelJson, String modelYaml, Hdf5Archive weig } /* Import training configuration. */ - if (trainingJson != null) + if (trainingJson != null && enforceTrainingConfig) importTrainingConfiguration(trainingJson); /* Infer output types for each layer. */ diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras1LayerConfiguration.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras1LayerConfiguration.java index 6f8c8ef26e75..736d35329040 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras1LayerConfiguration.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras1LayerConfiguration.java @@ -76,7 +76,7 @@ public class Keras1LayerConfiguration extends KerasLayerConfiguration { /* Pooling / Upsampling layer properties */ private final String LAYER_FIELD_POOL_1D_SIZE = "pool_length"; private final String LAYER_FIELD_POOL_1D_STRIDES = "stride"; - private final String LAYER_FIELD_UPSAMPLING_SIZE = "length"; + private final String LAYER_FIELD_UPSAMPLING_1D_SIZE = "length"; /* Keras convolution border modes. */ private final String LAYER_FIELD_BORDER_MODE = "border_mode"; diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras2LayerConfiguration.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras2LayerConfiguration.java index c8cfa67e2e86..8479b467179c 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras2LayerConfiguration.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/Keras2LayerConfiguration.java @@ -74,7 +74,7 @@ public class Keras2LayerConfiguration extends KerasLayerConfiguration { /* Pooling / Upsampling layer properties */ private final String LAYER_FIELD_POOL_1D_SIZE = "pool_size"; private final String LAYER_FIELD_POOL_1D_STRIDES = "strides"; - private final String LAYER_FIELD_UPSAMPLING_SIZE = "size"; + private final String LAYER_FIELD_UPSAMPLING_1D_SIZE = "size"; /* Keras convolution border modes. */ private final String LAYER_FIELD_BORDER_MODE = "padding"; diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/KerasLayerConfiguration.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/KerasLayerConfiguration.java index 5c9d76188f46..f201507cbeaa 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/KerasLayerConfiguration.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/config/KerasLayerConfiguration.java @@ -67,6 +67,7 @@ public class KerasLayerConfiguration { private final String LAYER_CLASS_NAME_CONVOLUTION_1D = ""; // 1: Convolution1D, 2: Conv1D private final String LAYER_CLASS_NAME_CONVOLUTION_2D = ""; // 1: Convolution2D, 2: Conv2D private final String LAYER_CLASS_NAME_LEAKY_RELU = "LeakyReLU"; + private final String LAYER_CLASS_NAME_UPSAMPLING_2D = "UpSampling2D"; /* Partially shared layer configurations. */ @@ -140,7 +141,9 @@ public class KerasLayerConfiguration { private final String LAYER_FIELD_POOL_STRIDES = "strides"; private final String LAYER_FIELD_POOL_1D_SIZE = ""; // 1: pool_length, 2: pool_size private final String LAYER_FIELD_POOL_1D_STRIDES = ""; // 1: stride, 2: strides - private final String LAYER_FIELD_UPSAMPLING_SIZE = ""; // 1: length, 2: size + private final String LAYER_FIELD_UPSAMPLING_1D_SIZE = ""; // 1: length, 2: size + private final String LAYER_FIELD_UPSAMPLING_2D_SIZE = "size"; + /* Keras convolution border modes. */ private final String LAYER_FIELD_BORDER_MODE = ""; // 1: border_mode, 2: padding diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/KerasLoss.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/KerasLoss.java index b63c8f9747d3..59125b1bf68c 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/KerasLoss.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/KerasLoss.java @@ -69,10 +69,6 @@ public KerasLoss(String layerName, String inboundLayerName, String kerasLoss, bo this.layer = new LossLayer.Builder(loss).name(layerName).build(); } -// private KerasLoss(Map layerConfig) {} -// -// private KerasLoss(Map layerConfig, boolean enforceTrainingConfig) {} - /** * Get DL4J LossLayer. * diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/convolutional/KerasConvolutionUtils.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/convolutional/KerasConvolutionUtils.java index 6fdf7d81bc57..8b6d598dc8a4 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/convolutional/KerasConvolutionUtils.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/convolutional/KerasConvolutionUtils.java @@ -106,6 +106,33 @@ public static int[] getDilationRate(Map layerConfig, int dimensi } + /** + * Get upsampling size from Keras layer configuration. + * + * @param layerConfig dictionary containing Keras layer configuration + * @return + * @throws InvalidKerasConfigurationException + */ + public static int[] getUpsamplingSizeFromConfig(Map layerConfig, int dimension, + KerasLayerConfiguration conf) + throws InvalidKerasConfigurationException { + Map innerConfig = KerasLayerUtils.getInnerLayerConfigFromConfig(layerConfig, conf); + int[] size; + if (innerConfig.containsKey(conf.getLAYER_FIELD_UPSAMPLING_2D_SIZE()) && dimension == 2) { + List sizeList = (List) innerConfig.get(conf.getLAYER_FIELD_UPSAMPLING_2D_SIZE()); + size = ArrayUtil.toArray(sizeList); + } else if (innerConfig.containsKey(conf.getLAYER_FIELD_UPSAMPLING_1D_SIZE()) && dimension == 1) { + int upsamplingSize1D = (int) innerConfig.get(conf.getLAYER_FIELD_UPSAMPLING_1D_SIZE()); + size = new int[]{ upsamplingSize1D }; + } else { + throw new InvalidKerasConfigurationException("Could not determine kernel size: no " + + conf.getLAYER_FIELD_UPSAMPLING_1D_SIZE() + ", " + + conf.getLAYER_FIELD_UPSAMPLING_2D_SIZE()); + } + return size; + } + + /** * Get (convolution) kernel size from Keras layer configuration. diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/convolutional/KerasUpsampling2D.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/convolutional/KerasUpsampling2D.java new file mode 100644 index 000000000000..17d631554f24 --- /dev/null +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/convolutional/KerasUpsampling2D.java @@ -0,0 +1,98 @@ +/*- + * + * * Copyright 2017 Skymind,Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * 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. + * + */ +package org.deeplearning4j.nn.modelimport.keras.layers.convolutional; + +import org.deeplearning4j.nn.conf.inputs.InputType; +import org.deeplearning4j.nn.conf.layers.Upsampling2D; +import org.deeplearning4j.nn.modelimport.keras.KerasLayer; +import org.deeplearning4j.nn.modelimport.keras.exceptions.InvalidKerasConfigurationException; +import org.deeplearning4j.nn.modelimport.keras.exceptions.UnsupportedKerasConfigurationException; + +import java.util.Map; + + +/** + * Keras Upsampling2D layer support + * + * @author Max Pumperla + */ +public class KerasUpsampling2D extends KerasLayer { + + /** + * Constructor from parsed Keras layer configuration dictionary. + * + * @param layerConfig dictionary containing Keras layer configuration. + * @throws InvalidKerasConfigurationException Invalid Keras configuration exception + * @throws UnsupportedKerasConfigurationException Unsupported Keras configuration exception + */ + public KerasUpsampling2D(Map layerConfig) + throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { + this(layerConfig, true); + } + + /** + * Constructor from parsed Keras layer configuration dictionary. + * + * @param layerConfig dictionary containing Keras layer configuration + * @param enforceTrainingConfig whether to enforce training-related configuration options + * @throws InvalidKerasConfigurationException Invalid Keras configuration exception + * @throws UnsupportedKerasConfigurationException Invalid Keras configuration exception + */ + public KerasUpsampling2D(Map layerConfig, boolean enforceTrainingConfig) + throws InvalidKerasConfigurationException, UnsupportedKerasConfigurationException { + super(layerConfig, enforceTrainingConfig); + + int[] size = KerasConvolutionUtils.getUpsamplingSizeFromConfig(layerConfig, 2, conf); + if (size[0] != size[1]) + throw new UnsupportedKerasConfigurationException("First and second size arguments have to be the same" + + "got: " + size[0] + " and " + size[1]); + + Upsampling2D.Builder builder = new Upsampling2D.Builder() + .name(this.layerName) + .dropOut(this.dropout) + .size(size[0]); + + this.layer = builder.build(); + this.vertex = null; + } + + /** + * Get DL4J Upsampling2D layer. + * + * @return Upsampling2D layer + */ + public Upsampling2D getUpsampling2DLayer() { + return (Upsampling2D) this.layer; + } + + /** + * Get layer output type. + * + * @param inputType Array of InputTypes + * @return output type as InputType + * @throws InvalidKerasConfigurationException + */ + @Override + public InputType getOutputType(InputType... inputType) throws InvalidKerasConfigurationException { + if (inputType.length > 1) + throw new InvalidKerasConfigurationException( + "Keras Subsampling layer accepts only one input (received " + inputType.length + ")"); + return this.getUpsampling2DLayer().getOutputType(-1, inputType[0]); + } + +} diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasGlobalPooling.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasGlobalPooling.java index 8e15467ddffb..54598ccec4da 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasGlobalPooling.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasGlobalPooling.java @@ -1,3 +1,20 @@ +/*- + * + * * Copyright 2017 Skymind,Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * 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. + * + */ package org.deeplearning4j.nn.modelimport.keras.layers.pooling; import lombok.Data; diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling1D.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling1D.java index 1b54ab0f01db..666439c72cce 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling1D.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling1D.java @@ -1,3 +1,20 @@ +/*- + * + * * Copyright 2017 Skymind,Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * 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. + * + */ package org.deeplearning4j.nn.modelimport.keras.layers.pooling; import lombok.extern.slf4j.Slf4j; diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling2D.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling2D.java index 7fc76a933037..a65b85d8d0ea 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling2D.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/layers/pooling/KerasPooling2D.java @@ -1,3 +1,20 @@ +/*- + * + * * Copyright 2017 Skymind,Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * 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. + * + */ package org.deeplearning4j.nn.modelimport.keras.layers.pooling; import lombok.extern.slf4j.Slf4j; diff --git a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/utils/KerasLayerUtils.java b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/utils/KerasLayerUtils.java index b89dffb98043..490e8c9064cf 100644 --- a/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/utils/KerasLayerUtils.java +++ b/deeplearning4j-modelimport/src/main/java/org/deeplearning4j/nn/modelimport/keras/utils/KerasLayerUtils.java @@ -212,6 +212,8 @@ public static KerasLayer getKerasLayerFromConfig(Map layerConfig layer = new KerasReshape(layerConfig, enforceTrainingConfig); } else if (layerClassName.equals(conf.getLAYER_CLASS_NAME_ZERO_PADDING_2D())) { layer = new KerasZeroPadding2D(layerConfig, enforceTrainingConfig); + } else if (layerClassName.equals(conf.getLAYER_CLASS_NAME_UPSAMPLING_2D())) { + layer = new KerasUpsampling2D(layerConfig, enforceTrainingConfig); } else { // check if user registered a custom config Class customConfig = customLayers.get(layerClassName); diff --git a/deeplearning4j-modelimport/src/test/java/org/deeplearning4j/nn/modelimport/keras/e2e/KerasModelEndToEndTest.java b/deeplearning4j-modelimport/src/test/java/org/deeplearning4j/nn/modelimport/keras/e2e/KerasModelEndToEndTest.java index 8a69100c744e..84e9b89ae4eb 100644 --- a/deeplearning4j-modelimport/src/test/java/org/deeplearning4j/nn/modelimport/keras/e2e/KerasModelEndToEndTest.java +++ b/deeplearning4j-modelimport/src/test/java/org/deeplearning4j/nn/modelimport/keras/e2e/KerasModelEndToEndTest.java @@ -195,6 +195,30 @@ public void importCnnNoBiasTfKeras2() throws Exception { importEndModelTest(modelPath, inputsOutputPath, true, false); } + /** + * DCGAN import test + */ + @Test + public void importDcganDiscriminator() throws Exception { + importModelH5Test("modelimport/keras/examples/mnist_dcgan/dcgan_discriminator_epoch_50.h5"); + } + @Test + public void importDcganGenerator() throws Exception { + importModelH5Test("modelimport/keras/examples/mnist_dcgan/dcgan_generator_epoch_50.h5"); + } + + + void importModelH5Test(String modelPath) throws Exception { + ClassPathResource modelResource = + new ClassPathResource(modelPath, + KerasModelEndToEndTest.class.getClassLoader()); + File modelFile = File.createTempFile(TEMP_MODEL_FILENAME, H5_EXTENSION); + Files.copy(modelResource.getInputStream(), modelFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + MultiLayerNetwork model = new KerasModel().modelBuilder().modelHdf5Filename(modelFile.getAbsolutePath()) + .enforceTrainingConfig(false).buildSequential().getMultiLayerNetwork(); + } + + void importEndModelTest(String modelPath, String inputsOutputsPath, boolean tfOrdering, boolean checkPredictions) throws Exception { ClassPathResource modelResource = new ClassPathResource(modelPath, diff --git a/deeplearning4j-modelimport/src/test/java/org/deeplearning4j/nn/modelimport/keras/layers/convolution/KerasUpsampling2DTest.java b/deeplearning4j-modelimport/src/test/java/org/deeplearning4j/nn/modelimport/keras/layers/convolution/KerasUpsampling2DTest.java new file mode 100644 index 000000000000..ddac2e7e6c5b --- /dev/null +++ b/deeplearning4j-modelimport/src/test/java/org/deeplearning4j/nn/modelimport/keras/layers/convolution/KerasUpsampling2DTest.java @@ -0,0 +1,73 @@ +/*- + * + * * Copyright 2017 Skymind,Inc. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * 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. + * + */ +package org.deeplearning4j.nn.modelimport.keras.layers.convolution; + +import org.deeplearning4j.nn.conf.layers.Upsampling2D; +import org.deeplearning4j.nn.conf.layers.ZeroPadding1DLayer; +import org.deeplearning4j.nn.modelimport.keras.config.Keras1LayerConfiguration; +import org.deeplearning4j.nn.modelimport.keras.config.Keras2LayerConfiguration; +import org.deeplearning4j.nn.modelimport.keras.config.KerasLayerConfiguration; +import org.deeplearning4j.nn.modelimport.keras.layers.convolutional.KerasUpsampling2D; +import org.deeplearning4j.nn.modelimport.keras.layers.convolutional.KerasZeroPadding1D; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * @author Max Pumperla + */ +public class KerasUpsampling2DTest { + + private final String LAYER_NAME = "upsampling_2D_layer"; + private int[] size = new int[] {2, 2}; + + private Integer keras1 = 1; + private Integer keras2 = 2; + private Keras1LayerConfiguration conf1 = new Keras1LayerConfiguration(); + private Keras2LayerConfiguration conf2 = new Keras2LayerConfiguration(); + + @Test + public void testUpsampling2DLayer() throws Exception { + buildUpsampling2DLayer(conf1, keras1); + buildUpsampling2DLayer(conf2, keras2); + } + + + public void buildUpsampling2DLayer(KerasLayerConfiguration conf, Integer kerasVersion) throws Exception { + Map layerConfig = new HashMap<>(); + layerConfig.put(conf.getLAYER_FIELD_CLASS_NAME(), conf.getLAYER_CLASS_NAME_MAX_POOLING_1D()); + Map config = new HashMap<>(); + List sizeList = new ArrayList<>(); + sizeList.add(size[0]); + sizeList.add(size[1]); + config.put(conf.getLAYER_FIELD_UPSAMPLING_2D_SIZE(), sizeList); + config.put(conf.getLAYER_FIELD_NAME(), LAYER_NAME); + layerConfig.put(conf.getLAYER_FIELD_CONFIG(), config); + layerConfig.put(conf.getLAYER_FIELD_KERAS_VERSION(), kerasVersion); + + Upsampling2D layer = new KerasUpsampling2D(layerConfig).getUpsampling2DLayer(); + assertEquals(LAYER_NAME, layer.getLayerName()); + assertEquals(size[0], layer.getSize()); + } + +}