/// <summary> /// Setup the layer. /// </summary> /// <param name="colBottom">Specifies the collection of bottom (input) Blobs.</param> /// <param name="colTop">Specifies the collection of top (output) Blobs.</param> public override void LayerSetUp(BlobCollection <T> colBottom, BlobCollection <T> colTop) { m_log.CHECK(m_param.eltwise_param.coeff.Count == 0 || m_param.eltwise_param.coeff.Count == colBottom.Count, "Eltwise layer takes one coefficient per bottom blob."); m_log.CHECK(!((m_param.eltwise_param.operation == EltwiseParameter.EltwiseOp.PROD || m_param.eltwise_param.operation == EltwiseParameter.EltwiseOp.DIV) && m_param.eltwise_param.coeff.Count > 0), "Eltwise layer only takes coefficients for SUM and SUB operations."); m_op = m_param.eltwise_param.operation; m_bCoeffBlob = m_param.eltwise_param.coeff_blob; if (m_bCoeffBlob) { m_log.CHECK(m_op == EltwiseParameter.EltwiseOp.SUM || m_op == EltwiseParameter.EltwiseOp.SUB, "coeff_blob option only implemented for the SUM and SUB operation."); } int nCoeffSize = m_param.eltwise_param.coeff.Count; m_log.CHECK(nCoeffSize == 0 || (!m_bCoeffBlob && nCoeffSize == colBottom.Count) || (m_bCoeffBlob && nCoeffSize == colBottom.Count - 1), "Eltwise Layer takes one coefficient per bottom blob."); m_log.CHECK(m_op == EltwiseParameter.EltwiseOp.SUM || m_op == EltwiseParameter.EltwiseOp.SUB || layer_param.eltwise_param.coeff.Count == 0, "Eltwise layer only takes coefficients for SUM and SUB operations."); // Blob-wise coefficients for the elementwise operation. m_rgdfCoeffs = Utility.Create <double>(colBottom.Count, 1.0); int nCoeffBlobCount = (m_bCoeffBlob) ? 1 : 0; for (int i = 0; i < m_param.eltwise_param.coeff.Count - nCoeffBlobCount; i++) { m_rgdfCoeffs[i] = m_param.eltwise_param.coeff[i]; } m_bStableProdGrad = m_param.eltwise_param.stable_prod_grad; }
public Eltwise(EltwiseParameter.EltwiseOp operation, float[] coeffs, string name = FUNCTION_NAME, string[] inputNames = null, string[] outputNames = null) : base(name, inputNames, outputNames) { this._operation = operation; this._coeffs = coeffs; MultiInputForward = ForwardCpu; MultiOutputBackward = BackwardCpu; }
public Eltwise(EltwiseParameter.EltwiseOp operation, float[] coeffs, string name = FUNCTION_NAME, string[] inputNames = null, string[] outputNames = null) : base(name, inputNames, outputNames) { this._operation = operation; this._coeffs = coeffs; InitFunc(new StreamingContext()); }
public static NdArray <Real>[] MultiInputForward(NdArray <Real>[] xs, EltwiseParameter.EltwiseOp operation, float[] coeffs, List <int[]> PrevOutputIndex, IFunction <Real> eltwise) { Real[] result = new Real[xs[0].Data.Length]; switch (operation) { case EltwiseParameter.EltwiseOp.Prod: Array.Copy(xs[0].Data, result, result.Length); for (int i = 1; i < xs.Length; i++) { for (int j = 0; j < result.Length; j++) { result[j] *= xs[i].Data[j]; } } break; case EltwiseParameter.EltwiseOp.Sum: if (coeffs != null) { for (int i = 0; i < xs.Length; i++) { for (int j = 0; j < result.Length; j++) { result[j] += xs[i].Data[j] * coeffs[i]; } } } else { for (int i = 0; i < xs.Length; i++) { for (int j = 0; j < result.Length; j++) { result[j] += xs[i].Data[j]; } } } break; case EltwiseParameter.EltwiseOp.Max: Array.Copy(xs[0].Data, result, result.Length); int[] outputIndex = new int[result.Length]; for (int i = 1; i < xs.Length; i++) { for (int j = 0; j < result.Length; j++) { if (result[j] < xs[i].Data[j]) { outputIndex[j] = i; result[j] = xs[i].Data[j]; } } } PrevOutputIndex.Add(outputIndex); break; } return(new [] { NdArray.Convert(result, xs[0].Shape, xs[0].BatchCount, eltwise) }); }
public static void MultiOutputBackward(NdArray <Real> y, NdArray <Real>[] xs, EltwiseParameter.EltwiseOp operation, List <int[]> PrevOutputIndex) { Real[][] result = new Real[xs.Length][]; for (int i = 0; i < result.Length; i++) { result[i] = new Real[xs[i].Data.Length]; } switch (operation) { case EltwiseParameter.EltwiseOp.Prod: for (int i = 0; i < result.Length; i++) { Array.Copy(y.Grad, result[i], y.Grad.Length); for (int j = 0; j < xs.Length; j++) { if (i != j) { for (int k = 0; k < result[i].Length; k++) { result[i][k] *= xs[j].Data[k]; } } } } break; case EltwiseParameter.EltwiseOp.Sum: for (int i = 0; i < result.Length; i++) { Array.Copy(y.Grad, result[i], result[i].Length); } break; case EltwiseParameter.EltwiseOp.Max: var prevOutputIndex = PrevOutputIndex[PrevOutputIndex.Count - 1]; PrevOutputIndex.RemoveAt(PrevOutputIndex.Count - 1); for (int i = 0; i < prevOutputIndex.Length; i++) { result[prevOutputIndex[i]][i] = y.Grad[i]; } break; } for (int i = 0; i < xs.Length; i++) { for (int j = 0; j < xs[i].Grad.Length; j++) { xs[i].Grad[j] += result[i][j]; } } }