parent
8d73a7a410
commit
0bed17c97f
|
@ -45,6 +45,7 @@ import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
|
|||
import org.deeplearning4j.nn.conf.layers.*;
|
||||
import org.deeplearning4j.nn.conf.layers.variational.BernoulliReconstructionDistribution;
|
||||
import org.deeplearning4j.nn.conf.layers.variational.VariationalAutoencoder;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
|
||||
import org.deeplearning4j.nn.weights.WeightInit;
|
||||
import org.deeplearning4j.optimize.api.BaseTrainingListener;
|
||||
|
@ -924,8 +925,8 @@ public class TestEarlyStopping extends BaseDL4JTest {
|
|||
};
|
||||
|
||||
for(EpochTerminationCondition e : etc ){
|
||||
String s = NeuralNetConfiguration.mapper().writeValueAsString(e);
|
||||
EpochTerminationCondition c = NeuralNetConfiguration.mapper().readValue(s, EpochTerminationCondition.class);
|
||||
String s = CavisMapper.getMapper(CavisMapper.Type.JSON).writeValueAsString(e);
|
||||
EpochTerminationCondition c = CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(s, EpochTerminationCondition.class);
|
||||
assertEquals(e, c);
|
||||
}
|
||||
|
||||
|
@ -936,8 +937,8 @@ public class TestEarlyStopping extends BaseDL4JTest {
|
|||
};
|
||||
|
||||
for(IterationTerminationCondition i : itc ){
|
||||
String s = NeuralNetConfiguration.mapper().writeValueAsString(i);
|
||||
IterationTerminationCondition c = NeuralNetConfiguration.mapper().readValue(s, IterationTerminationCondition.class);
|
||||
String s = CavisMapper.getMapper(CavisMapper.Type.JSON).writeValueAsString(i);
|
||||
IterationTerminationCondition c = CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(s, IterationTerminationCondition.class);
|
||||
assertEquals(i, c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ public class CNN3DGradientCheckTest extends BaseDL4JTest {
|
|||
|
||||
NeuralNetConfiguration conf = NeuralNetConfiguration.builder()
|
||||
.dataType(DataType.DOUBLE)
|
||||
.updater(new NoOp()).weightInit(WeightInit.LECUN_NORMAL)
|
||||
.updater(new NoOp())
|
||||
.dist(new NormalDistribution(0, 1))
|
||||
.layer(0, Convolution3D.builder().activation(afn).kernelSize(kernel)
|
||||
.stride(stride).nIn(convNIn).nOut(convNOut1).hasBias(false)
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.deeplearning4j.nn.conf.distribution.UniformDistribution;
|
|||
import org.deeplearning4j.nn.conf.layers.DenseLayer;
|
||||
import org.deeplearning4j.nn.conf.layers.LossLayer;
|
||||
import org.deeplearning4j.nn.conf.layers.OutputLayer;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.nd4j.linalg.activations.Activation;
|
||||
|
@ -336,7 +337,7 @@ public class LossFunctionGradientCheck extends BaseDL4JTest {
|
|||
// to ensure that we carry the parameters through
|
||||
// the serializer.
|
||||
try{
|
||||
ObjectMapper m = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper m = CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
String s = m.writeValueAsString(lossFunctions[i]);
|
||||
ILossFunction lf2 = m.readValue(s, lossFunctions[i].getClass());
|
||||
lossFunctions[i] = lf2;
|
||||
|
|
|
@ -23,6 +23,7 @@ package org.deeplearning4j.regressiontest;
|
|||
import org.deeplearning4j.BaseDL4JTest;
|
||||
import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
|
||||
import org.deeplearning4j.nn.conf.distribution.*;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
@ -38,7 +39,7 @@ public class TestDistributionDeserializer extends BaseDL4JTest {
|
|||
new Distribution[] {new NormalDistribution(3, 0.5), new UniformDistribution(-2, 1),
|
||||
new GaussianDistribution(2, 1.0), new BinomialDistribution(10, 0.3)};
|
||||
|
||||
ObjectMapper om = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper om = CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
|
||||
for (Distribution d : distributions) {
|
||||
String json = om.writeValueAsString(d);
|
||||
|
@ -50,7 +51,7 @@ public class TestDistributionDeserializer extends BaseDL4JTest {
|
|||
|
||||
@Test
|
||||
public void testDistributionDeserializerLegacyFormat() throws Exception {
|
||||
ObjectMapper om = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper om = CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
|
||||
String normalJson = "{\n" + " \"normal\" : {\n" + " \"mean\" : 0.1,\n"
|
||||
+ " \"std\" : 1.2\n" + " }\n" + " }";
|
||||
|
|
|
@ -41,8 +41,8 @@ public class JsonTest extends BaseDL4JTest {
|
|||
|
||||
};
|
||||
for(InputPreProcessor p : pp ){
|
||||
String s = NeuralNetConfiguration.mapper().writeValueAsString(p);
|
||||
InputPreProcessor p2 = NeuralNetConfiguration.mapper().readValue(s, InputPreProcessor.class);
|
||||
String s = CavisMapper.getMapper(CavisMapper.Type.JSON).writeValueAsString(p);
|
||||
InputPreProcessor p2 = CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(s, InputPreProcessor.class);
|
||||
assertEquals(p, p2);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.deeplearning4j.nn.conf.layers.recurrent.LastTimeStep;
|
|||
import org.deeplearning4j.nn.conf.layers.samediff.SameDiffVertex;
|
||||
import org.deeplearning4j.nn.conf.memory.MemoryReport;
|
||||
import org.deeplearning4j.nn.conf.memory.NetworkMemoryReport;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.deeplearning4j.nn.conf.serde.JsonMappers;
|
||||
import org.deeplearning4j.nn.weights.IWeightInit;
|
||||
import org.deeplearning4j.nn.weights.WeightInit;
|
||||
|
@ -110,7 +111,7 @@ public class ComputationGraphConfiguration implements Serializable, Cloneable {
|
|||
* @return YAML representation of configuration
|
||||
*/
|
||||
public String toYaml() {
|
||||
ObjectMapper mapper = NeuralNetConfiguration.mapperYaml();
|
||||
ObjectMapper mapper = CavisMapper.getMapper(CavisMapper.Type.YAML);
|
||||
synchronized (mapper) {
|
||||
try {
|
||||
return mapper.writeValueAsString(this);
|
||||
|
@ -127,7 +128,7 @@ public class ComputationGraphConfiguration implements Serializable, Cloneable {
|
|||
* @return {@link ComputationGraphConfiguration}
|
||||
*/
|
||||
public static ComputationGraphConfiguration fromYaml(String json) {
|
||||
ObjectMapper mapper = NeuralNetConfiguration.mapperYaml();
|
||||
ObjectMapper mapper = CavisMapper.getMapper(CavisMapper.Type.YAML);
|
||||
try {
|
||||
return mapper.readValue(json, ComputationGraphConfiguration.class);
|
||||
} catch (IOException e) {
|
||||
|
@ -140,7 +141,7 @@ public class ComputationGraphConfiguration implements Serializable, Cloneable {
|
|||
*/
|
||||
public String toJson() {
|
||||
//As per NeuralNetConfiguration.toJson()
|
||||
ObjectMapper mapper = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper mapper =CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
synchronized (mapper) {
|
||||
//JSON mappers are supposed to be thread safe: however, in practice they seem to miss fields occasionally
|
||||
//when writeValueAsString is used by multiple threads. This results in invalid JSON. See issue #3243
|
||||
|
@ -160,7 +161,7 @@ public class ComputationGraphConfiguration implements Serializable, Cloneable {
|
|||
*/
|
||||
public static ComputationGraphConfiguration fromJson(String json) {
|
||||
//As per NeuralNetConfiguration.fromJson()
|
||||
ObjectMapper mapper = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper mapper =CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
ComputationGraphConfiguration conf;
|
||||
try {
|
||||
conf = mapper.readValue(json, ComputationGraphConfiguration.class);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
package org.deeplearning4j.nn.conf;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
@ -39,6 +40,7 @@ import org.deeplearning4j.nn.conf.inputs.InputType;
|
|||
import org.deeplearning4j.nn.conf.layers.BaseLayerConfiguration;
|
||||
import org.deeplearning4j.nn.conf.layers.ConvolutionLayer;
|
||||
import org.deeplearning4j.nn.conf.layers.LayerConfiguration;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.deeplearning4j.nn.conf.serde.JsonMappers;
|
||||
import org.deeplearning4j.nn.conf.stepfunctions.StepFunction;
|
||||
import org.deeplearning4j.nn.conf.weightnoise.IWeightNoise;
|
||||
|
@ -417,113 +419,6 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor
|
|||
@Getter @Setter @lombok.Builder.Default private double biasInit = 0.0;
|
||||
@Getter @Setter @lombok.Builder.Default private double gainInit = 1.0;
|
||||
|
||||
/**
|
||||
* Handle {@link WeightInit} and {@link Distribution} from legacy configs in Json format. Copied
|
||||
* from handling of {@link Activation} above.
|
||||
*
|
||||
* @return True if all is well and layer iteration shall continue. False else-wise.
|
||||
*/
|
||||
private static boolean handleLegacyWeightInitFromJson(
|
||||
String json, LayerConfiguration l, ObjectMapper mapper, JsonNode confs, int layerCount) {
|
||||
if ((l instanceof BaseLayerConfiguration)
|
||||
&& ((BaseLayerConfiguration) l).getWeightInit() == null) {
|
||||
try {
|
||||
JsonNode jsonNode = mapper.readTree(json);
|
||||
if (confs == null) {
|
||||
confs = jsonNode.get("confs");
|
||||
}
|
||||
if (confs instanceof ArrayNode) {
|
||||
ArrayNode layerConfs = (ArrayNode) confs;
|
||||
JsonNode outputLayerNNCNode = layerConfs.get(layerCount);
|
||||
if (outputLayerNNCNode == null) {
|
||||
return false; // Should never happen...
|
||||
}
|
||||
JsonNode layerWrapperNode = outputLayerNNCNode.get("layer");
|
||||
|
||||
if (layerWrapperNode == null || layerWrapperNode.size() != 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
JsonNode layerNode = layerWrapperNode.elements().next();
|
||||
JsonNode weightInit =
|
||||
layerNode.get("weightInit"); // Should only have 1 element: "dense", "output", etc
|
||||
JsonNode distribution = layerNode.get("dist");
|
||||
|
||||
Distribution dist = null;
|
||||
if (distribution != null) {
|
||||
dist = mapper.treeToValue(distribution, Distribution.class);
|
||||
}
|
||||
|
||||
if (weightInit != null) {
|
||||
final IWeightInit wi =
|
||||
WeightInit.valueOf(weightInit.asText()).getWeightInitFunction(dist);
|
||||
((BaseLayerConfiguration) l).setWeightInit(wi);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.warn(
|
||||
"ILayer with null WeightInit detected: " + l.getName() + ", could not parse JSON",
|
||||
e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object mapper for serialization of configurations
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ObjectMapper mapperYaml() {
|
||||
return JsonMappers.getMapperYaml();
|
||||
}
|
||||
|
||||
/**
|
||||
* Object mapper for serialization of configurations
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ObjectMapper mapper() {
|
||||
return JsonMappers.getMapper();
|
||||
}
|
||||
|
||||
public static NeuralNetBaseBuilderConfiguration fromYaml(String input) {
|
||||
throw new RuntimeException("Needs fixing - not supported."); // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JSON representation of NN configuration
|
||||
*/
|
||||
public String toYaml() {
|
||||
ObjectMapper mapper = NeuralNetBaseBuilderConfiguration.mapperYaml();
|
||||
synchronized (mapper) {
|
||||
try {
|
||||
return mapper.writeValueAsString(this);
|
||||
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JSON representation of NN configuration
|
||||
*/
|
||||
public String toJson() {
|
||||
ObjectMapper mapper = NeuralNetBaseBuilderConfiguration.mapper();
|
||||
synchronized (mapper) {
|
||||
// JSON mappers are supposed to be thread safe: however, in practice they seem to miss fields
|
||||
// occasionally
|
||||
// when writeValueAsString is used by multiple threads. This results in invalid JSON. See
|
||||
// issue #3243
|
||||
try {
|
||||
return mapper.writeValueAsString(this);
|
||||
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NeuralNetBaseBuilderConfiguration clone() {
|
||||
NeuralNetBaseBuilderConfiguration clone;
|
||||
|
@ -562,15 +457,7 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor
|
|||
|
||||
List<Object> innerConfigurations$value = new ArrayList<>(); // initialize with an empty list
|
||||
|
||||
public B activation(Activation activation) {
|
||||
this.activation = activation;
|
||||
return self();
|
||||
}
|
||||
@JsonIgnore
|
||||
public B activation(IActivation activation) {
|
||||
this.activation = activation;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set constraints to be applied to all layers. Default: no constraints.<br>
|
||||
* Constraints can be used to enforce certain conditions (non-negativity of parameters, max-norm
|
||||
|
@ -897,6 +784,7 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor
|
|||
*
|
||||
* @param distribution Distribution to use for weight initialization
|
||||
*/
|
||||
@JsonIgnore @Deprecated
|
||||
public B weightInit(Distribution distribution) {
|
||||
this.weightInit$value = new WeightInitDistribution(distribution);
|
||||
this.weightInit$set = true;
|
||||
|
@ -909,6 +797,7 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor
|
|||
return self();
|
||||
}
|
||||
|
||||
@JsonProperty("weightInit") //this is needed for Jackson < 2.4, otherwise JsonIgnore on the other setters will ignore this also
|
||||
public B weightInit(IWeightInit iWeightInit) {
|
||||
this.weightInit$value = iWeightInit;
|
||||
this.weightInit$set = true;
|
||||
|
@ -921,6 +810,7 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor
|
|||
* @param distribution
|
||||
* @return
|
||||
*/
|
||||
@JsonIgnore
|
||||
public B dist(@NonNull Distribution distribution) {
|
||||
return weightInit(distribution);
|
||||
}
|
||||
|
@ -951,5 +841,6 @@ public abstract class NeuralNetBaseBuilderConfiguration implements INeuralNetwor
|
|||
innerConfigurations$set = true;
|
||||
return self();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,39 +24,24 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.brutex.ai.dnn.api.IModel;
|
||||
import org.deeplearning4j.nn.conf.distribution.Distribution;
|
||||
import org.deeplearning4j.nn.conf.inputs.InputType;
|
||||
import org.deeplearning4j.nn.conf.layers.*;
|
||||
import org.deeplearning4j.nn.conf.layers.recurrent.LastTimeStep;
|
||||
import org.deeplearning4j.nn.conf.memory.LayerMemoryReport;
|
||||
import org.deeplearning4j.nn.conf.memory.MemoryReport;
|
||||
import org.deeplearning4j.nn.conf.memory.NetworkMemoryReport;
|
||||
import org.deeplearning4j.nn.conf.serde.JsonMappers;
|
||||
import org.deeplearning4j.nn.weights.IWeightInit;
|
||||
import org.deeplearning4j.nn.weights.WeightInit;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.deeplearning4j.util.OutputLayerUtil;
|
||||
import org.nd4j.linalg.activations.Activation;
|
||||
import org.nd4j.linalg.factory.Nd4j;
|
||||
import org.nd4j.linalg.learning.config.IUpdater;
|
||||
import org.nd4j.linalg.learning.config.Sgd;
|
||||
import org.nd4j.linalg.lossfunctions.LossFunctions;
|
||||
import org.nd4j.linalg.lossfunctions.impl.LossBinaryXENT;
|
||||
import org.nd4j.linalg.lossfunctions.impl.LossMCXENT;
|
||||
import org.nd4j.linalg.lossfunctions.impl.LossMSE;
|
||||
import org.nd4j.linalg.lossfunctions.impl.LossNegativeLogLikelihood;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Deeplearning4j is a domain-specific language to configure deep neural networks, which are made of
|
||||
|
@ -64,71 +49,50 @@ import java.util.stream.Collectors;
|
|||
* and their hyperparameters. Hyperparameters are variables that determine how a neural network
|
||||
* learns. They include how many times to update the weights of the model, how to initialize those
|
||||
* weights, which activation function to attach to the nodes, which optimization algorithm to use,
|
||||
* and how fast the model should learn. This is what one configuration would look like:
|
||||
* <br/><br/>
|
||||
*
|
||||
* NeuralNetConfiguration conf = NeuralNetConfiguration.builder()<br/>
|
||||
* .weightInit(WeightInit.XAVIER) .activation(Activation.RELU)<br/>
|
||||
* .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)<br/>
|
||||
* .updater(new Sgd(0.05)) //... other hyperparameters <br/>
|
||||
* .backprop(true)<br/>
|
||||
* .build();<br/><br/>
|
||||
*
|
||||
* With Deeplearning4j, you add a layer
|
||||
* by calling layer on the NeuralNetConfiguration.NeuralNetConfigurationBuilder(), specifying its place in the order of
|
||||
* and how fast the model should learn. This is what one configuration would look like: <br>
|
||||
* <br>
|
||||
* NeuralNetConfiguration conf = NeuralNetConfiguration.builder()<br>
|
||||
* .weightInit(WeightInit.XAVIER) .activation(Activation.RELU)<br>
|
||||
* .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)<br>
|
||||
* .updater(new Sgd(0.05)) //... other hyperparameters <br>
|
||||
* .backprop(true)<br>
|
||||
* .build();<br>
|
||||
* <br>
|
||||
* With Deeplearning4j, you add a layer by calling layer on the
|
||||
* NeuralNetConfiguration.NeuralNetConfigurationBuilder(), specifying its place in the order of
|
||||
* layers (the zero-indexed layer below is the input layer), the number of input and output nodes,
|
||||
* nIn and nOut, as well as the type: DenseLayer.<br/><br/>
|
||||
*
|
||||
* .layer(0, DenseLayer.builder().nIn(784).nOut(250)<br/>
|
||||
* .build())<br/><br/>
|
||||
*
|
||||
* Once you've configured your net, you train the
|
||||
* model with model.fit.
|
||||
* nIn and nOut, as well as the type: DenseLayer.<br>
|
||||
* <br>
|
||||
* .layer(0, DenseLayer.builder().nIn(784).nOut(250)<br>
|
||||
* .build())<br>
|
||||
* <br>
|
||||
* Once you've configured your net, you train the model with model.fit.
|
||||
*/
|
||||
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
@Jacksonized
|
||||
@JsonIgnoreProperties(value={"net"}, ignoreUnknown = true)
|
||||
@EqualsAndHashCode(exclude = {"net"}, callSuper = true)
|
||||
//@JsonIdentityInfo(generator= ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
|
||||
@JsonIgnoreProperties(value = {"net"})
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
// @JsonIdentityInfo(generator= ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
|
||||
|
||||
//The inner builder, that we can then extend ...
|
||||
@SuperBuilder //TODO fix access
|
||||
// The inner builder, that we can then extend ...
|
||||
@Jacksonized
|
||||
@SuperBuilder // TODO fix access
|
||||
public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
||||
|
||||
|
||||
private IModel net;
|
||||
private static final int DEFAULT_TBPTT_LENGTH = 20;
|
||||
private boolean initCalled = false;
|
||||
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NonNull
|
||||
@lombok.Builder.Default
|
||||
@Deprecated
|
||||
@Getter @Setter @NonNull @lombok.Builder.Default @Deprecated
|
||||
protected WorkspaceMode trainingWorkspaceMode = WorkspaceMode.ENABLED;
|
||||
@Getter
|
||||
@Setter
|
||||
@NonNull
|
||||
@lombok.Builder.Default
|
||||
@Deprecated
|
||||
|
||||
@Getter @Setter @NonNull @lombok.Builder.Default @Deprecated
|
||||
protected WorkspaceMode inferenceWorkspaceMode = WorkspaceMode.ENABLED;
|
||||
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@lombok.Builder.Default
|
||||
protected int iterationCount = 0;
|
||||
//Counter for the number of epochs completed so far. Used for per-epoch schedules
|
||||
@Getter
|
||||
@Setter
|
||||
@lombok.Builder.Default
|
||||
protected int epochCount = 0;
|
||||
@lombok.Builder.Default
|
||||
protected double dampingFactor = 100;
|
||||
@Getter @Setter @lombok.Builder.Default protected int iterationCount = 0;
|
||||
// Counter for the number of epochs completed so far. Used for per-epoch schedules
|
||||
@Getter @Setter @lombok.Builder.Default protected int epochCount = 0;
|
||||
@lombok.Builder.Default protected double dampingFactor = 100;
|
||||
@EqualsAndHashCode.Exclude private IModel net;
|
||||
private boolean initCalled = false;
|
||||
// gradient keys used for ensuring order when getting and setting the gradient
|
||||
@lombok.Builder.Default private LinkedHashSet<String> netWideVariables = new LinkedHashSet<>();
|
||||
|
||||
|
@ -143,22 +107,19 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
*/
|
||||
@Getter @Setter @Builder.Default private IUpdater updater = new Sgd();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the cuDNN algo mode for convolutional layers, which impacts performance and memory usage of cuDNN.
|
||||
* See {@link ConvolutionLayer.AlgoMode} for details. Defaults to "PREFER_FASTEST", but "NO_WORKSPACE" uses less memory.
|
||||
* <br>
|
||||
* Note: values set by this method will be applied to all applicable layers in the network, unless a different
|
||||
* value is explicitly set on a given layer. In other words: values set via this method are used as the default
|
||||
* value, and can be overridden on a per-layer basis.
|
||||
* Sets the cuDNN algo mode for convolutional layers, which impacts performance and memory usage
|
||||
* of cuDNN. See {@link ConvolutionLayer.AlgoMode} for details. Defaults to "PREFER_FASTEST", but
|
||||
* "NO_WORKSPACE" uses less memory. <br>
|
||||
* Note: values set by this method will be applied to all applicable layers in the network, unless
|
||||
* a different value is explicitly set on a given layer. In other words: values set via this
|
||||
* method are used as the default value, and can be overridden on a per-layer basis.
|
||||
*
|
||||
* @param cudnnAlgoMode cuDNN algo mode to use
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@lombok.Builder.Default
|
||||
@Getter @Setter @lombok.Builder.Default
|
||||
private ConvolutionLayer.AlgoMode cudnnAlgoMode = ConvolutionLayer.AlgoMode.PREFER_FASTEST;
|
||||
|
||||
|
||||
/**
|
||||
* Create a neural net configuration from json
|
||||
*
|
||||
|
@ -166,270 +127,23 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
* @return {@link NeuralNetConfiguration}
|
||||
*/
|
||||
public static NeuralNetConfiguration fromJson(String json) {
|
||||
//ObjectMapper mapper = NeuralNetConfiguration.mapper();
|
||||
JsonMapper mapper = JsonMapper.builder()
|
||||
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
|
||||
.build();
|
||||
ObjectMapper mapper = CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
try {
|
||||
return mapper.readValue(json, NeuralNetConfiguration.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
/*
|
||||
try {
|
||||
conf = mapper.readValue(json, NeuralNetConfiguration.class);
|
||||
} catch (InvalidTypeIdException e) {
|
||||
if (e.getMessage().contains("@class")) {
|
||||
try {
|
||||
//JSON may be legacy (1.0.0-alpha or earlier), attempt to load it using old format
|
||||
return JsonMappers.getLegacyMapper().readValue(json, NeuralNetConfiguration.class);
|
||||
} catch (InvalidTypeIdException e2) {
|
||||
//Check for legacy custom layers: "Could not resolve type id 'CustomLayer' as a subtype of [simple type, class org.deeplearning4j.nn.conf.layers.ILayer]: known type ids = [Bidirectional, CenterLossOutputLayer, CnnLossLayer, ..."
|
||||
//1.0.0-beta5: dropping support for custom layers defined in pre-1.0.0-beta format. Built-in layers from these formats still work
|
||||
String msg = e2.getMessage();
|
||||
if (msg != null && msg.contains("Could not resolve type id")) {
|
||||
throw new RuntimeException(
|
||||
"Error deserializing NeuralNetConfiguration - configuration may have a custom " +
|
||||
"layer, vertex or preprocessor, in pre version 1.0.0-beta JSON format.\nModels in legacy format with custom"
|
||||
+
|
||||
" layers should be loaded in 1.0.0-beta to 1.0.0-beta4 and saved again, before loading in the current version of DL4J",
|
||||
e);
|
||||
}
|
||||
throw new RuntimeException(e2);
|
||||
} catch (IOException e2) {
|
||||
throw new RuntimeException(e2);
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
//Check if this exception came from legacy deserializer...
|
||||
String msg = e.getMessage();
|
||||
if (msg != null && msg.contains("legacy")) {
|
||||
throw new RuntimeException(
|
||||
"Error deserializing NeuralNetConfiguration - configuration may have a custom " +
|
||||
"layer, vertex or preprocessor, in pre version 1.0.0-alpha JSON format. These layers can be "
|
||||
+
|
||||
"deserialized by first registering them with NeuralNetConfiguration.registerLegacyCustomClassesForJSON(Class...)",
|
||||
e);
|
||||
}
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
//To maintain backward compatibility after loss function refactoring (configs generated with v0.5.0 or earlier)
|
||||
// Previously: enumeration used for loss functions. Now: use classes
|
||||
// IN the past, could have only been an OutputLayer or RnnOutputLayer using these enums
|
||||
int layerCount = 0;
|
||||
JsonNode confs = null;
|
||||
for (LayerConfiguration nnc : conf.getFlattenedLayerConfigurations()) {
|
||||
LayerConfiguration l = nnc;
|
||||
if (l instanceof BaseOutputLayer && ((BaseOutputLayer) l).getLossFunction() == null) {
|
||||
//lossFn field null -> may be an old config format, with lossFunction field being for the enum
|
||||
//if so, try walking the JSON graph to extract out the appropriate enum value
|
||||
|
||||
BaseOutputLayer ol = (BaseOutputLayer) l;
|
||||
try {
|
||||
JsonNode jsonNode = mapper.readTree(json);
|
||||
if (confs == null) {
|
||||
confs = jsonNode.get("confs");
|
||||
}
|
||||
if (confs instanceof ArrayNode) {
|
||||
ArrayNode layerConfs = (ArrayNode) confs;
|
||||
JsonNode outputLayerNNCNode = layerConfs.get(layerCount);
|
||||
if (outputLayerNNCNode == null) {
|
||||
throw new RuntimeException(
|
||||
"should never happen"); //return conf; //Should never happen...
|
||||
}
|
||||
JsonNode outputLayerNode = outputLayerNNCNode.get("layer");
|
||||
|
||||
JsonNode lossFunctionNode = null;
|
||||
if (outputLayerNode.has("output")) {
|
||||
lossFunctionNode = outputLayerNode.get("output").get("lossFunction");
|
||||
} else if (outputLayerNode.has("rnnoutput")) {
|
||||
lossFunctionNode = outputLayerNode.get("rnnoutput").get("lossFunction");
|
||||
}
|
||||
|
||||
if (lossFunctionNode != null) {
|
||||
String lossFunctionEnumStr = lossFunctionNode.asText();
|
||||
LossFunctions.LossFunction lossFunction = null;
|
||||
try {
|
||||
lossFunction = LossFunctions.LossFunction.valueOf(lossFunctionEnumStr);
|
||||
} catch (Exception e) {
|
||||
log.warn(
|
||||
"OutputLayer with null LossFunction or pre-0.6.0 loss function configuration detected: could not parse JSON",
|
||||
e);
|
||||
}
|
||||
|
||||
if (lossFunction != null) {
|
||||
switch (lossFunction) {
|
||||
case MSE:
|
||||
ol.setLossFunction(new LossMSE());
|
||||
break;
|
||||
case XENT:
|
||||
ol.setLossFunction(new LossBinaryXENT());
|
||||
break;
|
||||
case NEGATIVELOGLIKELIHOOD:
|
||||
ol.setLossFunction(new LossNegativeLogLikelihood());
|
||||
break;
|
||||
case MCXENT:
|
||||
ol.setLossFunction(new LossMCXENT());
|
||||
break;
|
||||
|
||||
//Remaining: TODO
|
||||
case SQUARED_LOSS:
|
||||
case RECONSTRUCTION_CROSSENTROPY:
|
||||
default:
|
||||
log.warn(
|
||||
"OutputLayer with null LossFunction or pre-0.6.0 loss function configuration detected: could not set loss function for {}",
|
||||
lossFunction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
log.warn(
|
||||
"OutputLayer with null LossFunction or pre-0.6.0 loss function configuration detected: could not parse JSON: layer 'confs' field is not an ArrayNode (is: {})",
|
||||
(confs != null ? confs.getClass() : null));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn(
|
||||
"OutputLayer with null LossFunction or pre-0.6.0 loss function configuration detected: could not parse JSON",
|
||||
e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Also, pre 0.7.2: activation functions were Strings ("activationFunction" field), not classes ("activationFn")
|
||||
//Try to load the old format if necessary, and create the appropriate IActivation instance
|
||||
if ((l instanceof BaseLayerConfiguration) && ((BaseLayerConfiguration) l).getActivationFn() == null) {
|
||||
try {
|
||||
JsonNode jsonNode = mapper.readTree(json);
|
||||
if (confs == null) {
|
||||
confs = jsonNode.get("confs");
|
||||
}
|
||||
if (confs instanceof ArrayNode) {
|
||||
ArrayNode layerConfs = (ArrayNode) confs;
|
||||
JsonNode outputLayerNNCNode = layerConfs.get(layerCount);
|
||||
if (outputLayerNNCNode == null) {
|
||||
throw new RuntimeException(
|
||||
"Should never happen"); //return conf; //Should never happen...
|
||||
}
|
||||
JsonNode layerWrapperNode = outputLayerNNCNode.get("layer");
|
||||
|
||||
if (layerWrapperNode == null || layerWrapperNode.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JsonNode layerNode = layerWrapperNode.elements().next();
|
||||
JsonNode activationFunction = layerNode.get(
|
||||
"activationFunction"); //Should only have 1 element: "dense", "output", etc
|
||||
|
||||
if (activationFunction != null) {
|
||||
Activation ia = Activation.fromString(activationFunction.asText());
|
||||
((BaseLayerConfiguration) l).setActivation(ia.getActivationFunction());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.warn(
|
||||
"ILayer with null ActivationFn field or pre-0.7.2 activation function detected: could not parse JSON",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handleLegacyWeightInitFromJson(json, l, mapper, confs, layerCount)) {
|
||||
return conf;
|
||||
}
|
||||
|
||||
layerCount++;
|
||||
}
|
||||
return conf;
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link WeightInit} and {@link Distribution} from legacy configs in Json format. Copied
|
||||
* from handling of {@link Activation} above.
|
||||
*
|
||||
* @return True if all is well and layer iteration shall continue. False else-wise.
|
||||
*/
|
||||
private static boolean handleLegacyWeightInitFromJson(String json, LayerConfiguration l,
|
||||
ObjectMapper mapper,
|
||||
JsonNode confs, int layerCount) {
|
||||
if ((l instanceof BaseLayerConfiguration) ) { //&& ((BaseLayerConfiguration) l).getWeightInit() == null) {
|
||||
try {
|
||||
JsonNode jsonNode = mapper.readTree(json);
|
||||
if (confs == null) {
|
||||
confs = jsonNode.get("confs");
|
||||
}
|
||||
if (confs instanceof ArrayNode) {
|
||||
ArrayNode layerConfs = (ArrayNode) confs;
|
||||
JsonNode outputLayerNNCNode = layerConfs.get(layerCount);
|
||||
if (outputLayerNNCNode == null) {
|
||||
return false; //Should never happen...
|
||||
}
|
||||
JsonNode layerWrapperNode = outputLayerNNCNode.get("layer");
|
||||
|
||||
if (layerWrapperNode == null || layerWrapperNode.size() != 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
JsonNode layerNode = layerWrapperNode.elements().next();
|
||||
JsonNode weightInit = layerNode.get(
|
||||
"weightInit"); //Should only have 1 element: "dense", "output", etc
|
||||
JsonNode distribution = layerNode.get("dist");
|
||||
|
||||
Distribution dist = null;
|
||||
if (distribution != null) {
|
||||
dist = mapper.treeToValue(distribution, Distribution.class);
|
||||
}
|
||||
|
||||
if (weightInit != null) {
|
||||
final IWeightInit wi = WeightInit.valueOf(weightInit.asText())
|
||||
.getWeightInitFunction(dist);
|
||||
((BaseLayerConfiguration) l).setWeightInit(wi);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.warn(
|
||||
"ILayer with null WeightInit detected: " + l.getName() + ", could not parse JSON",
|
||||
e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Object mapper for serialization of configurations
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ObjectMapper mapperYaml() {
|
||||
return JsonMappers.getMapperYaml();
|
||||
}
|
||||
|
||||
/**
|
||||
* Object mapper for serialization of configurations
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ObjectMapper mapper() {
|
||||
return JsonMappers.getMapper();
|
||||
}
|
||||
|
||||
public static NeuralNetConfiguration fromYaml(String input) {
|
||||
throw new RuntimeException("Needs fixing - not supported."); //TODO
|
||||
throw new RuntimeException("Needs fixing - not supported."); // TODO
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return JSON representation of NN configuration
|
||||
*/
|
||||
public String toYaml() {
|
||||
ObjectMapper mapper = NeuralNetConfiguration.mapperYaml();
|
||||
ObjectMapper mapper = CavisMapper.getMapper(CavisMapper.Type.YAML);
|
||||
synchronized (mapper) {
|
||||
try {
|
||||
return mapper.writeValueAsString(this);
|
||||
|
@ -443,14 +157,12 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
* @return JSON representation of NN configuration
|
||||
*/
|
||||
public String toJson() {
|
||||
JsonMapper mapper = JsonMapper.builder()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
|
||||
.build();
|
||||
//ObjectMapper mapper = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper mapper = CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
synchronized (mapper) {
|
||||
//JSON mappers are supposed to be thread safe: however, in practice they seem to miss fields occasionally
|
||||
//when writeValueAsString is used by multiple threads. This results in invalid JSON. See issue #3243
|
||||
// JSON mappers are supposed to be thread safe: however, in practice they seem to miss fields
|
||||
// occasionally
|
||||
// when writeValueAsString is used by multiple threads. This results in invalid JSON. See
|
||||
// issue #3243
|
||||
try {
|
||||
return mapper.writeValueAsString(this);
|
||||
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
|
||||
|
@ -469,7 +181,9 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
public NeuralNetConfiguration clone() {
|
||||
NeuralNetConfiguration clone;
|
||||
clone = (NeuralNetConfiguration) super.clone();
|
||||
if(getStepFunction() != null) { clone.setStepFunction(getStepFunction().clone()); }
|
||||
if (getStepFunction() != null) {
|
||||
clone.setStepFunction(getStepFunction().clone());
|
||||
}
|
||||
clone.netWideVariables = new LinkedHashSet<>(netWideVariables);
|
||||
clone.setInnerConfigurations(new ArrayList<>(innerConfigurations));
|
||||
|
||||
|
@ -489,98 +203,106 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
clone.setDataType(this.getDataType());
|
||||
|
||||
return clone;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/** */
|
||||
@Override
|
||||
public void init() {
|
||||
if(initCalled) return;
|
||||
initCalled=true;
|
||||
if (initCalled) return;
|
||||
initCalled = true;
|
||||
|
||||
/**
|
||||
* Run init() for each layer
|
||||
*/
|
||||
for( NeuralNetConfiguration nconf : getNetConfigurations() ) {
|
||||
/** Run init() for each layer */
|
||||
for (NeuralNetConfiguration nconf : getNetConfigurations()) {
|
||||
nconf.init();
|
||||
}
|
||||
//getNetConfigurations().stream().forEach( conf -> {
|
||||
// getNetConfigurations().stream().forEach( conf -> {
|
||||
// conf.init(); //do not call on self
|
||||
//}); //call init on all embedded net configurations
|
||||
// }); //call init on all embedded net configurations
|
||||
|
||||
//TODO do not put inside self to avoid serialization issues
|
||||
// TODO do not put inside self to avoid serialization issues
|
||||
// innerConfigurations.add(0, this); //put this configuration at first place
|
||||
|
||||
/**
|
||||
* Inherit network wide configuration setting to those layer configurations
|
||||
* that do not have an individual setting (nor a default)
|
||||
* Inherit network wide configuration setting to those layer configurations that do not have an
|
||||
* individual setting (nor a default)
|
||||
*/
|
||||
for(LayerConfiguration lconf : this.getFlattenedLayerConfigurations()) {
|
||||
for (LayerConfiguration lconf : this.getFlattenedLayerConfigurations()) {
|
||||
lconf.runInheritance();
|
||||
}
|
||||
|
||||
getLayerConfigurations().stream().forEach( lconf -> lconf.setNetConfiguration(this)); //set this as net config for all layers (defined in here, not stacked
|
||||
getLayerConfigurations().stream()
|
||||
.forEach(
|
||||
lconf ->
|
||||
lconf.setNetConfiguration(
|
||||
this)); // set this as net config for all layers (defined in here, not stacked
|
||||
|
||||
|
||||
//Validate BackpropType setting
|
||||
// Validate BackpropType setting
|
||||
if ((tbpttBackLength != DEFAULT_TBPTT_LENGTH || tbpttFwdLength != DEFAULT_TBPTT_LENGTH)
|
||||
&& backpropType != BackpropType.TruncatedBPTT) {
|
||||
log.warn("Truncated backpropagation through time lengths have been configured with values "
|
||||
log.warn(
|
||||
"Truncated backpropagation through time lengths have been configured with values "
|
||||
+ tbpttFwdLength
|
||||
+ " and " + tbpttBackLength + " but backprop type is set to " + backpropType
|
||||
+ ". TBPTT configuration" +
|
||||
" settings will only take effect if backprop type is set to BackpropType.TruncatedBPTT");
|
||||
+ " and "
|
||||
+ tbpttBackLength
|
||||
+ " but backprop type is set to "
|
||||
+ backpropType
|
||||
+ ". TBPTT configuration"
|
||||
+ " settings will only take effect if backprop type is set to BackpropType.TruncatedBPTT");
|
||||
}
|
||||
|
||||
if (backpropType == BackpropType.TruncatedBPTT && isValidateTbpttConfig()) {
|
||||
//Check for invalid combination - tbptt plus LastTimeStepLayer or
|
||||
// Check for invalid combination - tbptt plus LastTimeStepLayer or
|
||||
for (int i = 0; i < getFlattenedLayerConfigurations().size(); i++) {
|
||||
LayerConfiguration l = getFlattenedLayerConfigurations().get(i);
|
||||
if (l instanceof LastTimeStep || l instanceof GlobalPoolingLayer) {
|
||||
throw new IllegalStateException(
|
||||
"Invalid network configuration detected: Truncated backpropagation through time (TBPTT)"
|
||||
+
|
||||
" cannot be used with layer " + i + " of type " + l.getClass().getName()
|
||||
+ ": TBPTT is incompatible with this layer type (which is designed " +
|
||||
"to process entire sequences at once, and does support the type of sequence segments that TPBTT uses).\n"
|
||||
+
|
||||
"This check can be disabled using validateTbpttConfig(false) but this is not recommended.");
|
||||
+ " cannot be used with layer "
|
||||
+ i
|
||||
+ " of type "
|
||||
+ l.getClass().getName()
|
||||
+ ": TBPTT is incompatible with this layer type (which is designed "
|
||||
+ "to process entire sequences at once, and does support the type of sequence segments that TPBTT uses).\n"
|
||||
+ "This check can be disabled using validateTbpttConfig(false) but this is not recommended.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getInputType() == null && inputPreProcessors.get(0) == null) {
|
||||
//User hasn't set the InputType. Sometimes we can infer it...
|
||||
// For example, Dense/RNN layers, where preprocessor isn't set -> user is *probably* going to feed in
|
||||
// User hasn't set the InputType. Sometimes we can infer it...
|
||||
// For example, Dense/RNN layers, where preprocessor isn't set -> user is *probably* going to
|
||||
// feed in
|
||||
// standard feedforward or RNN data
|
||||
//This isn't the most elegant implementation, but should avoid breaking backward compatibility here
|
||||
//Can't infer InputType for CNN layers, however (don't know image dimensions/depth)
|
||||
// This isn't the most elegant implementation, but should avoid breaking backward
|
||||
// compatibility here
|
||||
// Can't infer InputType for CNN layers, however (don't know image dimensions/depth)
|
||||
LayerConfiguration firstLayer = getFlattenedLayerConfigurations().get(0);
|
||||
if (firstLayer instanceof BaseRecurrentLayer) {
|
||||
BaseRecurrentLayer brl = (BaseRecurrentLayer) firstLayer;
|
||||
val nIn = brl.getNIn();
|
||||
if (nIn > 0) {
|
||||
setInputType( InputType.recurrent(nIn, brl.getDataFormat()));
|
||||
setInputType(InputType.recurrent(nIn, brl.getDataFormat()));
|
||||
}
|
||||
} else if (firstLayer instanceof DenseLayer || firstLayer instanceof EmbeddingLayer
|
||||
} else if (firstLayer instanceof DenseLayer
|
||||
|| firstLayer instanceof EmbeddingLayer
|
||||
|| firstLayer instanceof OutputLayer) {
|
||||
//Can't just use "instanceof FeedForwardLayer" here. ConvolutionLayer is also a FeedForwardLayer
|
||||
// Can't just use "instanceof FeedForwardLayer" here. ConvolutionLayer is also a
|
||||
// FeedForwardLayer
|
||||
FeedForwardLayer ffl = (FeedForwardLayer) firstLayer;
|
||||
val nIn = ffl.getNIn();
|
||||
if (nIn > 0) {
|
||||
setInputType( InputType.feedForward(nIn));
|
||||
setInputType(InputType.feedForward(nIn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add preprocessors and set nIns, if InputType has been set
|
||||
// Add preprocessors and set nIns, if InputType has been set
|
||||
// Builder.inputType field can be set in 1 of 4 ways:
|
||||
// 1. User calls setInputType directly
|
||||
// 2. Via ConvolutionLayerSetup -> internally calls setInputType(InputType.convolutional(...))
|
||||
// 3. Via the above code: i.e., assume input is as expected by the RNN or dense layer -> sets the inputType field
|
||||
if(inputPreProcessors == null) {
|
||||
// 3. Via the above code: i.e., assume input is as expected by the RNN or dense layer -> sets
|
||||
// the inputType field
|
||||
if (inputPreProcessors == null) {
|
||||
inputPreProcessors = new HashMap<>();
|
||||
}
|
||||
if (getInputType() != null) {
|
||||
|
@ -588,7 +310,7 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
for (int i = 0; i < getFlattenedLayerConfigurations().size(); i++) {
|
||||
LayerConfiguration l = getFlattenedLayerConfigurations().get(i);
|
||||
if (inputPreProcessors.get(i) == null) {
|
||||
//Don't override preprocessor setting, but set preprocessor if required...
|
||||
// Don't override preprocessor setting, but set preprocessor if required...
|
||||
@NonNull
|
||||
InputPreProcessor inputPreProcessor = l.getPreProcessorForInputType(currentInputType);
|
||||
if (inputPreProcessor != null) {
|
||||
|
@ -602,41 +324,47 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
}
|
||||
if (i > 0) {
|
||||
LayerConfiguration layer = getFlattenedLayerConfigurations().get(i - 1);
|
||||
//convolution 1d is an edge case where it has rnn input type but the filters
|
||||
//should be the output
|
||||
// convolution 1d is an edge case where it has rnn input type but the filters
|
||||
// should be the output
|
||||
if (layer instanceof Convolution1DLayer) {
|
||||
if (l instanceof DenseLayer && getInputType() instanceof InputType.InputTypeRecurrent) {
|
||||
FeedForwardLayer feedForwardLayer = (FeedForwardLayer) l;
|
||||
if (getInputType() instanceof InputType.InputTypeRecurrent) {
|
||||
InputType.InputTypeRecurrent recurrent = (InputType.InputTypeRecurrent) getInputType();
|
||||
InputType.InputTypeRecurrent recurrent =
|
||||
(InputType.InputTypeRecurrent) getInputType();
|
||||
feedForwardLayer.setNIn(recurrent.getTimeSeriesLength());
|
||||
}
|
||||
} else {
|
||||
l.setNIn(currentInputType,
|
||||
isOverrideNinUponBuild()); //Don't override the nIn setting, if it's manually set by the user
|
||||
l.setNIn(
|
||||
currentInputType,
|
||||
isOverrideNinUponBuild()); // Don't override the nIn setting, if it's manually set
|
||||
// by the user
|
||||
}
|
||||
} else {
|
||||
l.setNIn(currentInputType,
|
||||
isOverrideNinUponBuild()); //Don't override the nIn setting, if it's manually set by the user
|
||||
l.setNIn(
|
||||
currentInputType,
|
||||
isOverrideNinUponBuild()); // Don't override the nIn setting, if it's manually set
|
||||
// by the user
|
||||
}
|
||||
|
||||
} else {
|
||||
l.setNIn(currentInputType,
|
||||
isOverrideNinUponBuild()); //Don't override the nIn setting, if it's manually set by the user
|
||||
l.setNIn(
|
||||
currentInputType,
|
||||
isOverrideNinUponBuild()); // Don't override the nIn setting, if it's manually set by
|
||||
// the user
|
||||
}
|
||||
|
||||
currentInputType = l.getOutputType(i, currentInputType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Nd4j.getRandom().setSeed(getSeed());
|
||||
|
||||
//Validate output layer configuration
|
||||
// Validate output layer configuration
|
||||
if (isValidateOutputLayerConfig()) {
|
||||
//Validate output layer configurations...
|
||||
// Validate output layer configurations...
|
||||
for (LayerConfiguration n : getFlattenedLayerConfigurations()) {
|
||||
OutputLayerUtil.validateOutputLayer(n.getName(), n); //No-op for non output/loss layers
|
||||
OutputLayerUtil.validateOutputLayer(n.getName(), n); // No-op for non output/loss layers
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -662,26 +390,28 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
layerName = String.valueOf(i);
|
||||
}
|
||||
|
||||
//Pass input type through preprocessor, if necessary
|
||||
// Pass input type through preprocessor, if necessary
|
||||
InputPreProcessor preproc = getInputPreProcess(i);
|
||||
//TODO memory requirements for preprocessor
|
||||
// TODO memory requirements for preprocessor
|
||||
if (preproc != null) {
|
||||
inputType = preproc.getOutputType(inputType);
|
||||
}
|
||||
|
||||
LayerMemoryReport report = getFlattenedLayerConfigurations().get(i).getMemoryReport(inputType);
|
||||
LayerMemoryReport report =
|
||||
getFlattenedLayerConfigurations().get(i).getMemoryReport(inputType);
|
||||
memoryReportMap.put(layerName, report);
|
||||
|
||||
inputType = getFlattenedLayerConfigurations().get(i).getOutputType(i, inputType);
|
||||
}
|
||||
|
||||
return new NetworkMemoryReport(memoryReportMap, NeuralNetConfiguration.class,
|
||||
"MultiLayerNetwork", inputType);
|
||||
return new NetworkMemoryReport(
|
||||
memoryReportMap, NeuralNetConfiguration.class, "MultiLayerNetwork", inputType);
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given input shape/type for the network, return a list of activation sizes for each
|
||||
* layer in the network.<br> i.e., list.get(i) is the output activation sizes for layer i
|
||||
* layer in the network.<br>
|
||||
* i.e., list.get(i) is the output activation sizes for layer i
|
||||
*
|
||||
* @param inputType Input type for the network
|
||||
* @return A lits of activation types for the network, indexed by layer number
|
||||
|
@ -715,38 +445,47 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
public void addNetWideVariable(String variable) {
|
||||
if (!netWideVariables.contains(variable)) {
|
||||
netWideVariables.add(variable);
|
||||
log.trace("Adding neural network wide variable '{}' to the list of variables. New length is {}.", variable, netWideVariables.size());
|
||||
log.trace(
|
||||
"Adding neural network wide variable '{}' to the list of variables. New length is {}.",
|
||||
variable,
|
||||
netWideVariables.size());
|
||||
}
|
||||
log.trace("Skipped adding neural network wide variable '{}' to the list of variables. It was already present. Length remains {}.", variable, netWideVariables.size());
|
||||
log.trace(
|
||||
"Skipped adding neural network wide variable '{}' to the list of variables. It was already present. Length remains {}.",
|
||||
variable,
|
||||
netWideVariables.size());
|
||||
}
|
||||
|
||||
public void clearNetWideVariable() {
|
||||
|
||||
netWideVariables.clear();
|
||||
log.trace("Adding neural network wide variables have been cleared. New length is {}.", netWideVariables.size());
|
||||
log.trace(
|
||||
"Adding neural network wide variables have been cleared. New length is {}.",
|
||||
netWideVariables.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* From the list of layers and neural net configurations, only return the Layer Configurations that
|
||||
* are defined in this neural network (it does not include embedded neural network configuration
|
||||
* layers)
|
||||
* From the list of layers and neural net configurations, only return the Layer Configurations
|
||||
* that are defined in this neural network (it does not include embedded neural network
|
||||
* configuration layers)
|
||||
*
|
||||
* @return list with layer configurations
|
||||
*/
|
||||
@JsonIgnore
|
||||
public List<LayerConfiguration> getLayerConfigurations() {
|
||||
return innerConfigurations.stream()
|
||||
.filter(obj -> (obj instanceof LayerConfiguration))
|
||||
.map( obj -> (LayerConfiguration)obj )
|
||||
.collect( Collectors.toList());
|
||||
.map(obj -> (LayerConfiguration) obj)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* From the list of layers and neural net configurations, only return the neural net configurations
|
||||
* From the list of layers and neural net configurations, only return the neural net
|
||||
* configurations
|
||||
*
|
||||
* @return list with neural net configurations
|
||||
*/
|
||||
//@Synchronized("innerConfigurationsLock")
|
||||
// @Synchronized("innerConfigurationsLock")
|
||||
@JsonIgnore
|
||||
public List<NeuralNetConfiguration> getNetConfigurations() {
|
||||
List<NeuralNetConfiguration> list;
|
||||
|
@ -767,23 +506,29 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
* @return list of layer configurations
|
||||
*/
|
||||
public List<LayerConfiguration> getFlattenedLayerConfigurations(NeuralNetConfiguration conf) {
|
||||
List<LayerConfiguration> ret = new ArrayList<>(); //create the final return list
|
||||
//When properly initialized, _this_ configuration is set first in the list, however we
|
||||
//can find cases where this is not true, thus the first configuration is another net or layer configuration
|
||||
//and should not be skipped. In essence, skip first configuration if that is "this".
|
||||
//TODO: skipping not needed anymore as we removed _this_ from innerConfigurations
|
||||
List<LayerConfiguration> ret = new ArrayList<>(); // create the final return list
|
||||
// When properly initialized, _this_ configuration is set first in the list, however we
|
||||
// can find cases where this is not true, thus the first configuration is another net or layer
|
||||
// configuration
|
||||
// and should not be skipped. In essence, skip first configuration if that is "this".
|
||||
// TODO: skipping not needed anymore as we removed _this_ from innerConfigurations
|
||||
int iSkip = 0;
|
||||
if(conf.getInnerConfigurations().size()>0 && conf.getInnerConfigurations().get(0).equals(this)) { iSkip=1;}
|
||||
conf.getInnerConfigurations().stream().skip(iSkip)
|
||||
.forEach(obj -> {
|
||||
//if Layer Config, include in list and inherit parameters from this conf
|
||||
//else if neural net configuration, call self recursively to resolve layer configurations
|
||||
if (conf.getInnerConfigurations().size() > 0
|
||||
&& conf.getInnerConfigurations().get(0).equals(this)) {
|
||||
iSkip = 1;
|
||||
}
|
||||
conf.getInnerConfigurations().stream()
|
||||
.skip(iSkip)
|
||||
.forEach(
|
||||
obj -> {
|
||||
// if Layer Config, include in list and inherit parameters from this conf
|
||||
// else if neural net configuration, call self recursively to resolve layer
|
||||
// configurations
|
||||
if (obj instanceof LayerConfiguration) {
|
||||
((LayerConfiguration) obj).setNetConfiguration(conf);
|
||||
ret.add((LayerConfiguration) obj);
|
||||
} else if (obj instanceof NeuralNetConfiguration)
|
||||
ret.addAll(getFlattenedLayerConfigurations(
|
||||
(NeuralNetConfiguration) obj));
|
||||
ret.addAll(getFlattenedLayerConfigurations((NeuralNetConfiguration) obj));
|
||||
else {
|
||||
log.error(
|
||||
"The list of layers and neural network configurations does contain an object of {}. Element will be ignored.",
|
||||
|
@ -794,8 +539,9 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sames as {@link #getFlattenedLayerConfigurations(NeuralNetConfiguration)}, but uses this configurations
|
||||
* list of configurations
|
||||
* Sames as {@link #getFlattenedLayerConfigurations(NeuralNetConfiguration)}, but uses this
|
||||
* configurations list of configurations
|
||||
*
|
||||
* @return list of layer configurations
|
||||
*/
|
||||
@JsonIgnore
|
||||
|
@ -805,6 +551,7 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
|
||||
/**
|
||||
* Add a new layer to the first position
|
||||
*
|
||||
* @param layer configuration
|
||||
*/
|
||||
public void setLayer(@NonNull LayerConfiguration layer) {
|
||||
|
@ -817,26 +564,28 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
}
|
||||
|
||||
/**
|
||||
* Deprecated, do not use. Workaround for old tests
|
||||
* and getFlattenedLayerConfigurations().get(0);
|
||||
* Deprecated, do not use. Workaround for old tests and getFlattenedLayerConfigurations().get(0);
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated @JsonIgnore
|
||||
@Deprecated
|
||||
@JsonIgnore
|
||||
public LayerConfiguration getFirstLayer() {
|
||||
log.warn("This getFirstLayer method is an ugly workaround and will be removed.");
|
||||
return getFlattenedLayerConfigurations().get(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
protected boolean canEqual(final Object other) {
|
||||
return other instanceof NeuralNetConfiguration;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public static abstract class NeuralNetConfigurationBuilder<C extends NeuralNetConfiguration,
|
||||
B extends NeuralNetConfiguration.NeuralNetConfigurationBuilder<C, B>> extends
|
||||
NeuralNetBaseBuilderConfigurationBuilder<C, B> {
|
||||
public abstract static class NeuralNetConfigurationBuilder<
|
||||
C extends NeuralNetConfiguration,
|
||||
B extends NeuralNetConfiguration.NeuralNetConfigurationBuilder<C, B>>
|
||||
extends NeuralNetBaseBuilderConfigurationBuilder<C, B> {
|
||||
|
||||
public ComputationGraphConfiguration.GraphBuilder graphBuilder() {
|
||||
return new ComputationGraphConfiguration.GraphBuilder(this);
|
||||
|
@ -845,10 +594,9 @@ public class NeuralNetConfiguration extends NeuralNetBaseBuilderConfiguration {
|
|||
public NeuralNetConfigurationBuilder clone() {
|
||||
try {
|
||||
return (NeuralNetConfigurationBuilder) super.clone();
|
||||
} catch(CloneNotSupportedException ex) {
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type",
|
||||
defaultImpl = LegacyDistributionHelper.class)
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
|
||||
public abstract class Distribution implements Serializable, Cloneable {
|
||||
|
||||
private static final long serialVersionUID = 5401741214954998498L;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
package org.deeplearning4j.nn.conf.distribution;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
@ -48,21 +49,7 @@ public class NormalDistribution extends Distribution {
|
|||
this.std = std;
|
||||
}
|
||||
|
||||
public double getMean() {
|
||||
return mean;
|
||||
}
|
||||
|
||||
public void setMean(double mean) {
|
||||
this.mean = mean;
|
||||
}
|
||||
|
||||
public double getStd() {
|
||||
return std;
|
||||
}
|
||||
|
||||
public void setStd(double std) {
|
||||
this.std = std;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
|
|
@ -24,6 +24,7 @@ import lombok.EqualsAndHashCode;
|
|||
import lombok.NonNull;
|
||||
import org.deeplearning4j.nn.conf.CacheMode;
|
||||
import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.nd4j.linalg.api.buffer.DataBuffer;
|
||||
import org.nd4j.linalg.api.buffer.DataType;
|
||||
import org.nd4j.linalg.api.buffer.util.DataTypeUtil;
|
||||
|
@ -151,7 +152,7 @@ public abstract class MemoryReport {
|
|||
|
||||
public String toJson() {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapper().writeValueAsString(this);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.JSON).writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -159,7 +160,7 @@ public abstract class MemoryReport {
|
|||
|
||||
public String toYaml() {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapperYaml().writeValueAsString(this);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.YAML).writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -167,7 +168,7 @@ public abstract class MemoryReport {
|
|||
|
||||
public static MemoryReport fromJson(String json) {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapper().readValue(json, MemoryReport.class);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(json, MemoryReport.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -175,7 +176,7 @@ public abstract class MemoryReport {
|
|||
|
||||
public static MemoryReport fromYaml(String yaml) {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapperYaml().readValue(yaml, MemoryReport.class);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(yaml, MemoryReport.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ public abstract class BaseNetConfigDeserializer<T> extends StdDeserializer<T> im
|
|||
Distribution d = null;
|
||||
if(w == WeightInit.DISTRIBUTION && on.has("dist")){
|
||||
String dist = on.get("dist").toString();
|
||||
d = NeuralNetConfiguration.mapper().readValue(dist, Distribution.class);
|
||||
d = CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(dist, Distribution.class);
|
||||
}
|
||||
IWeightInit iwi = w.getWeightInitFunction(d);
|
||||
baseLayerConfiguration.setWeightInit(iwi);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* * 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 org.deeplearning4j.nn.conf.serde;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
|
||||
import lombok.NonNull;
|
||||
|
||||
public class CavisMapper {
|
||||
|
||||
public static ObjectMapper getMapper(@NonNull Type type) {
|
||||
ObjectMapper mapper;
|
||||
switch (type) {
|
||||
case JSON:
|
||||
mapper = JsonMapper.builder()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
|
||||
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
|
||||
.enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)
|
||||
.enable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)
|
||||
.build();
|
||||
break;
|
||||
case YAML:
|
||||
mapper = YAMLMapper.builder().build();
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Mapper type not recognised.");
|
||||
}
|
||||
|
||||
return mapper;
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
JSON,
|
||||
YAML
|
||||
}
|
||||
}
|
|
@ -96,7 +96,7 @@ public class ComputationGraphConfigurationDeserializer
|
|||
}
|
||||
jsonSubString = s.substring((int) charOffsetStart - 1, charOffsetEnd.intValue());
|
||||
|
||||
ObjectMapper om = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper om = CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
JsonNode rootNode = om.readTree(jsonSubString);
|
||||
|
||||
ObjectNode verticesNode = (ObjectNode) rootNode.get("vertices");
|
||||
|
|
|
@ -78,7 +78,7 @@ public class NeuralNetConfigurationDeserializer extends BaseNetConfigDeserialize
|
|||
}
|
||||
String jsonSubString = s.substring((int) charOffsetStart - 1, (int) charOffsetEnd);
|
||||
|
||||
ObjectMapper om = NeuralNetConfiguration.mapper();
|
||||
ObjectMapper om = CavisMapper.getMapper(CavisMapper.Type.JSON);
|
||||
JsonNode rootNode = om.readTree(jsonSubString);
|
||||
|
||||
ArrayNode confsNode = (ArrayNode)rootNode.get("confs");
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.deeplearning4j.nn.conf.layers.ConvolutionLayer;
|
|||
import org.deeplearning4j.nn.conf.layers.LayerConfiguration;
|
||||
import org.deeplearning4j.nn.conf.layers.LayerValidation;
|
||||
import org.deeplearning4j.nn.conf.layers.SubsamplingLayer;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.deeplearning4j.nn.conf.stepfunctions.StepFunction;
|
||||
import org.deeplearning4j.nn.conf.weightnoise.IWeightNoise;
|
||||
import org.deeplearning4j.nn.weights.IWeightInit;
|
||||
|
@ -118,7 +119,7 @@ public class FineTuneConfiguration {
|
|||
|
||||
public static FineTuneConfiguration fromJson(String json) {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapper().readValue(json, FineTuneConfiguration.class);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(json, FineTuneConfiguration.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -126,7 +127,7 @@ public class FineTuneConfiguration {
|
|||
|
||||
public static FineTuneConfiguration fromYaml(String yaml) {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapperYaml().readValue(yaml, FineTuneConfiguration.class);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.YAML).readValue(yaml, FineTuneConfiguration.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -322,7 +323,7 @@ public class FineTuneConfiguration {
|
|||
|
||||
public String toJson() {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapper().writeValueAsString(this);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.JSON).writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -330,7 +331,7 @@ public class FineTuneConfiguration {
|
|||
|
||||
public String toYaml() {
|
||||
try {
|
||||
return NeuralNetConfiguration.mapperYaml().writeValueAsString(this);
|
||||
return CavisMapper.getMapper(CavisMapper.Type.YAML).writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
setterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
public interface IWeightInit extends Serializable {
|
||||
|
|
|
@ -20,19 +20,24 @@
|
|||
|
||||
package org.deeplearning4j.nn.weights;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import lombok.*;
|
||||
import org.deeplearning4j.nn.conf.distribution.Distribution;
|
||||
import org.deeplearning4j.nn.conf.distribution.Distributions;
|
||||
import org.deeplearning4j.nn.conf.distribution.NormalDistribution;
|
||||
import org.nd4j.linalg.api.ndarray.INDArray;
|
||||
import org.nd4j.linalg.api.rng.distribution.impl.OrthogonalDistribution;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor
|
||||
public class WeightInitDistribution implements IWeightInit {
|
||||
|
||||
private final Distribution distribution;
|
||||
@Getter @Setter
|
||||
private Distribution distribution;
|
||||
|
||||
public WeightInitDistribution(@JsonProperty("distribution") Distribution distribution) {
|
||||
|
||||
public WeightInitDistribution(@NonNull Distribution distribution) {
|
||||
if(distribution == null) {
|
||||
// Would fail later below otherwise
|
||||
throw new IllegalArgumentException("Must set distribution!");
|
||||
|
@ -40,6 +45,7 @@ public class WeightInitDistribution implements IWeightInit {
|
|||
this.distribution = distribution;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public INDArray init(double fanIn, double fanOut, long[] shape, char order, INDArray paramView) {
|
||||
//org.nd4j.linalg.api.rng.distribution.Distribution not serializable
|
||||
|
|
|
@ -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.ai.dnn.serde;
|
||||
|
||||
import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
|
||||
import org.deeplearning4j.nn.conf.distribution.NormalDistribution;
|
||||
import org.deeplearning4j.nn.conf.layers.DenseLayer;
|
||||
import org.deeplearning4j.nn.conf.layers.OutputLayer;
|
||||
import org.deeplearning4j.nn.weights.WeightInit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.nd4j.linalg.lossfunctions.LossFunctions;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
class NeuralNetConfigurationSerdeTest {
|
||||
|
||||
@Test
|
||||
void toYaml() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void toJson() {
|
||||
final var conf = NeuralNetConfiguration.builder()
|
||||
.weightInit(new NormalDistribution(3, 2))
|
||||
.layer(DenseLayer.builder().nIn(100).nOut(30).build())
|
||||
.layer(OutputLayer.builder().lossFunction(LossFunctions.LossFunction.SQUARED_LOSS).build())
|
||||
.build();
|
||||
assertEquals(conf.toJson(), NeuralNetConfiguration.fromJson(conf.toJson()).toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toJson2() {
|
||||
final var conf = NeuralNetConfiguration.builder()
|
||||
.weightInit(WeightInit.IDENTITY)
|
||||
.layer(DenseLayer.builder().nIn(100).nOut(30).build())
|
||||
.layer(OutputLayer.builder().lossFunction(LossFunctions.LossFunction.SQUARED_LOSS).build())
|
||||
.build();
|
||||
assertEquals(conf.toJson(), NeuralNetConfiguration.fromJson(conf.toJson()).toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromJson() {
|
||||
final String json = "{\n" +
|
||||
" \"activation\" : null,\n" +
|
||||
" \"seed\" : 12345, \n" +
|
||||
" \"allParamConstraints\" : [ ],\n" +
|
||||
" \"backpropType\" : \"Standard\",\n" +
|
||||
" \"biasConstraints\" : [ ],\n" +
|
||||
" \"biasInit\" : 0.0,\n" +
|
||||
" \"biasUpdater\" : null,\n" +
|
||||
" \"cacheMode\" : \"NONE\",\n" +
|
||||
" \"constrainWeights\" : [ ],\n" +
|
||||
" \"convolutionMode\" : \"Truncate\",\n" +
|
||||
" \"cudnnAlgoMode\" : \"PREFER_FASTEST\",\n" +
|
||||
" \"dampingFactor\" : 100.0,\n" +
|
||||
" \"dataType\" : \"FLOAT\",\n" +
|
||||
" \"epochCount\" : 0,\n" +
|
||||
" \"gainInit\" : 1.0,\n" +
|
||||
" \"gradientNormalization\" : \"None\",\n" +
|
||||
" \"gradientNormalizationThreshold\" : 0.0,\n" +
|
||||
" \"idropOut\" : null,\n" +
|
||||
" \"inferenceWorkspaceMode\" : \"ENABLED\",\n" +
|
||||
" \"initCalled\" : false,\n" +
|
||||
" \"innerConfigurations\" : [ {\n" +
|
||||
" \"org.deeplearning4j.nn.conf.layers.DenseLayer\" : {\n" +
|
||||
" \"activation\" : [ \"org.nd4j.linalg.activations.Activation\", \"IDENTITY\" ],\n" +
|
||||
" \"allParamConstraints\" : null,\n" +
|
||||
" \"biasConstraints\" : null,\n" +
|
||||
" \"biasInit\" : 0.0,\n" +
|
||||
" \"biasUpdater\" : null,\n" +
|
||||
" \"constrainWeights\" : [ ],\n" +
|
||||
" \"constraints\" : null,\n" +
|
||||
" \"dataType\" : null,\n" +
|
||||
" \"dropOut\" : null,\n" +
|
||||
" \"gainInit\" : 0.0,\n" +
|
||||
" \"gradientNormalization\" : \"None\",\n" +
|
||||
" \"gradientNormalizationThreshold\" : 1.0,\n" +
|
||||
" \"hasBias\" : true,\n" +
|
||||
" \"hasLayerNorm\" : false,\n" +
|
||||
" \"name\" : null,\n" +
|
||||
" \"nout\" : 30,\n" +
|
||||
" \"regularization\" : [ ],\n" +
|
||||
" \"regularizationBias\" : [ ],\n" +
|
||||
" \"type\" : \"UNKNOWN\",\n" +
|
||||
" \"variables\" : [ ],\n" +
|
||||
" \"weightConstraints\" : null,\n" +
|
||||
" \"weightInit\" : null,\n" +
|
||||
" \"weightNoise\" : null\n" +
|
||||
" }\n" +
|
||||
" }, {\n" +
|
||||
" \"org.deeplearning4j.nn.conf.layers.OutputLayer\" : {\n" +
|
||||
" \"activation\" : [ \"org.nd4j.linalg.activations.Activation\", \"IDENTITY\" ],\n" +
|
||||
" \"allParamConstraints\" : null,\n" +
|
||||
" \"biasConstraints\" : null,\n" +
|
||||
" \"biasInit\" : 0.0,\n" +
|
||||
" \"biasUpdater\" : null,\n" +
|
||||
" \"constrainWeights\" : [ ],\n" +
|
||||
" \"constraints\" : null,\n" +
|
||||
" \"dataType\" : null,\n" +
|
||||
" \"dropOut\" : null,\n" +
|
||||
" \"gainInit\" : 0.0,\n" +
|
||||
" \"gradientNormalization\" : \"None\",\n" +
|
||||
" \"gradientNormalizationThreshold\" : 1.0,\n" +
|
||||
" \"hasBias\" : true,\n" +
|
||||
" \"lossFunction\" : {\n" +
|
||||
" \"@class\" : \"org.nd4j.linalg.lossfunctions.impl.LossMSE\"\n" +
|
||||
" },\n" +
|
||||
" \"name\" : null,\n" +
|
||||
" \"nout\" : 0,\n" +
|
||||
" \"regularization\" : [ ],\n" +
|
||||
" \"regularizationBias\" : [ ],\n" +
|
||||
" \"type\" : \"UNKNOWN\",\n" +
|
||||
" \"variables\" : [ ],\n" +
|
||||
" \"weightConstraints\" : null,\n" +
|
||||
" \"weightInit\" : null,\n" +
|
||||
" \"weightNoise\" : null\n" +
|
||||
" }\n" +
|
||||
" } ],\n" +
|
||||
" \"inputPreProcessors\" : { },\n" +
|
||||
" \"inputType\" : null,\n" +
|
||||
" \"iterationCount\" : 0,\n" +
|
||||
" \"maxNumLineSearchIterations\" : 5,\n" +
|
||||
" \"miniBatch\" : false,\n" +
|
||||
" \"minimize\" : true,\n" +
|
||||
" \"name\" : \"Anonymous INeuralNetworkConfiguration\",\n" +
|
||||
" \"netWideVariables\" : [ ],\n" +
|
||||
" \"optimizationAlgo\" : \"STOCHASTIC_GRADIENT_DESCENT\",\n" +
|
||||
" \"overrideNinUponBuild\" : true,\n" +
|
||||
" \"regularization\" : [ ],\n" +
|
||||
" \"regularizationBias\" : [ ],\n" +
|
||||
" \"stepFunction\" : null,\n" +
|
||||
" \"tbpttBackLength\" : 20,\n" +
|
||||
" \"tbpttFwdLength\" : 20,\n" +
|
||||
" \"trainingWorkspaceMode\" : \"ENABLED\",\n" +
|
||||
" \"updater\" : {\n" +
|
||||
" \"@class\" : \"org.nd4j.linalg.learning.config.Sgd\",\n" +
|
||||
" \"learningRate\" : 0.001\n" +
|
||||
" },\n" +
|
||||
" \"validateOutputLayerConfig\" : true,\n" +
|
||||
" \"validateTbpttConfig\" : true,\n" +
|
||||
" \"weightInit\" : {\n" +
|
||||
" \"@class\" : \"org.deeplearning4j.nn.weights.WeightInitIdentity\",\n" +
|
||||
" \"scale\" : null\n" +
|
||||
" },\n" +
|
||||
" \"weightNoise\" : null\n" +
|
||||
"}";
|
||||
final var conf = NeuralNetConfiguration.builder()
|
||||
.weightInit(WeightInit.IDENTITY)
|
||||
.layer(DenseLayer.builder().nIn(100).nOut(30).build())
|
||||
.layer(OutputLayer.builder().lossFunction(LossFunctions.LossFunction.SQUARED_LOSS).build())
|
||||
.seed(12345)
|
||||
.build();
|
||||
NeuralNetConfiguration conf2 = NeuralNetConfiguration.fromJson(json);
|
||||
assertEquals(conf.toJson(),conf2.toJson());
|
||||
assertEquals(conf, conf2);
|
||||
}
|
||||
|
||||
}
|
|
@ -42,6 +42,7 @@ import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
|
|||
import org.deeplearning4j.nn.conf.graph.GraphVertex;
|
||||
import org.deeplearning4j.nn.conf.graph.LayerVertex;
|
||||
import org.deeplearning4j.nn.conf.layers.*;
|
||||
import org.deeplearning4j.nn.conf.serde.CavisMapper;
|
||||
import org.deeplearning4j.nn.conf.serde.JsonMappers;
|
||||
import org.deeplearning4j.ui.VertxUIServer;
|
||||
import org.deeplearning4j.ui.api.HttpMethod;
|
||||
|
@ -909,7 +910,7 @@ public class TrainModule implements UIModule {
|
|||
} else {
|
||||
try {
|
||||
NeuralNetConfiguration layer =
|
||||
NeuralNetConfiguration.mapper().readValue(config, NeuralNetConfiguration.class);
|
||||
CavisMapper.getMapper(CavisMapper.Type.JSON).readValue(config, NeuralNetConfiguration.class);
|
||||
return new Triple<>(null, null, layer);
|
||||
} catch (Exception e) {
|
||||
log.error("",e);
|
||||
|
|
Loading…
Reference in New Issue