提交 f3e98cb7 authored 作者: Caglar's avatar Caglar 提交者: Tanjay94

Fixed bugs in A_Xinv_b.

上级 cd1b4a21
...@@ -489,7 +489,8 @@ class MatrixPinv(Op): ...@@ -489,7 +489,8 @@ class MatrixPinv(Op):
:math:`Ax = b`," i.e., if :math:`\\bar{x}` is said solution, then :math:`Ax = b`," i.e., if :math:`\\bar{x}` is said solution, then
:math:`A^+` is that matrix such that :math:`\\bar{x} = A^+b`. :math:`A^+` is that matrix such that :math:`\\bar{x} = A^+b`.
Note that :math:`Ax=AA^+b`, so :math:`AA^+` is close to the identity matrix. Note that :math:`Ax=AA^+b`, so :math:`AA^+` is close to the identity
matrix.
This method is not faster then `matrix_inverse`. Its strength comes from This method is not faster then `matrix_inverse`. Its strength comes from
that it works for non-square matrices. that it works for non-square matrices.
If you have a square matrix though, `matrix_inverse` can be both more If you have a square matrix though, `matrix_inverse` can be both more
...@@ -519,14 +520,10 @@ class MatrixPinv(Op): ...@@ -519,14 +520,10 @@ class MatrixPinv(Op):
return Apply(self, [x], [x.type()]) return Apply(self, [x], [x.type()])
def perform(self, node, (x,), (z, )): def perform(self, node, (x,), (z, )):
try: if imported_scipy:
if imported_scipy: z[0] = scipy.linalg.pinv(x).astype(x.dtype)
z[0] = scipy.linalg.pinv(x).astype(x.dtype) else:
else: z[0] = numpy.linalg.pinv(x).astype(x.dtype)
z[0] = numpy.linalg.pinv(x).astype(x.dtype)
except numpy.linalg.LinAlgError:
logger.debug('Failed to invert %s' % str(node.inputs[0]))
raise
def __str__(self): def __str__(self):
return "MatrixPseudoInverse" return "MatrixPseudoInverse"
...@@ -857,6 +854,7 @@ def spectral_radius_bound(X, log2_exponent): ...@@ -857,6 +854,7 @@ def spectral_radius_bound(X, log2_exponent):
if log2_exponent <= 0: if log2_exponent <= 0:
raise ValueError('spectral_radius_bound requires a strictly positive ' raise ValueError('spectral_radius_bound requires a strictly positive '
'exponent', log2_exponent) 'exponent', log2_exponent)
XX = X XX = X
for i in xrange(log2_exponent): for i in xrange(log2_exponent):
XX = tensor.dot(XX, XX) XX = tensor.dot(XX, XX)
...@@ -876,7 +874,7 @@ class A_Xinv_b(Op): ...@@ -876,7 +874,7 @@ class A_Xinv_b(Op):
assert a.ndim == 2 assert a.ndim == 2
assert X.ndim == 2 assert X.ndim == 2
assert b.ndim == 2 assert b.ndim == 2
o = theano.tensor.matrix(dtype=x.dtype) o = theano.tensor.matrix(dtype=X.dtype)
return Apply(self, [a, X, b], [o]) return Apply(self, [a, X, b], [o])
def perform(self, ndoe, inputs, outstor): def perform(self, ndoe, inputs, outstor):
...@@ -896,7 +894,7 @@ class A_Xinv_b(Op): ...@@ -896,7 +894,7 @@ class A_Xinv_b(Op):
iX = matrix_inverse(X) iX = matrix_inverse(X)
ga = matrix_dot(gz, b.T, iX.T) ga = matrix_dot(gz, b.T, iX.T)
gX = -matrix_dot(iX.T, a, gz, b.T, iX.T) gX = -matrix_dot(iX.T, a, gz, b.T, iX.T)
gb = matrix_dot(ix.T, a.T, gz) gb = matrix_dot(iX.T, a.T, gz)
return [ga, gX, gb] return [ga, gX, gb]
...@@ -928,12 +926,7 @@ class Eig(Op): ...@@ -928,12 +926,7 @@ class Eig(Op):
return Apply(self, [x], [w, v]) return Apply(self, [x], [w, v])
def perform(self, node, (x,), (w, v)): def perform(self, node, (x,), (w, v)):
try: w[0], v[0] = [z.astype(x.dtype) for z in self._numop(x)]
w[0], v[0] = [z.astype(x.dtype) for z in self._numop(x)]
except numpy.linalg.LinAlgError:
logger.debug('Failed to find %s of %s' % (self._numop.__name__,
node.inputs[0]))
raise
def infer_shape(self, node, shapes): def infer_shape(self, node, shapes):
n = shapes[0][0] n = shapes[0][0]
...@@ -987,15 +980,10 @@ class SVD(Op): ...@@ -987,15 +980,10 @@ class SVD(Op):
return Apply(self, [x], [w, u, v]) return Apply(self, [x], [w, u, v])
def perform(self, node, (x,), (w, u, v)): def perform(self, node, (x,), (w, u, v)):
try: assert x.ndim == 2, "The input of svd function should be a matrix."
assert x.ndim == 2, "The input of svd function should be a matrix." w[0], u[0], v[0] = self._numop(x,
w[0], u[0], v[0] = self._numop(x, self.full_matrices,
self.full_matrices, self.compute_uv)
self.compute_uv)
except numpy.linalg.LinAlgError:
logger.debug('Failed to find %s of %s' % (self._numop.__name__,
node.inputs[0]))
raise
def __str__(self): def __str__(self):
return self._numop.__name__.capitalize() return self._numop.__name__.capitalize()
...@@ -1006,7 +994,8 @@ def svd(a, full_matrices=1, compute_uv=1): ...@@ -1006,7 +994,8 @@ def svd(a, full_matrices=1, compute_uv=1):
This function performs the SVD on CPU. This function performs the SVD on CPU.
Parameters : Parameters :
-------- ------------
full_matrices : bool, optional full_matrices : bool, optional
If True (default), u and v have the shapes (M, M) and (N, N), If True (default), u and v have the shapes (M, M) and (N, N),
respectively. respectively.
...@@ -1015,6 +1004,10 @@ def svd(a, full_matrices=1, compute_uv=1): ...@@ -1015,6 +1004,10 @@ def svd(a, full_matrices=1, compute_uv=1):
compute_uv : bool, optional compute_uv : bool, optional
Whether or not to compute u and v in addition to s. Whether or not to compute u and v in addition to s.
True by default. True by default.
Returns :
-------
U, V and D matrices.
""" """
return SVD(full_matrices, compute_uv)(a) return SVD(full_matrices, compute_uv)(a)
...@@ -1048,21 +1041,17 @@ class QRFull(Op): ...@@ -1048,21 +1041,17 @@ class QRFull(Op):
return self.mode return self.mode
def perform(self, node, (x,), (q, r)): def perform(self, node, (x,), (q, r)):
try: assert x.ndim == 2, "The input of qr function should be a matrix."
assert x.ndim == 2, "The input of qr function should be a matrix."
q[0], r[0] = self._numop(x, q[0], r[0] = self._numop(x,
self.mode) self.mode)
q[0] = q[0].astype(x.dtype) q[0] = q[0].astype(x.dtype)
r[0] = r[0].astype(x.dtype) r[0] = r[0].astype(x.dtype)
except numpy.linalg.LinAlgError:
logger.debug('Failed to find %s of %s' % (self._numop.__name__,
node.inputs[0]))
raise
def __str__(self): def __str__(self):
return self._numop.__name__.capitalize() return self._numop.__name__.capitalize()
class QRIncomplete(Op): class QRIncomplete(Op):
""" """
Incomplete QR Decomposition. Incomplete QR Decomposition.
...@@ -1091,17 +1080,11 @@ class QRIncomplete(Op): ...@@ -1091,17 +1080,11 @@ class QRIncomplete(Op):
return Apply(self, [x], [q]) return Apply(self, [x], [q])
def perform(self, node, (x,), (q,)): def perform(self, node, (x,), (q,)):
try: assert x.ndim == 2, "The input of qr function should be a matrix."
assert x.ndim == 2, "The input of qr function should be a matrix." q[0] = self._numop(x,
q[0] = self._numop(x, self.mode)
self.mode)
q[0] = q[0].astype(x.dtype)
except numpy.linalg.LinAlgError: q[0] = q[0].astype(x.dtype)
logger.debug('Failed to find %s of %s' % (self._numop.__name__,
node.inputs[0]))
raise
def __str__(self): def __str__(self):
return self._numop.__name__.capitalize() return self._numop.__name__.capitalize()
...@@ -1139,19 +1122,14 @@ def qr(a, mode="full"): ...@@ -1139,19 +1122,14 @@ def qr(a, mode="full"):
Returns : Returns :
--------- ---------
q : ndarray of float or complex, optional q : matrix of float or complex, optional
A matrix with orthonormal columns. When mode = 'complete' A matrix with orthonormal columns. When mode = 'complete'
the result is an orthogonal/unitary matrix depending on whether the result is an orthogonal/unitary matrix depending on whether
or not a is real/complex. The determinant may be either +/- 1 in that case. or not a is real/complex. The determinant may be either +/- 1 in that case.
r : ndarray of float or complex, optional r : matrix of float or complex, optional
The upper-triangular matrix. The upper-triangular matrix.
(h, tau) : ndarrays of np.double or np.cdouble, optional
The array h contains the Householder reflectors that
generate q along with r. The tau array contains scaling
factors for the reflectors. In the deprecated
'economic' mode only h is returned.
""" """
if mode == "full": if mode == "full":
return QRFull()(a) return QRFull()(a)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论