public void ConvUtils_ReshapeConvolutionsToRowMajor() { var batchSize = 5; var filterHeight = 2; var filterWidth = 2; var filterDepth = 2; var stride = 1; var padding = 0; var inputWidth = 3; var inputHeight = 3; var inputDepth = 3; var filterGridWidth = ConvUtils.GetFilterGridLength(inputWidth, filterWidth, stride, padding, BorderMode.Valid); var filterGridHeight = ConvUtils.GetFilterGridLength(inputHeight, filterHeight, stride, padding, BorderMode.Valid); var k = filterDepth; var crs = inputDepth * filterWidth * filterHeight; var npq = batchSize * filterGridWidth * filterGridHeight; var convolutedInput = Matrix <float> .Build.Dense(k, npq, new float[] { -6.260461f, 87.38299f, -7.173417f, 94.47046f, -8.999331f, 108.6454f, -9.912288f, 115.7329f, -6.260461f, 87.38299f, -7.173417f, 94.47046f, -8.999331f, 108.6454f, -9.912288f, 115.7329f, -6.260461f, 87.38299f, -7.173417f, 94.47046f, -8.999331f, 108.6454f, -9.912288f, 115.7329f, -6.260461f, 87.38299f, -7.173417f, 94.47046f, -8.999331f, 108.6454f, -9.912288f, 115.7329f, -6.260461f, 87.38299f, -7.173417f, 94.47046f, -8.999331f, 108.6454f, -9.912288f, 115.7329f }); var actual = Matrix <float> .Build.Dense(batchSize, k *filterGridWidth *filterGridHeight); ConvUtils.ReshapeConvolutionsToRowMajor(convolutedInput, inputDepth, inputHeight, inputWidth, filterHeight, filterWidth, padding, padding, stride, stride, BorderMode.Valid, actual); var expected = Matrix <float> .Build.Dense(batchSize, k *filterGridWidth *filterGridHeight, new float[] { -6.260461f, -6.260461f, -6.260461f, -6.260461f, -6.260461f, -7.173417f, -7.173417f, -7.173417f, -7.173417f, -7.173417f, -8.999331f, -8.999331f, -8.999331f, -8.999331f, -8.999331f, -9.912288f, -9.912288f, -9.912288f, -9.912288f, -9.912288f, 87.38299f, 87.38299f, 87.38299f, 87.38299f, 87.38299f, 94.47046f, 94.47046f, 94.47046f, 94.47046f, 94.47046f, 108.6454f, 108.6454f, 108.6454f, 108.6454f, 108.6454f, 115.7329f, 115.7329f, 115.7329f, 115.7329f, 115.7329f }); MatrixAsserts.AreEqual(expected, actual); }
public void BatchNormalizationLayer_Forward_SpatialInput() { var batchSize = 2; var filterHeight = 2; var filterWidth = 2; var filterDepth = 2; var stride = 1; var padding = 0; var inputWidth = 3; var inputHeight = 3; var inputDepth = 3; var filterGridWidth = ConvUtils.GetFilterGridLength(inputWidth, filterWidth, stride, padding, BorderMode.Valid); var filterGridHeight = ConvUtils.GetFilterGridLength(inputHeight, filterHeight, stride, padding, BorderMode.Valid); var k = filterDepth; var input = new float[] { 111, 121, 112, 122, 113, 123, 114, 124, 211, 221, 212, 222, 213, 223, 214, 224 }; var convInput = Matrix <float> .Build.Dense(2, 8, input); var rowWiseInput = Matrix <float> .Build.Dense(batchSize, k *filterGridWidth *filterGridHeight); Trace.WriteLine(convInput); ConvUtils.ReshapeConvolutionsToRowMajor(convInput, inputDepth, inputHeight, inputWidth, filterHeight, filterWidth, padding, padding, stride, stride, BorderMode.Valid, rowWiseInput); Trace.WriteLine(rowWiseInput); var sut = new BatchNormalizationLayer(); sut.Initialize(filterGridWidth, filterGridHeight, filterDepth, batchSize, Initialization.GlorotUniform, new Random(232)); var actual = sut.Forward(rowWiseInput); Trace.WriteLine(string.Join(", ", actual.ToColumnMajorArray())); Trace.WriteLine(actual); var expected = Matrix <float> .Build.Dense(batchSize, k *filterGridWidth *filterGridHeight, new float[] { -1.0297426f, 0.9697576f, -1.00974762f, 0.9897526f, -0.9897526f, 1.00974762f, -0.9697576f, 1.0297426f, -1.0297426f, 0.9697576f, -1.00974762f, 0.9897526f, -0.9897526f, 1.00974762f, -0.9697576f, 1.0297426f }); MatrixAsserts.AreEqual(expected, actual); }
/// <summary> /// /// </summary> /// <param name="input"></param> /// <returns></returns> public Matrix <float> Forward(Matrix <float> input) { m_inputActivations = input; // Arrange input item for GEMM version of convolution. ConvUtils.Batch_Im2Col(m_inputActivations, InputDepth, InputHeight, InputWidth, FilterWidth, FilterHeight, m_padHeight, m_padWidth, m_stride, m_stride, BorderMode, Im2Cols); // matrix multiplication for convolution Weights.Multiply(Im2Cols, Conv); Conv.AddColumnWise(Bias, Conv); // Return the covolved data to row major and copy data to output ConvUtils.ReshapeConvolutionsToRowMajor(Conv, InputDepth, InputHeight, InputWidth, FilterWidth, FilterHeight, m_padHeight, m_padWidth, m_stride, m_stride, BorderMode, OutputActivations); return(OutputActivations); }
/// <summary> /// /// </summary> /// <param name="delta"></param> /// <returns></returns> public Matrix <float> Backward(Matrix <float> delta) { // Reshape delta to fit with data layout in im2col ConvUtils.ReshapeConvolutionsToRowMajor(delta, InputDepth, InputHeight, InputWidth, FilterWidth, FilterHeight, m_padHeight, m_padWidth, m_stride, m_stride, BorderMode, m_deltaInReshape); // Calculate gradients for weights and biases m_deltaInReshape.TransposeAndMultiply(Im2Cols, WeightsGradients); m_deltaInReshape.SumRows(BiasGradients); // calcualte delta for next layer. Weights.TransposeThisAndMultiply(m_deltaInReshape, Im2Cols); // convert back to original layout m_delta.Clear(); ConvUtils.Batch_Col2Im(Im2Cols, InputDepth, InputHeight, InputWidth, FilterHeight, FilterWidth, m_padHeight, m_padWidth, m_stride, m_stride, BorderMode, m_delta); return(m_delta); }