使用lanczos算法进行的预处理共轭梯度算法(Preconditioned Conjugate Gradients Method)
构造预处理矩阵M(对称正定)
下图来自:预处理共轭梯度法(1)



下图来自:预处理(Preconditioning)

根据上面的对于预处理共轭梯度法的介绍,我们可以得到使用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 = np.array([[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]])
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__":
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
x = cg(lambda x: A.dot(x), b, cg_iters=5, verbose=True) # pylint: disable=W0108
assert np.allclose(A.dot(x), b)
Q, H = lanczos2(f_Ax, b, 10)
M_inv = Q.T.dot(Q)
x = preconditioned_cg(lambda x: A.dot(x), lambda x: M_inv.dot(x), b, cg_iters=5,
verbose=True) # pylint: disable=W0108
assert np.allclose(A.dot(x), b)
A_ = Q.T.dot(A).dot(Q)
b_ = Q.T.dot(b)
x_ = cg(lambda x: A_.dot(x), b_, cg_iters=5, verbose=True) # pylint: disable=W0108
x = Q.dot(x_)
assert np.allclose(A.dot(x), b)
运算结果:

因为预处理的共轭梯度法的适用环境:
“正定的大型稀疏矩阵”,并且矩阵的条件数(最大最小特征值之比)很大的情况。
因此,这里给出的使用lanczos算法进行的预处理共轭梯度算法并没有比共轭梯度法有运算速度上的提升。
使用lanczos算法进行的预处理共轭梯度算法(Preconditioned Conjugate Gradients Method)的更多相关文章
- 共轭梯度算法求最小值-scipy
# coding=utf-8 #共轭梯度算法求最小值 import numpy as np from scipy import optimize def f(x, *args): u, v = x a ...
- 机器学习: 共轭梯度算法(PCG)
今天介绍数值计算和优化方法中非常有效的一种数值解法,共轭梯度法.我们知道,在解大型线性方程组的时候,很少会有一步到位的精确解析解,一般都需要通过迭代来进行逼近,而 PCG 就是这样一种迭代逼近算法. ...
- Mahout 系列之----共轭梯度
无预处理共轭梯度 要求解线性方程组 ,稳定双共轭梯度法从初始解 开始按以下步骤迭代: 任意选择向量 使得 ,例如, 对 若 足够精确则退出 预处理共轭梯度 预处理通常被用来加速迭代方法的收敛.要使用预 ...
- 近端梯度算法(Proximal Gradient Descent)
L1正则化是一种常用的获取稀疏解的手段,同时L1范数也是L0范数的松弛范数.求解L1正则化问题最常用的手段就是通过加速近端梯度算法来实现的. 考虑一个这样的问题: minx f(x)+λg(x) x ...
- 3. OpenCV-Python——图像梯度算法、边缘检测、图像金字塔与轮廓检测、直方图与傅里叶变换
一.图像梯度算法 1.图像梯度-Sobel算子 dst = cv2.Sobel(src, ddepth, dx, dy, ksize) ddepth:图像的深度 dx和dy分别表示水平和竖直方向 ks ...
- 【算法随记】Canny边缘检测算法实现和优化分析。
以前的博文大部分都写的非常详细,有很多分析过程,不过写起来确实很累人,一般一篇好的文章要整理个三四天,但是,时间越来越紧张,后续的一些算法可能就以随记的方式,把实现过程的一些比较容易出错和有价值的细节 ...
- Machine Learning读书会,面试&算法讲座,算法公开课,创业活动,算法班集锦
Machine Learning读书会,面试&算法讲座,算法公开课,创业活动,算法班集锦 近期活动: 2014年9月3日,第8次西安面试&算法讲座视频 + PPT 的下载地址:http ...
- 前向分步算法 && AdaBoost算法 && 提升树(GBDT)算法 && XGBoost算法
1. 提升方法 提升(boosting)方法是一种常用的统计学方法,在分类问题中,它通过逐轮不断改变训练样本的权重,学习多个分类器,并将这些分类器进行线性组合,提高分类的性能 0x1: 提升方法的基本 ...
- 前向传播算法(Forward propagation)与反向传播算法(Back propagation)
虽然学深度学习有一段时间了,但是对于一些算法的具体实现还是模糊不清,用了很久也不是很了解.因此特意先对深度学习中的相关基础概念做一下总结.先看看前向传播算法(Forward propagation)与 ...
- 词性标注算法之CLAWS算法和VOLSUNGA算法
背景知识 词性标注:将句子中兼类词的词性根据上下文唯一地确定下来. 一.基于规则的词性标注方法 1.原理 利用事先制定好的规则对具有多个词性的词进行消歧,最后保留一个正确的词性. 2.步骤 ①对词性歧 ...
随机推荐
- kettle从入门到精通 第二十三课 kettle carte 错误(java.lang.OutOfMemoryError: GC overhead limit exceeded,Could not emit buffer due to lack of requests,java heap space)分析
1.Could not emit buffer due to lack of requests(无法发出缓冲区,因为请求不足.) 原因有两点:1)消费者处理数据能力较弱,如表输出步骤.2)消费者没有处 ...
- 可观测性平台夜莺开源项目发布V6正式版!
夜莺开源项目在2023.7月底发布了V6版本,这个版本开始,项目目标不止于做一款开源监控系统,而是要做一款开源可观测性平台,不过路漫漫其修远兮,初期只是把日志数据源引入并完成了基本的可视化,后续会着力 ...
- Spring扩展——BeanPostProcessor(BPP)
BeanPostProcess简介 在Spring中 BeanPostProcessor 是一个非常重要的接口,它用于在每个bean对象初始化前后修改Bean的属性信息,比如我们最常用的@Autowi ...
- 一个简单可分享的web数据透视分析
我推荐一个简单可分享的在线数据透视分析网站,首先看效果: 在线数据透视展示 用户上传一个Excel或csv文件后,把指标拖拽到左右两侧,再选择合适的分析方式,在中间展示区域就会出现分析数据或者图形了, ...
- Linux Debian安装教程
Debian 是一个免费的开源操作系统,是最古老的 Linux 发行版之一,于 1993 年由 Ian Murdock 创建.它采用了自由软件协议,并且由志愿者社区维护和支持.Debian 的目标是创 ...
- 从JDK8升级到JDK17
一.概述 鉴于JDK8已经是老古董,还有性能问题,兼且各个公司已经不再维护1.8的JDK,所以升级公司的核心产品之一的后端到JDK到17是相对要紧的事情. 通过升级到jdk17,具有以下好处: 不要在 ...
- MYSQL中怎么查询LONGBLOB类型数据的大小
在MySQL中,LONGBLOB 是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据.但是,LONGBLOB 数据类型本身并不直接存储数据的大小(长度).它存储的是二进制数据的实际内容. ...
- python重拾基础第三天
本节内容 函数基本语法及特性 参数与局部变量 返回值 嵌套函数 递归 匿名函数 函数式编程介绍 高阶函数 内置函数 1. 函数基本语法及特性 背景提要 现在老板让你写一个监控程序,监控服务器的系统状况 ...
- .NET 个人博客-首页排版优化
个人博客-首页排版优化 优化计划 置顶3个且可滚动或切换 推荐改为4个,然后新增历史文章,将推荐的加载更多放入历史文章,按文章发布时间降序排列. 标签功能,可以为文章贴上标签 推荐点赞功能 本篇文章优 ...
- 韦东山freeRTOS系列教程之【第八章】事件组(event group)
目录 系列教程总目录 概述 8.1 事件组概念与操作 8.1.1 事件组的概念 8.1.2 事件组的操作 8.2 事件组函数 8.2.1 创建 8.2.2 删除 8.2.3 设置事件 8.2.4 等待 ...