58 lines
1.6 KiB
Python
Executable File
58 lines
1.6 KiB
Python
Executable File
import numpy as np
|
|
from prml.nn.tensor.constant import Constant
|
|
from prml.nn.tensor.tensor import Tensor
|
|
from prml.nn.function import Function
|
|
from prml.nn.array.broadcast import broadcast_to
|
|
|
|
|
|
class Power(Function):
|
|
"""
|
|
First array elements raised to powers from second array
|
|
"""
|
|
|
|
def _check_input(self, x, y):
|
|
x = self._convert2tensor(x)
|
|
y = self._convert2tensor(y)
|
|
if x.shape != y.shape:
|
|
shape = np.broadcast(x.value, y.value).shape
|
|
if x.shape != shape:
|
|
x = broadcast_to(x, shape)
|
|
if y.shape != shape:
|
|
y = broadcast_to(y, shape)
|
|
return x, y
|
|
|
|
def forward(self, x, y):
|
|
x, y = self._check_input(x, y)
|
|
self.x = x
|
|
self.y = y
|
|
self.output = np.power(x.value, y.value)
|
|
if isinstance(self.x, Constant) and isinstance(self.y, Constant):
|
|
return Constant(self.output)
|
|
return Tensor(self.output, function=self)
|
|
|
|
def backward(self, delta):
|
|
dx = self.y.value * np.power(self.x.value, self.y.value - 1) * delta
|
|
if self.x.size == 1:
|
|
if self.x.value > 0:
|
|
dy = self.output * np.log(self.x.value) * delta
|
|
else:
|
|
dy = None
|
|
else:
|
|
if (self.x.value > 0).all():
|
|
dy = self.output * np.log(self.x.value) * delta
|
|
else:
|
|
dy = None
|
|
self.x.backward(dx)
|
|
self.y.backward(dy)
|
|
|
|
|
|
def power(x, y):
|
|
"""
|
|
First array elements raised to powers from second array
|
|
"""
|
|
return Power().forward(x, y)
|
|
|
|
|
|
def rpower(x, y):
|
|
return Power().forward(y, x)
|