def run(self, X, Y, start_vector=None): """Find the right-singular vector of the product of two matrices. Parameters ---------- X : Numpy array with shape (n, p). The first matrix of the product. Y : Numpy array with shape (p, m). The second matrix of the product. start_vector : BaseStartVector. A start vector generator. Default is to use a random start vector. """ if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = utils.time() if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, False) M, N = X.shape if start_vector is None: start_vector = start_vectors.RandomStartVector(normalise=True) v = start_vector.get_vector(Y.shape[1]) for it in xrange(1, self.max_iter + 1): v_ = v v = np.dot(X, np.dot(Y, v_)) v = np.dot(Y.T, np.dot(X.T, v)) v *= 1.0 / maths.norm(v) if maths.norm(v_ - v) / maths.norm(v) < self.eps \ and it >= self.min_iter: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, utils.time() - _t) if self.info_requested(utils.Info.func_val): _f = maths.norm(np.dot(X, np.dot(Y, v))) # Largest singular value. self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return utils.direct_vector(v)
def run(self, X, Y, start_vector=None): """Find the right-singular vector of the product of two matrices. Parameters ---------- X : Numpy array with shape (n, p). The first matrix of the product. Y : Numpy array with shape (p, m). The second matrix of the product. start_vector : BaseStartVector. A start vector generator. Default is to use a random start vector. """ if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = utils.time() if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, False) M, N = X.shape if start_vector is None: start_vector = weights.RandomUniformWeights(normalise=True) v = start_vector.get_weights(Y.shape[1]) for it in range(1, self.max_iter + 1): v_ = v v = np.dot(X, np.dot(Y, v_)) v = np.dot(Y.T, np.dot(X.T, v)) v *= 1.0 / maths.norm(v) if maths.norm(v_ - v) / maths.norm(v) < self.eps \ and it >= self.min_iter: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, utils.time() - _t) if self.info_requested(utils.Info.func_val): _f = maths.norm(np.dot(X, np.dot(Y, v))) # Largest singular value. self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return utils.direct_vector(v)
def run(self, X, start_vector=None): """Find the right-singular vector of the given sparse matrix. Parameters ---------- X : Scipy sparse array. The sparse matrix to decompose. start_vector : BaseStartVector. A start vector generator. Default is to use a random start vector. """ if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = utils.time() if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, False) if start_vector is None: start_vector = start_vectors.RandomStartVector(normalise=True) v0 = start_vector.get_vector(np.min(X.shape)) # determine when to use power method or scipy_sparse use_power = True if X.shape[1] >= 10 ** 3 else False if not use_power: try: if not sp.sparse.issparse(X): X = sp.sparse.csr_matrix(X) try: [_, _, v] = sparse_linalg.svds(X, k=1, v0=v0, tol=self.eps, maxiter=self.max_iter, return_singular_vectors=True) except TypeError: # For scipy 0.9.0. [_, _, v] = sparse_linalg.svds(X, k=1, tol=self.eps) v = v.T if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) except ArpackNoConvergence: use_power = True if use_power: # Use the power method if scipy failed or if determined. M, N = X.shape if M < N: K = X.dot(X.T) t = v0 for it in xrange(self.max_iter): t_ = t t = K.dot(t_) t *= 1.0 / maths.norm(t) crit = float(maths.norm(t_ - t)) / float(maths.norm(t)) if crit < consts.TOLERANCE: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break v = X.T.dot(t) v *= 1.0 / maths.norm(v) else: K = X.T.dot(X) v = v0 for it in xrange(self.max_iter): v_ = v v = K.dot(v_) v *= 1.0 / maths.norm(v) crit = float(maths.norm(v_ - v)) / float(maths.norm(v)) if crit < consts.TOLERANCE: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, utils.time() - _t) if self.info_requested(utils.Info.func_val): _f = maths.norm(X.dot(v)) # Largest singular value. self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return utils.direct_vector(v)
def run(self, X, start_vector=None): """Find the right-singular vector of the given matrix. Parameters ---------- X : Numpy array. The matrix to decompose. start_vector : BaseStartVector. A start vector generator. Default is to use a random start vector. """ if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = utils.time() if start_vector is None: start_vector = start_vectors.RandomStartVector(normalise=True) v0 = start_vector.get_vector(np.min(X.shape)) arpack_failed = False try: try: [_, _, v] = sparse_linalg.svds(X, k=1, v0=v0, tol=self.eps, maxiter=self.max_iter, return_singular_vectors=True) except TypeError: # For scipy 0.9.0. [_, _, v] = sparse_linalg.svds(X, k=1, tol=self.eps) v = v.T if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) except ArpackNoConvergence: arpack_failed = True if arpack_failed: # Use the power method if this happens. M, N = X.shape if M < 80 and N < 80: # Very arbitrary threshold from one computer _, _, V = scipy.linalg.svd(X, full_matrices=True) v = V[[0], :].T elif M < N: K = np.dot(X, X.T) t = v0 for it in xrange(self.max_iter): t_ = t t = np.dot(K, t_) t *= 1.0 / maths.norm(t) if maths.norm(t_ - t) / maths.norm(t) < self.eps: break v = np.dot(X.T, t) v *= 1.0 / maths.norm(v) else: K = np.dot(X.T, X) v = v0 for it in xrange(self.max_iter): v_ = v v = np.dot(K, v_) v *= 1.0 / maths.norm(v) if maths.norm(v_ - v) / maths.norm(v) < self.eps: break if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, utils.time() - _t) if self.info_requested(utils.Info.func_val): _f = maths.norm(np.dot(X, v)) # Largest singular value. self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return utils.direct_vector(v)
def run(self, X, start_vector=None): """Find the right-singular vector of the given sparse matrix. Parameters ---------- X : Scipy sparse array. The sparse matrix to decompose. start_vector : BaseStartVector. A start vector generator. Default is to use a random start vector. """ if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = utils.time() if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, False) if start_vector is None: start_vector = weights.RandomUniformWeights(normalise=True) v0 = start_vector.get_weights(np.min(X.shape)) # determine when to use power method or scipy_sparse use_power = True if X.shape[1] >= 10 ** 3 else False if not use_power: try: if not sp.sparse.issparse(X): X = sp.sparse.csr_matrix(X) try: [_, _, v] = sparse_linalg.svds(X, k=1, v0=v0, tol=self.eps, maxiter=self.max_iter, return_singular_vectors=True) except TypeError: # For scipy 0.9.0. [_, _, v] = sparse_linalg.svds(X, k=1, tol=self.eps) v = v.T if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) except ArpackNoConvergence: use_power = True if use_power: # Use the power method if scipy failed or if determined. # TODO: Use estimators for this! M, N = X.shape if M < N: K = X.dot(X.T) t = v0 for it in range(self.max_iter): t_ = t t = K.dot(t_) t *= 1.0 / maths.norm(t) crit = float(maths.norm(t_ - t)) / float(maths.norm(t)) if crit < consts.TOLERANCE: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break v = X.T.dot(t) v *= 1.0 / maths.norm(v) else: K = X.T.dot(X) v = v0 for it in range(self.max_iter): v_ = v v = K.dot(v_) v *= 1.0 / maths.norm(v) crit = float(maths.norm(v_ - v)) / float(maths.norm(v)) if crit < consts.TOLERANCE: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, utils.time() - _t) if self.info_requested(utils.Info.func_val): _f = maths.norm(X.dot(v)) # Largest singular value. self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return utils.direct_vector(v)
def run(self, X, start_vector=None): """Find the right-singular vector of the given matrix. Parameters ---------- X : Numpy array. The matrix to decompose. start_vector : BaseStartVector. A start vector generator. Default is to use a random start vector. """ if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = utils.time() if start_vector is None: start_vector = weights.RandomUniformWeights(normalise=True) v0 = start_vector.get_weights(np.min(X.shape)) arpack_failed = False try: try: [_, _, v] = sparse_linalg.svds(X, k=1, v0=v0, tol=self.eps, maxiter=self.max_iter, return_singular_vectors=True) except TypeError: # For scipy 0.9.0. [_, _, v] = sparse_linalg.svds(X, k=1, tol=self.eps) v = v.T if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) except ArpackNoConvergence: arpack_failed = True if arpack_failed: # Use the power method if this happens. M, N = X.shape if M < 80 and N < 80: # Very arbitrary threshold from one computer _, _, V = scipy.linalg.svd(X, full_matrices=True) v = V[[0], :].T elif M < N: K = np.dot(X, X.T) t = v0 for it in range(self.max_iter): t_ = t t = np.dot(K, t_) t *= 1.0 / maths.norm(t) if maths.norm(t_ - t) / maths.norm(t) < self.eps: break v = np.dot(X.T, t) v *= 1.0 / maths.norm(v) else: K = np.dot(X.T, X) v = v0 for it in range(self.max_iter): v_ = v v = np.dot(K, v_) v *= 1.0 / maths.norm(v) if maths.norm(v_ - v) / maths.norm(v) < self.eps: break if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, utils.time() - _t) if self.info_requested(utils.Info.func_val): _f = maths.norm(np.dot(X, v)) # Largest singular value. self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return utils.direct_vector(v)