`f(x) = a^b`, is applied to the tensor elementwise.
| 2830 | |
| 2831 | |
| 2832 | class Pow(Operator): |
| 2833 | """ |
| 2834 | `f(x) = a^b`, is applied to the tensor elementwise. |
| 2835 | """ |
| 2836 | |
| 2837 | def __init__(self): |
| 2838 | super(Pow, self).__init__() |
| 2839 | |
| 2840 | def forward(self, a, b): |
| 2841 | """ |
| 2842 | Return `a^b`, where a and b are CTensor. |
| 2843 | """ |
| 2844 | res = singa.Pow(a, b) |
| 2845 | if training: |
| 2846 | self.input = (a, b) |
| 2847 | self.shape0 = list(a.shape()) |
| 2848 | self.shape1 = list(b.shape()) |
| 2849 | self.shape3 = list(res.shape()) |
| 2850 | return res |
| 2851 | |
| 2852 | def backward(self, dy): |
| 2853 | """ |
| 2854 | Args: |
| 2855 | dy (CTensor): the gradient tensor from upper operations |
| 2856 | Returns: |
| 2857 | a tuple for (da, db), da is data for dL / da, db is data |
| 2858 | for dL / db. |
| 2859 | """ |
| 2860 | da1 = singa.__mul__( |
| 2861 | self.input[1], |
| 2862 | singa.Pow(self.input[0], singa.SubFloat(self.input[1], 1.0))) |
| 2863 | dx0 = singa.__mul__(da1, dy) |
| 2864 | db1 = singa.__mul__(singa.Pow(self.input[0], self.input[1]), |
| 2865 | singa.Log(self.input[0])) |
| 2866 | dx1 = singa.__mul__(db1, dy) |
| 2867 | if (type(dy) == float) or self.shape0 == self.shape1: |
| 2868 | assert self.shape0 == self.shape1, ('should have same shape') |
| 2869 | return dx0, dx1 |
| 2870 | # handle broadcast |
| 2871 | dx0 = back_broadcast(self.shape3, self.shape0, dx0) |
| 2872 | dx1 = back_broadcast(self.shape3, self.shape1, dx1) |
| 2873 | return dx0, dx1 |
| 2874 | |
| 2875 | |
| 2876 | def pow(a, b): |