ValueLmFit太大,array失败

2024-05-01 21:32:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用“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)

但是,这样做失败了:

^{pr2}$

是什么引起了这个问题?在


Tags: inimportfordatadefrangerandomparams
1条回答
网友
1楼 · 发布于 2024-05-01 21:32:44

“是什么导致了这个问题”

Math

因为暴力方法require exponential work(时间和内存,如果实现得很幼稚的话)就不能强行解决高维问题。在

更直接地说,lmfit在引擎盖下使用numpy(*),它有一个可以分配多少数据的最大大小。你的初始数据结构不是太大(10x10),而是暴力所需的组合表导致了问题。在

如果您愿意破解实现,可以切换到稀疏内存结构。但这并不能解决数学问题。在

关于高维优化

尝试使用不同的minizer,但要注意:在高维空间中全局最小化是非常困难的。”像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关于无约束最小化的文档中,您有许多选项:

Method Nelder-Mead uses the Simplex algorithm [], []. This algorithm is robust in many applications. However, if numerical computation of derivative can be trusted, other algorithms using the first and/or second derivatives information might be preferred for their better performance in general.

Method Powell is a modification of Powell’s method [], [] which is a conjugate direction method. It performs sequential one-dimensional minimizations along each vector of the directions set (direc field in options and info), which is updated at each iteration of the main minimization loop. The function need not be differentiable, and no derivatives are taken.

还有更多基于导数的方法可用。(通常,当您有可用的派生信息时,您会做得更好。)


脚注/查看源代码

(*)这里的实际错误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;`

相关问题 更多 >