我试图用“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}$是什么引起了这个问题?在
“是什么导致了这个问题”
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关于无约束最小化的文档中,您有许多选项:
还有更多基于导数的方法可用。(通常,当您有可用的派生信息时,您会做得更好。)
脚注/查看源代码
(*)这里的实际错误is thrown,基于您的numpy实现。引用:
相关问题 更多 >
编程相关推荐