在 scipy.sparse.linalg.cg 中打印回调的当前残差

问题描述 投票:0回答:2

我正在使用

scipy.sparse.linalg.cg
来求解大型稀疏线性系统,它工作得很好,除了我想添加进度报告,以便我可以在求解器工作时监视残差。我已经设法设置了回调,但我不知道如何从回调内部访问当前的残差。当然,我自己计算残差是可能的,但这是一个相当繁重的操作,我想避免。我是否错过了什么,或者没有有效的方法来获取残差?

python scipy linear-algebra
2个回答
8
投票

回调仅发送当前解向量

xk
。因此您无法直接访问残差。然而,源代码显示
resid
cg
函数中的局部变量。

因此,使用 CPython,可以使用

inspect
模块来查看调用者框架中的局部变量:

import inspect
import numpy as np
import scipy as sp
import scipy.sparse as sparse
import scipy.sparse.linalg as splinalg
import random

def report(xk):
    frame = inspect.currentframe().f_back
    print(frame.f_locals['resid'])

N = 200
A = sparse.lil_matrix( (N, N) )
for _ in xrange(N):
    A[random.randint(0, N-1), random.randint(0, N-1)] = random.randint(1, 100)

b = np.random.randint(0, N-1, size = N)
x, info = splinalg.cg(A, b, callback = report)

0
投票

正如之前回答的那样,您可以使用回调函数来访问cg调用中的变量。我将其与外部命名范围结合起来来跟踪我的训练的一些指标。以下是计算残差 MSE 的方法,例如:

    # Solving a linear system Au = b
    # Here, the result of Au is given by a function called `laplacian_operator`

    matrix = scipy.sparse.linalg.LinearOperator(
        (num_points, num_points), matvec=laplacian_operator
    )

    residuals = []  # here is where you will store the metrics

    def report_callback(sol_vec):
        # notice that `matrix`, `b` and `residuals` come from the outer scope
        mse = (np.square(matrix * sol_vec - b)).mean()  
        residuals.append(mse)

    u, cg_info = scipy.sparse.linalg.cg(matrix, b, callback=report_callback)

请注意,在这种方法中,您需要在每次迭代时重新评估乘积 Ax,但它比使用

inspect
访问内部变量要简单。

© www.soinside.com 2019 - 2024. All rights reserved.