public NNValue Nonlin(INonlinearity neuron, NNValue m) { NNValue returnObj = new NNValue(m.H, m.W); int n = m.DataInTensor.Length; returnObj = neuron.Forward(m); if (this.ApplyBackprop) { Runnable bp = new Runnable(); bp.Run = delegate() { var data = neuron.Backward(m); for (int i = 0; i < n; i++) { m.DifData[i] += data.DataInTensor[i] * returnObj.DifData[i]; } }; Backprop.Add(bp); } return(returnObj); }
/// <summary> /// Макс пул /// </summary> /// <param name="inp"></param> /// <param name="h"></param> /// <param name="w"></param> /// <returns></returns> public NNValue MaxPooling(NNValue input, int h, int w) { //Func<double[], double> funcMax = (dataArray) => //{ // return dataArray.Max(); //}; int outpH = input.H / h, outpW = input.W / w, outpD = input.D; double[] data = new double[h * w]; bool[,,] map = new bool[input.H, input.W, input.D]; if ((outpW < 1) || (outpH < 1)) { throw new Exception("Недостаточная размерность выхода"); } int modW = input.W % w; int modH = input.H % h; int maxX = input.W - modW; int maxY = input.H - modH; NNValue returnObj = new NNValue(outpH, outpW, outpD); for (int s = 0; s < outpD; s++) { for (int y = 0, y1 = 0; y < maxY; y += h, y1++) { for (int x = 0, x1 = 0; x < maxX; x += w, x1++) { int i = y, j = x; for (int dy = 0; dy < h; dy++) { for (int dx = 0; dx < w; dx++) { if (input[i, j, s] < input[y + dy, x + dx, s]) { i = y + dy; j = x + dx; } } } var max = input[i, j, s]; returnObj[y1, x1, s] = max; map[i, j, s] = true; } } } ; //------------------------------------------------------------------------------------------ // Обратный проход if (this.ApplyBackprop) { int i = 0; Runnable bp = new Runnable(); bp.Run = delegate() { for (int n = 0; n < input.D; n++) { for (int y = 0; y < input.H; y++) { for (int x = 0; x < input.W; x++) { input.DifData[input.W * y + x + input.W * input.H * n] = map[y, x, n]? returnObj.DifData[i++]:0; } } } }; Backprop.Add(bp); } return(returnObj); }
/// <summary> /// Свертка /// </summary> /// <param name="input">Тензор входа</param> /// <param name="filters">Фильтры</param> public NNValue Convolution(NNValue input, NNValue[] filters, int padX, int padY) { int outpH, outpW, outpD = filters.Length; outpH = input.H - filters[0].H + 1 + padY; outpW = input.W - filters[0].W + 1 + padX; if ((outpW < 1) || (outpH < 1)) { throw new Exception("Недостаточная размерность выхода"); } NNValue returnObj = new NNValue(outpH, outpW, outpD); // Parallel.For(0, outpD, new ParallelOptions() { MaxDegreeOfParallelism = 2}, s => for (int s = 0; s < outpD; s++) { for (int y = -padY; y < outpH; y++) { for (int x = -padX; x < outpW; x++) { for (int z = 0; z < input.D; z++) { for (int dy = 0; dy < filters[0].H; dy++) { int y1 = y + dy; for (int dx = 0; dx < filters[0].W; dx++) { int x1 = x + dx; if ((x1 > -1) && (y1 > -1) && (x1 < outpW) && (y1 < outpH)) { returnObj[y1, x1, s] += input[y + dy, x + dx, z] * filters[s][dy, dx, z]; } } } } } } } //------------------------------------------------------------------------------------------ // Обратный проход if (this.ApplyBackprop) { Runnable bp = new Runnable(); bp.Run = delegate() { Parallel.For(0, outpD, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, d => { for (int z = 0; z < input.D; z++) { for (int y = 0; y < filters[0].H; y++) { for (int x = 0; x < filters[0].W; x++) { for (int a = -padY; a < outpH; a++) { for (int b = -padX; b < outpW; b++) { int x1 = b + x; int y1 = a + y; if ((y1 > -1) && (x1 > -1) && (y1 < outpH) && (x1 < outpW)) { double delt = returnObj.DifData[outpW * y1 + x1 + outpW * outpH * d]; filters[d].DifData[filters[0].W * y + x + filters[0].W * filters[0].H * z] += delt * input[a + y, b + x, z]; } // --------------- ------------- ------------ ---------------// } } } } } }); Parallel.For(0, input.D, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, n => { for (int y = -padY; y < input.H; y++) { for (int x = -padX; x < input.W; x++) { for (int i = 0; i < outpD; i++) { for (int dy = 0; dy < filters[0].H; dy++) { var dyy = y - dy; for (int dx = 0; dx < filters[0].W; dx++) { var dxx = x - dx; if ((dyy > -1) && (dxx > -1) && (dyy < outpH) && (dxx < outpW)) { if ((dxx > -1) && (dyy > -1) && (dyy < outpH) && (dxx < outpW)) { double delt = returnObj.DifData[outpW * (y - dy) + (x - dx) + outpW * outpH * i]; input.DifData[input.W * y + x + input.W * input.H * n] += delt * filters[i][dy, dx, n]; } } } } } } } }); }; Backprop.Add(bp); } return(returnObj); }
public NNValue smul(double s, NNValue m) { NNValue returnObj = smul(m, s); return(returnObj); }
public NNValue smul(NNValue m, double s) { NNValue m2 = NNValue.Uniform(m.H, m.W, s); return(Elmul(m, m2)); }
public NNValue Subtract(NNValue m1, NNValue m2) { return(Add(m1, Neg(m2))); }
public NNValue OneMinus(NNValue m) { NNValue ones = NNValue.Ones(m.H, m.W); return(Subtract(ones, m)); }