提交 2060b8f7 authored 作者: lamblin's avatar lamblin

Merge pull request #1102 from nouiz/py24

Fix tests
......@@ -662,10 +662,10 @@ class Solve(Op):
def infer_shape(self, node, shapes):
Ashape, Bshape = shapes
rows = Ashape[1]
if len(Bshape) == 1: # b is a Vector
if len(Bshape) == 1: # b is a Vector
return [(rows,)]
else:
cols = Bshape[1] # b is a Matrix
cols = Bshape[1] # b is a Matrix
return [(rows, cols)]
solve = Solve() # general solve
......@@ -879,6 +879,7 @@ class A_Xinv_b(Op):
gb = matrix_dot(ix.T, a.T, gz)
return [ga, gX, gb]
class Eig(Op):
"""Compute the eigenvalues and right eigenvectors of a square array.
......@@ -916,24 +917,31 @@ class Eig(Op):
def infer_shape(self, node, shapes):
n = shapes[0][0]
return [(n,), (n,n)]
return [(n,), (n, n)]
def __str__(self):
return self._numop.__name__.capitalize()
eig = Eig()
def _zero_disconnected(outputs, grads):
return [o.zeros_like()
if isinstance(g.type, DisconnectedType) else g
for o, g in zip(outputs, grads)]
l = []
for o, g in zip(outputs, grads):
if isinstance(g.type, DisconnectedType):
l.append(o.zeros_like())
else:
l.append(g)
return l
class Eigh(Eig):
"""
Return the eigenvalues and eigenvectors of a Hermitian or symmetric matrix.
"""
_numop = staticmethod(numpy.linalg.eigh)
def __init__(self, UPLO='L'):
self.UPLO = UPLO
......@@ -962,9 +970,8 @@ class Eigh(Eig):
except numpy.linalg.LinAlgError:
logger.debug('Failed to find %s of %s' % (self._numop.__name__,
node.inputs[0]))
raise
def grad(self, inputs, g_outputs):
r"""The gradient function should return
......@@ -972,7 +979,7 @@ class Eigh(Eig):
{\partial a_{ij}} +
\sum_k V_{nk}\frac{\partial\,v_{nk}}
{\partial a_{ij}}\right),
where [:math:`W`, :math:`V`] corresponds to ``g_outputs``,
:math:`a` to ``inputs``, and :math:`(w, v)=\mbox{eig}(a)`.
......@@ -984,7 +991,7 @@ class Eigh(Eig):
.. math:: \frac{\partial\,v_{kn}}
{\partial a_{ij}} =
{\partial a_{ij}} =
\sum_{m\ne n}\frac{v_{km}v_{jn}}{w_n-w_m}
"""
x, = inputs
......@@ -994,8 +1001,10 @@ class Eigh(Eig):
gw, gv = _zero_disconnected([w, v], g_outputs)
return [EighGrad(self.UPLO)(x, w, v, gw, gv)]
def eigh(a, UPLO='L'):
return Eigh(UPLO)(a)
return Eigh(UPLO)(a)
class EighGrad(Op):
"""Gradient of an eigensystem of a Hermitian matrix.
......@@ -1009,7 +1018,7 @@ class EighGrad(Op):
else:
self.tri0 = numpy.triu
self.tri1 = lambda a: numpy.tril(a, -1)
def props(self):
return ()
......@@ -1021,7 +1030,6 @@ class EighGrad(Op):
def __str__(self):
return 'EighGrad{%s}' % self.UPLO
def make_node(self, x, w, v, gw, gv):
x, w, v, gw, gv = map(as_tensor_variable, (x, w, v, gw, gv))
......@@ -1036,9 +1044,9 @@ class EighGrad(Op):
N = x.shape[0]
outer = numpy.outer
G = lambda n: sum(v[:,m]*V.T[n].dot(v[:,m])/(w[n]-w[m])
G = lambda n: sum(v[:, m] * V.T[n].dot(v[:, m]) / (w[n] - w[m])
for m in xrange(N) if m != n)
g = sum(outer(v[:,n], v[:,n]*W[n] + G(n))
g = sum(outer(v[:, n], v[:, n] * W[n] + G(n))
for n in xrange(N))
# Numpy's eigh(a, 'L') (eigh(a, 'U')) is a function of tril(a)
......@@ -1053,4 +1061,3 @@ class EighGrad(Op):
def infer_shape(self, node, shapes):
return [shapes[0]]
......@@ -185,6 +185,7 @@ def test_inverse_grad():
r = rng.randn(4, 4)
tensor.verify_grad(matrix_inverse, [r], rng=numpy.random)
def test_rop_lop():
mx = tensor.matrix('mx')
mv = tensor.matrix('mv')
......@@ -442,6 +443,7 @@ def test_spectral_radius_bound():
ok = True
assert ok
class test_Solve(utt.InferShapeTester):
def setUp(self):
super(test_Solve, self).setUp()
......@@ -474,10 +476,12 @@ class test_Solve(utt.InferShapeTester):
dtype=config.floatX)],
self.op_class)
class test_Eig(utt.InferShapeTester):
op_class = Eig
op = eig
dtype = 'float64'
def setUp(self):
super(test_Eig, self).setUp()
self.rng = numpy.random.RandomState(utt.fetch_seed())
......@@ -485,7 +489,7 @@ class test_Eig(utt.InferShapeTester):
X = numpy.asarray(self.rng.rand(5, 5),
dtype=self.dtype)
self.S = X.dot(X.T)
def test_infer_shape(self):
A = self.A
S = self.S
......@@ -494,26 +498,29 @@ class test_Eig(utt.InferShapeTester):
# S must be square
[S],
self.op_class)
def test_eval(self):
import math
A = theano.tensor.matrix(dtype=self.dtype)
self.assertEquals([e.eval({A: [[1]]}) for e in self.op(A)],
[[1.0], [[1.0]]])
x = [[0, 1], [1, 0]]
x = [[0, 1], [1, 0]]
w, v = [e.eval({A: x}) for e in self.op(A)]
assert_array_almost_equal(numpy.dot(x,v), w * v)
assert_array_almost_equal(numpy.dot(x, v), w * v)
class test_Eigh(test_Eig):
op = staticmethod(eigh)
def test_uplo(self):
S = self.S
a = theano.tensor.matrix()
a = theano.tensor.matrix(dtype=self.dtype)
wu, vu = [out.eval({a: S}) for out in self.op(a, 'U')]
wl, vl = [out.eval({a: S}) for out in self.op(a, 'L')]
assert_array_almost_equal(wu, wl)
assert_array_almost_equal(vu*numpy.sign(vu[0,:]),
vl*numpy.sign(vl[0,:]))
assert_array_almost_equal(vu * numpy.sign(vu[0, :]),
vl * numpy.sign(vl[0, :]))
def test_grad(self):
S = self.S
utt.verify_grad(lambda x: self.op(x)[0], [S], rng=self.rng)
......@@ -521,5 +528,6 @@ class test_Eigh(test_Eig):
utt.verify_grad(lambda x: self.op(x, 'U')[0], [S], rng=self.rng)
utt.verify_grad(lambda x: self.op(x, 'U')[1], [S], rng=self.rng)
class test_Eigh_float32(test_Eigh):
dtype = 'float32'
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论