lanczos算法——求解线性方程组时的辅助算法
lanczos算法
Lanczos算法是一种将对称矩阵通过正交相似变换变成对称三对角矩阵的算法,以20世纪匈牙利数学家Cornelius Lanczos命名。
注意:Lanczos算法只能对“对称矩阵”进行转换。
Lanczos算法是一种将对称矩阵通过正交相似变换变成对称 三对角矩阵的算法。
对称三对角矩阵类似于下式:


lanczos算法的主要功能就是对矩阵进行转换,将原有的对称矩阵转变为与正交矩阵相乘的“三对角矩阵”,然后再对这个“三对角矩阵”进行处理,比如进行奇异值分解,最后我们可以通过这种转换得到一个近似等价的矩阵,而这个过程计算速度快,最后获得的这个近似的等价矩阵可以代替原矩阵进行一定的操作,以此来达到加速计算获得近似计算的目的。
给出lanczos算法的实现代码:
import numpy as np
# from rllab.misc.ext import sliced_fun
EPS = np.finfo('float64').tiny
def cg(f_Ax, b, cg_iters=10, callback=None, verbose=False, residual_tol=1e-10):
"""
Demmel p 312
"""
p = b.copy()
r = b.copy()
x = np.zeros_like(b)
rdotr = r.dot(r)
fmtstr = "%10i %10.3g %10.3g"
titlestr = "%10s %10s %10s"
if verbose: print(titlestr % ("iter", "residual norm", "soln norm"))
for i in range(cg_iters):
if callback is not None:
callback(x)
if verbose: print(fmtstr % (i, rdotr, np.linalg.norm(x)))
z = f_Ax(p)
v = rdotr / p.dot(z)
x += v * p
r -= v * z
newrdotr = r.dot(r)
mu = newrdotr / rdotr
p = r + mu * p
rdotr = newrdotr
if rdotr < residual_tol:
break
if callback is not None:
callback(x)
if verbose: print(fmtstr % (i + 1, rdotr, np.linalg.norm(x))) # pylint: disable=W0631
return x
def preconditioned_cg(f_Ax, f_Minvx, b, cg_iters=10, callback=None, verbose=False, residual_tol=1e-10):
"""
Demmel p 318
"""
x = np.zeros_like(b)
r = b.copy()
p = f_Minvx(b)
y = p
ydotr = y.dot(r)
fmtstr = "%10i %10.3g %10.3g"
titlestr = "%10s %10s %10s"
if verbose: print(titlestr % ("iter", "residual norm", "soln norm"))
for i in range(cg_iters):
if callback is not None:
callback(x, f_Ax)
if verbose: print(fmtstr % (i, ydotr, np.linalg.norm(x)))
z = f_Ax(p)
v = ydotr / p.dot(z)
x += v * p
r -= v * z
y = f_Minvx(r)
newydotr = y.dot(r)
mu = newydotr / ydotr
p = y + mu * p
ydotr = newydotr
if ydotr < residual_tol:
break
if verbose: print(fmtstr % (cg_iters, ydotr, np.linalg.norm(x)))
return x
def test_cg():
A = np.random.randn(5, 5)
A = A.T.dot(A)
b = np.random.randn(5)
x = cg(lambda x: A.dot(x), b, cg_iters=5, verbose=True) # pylint: disable=W0108
assert np.allclose(A.dot(x), b)
x = preconditioned_cg(lambda x: A.dot(x), lambda x: np.linalg.solve(A, x), b, cg_iters=5,
verbose=True) # pylint: disable=W0108
assert np.allclose(A.dot(x), b)
x = preconditioned_cg(lambda x: A.dot(x), lambda x: x / np.diag(A), b, cg_iters=5,
verbose=True) # pylint: disable=W0108
assert np.allclose(A.dot(x), b)
def lanczos(f_Ax, b, k):
"""
Runs Lanczos algorithm to generate a orthogonal basis for the Krylov subspace
b, Ab, A^2b, ...
as well as the upper hessenberg matrix T = Q^T A Q
from Demmel ch 6
"""
assert k > 1
alphas = []
betas = []
qs = []
q = b / np.linalg.norm(b)
beta = 0
qm = np.zeros_like(b)
for j in range(k):
qs.append(q)
z = f_Ax(q)
alpha = q.dot(z)
alphas.append(alpha)
z -= alpha * q + beta * qm
beta = np.linalg.norm(z)
betas.append(beta)
print("beta", beta)
if beta < 1e-9:
print("lanczos: early after %i/%i dimensions" % (j + 1, k))
break
else:
qm = q
q = z / beta
return np.array(qs, 'float64').T, np.array(alphas, 'float64'), np.array(betas[:-1], 'float64')
def lanczos2(f_Ax, b, k, residual_thresh=1e-9):
"""
Runs Lanczos algorithm to generate a orthogonal basis for the Krylov subspace
b, Ab, A^2b, ...
as well as the upper hessenberg matrix T = Q^T A Q
from Demmel ch 6
"""
b = b.astype('float64')
assert k > 1
H = np.zeros((k, k))
qs = []
q = b / np.linalg.norm(b)
beta = 0
for j in range(k):
qs.append(q)
z = f_Ax(q.astype('float64')).astype('float64')
for (i, q) in enumerate(qs):
H[j, i] = H[i, j] = h = q.dot(z)
z -= h * q
beta = np.linalg.norm(z)
if beta < residual_thresh:
print("lanczos2: stopping early after %i/%i dimensions residual %f < %f" % (j + 1, k, beta, residual_thresh))
break
else:
q = z / beta
return np.array(qs).T, H[:len(qs), :len(qs)]
def make_tridiagonal(alphas, betas):
assert len(alphas) == len(betas) + 1
N = alphas.size
out = np.zeros((N, N), 'float64')
out.flat[0:N ** 2:N + 1] = alphas
out.flat[1:N ** 2 - N:N + 1] = betas
out.flat[N:N ** 2 - 1:N + 1] = betas
return out
def tridiagonal_eigenvalues(alphas, betas):
T = make_tridiagonal(alphas, betas)
return np.linalg.eigvalsh(T)
def test_lanczos():
np.set_printoptions(precision=4)
A = np.random.randn(5, 5)
A = A.T.dot(A)
b = np.random.randn(5)
f_Ax = lambda x: A.dot(x) # pylint: disable=W0108
Q, alphas, betas = lanczos(f_Ax, b, 10)
H = make_tridiagonal(alphas, betas)
assert np.allclose(Q.T.dot(A).dot(Q), H)
assert np.allclose(Q.dot(H).dot(Q.T), A)
assert np.allclose(np.linalg.eigvalsh(H), np.linalg.eigvalsh(A))
Q, H1 = lanczos2(f_Ax, b, 10)
assert np.allclose(H, H1, atol=1e-6)
print("ritz eigvals:")
for i in range(1, 6):
Qi = Q[:, :i]
Hi = Qi.T.dot(A).dot(Qi)
print(np.linalg.eigvalsh(Hi)[::-1])
print("true eigvals:")
print(np.linalg.eigvalsh(A)[::-1])
print("lanczos on ill-conditioned problem")
A = np.diag(10 ** np.arange(5))
Q, H1 = lanczos2(f_Ax, b, 10)
print(np.linalg.eigvalsh(H1))
print("lanczos on ill-conditioned problem with noise")
def f_Ax_noisy(x):
return A.dot(x) + np.random.randn(x.size) * 1e-3
Q, H1 = lanczos2(f_Ax_noisy, b, 10)
print(np.linalg.eigvalsh(H1))
if __name__ == "__main__":
test_lanczos()
test_cg()
注意:上面代码中lanczos函数和lanczos2函数都是求解的lanczos算法,不同的是求解出的结果的形式,lanczos函数是求解出“三对角矩阵”的两个对角线上的向量,lanczos2函数是直接得到“三对角矩阵”。
参考:
lanczos算法——求解线性方程组时的辅助算法的更多相关文章
- [Matlab]求解线性方程组
转自:http://silencethinking.blog.163.com/blog/static/911490562008928105813169/ AX=B或XA=B在MATLAB中,求解线性方 ...
- 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...
- 转载 - 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
出处:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 ...
- Bellman-Ford & SPFA 算法——求解单源点最短路径问题
Bellman-Ford算法与另一个非常著名的Dijkstra算法一样,用于求解单源点最短路径问题.Bellman-ford算法除了可求解边权均非负的问题外,还可以解决存在负权边的问题(意义是什么,好 ...
- 基于粒子群算法求解求解TSP问题(JAVA)
一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...
- 文本主题模型之LDA(三) LDA求解之变分推断EM算法
文本主题模型之LDA(一) LDA基础 文本主题模型之LDA(二) LDA求解之Gibbs采样算法 文本主题模型之LDA(三) LDA求解之变分推断EM算法 本文是LDA主题模型的第三篇,读这一篇之前 ...
- 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数
隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数(TODO) 隐马尔科夫模型HMM(四)维特比算法 ...
- EM 算法求解高斯混合模型python实现
注:本文是对<统计学习方法>EM算法的一个简单总结. 1. 什么是EM算法? 引用书上的话: 概率模型有时既含有观测变量,又含有隐变量或者潜在变量.如果概率模型的变量都是观测变量,可以直接 ...
- 算法实践——舞蹈链(Dancing Links)算法求解数独
在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...
- 鲍姆-韦尔奇算法求解HMM参数
1. HMM模型参数求解概述 HMM模型参数求解根据已知的条件可以分为两种情况. 第一种情况较为简单,就是我们已知DD个长度为TT的观测序列和对应的隐藏状态序列,即{(O1,I1),(O2,I2),. ...
随机推荐
- 使用 OpenTelemetry 构建可观测性 01 - 介绍
毫无疑问,在过去几年里,你可能已经多次听到过可观测性这个词.对于很多人来说,很难理解这个词的真正含义.对许多人来说,他们错误地将其等同于"监控".虽然可观测性的根本定义以及它所包含 ...
- 什么是 SpringMvc?
SpringMvc 是 spring 的一个模块,基于 MVC 的一个框架,无需中间整合层来整合.
- 如何去掉安装IDEA生成的鼠标右键
IDEA去掉右键 在安装IDEA或其它Intellij软件时,因为整个安装流程都是英文的环境,有童鞋稍不注意,就会把Intellij系列软件自动生成鼠标右键给选上 但问题来了,Intellij系列软件 ...
- CloseableHttpClient设置超时时间demo 未设置默认是2分钟
# CloseableHttpClient设置超时时间demo 未设置默认是2分钟 import org.apache.http.HttpHeaders; import org.apache.http ...
- 实验六-Salt本地pojie实验
[实验目的]了解Salt型密码的加密机制,学会使用本地密码pojie工具来pojieSalt型密码,了解pojie密码原理. [知识点]Salt,密码pojie [实验原理] 1.Salt概念 在密码 ...
- Asp.net Core Flurl.Http 结合IHttpClientFactory管理HttpClient生命周期
Asp.net Core, 在我用过的多种Http REST 客户端: RestSharp WebApiClient Refit Flurl 中,Flurl可以说是最符合我口味的,用起来那可真的顺滑无 ...
- nginx 信号量
nginx支持的信号量 TERM, INT fast shutdown QUIT graceful shutdown HUP changing configuration, keeping up wi ...
- 高通lk阶段mipi 代码解析以及新屏幕添加
参考:https://www.cnblogs.com/linhaostudy/p/9237526.html 背景 前段时间做了这块的工作,但总结完以后领导说我的认识还是过于肤浅,因此重新再看了一下. ...
- Oracle 三种分页方法
Oracle的三层分页指的是在进行分页查询时,使用三种不同的方式来实现分页效果,分别是使用ROWNUM.使用OFFSET和FETCH.使用ROW_NUMBER() OVER() 1.使用ROWNUM ...
- 【冷启动#1】实用的MySQL基础
简单安装一下MySQL Windows下(5.7.x) 本体安装 1.首先先下载安装包,名字如下: mysql-5.7.19-winx64.zip 2.配置环境变量,将解压之后的bin目录添加一下 3 ...