Skip to content

Commit cc980b8

Browse files
authored
Merge pull request #498 from pinpom/pow
SINGA-475 add Pow operator
2 parents b21a6be + bb452e4 commit cc980b8

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

python/singa/autograd.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,27 @@ def backward(self, dy):
18291829
def leakyrelu(x, a=0.01):
18301830
return LeakyRelu(a)(x)[0]
18311831

1832+
1833+
class Pow(Operation):
1834+
def __init__(self):
1835+
super(Pow, self).__init__()
1836+
1837+
def forward(self, a, b):
1838+
if training:
1839+
self.input = (a, b)
1840+
return singa.Pow(a, b)
1841+
1842+
def backward(self, dy):
1843+
da1=singa.__mul__(self.input[1], singa.Pow(self.input[0], singa.SubFloat(self.input[1],1.0)))
1844+
da=singa.__mul__(da1, dy)
1845+
1846+
db1=singa.__mul__(singa.Pow(self.input[0],self.input[1]), singa.Log(self.input[0]))
1847+
db=singa.__mul__(db1, dy)
1848+
1849+
return da, db
1850+
1851+
def pow(a, b):
1852+
return Pow()(a,b)[0]
18321853

18331854
class SoftSign(Operation):
18341855
def __init__(self):
@@ -1860,10 +1881,12 @@ def forward(self, x):
18601881
if training:
18611882
self.input = x
18621883
return singa.Sqrt(x)
1863-
1884+
18641885
def backward(self, dy):
18651886
dx = singa.PowFloat(self.input,-0.5)
18661887
dx = singa.MultFloat(dx,0.5)
1888+
dx = singa.__mul__(dy, dx)
1889+
return dx
18671890

18681891
def sqrt(x):
18691892
return Sqrt()(x)[0]

test/python/test_operation.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ def test_Sub_gpu(self):
814814
x1.to_device(gpu_dev)
815815
dy.to_device(gpu_dev)
816816

817+
817818
result = autograd.sub(x0, x1)
818819
dx0, dx1 = result.creator.backward(dy.data)
819820
DX0 = np.multiply(DY, 1.0)
@@ -822,6 +823,56 @@ def test_Sub_gpu(self):
822823
np.testing.assert_array_almost_equal(tensor.to_numpy(result), XT, decimal=5)
823824
np.testing.assert_array_almost_equal(tensor.to_numpy(tensor.from_raw_tensor(dx0)), DX0, decimal=5)
824825
np.testing.assert_array_almost_equal(tensor.to_numpy(tensor.from_raw_tensor(dx1)), DX1, decimal=5)
826+
827+
def test_Pow_cpu(self):
828+
X0 = np.array([7, 5, 0.2, 0.1, 0.3, 4]).reshape(3, 2).astype(np.float32)
829+
X1 = np.array([-1.0, 2.0, -1.0, -2.1, 1.0, -2.0]).reshape(3, 2).astype(np.float32)
830+
XT = np.power(X0, X1)
831+
832+
DY = np.ones((3, 2), dtype = np.float32)
833+
x0 = tensor.from_numpy(X0)
834+
x1 = tensor.from_numpy(X1)
835+
dy = tensor.from_numpy(DY)
836+
x0.to_device(cpu_dev)
837+
x1.to_device(cpu_dev)
838+
dy.to_device(cpu_dev)
839+
840+
result = autograd.pow(x0, x1)
841+
dx0, dx1 = result.creator.backward(dy.data)
842+
843+
G0 = np.multiply(X1, np.power(X0, (X1 - 1.0)) )
844+
DX0 = np.multiply(G0, DY)
845+
G1 = np.multiply(np.power(X0, X1), np.log(X0) )
846+
DX1 = np.multiply(G1, DY)
847+
848+
np.testing.assert_array_almost_equal(tensor.to_numpy(result), XT, decimal=5)
849+
np.testing.assert_array_almost_equal(tensor.to_numpy(tensor.from_raw_tensor(dx0)), DX0, decimal=4)
850+
np.testing.assert_array_almost_equal(tensor.to_numpy(tensor.from_raw_tensor(dx1)), DX1, decimal=4)
851+
852+
def test_Pow_gpu(self):
853+
X0 = np.array([7, 5, 0.2, 0.1, 0.3, 4]).reshape(3, 2).astype(np.float32)
854+
X1 = np.array([-1.0, 2.0, -1.0, -2.1, 1.0, -2.0]).reshape(3, 2).astype(np.float32)
855+
XT = np.power(X0, X1)
856+
857+
DY = np.ones((3, 2), dtype = np.float32)
858+
x0 = tensor.from_numpy(X0)
859+
x1 = tensor.from_numpy(X1)
860+
dy = tensor.from_numpy(DY)
861+
x0.to_device(gpu_dev)
862+
x1.to_device(gpu_dev)
863+
dy.to_device(gpu_dev)
864+
865+
result = autograd.pow(x0, x1)
866+
dx0, dx1 = result.creator.backward(dy.data)
867+
868+
G0 = np.multiply(X1, np.power(X0, (X1 - 1.0)) )
869+
DX0 = np.multiply(G0, DY)
870+
G1 = np.multiply(np.power(X0, X1), np.log(X0) )
871+
DX1 = np.multiply(G1, DY)
872+
873+
np.testing.assert_array_almost_equal(tensor.to_numpy(result), XT, decimal=5)
874+
np.testing.assert_array_almost_equal(tensor.to_numpy(tensor.from_raw_tensor(dx0)), DX0, decimal=4)
875+
np.testing.assert_array_almost_equal(tensor.to_numpy(tensor.from_raw_tensor(dx1)), DX1, decimal=4)
825876

826877
def test_SoftSign_cpu(self):
827878
# y = x / (1 + np.abs(x))

0 commit comments

Comments
 (0)