在scipy.optimize.root method = lm
的文档中,以下是options
关键字的默认值。
options={'col_deriv': 0, 'diag': None, 'factor': 100, 'gtol': 0.0, 'eps': 0.0, 'func': None, 'maxiter': 0, 'xtol': 1.49012e-08, 'ftol': 1.49012e-08}
关于col_deriv
的说明,他们说
col_deriv : bool, optional
non-zero to specify that the Jacobian function computes derivatives down the columns (faster, because there is no transpose operation)
如果我理解它的说法,如果我写col_deriv = True
例如,jacobian
将按列计算,因此更快。
问题:如果速度更快,为什么col_deriv
的默认值为非零值?
我在这里错过了什么吗?
答案 0 :(得分:2)
也许来自scipy.optimize.leastsq
的文档可以提供帮助,因为它同时记录Dfun
(雅各布)和col_deriv
。从Dfun
我们得到:
Dfun:可调用,可选
使用行中的导数计算func 的雅可比行列式的函数或方法。如果这是None,则估计Jacobian。
从col_deriv
我们得到:
col_deriv:bool,可选
非零指定雅可比函数计算列中的导数(更快,因为没有转置操作)。
我对此的解读如下:
默认情况下,scipy
期望计算雅可比矩阵的函数返回一个遵循“正常”定义的矩阵(例如,参见https://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant)。
但是,scipy
本身会调用其他函数,可能是用Fortran see, e.g., minpack编写的,它们希望衍生物(关于坐标)放在列中。
如果计算雅可比矩阵的函数可以返回一个矩阵,其中衍生物沿着列而不是行放置,那么scipy
在将它传递给minpack
之前不需要转置雅可比矩阵。因此节省了计算时间。
答案 1 :(得分:2)
默认值对应于写入雅可比矩阵的数学约定,如Wikipedia中记录的那样:矩阵的第一行由函数的第一个分量的偏导数等组成。在多变量微积分中效果更好,因为可以将右边的矩阵乘以变量的列向量,以获得函数的线性逼近。
例如,让
fun = lambda x: [x[0]**3-x[1], 2*x[0]+x[1]-12]
雅各比派的传统写法是
jac = lambda x: [[3*x[0]**2, -1], [2, 1]]
其中[3*x[0]**2, -1]
来区分fun
的第一个组成部分,x[0]**3-x[1]
。
方法root(fun, [0, 0], jac=jac)
在12次迭代中收敛。或者我们可以用转置的方式写雅可比,
jact = lambda x: [[3*x[0]**2, 2], [-1, 1]]
并使用
root(fun, [0, 0], jac=jact, options={"col_deriv": 1})
达到同样的效果。我不明白增益是值得的,但也许是非常大的系统。
如果"col_deriv": 1
是默认设置,那么用他们习惯的方式实现Jacobian的不满意的用户会发现性能很差(在上面的示例中使用了不正确的Jacobian版本更多比根搜索的步数加倍。