【问题标题】:lmfit minimize fails with ValueError: array is too biglmfit 最小化失败并出现 ValueError:数组太大
【发布时间】:2018-07-31 20:50:02
【问题描述】:

我正在尝试使用“蛮力”方法来最小化 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.

是什么导致了这个问题?

【问题讨论】:

    标签: python optimization lmfit


    【解决方案1】:

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

    Math

    你不能暴力破解一个高维问题,因为暴力破解方法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 使用单纯形算法 [], []。这个算法 在许多应用中都很稳健。然而,如果数值计算 可以信任导数,其他算法使用第一个和/或 二阶导数信息可能更受青睐 表现一般。

    鲍威尔方法是鲍威尔方法[]的修改,[]是一个 共轭方向法。它执行顺序一维 沿方向集的每个向量的最小化(在 选项和信息),在主程序的每次迭代中更新 最小化循环。该函数不必是可微的,并且没有 取导数。

    还有更多基于衍生的方法可用。 (一般来说,当您有可用的衍生信息时,您会做得更好。)


    脚注/查看源代码

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

    【讨论】:

    • 谢谢。那么它可以处理的最大尺寸是多少呢?我还发布了一个有关全局优化器失败的相关问题。 stackoverflow.com/questions/51621903/…
    • High Anush,稍作编辑,我将添加更多内容。这几乎肯定是依赖于实现的,如果你在底层使用稀疏/迭代器结构,它会上升很多。底线:网格搜索在这里不是一个好主意。
    • @en_Knight 说 lmfit “在后台使用熊猫”是不正确的。它不是。像 Python 一样,它应该只受物理内存的限制。但是 en_Knight 是正确的,因为您要求一个 20 维网格,每个网格有 10 个步骤,所以出现这个错误(来自 numpy)是正确的。那是 10**20 次函数评估。如果每个函数评估需要 1 毫秒,那么总运行时间将是 30 亿年。蛮力方法适用于 2 个或 3 个或 4 个变量参数。
    • @en_Knight 为方便起见,它可以处理 pandas.Series 中的数据,这就是它导入 pandas 的原因。但是这些被转换为 numpy 数组。在引擎盖下,都是 numpy 和 scipy,而不是 pandas。 Pandas 没有用于实际计算的任何部分,并且与此处的错误消息无关。当然,用户的问题是因为蛮力方法无法扩展到高维(变量数)问题,但这不是 pandas 或 numpy 的错。再说一次,这个问题是可并行的,所以如果你有 10 亿个计算节点,只需要 3 年就可以解决;)。
    • @MNewville 再次感谢您的意见。我在答案中将 pandas 切换为 numpy,保持指向实际异常的指针。我同意根本问题是算法 - 我将尝试重构答案以使其更清晰。这里的蛮力缺乏可扩展性有两个组成部分:1)时间复杂度,这不是用户遇到的实际问题(它根本没有运行,更不用说多年了)。 2) 是内存复杂度,可以通过强制 numpy 使用稀疏矩阵而不是密集矩阵或使用迭代器来解决...
    猜你喜欢
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 2022-07-06
    • 1970-01-01
    • 2015-12-05
    • 2016-08-26
    相关资源
    最近更新 更多