Пример #1
0
 object ForwardPropagation(NeuralNetworkLayer layer, object inputs)
 {
     if (layer.Previous == null || layer.Previous.Length == 0)
     {
         return(layer.ForwardPropagation(inputs));
     }
     if (layer.Previous.Length == 1)
     {
         if (layer.Previous[0].Flags != Flags)
         {
             layer.Previous[0].Flags = Flags;
             ForwardPropagation(layer.Previous[0], inputs);
         }
         return(layer.ForwardPropagation(layer.Previous[0].Outputs));
     }
     if (layer is NeuralNetworkAddLayer || layer is NeuralNetworkConcatenateLayer)
     {
         object[] multiOutputs = new object[layer.Previous.Length];
         for (int i = 0; i < layer.Previous.Length; i++)
         {
             if (layer.Previous[i].Flags != Flags)
             {
                 layer.Previous[i].Flags = Flags;
                 ForwardPropagation(layer.Previous[i], inputs);
             }
             multiOutputs[i] = layer.Previous[i].Outputs;
         }
         return(layer.ForwardPropagation(multiOutputs));
     }
     throw new NotImplementedException(layer.ToString());
 }
Пример #2
0
        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);
                }
            }
        }