Scipy minimize、fmin、leatsq类型问题(使用序列设置数组元素)、错误的fi

2024-05-29 03:15:44 发布

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

我无法使用scipy.optimize.fmin和scipy.optimize.minimize函数。我已经检查并确认传递给函数的所有参数都是numpy.array类型,以及error函数的返回值。此外,carreau函数返回一个标量值。

一些额外参数(比如size)的原因是:我需要用一个给定的模型(Carreau)来拟合数据。这些数据是在不同的温度下采集的,并用一个移位因子进行校正(该因子也被模型拟合),最后我得到了几组数据,这些数据都应该用来计算相同的4个常数(参数p)。

我知道我不能给fmin函数传递数组列表,所以我必须将所有数据连接到x_data_lin中,用size参数跟踪不同的集合。t保持不同的测试温度,而t_0是保持参考温度的单元素数组。

我确信(三重检查)传递给函数的所有参数以及结果都是一维数组。除此之外的代码如下:

import numpy as np
import scipy.optimize
from scipy.optimize import fmin as simplex

def err_func2(p, x, y, t, t_0, size):
    result = array([])
    temp = 0
    for i in range(0, int(len(size)-1)):
        for j in range(int(temp), int(temp+size[i])):
            result = np.append(result, (carreau(p, x[j], t[i], t_0[0])-y[i]))
        temp += size[i]
    return result

p1 = simplex(err_func2, initial_guess,
            args=(x_data_lin, y_data_lin, t_list, t_0, size), full_output=0)

错误如下:

Traceback (most recent call last):
  File "C:\Python27\Scripts\projects\Carreau - WLF\carreau_model_fit.py", line 146, in <module>
    main()
  File "C:\Python27\Scripts\projects\Carreau - WLF\carreau_model_fit.py", line 105, in main
    args=(x_data_lin, y_data_lin, t_list, t_0, size), full_output=0)
  File "C:\Python27\lib\site-packages\scipy\optimize\optimize.py", line 351, in fmin
    res = _minimize_neldermead(func, x0, args, callback=callback, **opts)
  File "C:\Python27\lib\site-packages\scipy\optimize\optimize.py", line 415, in _minimize_neldermead
    fsim[0] = func(x0)
ValueError: setting an array element with a sequence.

值得注意的是,我让leatsq函数在传递数组列表的同时工作。不幸的是,它在拟合数据方面做得很差。但是,由于我花了很多时间和研究才达到这一点,我将按如下方式发布代码。如果有人有兴趣看到所有的代码,我很乐意张贴它,如果你能推荐我上传一些文件(因为它包括另一个导入的脚本,当然还有示例数据):

##def error_function(p, x, y, t, t_0):
##    result = array([])
##    for index in range(len(x)):
##        result = np.append(result,(carreau(p, x[index],
##                                           t[index], t_0) - y[index]))
##    return result

##    p1, success = scipy.optimize.leastsq(error_function, initial_guess,
##                                         args=(x_list, y_list, t_list, t_0),
##                                         maxfev=10000)

(我本来打算用leatsq-fit发布一张图表数据的图片,但我没有必要的10分。

后期编辑:我现在得到了optimize.curvefit和optimize.leastsq(可能不是巧合地给出了相同的答案),但曲线不好。我一直在想如何优化,最小化,但是有点头疼。单纯形(fmin,Nelder_Mead,随便你叫它什么)会运行,但在任何地方都不会产生一个疯狂的答案。我以前从未处理过非线性优化问题,也不知道该朝哪个方向发展。

以下是工作曲线拟合代码:

def temp_shift(t_s, t, t_0):
    """ This function calculates the a_t temperature shift factor for polymer
    viscosity curves. Variable is the standard temperature, t_s
    """
    C_1 = 8.86
    C_2 = 101.6
    return(np.exp(
        (C_1*(t_0-t_s) / (C_2+(t_0-t_s))) - (C_1*(t-t_s) / (C_2 + (t-t_s)))
        ))

def pass_data(t, t_0):
    def carreau_2(x, p0, p1, p2, p3):
        visc_0 = p0
        m = p1
        n = p2
        t_s = p3
        a_T = temp_shift(p3, t, t_0)
        return (visc_0 * a_T / (1 + m * x * a_T)**n)
    return carreau_2

initial_guess = array([20000, 3, 0.94, -20])

p1, conv = scipy.optimize.curve_fit(pass_data(t_all, t_0), x_data_lin,
                                   y_data_lin, initial_guess)

以下是一些示例数据:

x_data_lin = array([0.01998, 0.04304, 0.2004, 0.43160, 0.92870, 2.0000, 4.30900,
                    9.28500, 15.51954, 21.94936, 37.52960, 90.41786, 204.35230,
                    331.58495, 811.92250, 1694.55309, 3464.27648, 8826.65738,
                    14008.00242])   

y_data_lin = array([13520.00000, 13740.00000, 12540.00000, 9384.00000, 5201,
                    3232.00000, 2094.00000, 1484.00000, 999.00000, 1162.05088
                    942.56946, 705.62489, 429.47341, 254.15136, 185.22916, 
                    122.07113, 76.46324, 47.85064, 25.74315, 18.84875])

t_all = array([190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 
               190, 190, 190, 190, 190, 190, 190])

t_0 = 80

这是一张曲线拟合结果的图片(现在我有10个点,可以发布了!)。注意这里有3条曲线,因为我使用了3组数据来优化曲线,在3个不同的温度下。聚合物的特性是剪切速率-粘度关系保持不变,只是被温度因子a u T移动: scipy.optimize.curve_fit

我真的很感谢你对如何改进拟合,或者如何定义函数以便优化,最小化工作,以及哪种方法(Nelder-Mead,Powel,BFGS)可能有效的建议。

要添加的另一个编辑:我使用了Nelder Mead(optimize.fmin,默认值为optimize.minimize)函数-我将包括下面修改的错误函数。之前,我只是对结果数组求和并返回它。这会导致非常负的值(显然,因为函数的目标是最小化)。把结果平方再求和就解决了那个问题。注意,正如JaminSore所建议的那样,我还完全改变了函数以利用numpy的数组广播(谢谢Jamin!)

def err_func2(p, x, y, t, t_0):
    return ((carreau(p, x, t, t_0)-y)**2).sum()

不幸的是,Nelder-Mead函数给出的结果与leatsq和curve-fit相同。从上图中可以看出,它不是最佳拟合;事实上,在这一点上,Microsoft Excel的solver函数在数据方面做得更好。

至少,我希望这个线程对初学者将来进行scipy.optimize很有用,因为我花了很长时间才发现所有这些。


Tags: 数据函数indatasizedefscipy数组

热门问题