我正在尝试使用“ brute”方法来最小化20个变量的函数。它以一个神秘的错误失败。这是完整的代码:
import random
import numpy as np
import lmfit
def progress_update(params, iter, resid, *args, **kws):
pass
#print(resid)
def score(params, data = None):
parvals = params.valuesdict()
M = data
X_params = []
Y_params = []
for i in range(M.shape[0]):
X_params.append(parvals['x'+str(i)])
for j in range(M.shape[1]):
Y_params.append(parvals['y'+str(i)])
return diff(M, X_params, Y_params)
def diff(M, X_params, Y_params):
total = 0
for i in range(M.shape[0]):
for j in range(M.shape[1]):
total += abs(M[i,j] - (X_params[i] - Y_params[j])**2)
return total
dim = 10
random.seed(0)
M = np.empty((dim, dim))
for i in range(M.shape[0]):
for j in range(M.shape[1]):
M[i,j] = i*random.random()+j**2
params = lmfit.Parameters()
for i in range(M.shape[0]):
params.add('x'+str(i), value=random.random()*10, min=0, max=10)
for j in range(M.shape[1]):
params.add('y'+str(j), value=random.random()*10, min=0, max=10)
result = lmfit.minimize(score, params, method='brute', kws={'data': M}, iter_cb=progress_update)
但是,此操作失败并显示:
ValueError: array is too big; `arr.size * arr.dtype.itemsize` is larger than the maximum possible size.
是什么原因导致此问题?
答案 0 :(得分:1)
“导致此问题的原因”
您不能强行解决高维问题,因为强行方法require exponential work(时间和内存(如果是天真的实现的话))。
更直接地,lmfit在后台使用numpy(*),它具有可以分配多少数据的最大大小。您的初始数据结构不太大(10x10),它是导致问题的暴力破解所需的组合表。
如果您愿意破解该实现,则可以切换到稀疏的内存结构。但这并不能解决数学问题。
关于高维优化
尝试使用其他最小化器,但要警告:在高维空间中全局最小化非常困难。像fixed point / gradient descent之类的“局部最小值”方法可能会更有效率。
我不想过于悲观,但是一般情况下进行高级优化非常困难,而且恐怕超出了SO问题的范围。 Here is a survey。
实用替代方案
梯度下降为supported a little in sklearn,但对于机器学习而言,梯度下降比常规优化更多; scipy actually has pretty good optimization的覆盖范围和great documentation。我从那里开始。可以执行gradient descent there too,但不是必需的。
从scipy关于无约束最小化的文档中,您有很多选择:
方法Nelder-Mead使用单纯形算法[],[]。这个算法 在许多应用程序中都很强大。但是,如果数值计算 可以信任派生,使用第一和/或其他算法的其他算法 二阶导数信息可能会更好 表现一般。
方法Powell是对Powell方法[],[]的修改, 共轭方向法。它执行顺序一维 沿方向集的每个向量最小化 选项和信息),在每次主迭代时都会更新 最小化循环。函数不必是可区分的,并且不需要 取导数。
以及许多其他基于导数的方法可用。 (通常,当您拥有派生信息时,您会做得更好。)
脚注/查看源代码
(*)此处的实际错误is thrown(基于您的numpy实现)。引用:
`if (npy_mul_with_overflow_intp(&nbytes, nbytes, dim)) {
PyErr_SetString(PyExc_ValueError,
"array is too big; `arr.size * arr.dtype.itemsize` "
"is larger than the maximum possible size.");
Py_DECREF(descr);
return NULL;`