Python lmfit最小化失败,返回ValueError:数组太大
我试图使用“暴力”方法最小化20个变量的函数。它因一个神秘的错误而失败。以下是完整的代码:Python lmfit最小化失败,返回ValueError:数组太大,python,optimization,lmfit,Python,Optimization,Lmfit,我试图使用“暴力”方法最小化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 =
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.
是什么导致此问题?是什么导致此问题 你不能强行解决高维问题,因为强行解决方法(时间和内存,如果实现得很幼稚的话) 更直接地说,lmfit在引擎盖下使用numpy(*),它的最大大小是它可以分配多少数据。您的初始数据结构不是太大(10x10),它是导致问题的蛮力所需的组合表 如果您愿意破解实现,可以切换到稀疏内存结构。但这并不能解决数学问题 关于高维优化 尝试不同的最小化方法,但要注意:在高维空间中全局最小化是非常困难的。像/这样的“局部极小”方法可能更有效 我不想悲观,但一般来说,高级优化是非常困难的,我担心这超出了所谓的问题的范围 切实可行的备选方案 梯度下降比一般优化更适合机器学习;覆盖范围,以及。我从那里开始。这是可能的,但不是必须的 从scipy关于无约束最小化的文档中,您有许多选择: 方法Nelder-Mead使用单纯形算法[],[]。该算法 在许多应用中都是健壮的。然而,如果 导数可以信任,其他算法使用第一个和/或 二阶导数信息可能是更好的选择 一般表现 方法Powell是对Powell方法[]的修改,该方法是 共轭方向法。它执行顺序一维搜索 沿方向集的每个向量的最小化(图中的direc场) 选项和信息),它在主 最小化循环。函数不需要是可微的,并且 衍生品被采用 还有更多基于导数的方法可用。(一般来说,当你有衍生工具信息可用时,你会做得更好。)
脚注/查看源代码 (*)此处的实际错误,基于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;`
非常感谢。那么它能应付的最大规模是多少呢?我还发布了一个关于全局优化器失败的相关问题。高阿努什,编辑了一点,我会补充一点。这几乎可以肯定是依赖于实现的,如果在引擎盖下使用稀疏/迭代器结构,这一点会大大提高。一句话:网格搜索在这里不是一个好主意。@en_Knight说lmfit“在引擎盖下使用熊猫”是不正确的。事实并非如此。与Python一样,它应该只受物理内存的限制。但是en_Knight是正确的,这个错误(来自numpy)的产生是因为你要求一个20维的网格,每个网格有10个步骤。这是10*20次功能评估。如果每个函数评估需要1毫秒,那么总运行时间将为30亿年。蛮力方法适用于2个或3个或可能4个可变参数。@en_Knight为方便起见,它可以处理pandas.Series中的数据,这就是它导入pandas的原因。但是这些被转换为numpy数组。在引擎盖下,这一切都是裸体和肌肉,而不是熊猫。Pandas未用于实际计算的任何部分,与此处的错误消息无关。当然,用户的问题是因为暴力方法不能扩展到高维(变量)问题,但这不是pandas或numpy的错。再说一次,这个问题是可并行化的,所以如果你有10亿个计算节点,只需要3年就可以解决;)@再次感谢您的投入。在答案中,我将pandas切换到numpy,并将指针保持在实际异常的位置。我同意根本问题是算法——我将尝试重构答案以使其更清晰。暴力中缺乏可伸缩性的原因有两个:1)时间复杂性,这不是用户遇到的实际问题(它根本没有运行,更不用说多年了)。2) 是内存复杂性,可以通过强制numpy使用稀疏矩阵而不是密集矩阵或使用迭代器来解决。。。