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, g, x): """Find the best separating margin for the samples in X. Parameters ---------- g : MajoriserFunction The function that majorises self.function. x : array_like The point at which to start the minimisation process. """ x = check_arrays(x) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = [] if self.info_requested(utils.Info.func_val): _f = [] if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, False) xnew = xold = x for i in range(1, self.max_iter + 1): if self.info_requested(utils.Info.time): tm = utils.time() xold = xnew if isinstance(g, properties.MajoriserFunction): maj_f = g(self.function, xold) else: g.at_point(xold) maj_f = g xnew = self.algorithm.run(maj_f, xold) if self.info_requested(utils.Info.time): _t.append(utils.time() - tm) if self.info_requested(utils.Info.func_val): _f.append(g.f(xnew)) if self.callback is not None: self.callback(locals()) if i >= self.min_iter and np.linalg.norm(xnew - xold) < self.eps: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break self.num_iter = i if self.info_requested(utils.Info.num_iter): self.info_set(utils.Info.num_iter, self.num_iter) if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, _t) if self.info_requested(utils.Info.func_val): self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return xnew
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)
def run(self, g, x): """Run the optimiser using the majoriser function starting at the given point. Parameters ---------- g : MajoriserFunction The function that majorises self.function. x : array_like The point at which to start the minimisation process. """ # x = check_arrays(x) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, False) if self.info_requested(utils.Info.time): _t = [] if self.info_requested(utils.Info.func_val): _f = [] if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, False) xnew = xold = x for i in range(1, self.max_iter + 1): if self.info_requested(utils.Info.time): tm = utils.time() xold = xnew if isinstance(g, properties.MajoriserFunction): maj_f = g(self.function, xold) else: g.at_point(xold) maj_f = g xnew = self.algorithm.run(maj_f, xold) if self.info_requested(utils.Info.time): _t.append(utils.time() - tm) if self.info_requested(utils.Info.func_val): _f.append(g.f(xnew)) if self.callback is not None: self.callback(locals()) if isinstance(xnew, list): val = list_op((xnew, xold), lambda new, old: np.linalg.norm(new - old), aggregator=np.max) else: val = np.linalg.norm(xnew - xold) if i >= self.min_iter and val < self.eps: if self.info_requested(utils.Info.converged): self.info_set(utils.Info.converged, True) break self.num_iter = i if self.info_requested(utils.Info.num_iter): self.info_set(utils.Info.num_iter, self.num_iter) if self.info_requested(utils.Info.time): self.info_set(utils.Info.time, _t) if self.info_requested(utils.Info.func_val): self.info_set(utils.Info.func_val, _f) if self.info_requested(utils.Info.ok): self.info_set(utils.Info.ok, True) return xnew