| 18 | class UnaryGrad : public OpGrad { |
| 19 | public: |
| 20 | virtual std::vector<Express::VARP> onGrad(Express::EXPRP expr, |
| 21 | const std::vector<Express::VARP>& backwardOutput) override { |
| 22 | std::unique_ptr<OpT> forwardOp(expr->get()->UnPack()); |
| 23 | auto outputDiff = backwardOutput[0]; |
| 24 | auto input = expr->inputs()[0]; |
| 25 | std::vector<Express::VARP> res(1, nullptr); |
| 26 | std::vector<Express::VARP> output{Variable::create(expr, 0)}; |
| 27 | |
| 28 | switch (forwardOp->main.AsUnaryOp()->opType) { |
| 29 | case MNN::UnaryOpOperation_LOG1P: { |
| 30 | // d log(1+x) = 1/(1+x) * dx = dx / (1+x) |
| 31 | auto oneConst = _Const(1.0f, {}, NHWC); |
| 32 | auto addOne = _Add(input, oneConst); |
| 33 | res[0] = _Divide(outputDiff, addOne); |
| 34 | break; |
| 35 | } |
| 36 | case MNN::UnaryOpOperation_EXP: { |
| 37 | // d Exp(x) = Exp(x) * dx |
| 38 | res[0] = _Multiply(outputDiff, output[0]); |
| 39 | break; |
| 40 | } |
| 41 | case MNN::UnaryOpOperation_LOG: { |
| 42 | // d Log(x) = dx / x |
| 43 | res[0] = _Divide(outputDiff, input); |
| 44 | break; |
| 45 | } |
| 46 | case MNN::UnaryOpOperation_COS: { |
| 47 | // d Sin(x) = -dx * Sin(x) |
| 48 | res[0] = _Negative(outputDiff) * _Sin(input); |
| 49 | break; |
| 50 | } |
| 51 | case MNN::UnaryOpOperation_SIN: { |
| 52 | // d Sin(x) = dx * Cos(x) |
| 53 | res[0] = outputDiff * _Cos(input); |
| 54 | break; |
| 55 | } |
| 56 | case MNN::UnaryOpOperation_ABS: { |
| 57 | // d Abs(x) = dx * (x > 0 ? 1 : -1) |
| 58 | res[0] = outputDiff * _Sign(input); |
| 59 | break; |
| 60 | } |
| 61 | case MNN::UnaryOpOperation_NEG: { |
| 62 | // d (-x) = - dx |
| 63 | res[0] = _Negative(outputDiff); |
| 64 | break; |
| 65 | } |
| 66 | case MNN::UnaryOpOperation_SQRT: { |
| 67 | // d (-sqrt(x)) = 0.5 / sqrt(x) * dx |
| 68 | auto oneConst = _Const(0.5f, {}, NHWC); |
| 69 | auto mul = _Multiply(outputDiff, oneConst); |
| 70 | res[0] = OpGrad::divideAvoidZero(mul, output[0]); |
| 71 | break; |
| 72 | } |
| 73 | case MNN::UnaryOpOperation_SQUARE: { |
| 74 | // d (x^2) = (x*dx + x*dx) |
| 75 | auto mul = _Multiply(input, outputDiff); |
| 76 | res[0] = _Add(mul, mul); |
| 77 | break; |
nothing calls this directly
no test coverage detected