Example #1
0
        internal override NNDetailedFeedData FeedForward(NNFeedData input)
        {
            float[] output     = new float[Neurons];
            int[]   maxIndices = new int[Neurons];

            for (int zIdx = 0; zIdx < PreviousLayer.Depth; zIdx++)
            {
                for (int yiIdx = 0, yoIdx = 0; yoIdx < Height; yiIdx += this.Stride, yoIdx++)
                {
                    for (int xiIdx = 0, xoIdx = 0; xoIdx < Width; xiIdx += this.Stride, xoIdx++)
                    {
                        float max    = float.MinValue;
                        int   maxIdx = -1;

                        for (int fyIdx = 0; fyIdx < this.FilterSize; fyIdx++)
                        {
                            for (int fxIdx = 0; fxIdx < this.FilterSize; fxIdx++)
                            {
                                int idx = PreviousLayer.ConvertToNeuronIndex(xiIdx + fxIdx, yiIdx + fyIdx, zIdx);

                                if (input[idx] > max)
                                {
                                    max    = input[idx];
                                    maxIdx = idx;
                                }
                            }
                        }

                        int i = ConvertToNeuronIndex(xoIdx, yoIdx, zIdx);
                        output[i]     = max;
                        maxIndices[i] = maxIdx;
                    }
                }
            }

            NNDetailedFeedData feedData = new NNDetailedFeedData(this, output, output);

            feedData.CustomData[nameof(maxIndices)] = maxIndices;

            return(feedData);
        }
Example #2
0
        internal override void PropagateBackward(NNDetailedBackpropagationData backpropagationData)
        {
            float[] lastRawOutput = backpropagationData.FeedForwardData[this].RawOutputData;

            float[] dE_dz      = new float[Neurons];
            float[] newWeights = new float[this.weights.Length];

            // For each filter
            for (int fIdx = 0; fIdx < FilterCount; fIdx++)
            {
                float   dE_db = 0;
                float[] dE_dw = new float[FilterSize * FilterSize * PreviousLayer.Depth];

                for (int yIdx = 0; yIdx < Height; yIdx++)
                {
                    for (int xIdx = 0; xIdx < Width; xIdx++)
                    {
                        int oIdx = ConvertToNeuronIndex(xIdx, yIdx, fIdx);

                        float do_dz = Activation.Gradient(lastRawOutput[oIdx], lastRawOutput);

                        float dE_do;
                        if (NextLayer == null)
                        {
                            float o = backpropagationData.FeedForwardData[this].OutputData[oIdx];
                            dE_do = backpropagationData.ErrorGradient(o, oIdx);
                        }
                        else
                        {
                            dE_do = NextLayer.CalculateErrorByOutputGradient(backpropagationData, oIdx);
                        }

                        float dE_dz_tmp = dE_do * do_dz;
                        dE_dz[oIdx] = dE_dz_tmp;

                        for (int fzIdx = 0; fzIdx < PreviousLayer.Depth; fzIdx++)
                        {
                            for (int fyIdx = 0; fyIdx < FilterSize; fyIdx++)
                            {
                                for (int fxIdx = 0; fxIdx < FilterSize; fxIdx++)
                                {
                                    float dz_dw = backpropagationData.FeedForwardData[PreviousLayer].OutputData[PreviousLayer.ConvertToNeuronIndex(xIdx * Stride + fxIdx, yIdx * Stride + fyIdx, fzIdx)];

                                    dE_dw[ToWeightIndex(fxIdx, fyIdx, fzIdx, 0)] += dE_dz_tmp * dz_dw;
                                }
                            }
                        }

                        dE_db += dE_do * do_dz;   // dz_dw = 1 for bias
                    }
                }

                for (int fzIdx = 0; fzIdx < PreviousLayer.Depth; fzIdx++)
                {
                    for (int fyIdx = 0; fyIdx < FilterSize; fyIdx++)
                    {
                        for (int fxIdx = 0; fxIdx < FilterSize; fxIdx++)
                        {
                            int weightIndex = ToWeightIndex(fxIdx, fyIdx, fzIdx, fIdx);
                            newWeights[weightIndex] = backpropagationData.CalculateNewWeight(this.weights[weightIndex], dE_dw[ToWeightIndex(fxIdx, fyIdx, fzIdx, 0)], this, weightIndex);
                        }
                    }
                }

                this.biases[fIdx] += backpropagationData.CalculateNewWeight(this.biases[fIdx], dE_db, this, fIdx);
            }

            backpropagationData.dE_dz[this]          = dE_dz;
            backpropagationData.UpdatedWeights[this] = newWeights;
        }