/// <summary> /// 前向传播,计算卷积结果 /// </summary> public double[,] CalculatedConvolutionResult(List <double[, ]> value) { InputValue = value; double[,] result = new double[ConvolutionKernelWidth, ConvolutionKernelHeight]; for (int i = 0; i < ConvolutionKernelWidth; i++) { for (int j = 0; j < ConvolutionKernelHeight; j++) { for (int k = 0; k < value.Count; k++) { result[i, j] += CalculatedConvolutionPointResult(value[k], i, j, k);//卷积 } } } if (Standardization) { mean = CnnHelper.GetMean(result); variance = CnnHelper.GetVariance(result, mean); } //归一化每个结果 for (int i = 0; i < ConvolutionKernelWidth; i++) { for (int j = 0; j < ConvolutionKernelHeight; j++) { if (Standardization) { //调用激活函数计算结果 double z = (result[i, j] - mean) / Math.Sqrt(variance); //if (double.IsNaN(z)) // z = result[i, j] > 0 ? 1 : -1; result[i, j] = ActivationFunction(z + OutputOffset); } else { result[i, j] = ActivationFunction(result[i, j] + OutputOffset); } } } //正则化 if (CnnHelper.RandomObj.NextDouble() < dropoutChance) { for (int i = 0; i < ConvolutionKernelWidth; i++) { for (int j = 0; j < ConvolutionKernelHeight; j++) { result[i, j] = 0; } } dropoutState = true; } OutputValue = result; return(result); }
/// <summary> /// 前向传播,计算结果 /// </summary> public double[] CalculatedResult(double[] inputValue) { InputValue = inputValue; double[] result = new double[OutputCount]; for (int i = 0; i < OutputCount; i++) { result[i] = CalculatedPointResult(inputValue, i); //result[i] = CalculatedPointResult(value, i) + OutputOffset[i]; //调用激活函数计算结果 if (!Standardization) { result[i] = ActivationFunction(result[i] + OutputOffset[i]); } } if (Standardization) { mean = CnnHelper.GetMean(result); variance = CnnHelper.GetVariance(result, mean); //归一化每个结果 for (int i = 0; i < OutputCount; i++) { //调用激活函数计算结果 double z = (result[i] - mean) / Math.Sqrt(variance); result[i] = ActivationFunction(z + OutputOffset[i]); } } //正则化 if (CnnHelper.RandomObj.NextDouble() < dropoutChance) { for (int i = 0; i < OutputCount; i++) { result[i] = 0; } dropoutState = true; } OutputValue = result; return(result); }
/// <summary> /// 计算反向传播结果 /// </summary> /// <returns></returns> private List <double[, ]> CalculatedBackPropagationResult(double[,] residual, double learningRate) { //上一层残差 List <double[, ]> result = new List <double[, ]>(); //当前层残差 //double[,] residualNow = new double[ConvolutionKernelWidth, ConvolutionKernelHeight]; //权重残差 List <double[, ]> deltaWeight = new List <double[, ]>(); //偏置残差 double deltaOffset = 0; //正则化 if (dropoutState) { for (int inputIndex = 0; inputIndex < InputCount; inputIndex++) { result.Add(new double[inputWidth, inputHeight]); } dropoutState = false; return(result); } //残差 for (int i = 0; i < ConvolutionKernelWidth; i++) { for (int j = 0; j < ConvolutionKernelHeight; j++) { //residual[i, j] = ActivationFunctionDerivative(OutputValue[i, j]) * (output[i, j] - OutputValue[i, j]); //residual[i, j] = (output[i, j] - OutputValue[i, j]);//正确 } } for (int inputIndex = 0; inputIndex < InputCount; inputIndex++) { double[,] tmpResultDelta = CnnHelper.ConvolutionFull(CnnHelper.MatrixRotate180(ShareWeight[inputIndex]), residual);//CNN标准 //double[,] tmpResultDelta = CnnHelper.ConvolutionFull(ShareWeight[inputIndex], residual);//CNN例子 result.Add(tmpResultDelta); //double[,] tmpDeltaWeight = CnnHelper.ConvolutionValid(residual, CnnHelper.MatrixRotate180(InputValue[inputIndex]));//CNN例子 double[,] tmpDeltaWeight = CnnHelper.MatrixRotate180(CnnHelper.ConvolutionValid(residual, CnnHelper.MatrixRotate180(InputValue[inputIndex])));//CNN标准 deltaWeight.Add(tmpDeltaWeight); } //计算偏置残差 for (int i = 0; i < ConvolutionKernelWidth; i++) { for (int j = 0; j < ConvolutionKernelHeight; j++) { deltaOffset += residual[i, j]; } } //计算平均梯度 /* * meanListDeltaWeight.Add(deltaWeight); * for (int inputIndex = 0; inputIndex < InputCount; inputIndex++) * { * for (int i = 0; i < receptiveFieldWidth; i++) * { * for (int j = 0; j < receptiveFieldHeight; j++) * { * if (meanListDeltaWeight.Count > miniBatchSize) * { * meanDeltaWeight[inputIndex][i, j] -= meanListDeltaWeight[0][inputIndex][i, j] / miniBatchSize; * meanDeltaWeight[inputIndex][i, j] += deltaWeight[inputIndex][i, j] / miniBatchSize; * meanListDeltaWeight.RemoveAt(0); * } * else * { * meanDeltaWeight[inputIndex][i, j] = 0; * foreach (var tmpShareWeight in meanListDeltaWeight) * { * meanDeltaWeight[inputIndex][i, j] += tmpShareWeight[inputIndex][i, j] / meanListDeltaWeight.Count; * } * } * } * } * } * meanListDeltaOffset.Add(deltaOffset); * if (meanListDeltaOffset.Count > miniBatchSize) * { * meanDeltaOffset -= meanListDeltaOffset[0] / miniBatchSize; * meanDeltaOffset += deltaOffset / miniBatchSize; * meanListDeltaOffset.RemoveAt(0); * } * else * { * meanDeltaOffset = 0; * foreach (var tmpShareOffset in meanListDeltaOffset) * { * meanDeltaOffset += tmpShareOffset / meanListDeltaOffset.Count; * } * } * //*/ //计算正确输入值 for (int inputIndex = 0; inputIndex < InputCount; inputIndex++) { for (int i = 0; i < inputWidth; i++) { for (int j = 0; j < inputHeight; j++) { //resultDelta[inputIndex][i, j] *= ActivationFunctionDerivative(InputValue[inputIndex][i, j]); if (Standardization) { //反归一化每个结果 result[inputIndex][i, j] = result[inputIndex][i, j] * Math.Sqrt(variance) + mean; } } } } //更新权重和偏置 UpdateWeight(deltaWeight, learningRate); UpdateOffset(deltaOffset, learningRate); //UpdateWeight(meanDeltaWeight, learningRate); //UpdateOffset(meanDeltaOffset, learningRate); //调试参数 //debugResult = resultDelta; //debugResidual = residual; //debugDeltaWeight = deltaWeight; //debugDeltaOffset = deltaOffset; return(result); }