public NeuralNetworkMaxPooling2DLayer(int width, int height, int strideX, int strideY, NeuralNetworkPaddingType paddingType) { Type = NeuralNetworkLayerType.MaxPooling2D; Width = width; Height = height; StrideX = strideX; StrideY = strideY; PaddingType = paddingType; }
public NeuralNetworkConv2DLayer( NeuralNetworkKernel[] kernels, int width, int height, int strideX, int strideY, NeuralNetworkActivationFunctionType activationFunctionType, NeuralNetworkPaddingType paddingType ) { Type = NeuralNetworkLayerType.Conv2D; Kernels = kernels; Width = width; Height = height; StrideX = strideX; StrideY = strideY; ActivationFunctionType = activationFunctionType; PaddingType = paddingType; }
public static int CalculateOutputLength(int inputLength, int size, int stride, NeuralNetworkPaddingType paddingType) { switch (paddingType) { case NeuralNetworkPaddingType.Valid: return((int)Math.Ceiling((float)(inputLength - size + 1) / stride)); case NeuralNetworkPaddingType.Same: return((int)Math.Ceiling((float)inputLength / stride)); default: throw new NotImplementedException(paddingType.ToString()); } }
public void Load(INeuralNetworkLoader loader, JsonTextWriter textWriter = null) { if (loader is null) { throw new ArgumentNullException(nameof(loader)); } JsonObject modelConfig = loader.GetModelConfig(); if (textWriter != null) { textWriter.BeginObject(); textWriter.Write(NeuralNetworkKeyword.ModelConfig); new JsonTextBuilder(new JsonValueReader(modelConfig), textWriter).BuildObject(); } IsSequential = modelConfig["class_name"] == "Sequential"; NeuralNetworkLayer previousLayer = null; Layers.Clear(); foreach (JsonObject jsonLayer in modelConfig["config"]["layers"].Array) { string className = jsonLayer["class_name"]; JsonObject config = jsonLayer["config"]; string name = config["name"]; JsonValue activation = config["activation"]; JsonValue dataFormat = config["data_format"]; JsonValue padding = config["padding"]; NeuralNetworkLayer layer; JsonArray inboundNodes = jsonLayer["inbound_nodes"][0]; foreach (JsonValue inboundNode in inboundNodes) { string targetName = inboundNode[0]; foreach (NeuralNetworkLayer currentLayer in Layers) { if (currentLayer.Name == targetName) { previousLayer = currentLayer; break; } } } switch (className) { case "InputLayer": { JsonArray batchInputShape = config["batch_input_shape"]; batchInputShape.RemoveAt(0); List <int> inputShapes = JsonConvert.Deserialize <List <int> > (batchInputShape); AddLayer(new NeuralNetworkInputLayer()); layer.InputShape = inputShapes.ToArray(); layer.OutputShape = layer.InputShape; break; } case nameof(NeuralNetworkLayerType.Dense): { int units = config["units"]; float[,] weights = loader.GetDenseWeights(name, units, previousLayer.OutputShape[0]); float[] biases = loader.GetBiases(name, units); if (textWriter != null) { WriteLayer(textWriter, name, weights, biases); } NeuralNetworkNeuron[] neurons = new NeuralNetworkNeuron[units]; for (int i = 0; i < neurons.Length; i++) { neurons[i] = new NeuralNetworkNeuron(previousLayer.OutputShape[0], biases[i]); for (int n = 0; n < previousLayer.OutputShape[0]; n++) { neurons[i].Weights[n] = weights[n, i]; } } int[] outputShape = new int[] { units }; AddLayer(new NeuralNetworkDenseLayer(neurons, NeuralNetworkAPI.GetActivationFunctionType(activation))); layer.OutputShape = outputShape; break; } case nameof(NeuralNetworkLayerType.Conv2D): { JsonArray kernelSize = config["kernel_size"]; JsonArray strides = config["strides"]; int units = config["filters"]; int width = kernelSize[1]; int height = kernelSize[0]; int channel = previousLayer.OutputShape[2]; int strideX = strides[1]; int strideY = strides[0]; float[,,,] weights = loader.GetConv2DWeights(name, width, height, channel, units); float[] biases = loader.GetBiases(name, units); if (textWriter != null) { WriteLayer(textWriter, name, weights, biases); } NeuralNetworkPaddingType paddingType = NeuralNetworkAPI.GetPaddingType(padding); NeuralNetworkKernel[] kernels = new NeuralNetworkKernel[units]; for (int i = 0; i < kernels.Length; i++) { kernels[i] = new NeuralNetworkKernel(width, height, channel, strideX, strideY, biases[i], paddingType); for (int c = 0; c < channel; c++) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { kernels[i].Weights[y, x, c] = weights[y, x, c, i]; } } } } int[] outputShape = new int[] { NeuralNetworkAPI.CalculateOutputLength(previousLayer.OutputShape[0], height, strideY, paddingType), NeuralNetworkAPI.CalculateOutputLength(previousLayer.OutputShape[1], width, strideX, paddingType), units }; AddLayer(new NeuralNetworkConv2DLayer( kernels, width, height, strideX, strideY, NeuralNetworkAPI.GetActivationFunctionType(activation), paddingType) ); layer.OutputShape = outputShape; break; } case nameof(NeuralNetworkLayerType.MaxPooling2D): { JsonArray poolSize = config["pool_size"]; JsonArray strides = config["strides"]; int width = poolSize[1]; int height = poolSize[0]; int strideX = strides[1]; int strideY = strides[0]; NeuralNetworkPaddingType paddingType = NeuralNetworkAPI.GetPaddingType(padding); int[] outputShape = new int[] { NeuralNetworkAPI.CalculateOutputLength(previousLayer.OutputShape[0], height, strideY, paddingType), NeuralNetworkAPI.CalculateOutputLength(previousLayer.OutputShape[1], width, strideX, paddingType), previousLayer.OutputShape[2] }; AddLayer(new NeuralNetworkMaxPooling2DLayer(width, height, strideX, strideY, paddingType)); layer.OutputShape = outputShape; break; } case nameof(NeuralNetworkLayerType.Dropout): { layer = new NeuralNetworkDropoutLayer(); layer.OutputShape = previousLayer.OutputShape; break; } case nameof(NeuralNetworkLayerType.Flatten): { NeuralNetworkDataFormatType dataFormatType = NeuralNetworkAPI.GetDataFormatType(dataFormat); int sum = 1; NeuralNetworkLayer lastLayer = Layers[Layers.Count - 1]; foreach (int length in lastLayer.OutputShape) { sum *= length; } int[] outputShape = new int[] { sum }; AddLayer(new NeuralNetworkFlattenLayer(dataFormatType)); layer.OutputShape = outputShape; break; } case nameof(NeuralNetworkLayerType.Add): { AddLayer(new NeuralNetworkAddLayer()); layer.OutputShape = previousLayer.OutputShape; break; } case nameof(NeuralNetworkLayerType.BatchNormalization): { AddLayer(new NeuralNetworkBatchNormalizationLayer( loader.GetValues(name, "beta", previousLayer.OutputShape[2]), loader.GetValues(name, "gamma", previousLayer.OutputShape[2]), loader.GetValues(name, "moving_mean", previousLayer.OutputShape[2]), loader.GetValues(name, "moving_variance", previousLayer.OutputShape[2]), config["epsilon"] )); layer.OutputShape = previousLayer.OutputShape; break; } case nameof(NeuralNetworkLayerType.LeakyReLU): { AddLayer(new NeuralNetworkLeakyReLULayer(config["alpha"])); layer.OutputShape = previousLayer.OutputShape; break; } case nameof(NeuralNetworkLayerType.ZeroPadding2D): { int paddingX = config["padding"][1][0]; int paddingY = config["padding"][0][0]; AddLayer(new NeuralNetworkZeroPadding2DLayer(paddingX, paddingY)); int[] outputShape = new int[] { previousLayer.OutputShape[0] + paddingY * 2, previousLayer.OutputShape[1] + paddingX * 2, previousLayer.OutputShape[2] }; layer.OutputShape = outputShape; break; } case nameof(NeuralNetworkLayerType.UpSampling2D): { int sizeX = config["size"][1]; int sizeY = config["size"][0]; AddLayer(new NeuralNetworkUpSampling2DLayer(sizeX, sizeY)); int[] outputShape = new int[] { previousLayer.OutputShape[0] * sizeY, previousLayer.OutputShape[1] * sizeX, previousLayer.OutputShape[2] }; layer.OutputShape = outputShape; break; } case nameof(NeuralNetworkLayerType.Concatenate): { AddLayer(new NeuralNetworkConcatenateLayer()); int channels = 0; foreach (NeuralNetworkLayer currentLayer in layer.Previous) { channels += currentLayer.OutputShape[2]; } int[] outputShape = new int[] { previousLayer.OutputShape[0], previousLayer.OutputShape[1], channels }; layer.OutputShape = outputShape; break; } default: throw new NotImplementedException(className); } void AddLayer(NeuralNetworkLayer newLayer) { newLayer.Name = name; if (IsSequential) { if (Layers.Count > 0) { newLayer.InputShape = previousLayer.OutputShape; previousLayer.Nexts.Add(newLayer); newLayer.Previous = new NeuralNetworkLayer[] { previousLayer }; } previousLayer = newLayer; } else { List <NeuralNetworkLayer> previous = new List <NeuralNetworkLayer> (); foreach (JsonValue inboundNode in inboundNodes) { string targetName = inboundNode[0]; foreach (NeuralNetworkLayer currentLayer in Layers) { if (currentLayer.Name == targetName) { currentLayer.Nexts.Add(newLayer); previous.Add(currentLayer); previousLayer = currentLayer; } } } if (previous.Count > 0) { newLayer.Previous = previous.ToArray(); newLayer.InputShape = newLayer.Previous[0].OutputShape; } } Layers.Add(newLayer); layer = newLayer; } } if (textWriter != null) { textWriter.EndObject(); } if (IsSequential) { OutputLayers = new NeuralNetworkLayer[] { previousLayer }; } else { JsonArray outputLayers = modelConfig["config"]["output_layers"]; OutputLayers = new NeuralNetworkLayer[outputLayers.Count]; for (int i = 0; i < outputLayers.Count; i++) { string targetName = outputLayers[i][0]; OutputLayers[i] = Layers.Find(layer => layer.Name == targetName); } } }