提交 8b62864b authored 作者: hantek's avatar hantek

test passing

上级 f4c355f4
...@@ -1102,9 +1102,7 @@ class GpuExtractDiag(Subtensor): ...@@ -1102,9 +1102,7 @@ class GpuExtractDiag(Subtensor):
broadcastable = x.broadcastable[:axis_small] + \ broadcastable = x.broadcastable[:axis_small] + \
x.broadcastable[axis_small + 1:axis_large] + \ x.broadcastable[axis_small + 1:axis_large] + \
x.broadcastable[axis_large + 1:] + (False,) x.broadcastable[axis_large + 1:] + (False,)
return gof.Apply(self, [x], [x.type.__class__( return gof.Apply(self, [x], [x.type.clone(broadcastable=broadcastable)()])
dtype=x.dtype,
broadcastable=broadcastable)()])
def perform(self, node, inputs, outputs): def perform(self, node, inputs, outputs):
(x,) = inputs (x,) = inputs
...@@ -1198,8 +1196,7 @@ class GpuAllocDiag(Op): ...@@ -1198,8 +1196,7 @@ class GpuAllocDiag(Op):
if x.ndim != 1: if x.ndim != 1:
raise ValueError('AllocDiag argument must be a vector!', x) raise ValueError('AllocDiag argument must be a vector!', x)
return gof.Apply(self, [x], [x.type.__class__(dtype=x.dtype, return gof.Apply(self, [x], [x.type.clone(broadcastable=(False, False))()])
broadcastable=x.broadcastable)()])
def perform(self, node, inputs, outputs): def perform(self, node, inputs, outputs):
(x,) = inputs (x,) = inputs
...@@ -1218,7 +1215,7 @@ class GpuAllocDiag(Op): ...@@ -1218,7 +1215,7 @@ class GpuAllocDiag(Op):
def grad(self, inputs, gout): def grad(self, inputs, gout):
(gz,) = gout (gz,) = gout
return [GpuExtractDiag(offset=self.offset, axis1=0, axis2=1, view=False)(gz)] return [GpuExtractDiag(offset=self.offset, axis1=0, axis2=1)(gz)]
def infer_shape(self, node, shapes): def infer_shape(self, node, shapes):
dim = shapes[0][0] + abs(self.offset) dim = shapes[0][0] + abs(self.offset)
......
...@@ -177,7 +177,7 @@ def test_adv_subtensor(): ...@@ -177,7 +177,7 @@ def test_adv_subtensor():
assert np.allclose(rval, rep) assert np.allclose(rval, rep)
class test_gpudiagonal(unittest.TestCase): class test_gpuextractdiag(unittest.TestCase):
def test_matrix(self): def test_matrix(self):
x = tensor.matrix() x = tensor.matrix()
np_x = np.arange(77).reshape(7, 11).astype(theano.config.floatX) np_x = np.arange(77).reshape(7, 11).astype(theano.config.floatX)
...@@ -213,8 +213,48 @@ class test_gpuallocdiag(unittest.TestCase): ...@@ -213,8 +213,48 @@ class test_gpuallocdiag(unittest.TestCase):
def test_grad(self): def test_grad(self):
x = tensor.vector() x = tensor.vector()
np_x = np.arange(7).astype(theano.config.floatX) np_x = np.random.randn(7).astype(theano.config.floatX)
# offset = 0 case:
mtx_x = GpuAllocDiag()(x) mtx_x = GpuAllocDiag()(x)
sum_mtx_x = tensor.sum(mtx_x) sum_mtx_x = tensor.sum(mtx_x)
grad = tensor.grad(sum_mtx_x, x) grad_x = tensor.grad(sum_mtx_x, x)
grad_mtx_x = tensor.grad(sum_mtx_x, mtx_x)
fn_grad_x = theano.function([x], grad_x)
fn_grad_mtx_x = theano.function([x], grad_mtx_x)
computed_grad_x = fn_grad_x(np_x)
computed_grad_mtx_x = fn_grad_mtx_x(np_x)
true_grad_x = np.diagonal(computed_grad_mtx_x, 0)
assert np.allclose(computed_grad_x, true_grad_x)
# offset > 0 case:
mtx_x = GpuAllocDiag(2)(x)
sum_mtx_x = tensor.sum(mtx_x)
grad_x = tensor.grad(sum_mtx_x, x)
grad_mtx_x = tensor.grad(sum_mtx_x, mtx_x)
fn_grad_x = theano.function([x], grad_x)
fn_grad_mtx_x = theano.function([x], grad_mtx_x)
computed_grad_x = fn_grad_x(np_x)
computed_grad_mtx_x = fn_grad_mtx_x(np_x)
true_grad_x = np.diagonal(computed_grad_mtx_x, 2)
assert np.allclose(computed_grad_x, true_grad_x)
# offset < 0 case:
mtx_x = GpuAllocDiag(-3)(x)
sum_mtx_x = tensor.sum(mtx_x)
grad_x = tensor.grad(sum_mtx_x, x)
grad_mtx_x = tensor.grad(sum_mtx_x, mtx_x)
fn_grad_x = theano.function([x], grad_x)
fn_grad_mtx_x = theano.function([x], grad_mtx_x)
computed_grad_x = fn_grad_x(np_x)
computed_grad_mtx_x = fn_grad_mtx_x(np_x)
true_grad_x = np.diagonal(computed_grad_mtx_x, -3)
assert np.allclose(computed_grad_x, true_grad_x)
# assert # assert
...@@ -6167,6 +6167,24 @@ class ExtractDiag(Op): ...@@ -6167,6 +6167,24 @@ class ExtractDiag(Op):
def diagonal(a, offset=0, axis1=0, axis2=1): def diagonal(a, offset=0, axis1=0, axis2=1):
"""
A helper function for `theano.tensor.ExtractDiag`. It accepts tensor with
`ndim >= 2` as input. The name `diagonal` is just meant to keep it
consistent with numpy.
Parameters
----------
a : symbolic tensor
offset : int
offset
axis1 : int
axis2 : int
Returns
-------
tensor : symbolic tensor
"""
return ExtractDiag(offset, axis1, axis2)(a) return ExtractDiag(offset, axis1, axis2)(a)
...@@ -6223,11 +6241,12 @@ class AllocDiag(Op): ...@@ -6223,11 +6241,12 @@ class AllocDiag(Op):
def diag(v, k=0): def diag(v, k=0):
""" """
A helper function for two ops: theano.tensor.ExtractDiag and A helper function for two ops: `theano.tensor.ExtractDiag` and
theano.tensor.AllocDiag. It both accepts tensor vector and tensor matrix. `theano.tensor.AllocDiag`. The name `diag` is meant to keep it consistent
with numpy. It both accepts tensor vector and tensor matrix.
While the passed tensor variable `v` has `v.ndim>=2`, it builds a While the passed tensor variable `v` has `v.ndim>=2`, it builds a
ExtractDiag instance, and returns a vector with its entries equal to `ExtractDiag` instance, and returns a vector with its entries equal to
`v`'s main diagonal; otherwise if `v.ndim` is `1`, it builds a AllocDiag `v`'s main diagonal; otherwise if `v.ndim` is `1`, it builds an `AllocDiag`
instance, and returns a matrix with `v` at its k-th diaogonal. instance, and returns a matrix with `v` at its k-th diaogonal.
Parameters Parameters
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论