scipy.optimize.root 中计算雅可比行列式的默认选项
Default options in computing the Jacobian in scipy.optimize.root
在 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
的非零值不是默认值?。
我是不是漏掉了什么?
也许来自 scipy.optimize.leastsq
的文档可以提供帮助,因为它同时记录了 Dfun
(Jacobian) 和 col_deriv
。从 Dfun
我们得到:
Dfun : callable, optional
A function or method to compute the Jacobian of func with derivatives across the rows. If this is None, the Jacobian will be estimated.
从 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).
我的解读如下:
默认情况下,scipy
期望计算雅可比矩阵的函数 return 一个遵循“正常”定义的矩阵(例如,参见 https://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant ).
但是,scipy
本身会调用其他函数,可能是用 Fortran see, e.g., minpack 编写的,这些函数期望将导数(关于坐标)放在列中。
因此,如果计算雅可比矩阵的函数可以 return 一个沿列而不是行放置导数的矩阵,那么 scipy
在传递之前不需要转置雅可比矩阵到 minpack
函数从而节省计算时间。
默认值对应于编写雅可比矩阵的数学约定,如 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 more比根搜索的步骤数加倍)。
在 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
的非零值不是默认值?。
我是不是漏掉了什么?
也许来自 scipy.optimize.leastsq
的文档可以提供帮助,因为它同时记录了 Dfun
(Jacobian) 和 col_deriv
。从 Dfun
我们得到:
Dfun : callable, optional
A function or method to compute the Jacobian of func with derivatives across the rows. If this is None, the Jacobian will be estimated.
从 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).
我的解读如下:
默认情况下,
scipy
期望计算雅可比矩阵的函数 return 一个遵循“正常”定义的矩阵(例如,参见 https://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant ).但是,
scipy
本身会调用其他函数,可能是用 Fortran see, e.g., minpack 编写的,这些函数期望将导数(关于坐标)放在列中。
因此,如果计算雅可比矩阵的函数可以 return 一个沿列而不是行放置导数的矩阵,那么 scipy
在传递之前不需要转置雅可比矩阵到 minpack
函数从而节省计算时间。
默认值对应于编写雅可比矩阵的数学约定,如 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 more比根搜索的步骤数加倍)。