http://blog.csdn.net/pipisorry/article/details/51106570
最优化函数库Optimization
优化是找到最小值或等式的数值解的问题。scipy.optimization子模块提供了函数最小值(标量或多维)、曲线拟合和寻找等式的根的有用算法。
from scipy import optimize皮皮blog
在optimize模块中可以使用leastsq()对数据进行最小二乘拟合计算。leastsq() 只需要将计算误差的函数和待确定参数 的初始值传递给它即可。
leastsq()函数传入误差计算函数和初始值,该初始值将作为误差计算函数的第一个参数传入;
计算的结果r是一个包含两个元素的元组,第一个元素是一个数组,表示拟合后的参数k、b;第二个元素如果等于1、2、3、4中的其中一个整数,则拟合成功,否则将会返回mesg。
"""
使用leastsq()对带噪声的正弦波数据进行拟合。拟合所得到的参数虽然和实际的参数有可能完全不同,但是由于正弦函数具有周期性,实际上拟合的结果和实际的函数是一致的。
"""
import numpy as np
from scipy.optimize import leastsq
def func(x, p):
"""
数据拟合所用的函数: A*sin(2*pi*k*x + theta)
"""
A, k, theta = p
return A*np.sin(2*np.pi*k*x+theta)
def residuals(p, y, x):
"""
实验数据x, y和拟合函数之间的差,p为拟合需要找到的系数
"""
return y - func(x, p)
x = np.linspace(-2*np.pi, 0, 100)
A, k, theta = 10, 0.34, np.pi/6 # 真实数据的函数参数
y0 = func(x, [A, k, theta]) # 真实数据
# 加入噪声之后的实验数据
y1 = y0 + 2 * np.random.randn(len(x))
p0 = [7, 0.2, 0] # 第一次猜测的函数拟合参数
# 调用leastsq进行数据拟合, residuals为计算误差的函数
# p0为拟合参数的初始值,# args为需要拟合的实验数据
plsq = leastsq(residuals, p0, args=(y1, x))
# 除了初始值之外,还调用了args参数,用于指定residuals中使用到的其他参数(直线拟合时直接使用了X,Y的全局变量),同样也返回一个元组,第一个元素为拟合后的参数数组;
这里将 (y1, x)传递给args参数。Leastsq()会将这两个额外的参数传递给residuals()。因此residuals()有三个参数,p是正弦函数的参数,y和x是表示实验数据的数组。
>>> 真实参数: [10, 0.34000000000000002, 0.52359877559829882]
>>> 拟合参数[-9.84152775 0.33829767 -2.68899335]
皮皮blog
def test(): import math from scipy import optimize func = lambda x: x * math.log(x, 2) a = optimize.minimize_scalar(func, bounds=[0.1, 1], method='bounded') print(a)fun: -0.5307378454230427
trunc = [0, 4]max_x = optimize.minimize_scalar( lambda x : -norm.pdf(x, p[ 0], p[ 1]) / norm.pdf(x, q[ 0], q[ 1]), bounds = trunc)[ 'x']
首先定义一个在区间(p[0], p[1])上要求最大值点x的函数norm.pdf(x, p[0], p[1])
Note: 要求最大值前面加一个-号就可以了,好像只有求最小值点的函数
加上求值区间
optimize.fminbound(lambda x: -norm.pdf(x, p[0], p[1]) / norm.pdf(x, q[0], q[1]), trunc[0], trunc[1])这样就可以计算出最小值点x在哪
代入原来的函数中就可以求出最大值y了
[Mathematical optimization: finding minima of functions]
"""
使用fmin()计算函数最小值,并用matplotlib绘制搜索最小值的路径。
"“”
import scipy.optimize as opt
import numpy as np
import sys
points = []
def f(p):
x, y = p
z = (1-x)**2 + 100*(y-x**2)**2
points.append((x,y,z))
return z
def fprime(p):
x, y = p
dx = -2 + 2*x - 400*x*(y - x**2)
dy = 200*y - 200*x**2
return np.array([dx, dy])
init_point =(-2,-2)
try:
method = sys.argv[1]
except:
method = "fmin_bfgs”
fmin_func = opt.__dict__[method]
if method in ["fmin", "fmin_powell"]:
result = fmin_func(f, init_point) #参数为目标函数和初始值
elif method in ["fmin_cg", "fmin_bfgs", "fmin_l_bfgs_b", "fmin_tnc"]:
result = fmin_func(f, init_point, fprime) #参数为目标函数、初始值和导函数(导函数可选?)
elif method in ["fmin_cobyla"]:
result = fmin_func(f, init_point, [])
else:
print "fmin function not found"
sys.exit(0)
f()计算f(x,y)的函数值,为了记录下最小化过程中的计算轨迹,在f()中将每个计算过的 点都添加进全局列表points中。fprime()计算f(x,y)对两个自变量在p处的偏导函数的值。最小化的初值设置为(-2,2),此程序从optimize模块的__dict_字典中获得由命令行 参数指定的最小值函数。
通过求解卷积的逆运算演示fmin的功能,比较fmin, fmin_powell, fmin_cg, fmin_bfgs。
对于一个离散的线性时不变系统h, 如果它的输入是x,那么其输出y可以用x和h的卷积表示:y = x (*) h。已知系统的输入x和输出y,计算传递函数h;或已知系统的传递函数h和输出y,计算系统的输入x。这种运算称为反卷积运算。fmin计算反卷积,这种方法只能用在很小规模的数列之上,不过用来评价fmin函数的性能还是不错的。
import scipy.optimize as opt
import numpy as np
def test_fmin_convolve(fminfunc, x, h, y, yn, x0):
#x (*) h = y, (*)表示卷积,yn为在y的基础上添加一些干扰噪声的结果,x0为求解x的初始值
def convolve_func(h):
#计算yn - x (*) h 的power,fmin将通过计算使得此power最小
return np.sum((yn - np.convolve(x, h))**2)
# 调用fmin函数,以x0为初始值
h0 = fminfunc(convolve_func, x0)
print fminfunc.__name__
print “---------------------“
# 输出x (*) h0 和y 之间的相对误差
print "error of y:", np.sum((np.convolve(x, h0)-y)**2)/np.sum(y**2)
# 输出h0 和h 之间的相对误差
print "error of h:", np.sum((h0-h)**2)/np.sum(h**2)
print
def test_n(m, n, nscale):
"""
随机产生x, h, y, yn, x0等数列,调用各种fmin函数求解b
m为x的长度, n为h的长度, nscale为干扰的强度
""“
x = np.random.rand(m)
h = np.random.rand(n)
y = np.convolve(x, h)
yn = y + np.random.rand(len(y)) * nscale
x0 = np.random.rand(n)
test_fmin_convolve(opt.fmin, x, h, y, yn, x0)
test_fmin_convolve(opt.fmin_powell, x, h, y, yn, x0)
test_fmin_convolve(opt.fmin_cg, x, h, y, yn, x0)
test_fmin_convolve(opt.fmin_bfgs, x, h, y, yn, x0)
if __name__ == "__main__":
test_n(200, 20, 0.1)
程序的输出:
fmin
---------------------
error of y: 0.00223334655127
error of h: 0.0883631777326
fmin_powell
---------------------
error of y: 0.000121416075668
error of h: 0.000191138253652
fmin_cg
---------------------
error of y: 0.000121010258418
error of h: 0.000191002626186
fmin_bfgs
---------------------
error of y: 0.000121010214197
error of h: 0.000191001784589
皮皮blog
Note: 由于fsolve函数在调用函数f时,传递的参数为数组,因此如果直接使用数组中的元素计算的话,计算速度将会有所降低,因此这里先用float函数将数组中的元素转换为Python中的标准浮点数,然后调用标准math库中的函数进行运算。
皮皮blog
然后绘制它。
该函数在大约-1.3有个全局最小值,在3.8有个局部最小值。
为了找到局部最小,我们把变量限制在(0, 10)之间,使用scipy.optimize.fminbound()
Note:在高级章节部分数学优化:找到函数最小值中有关于寻找函数最小值更详细的讨论。
找到标量函数的根
为了寻找根,例如令f(x)=0的点,对以上的用来示例的函数f我们可以使用scipy.optimize.fsolve()
注意仅仅一个根被找到。检查f的图像在-2.5附近有第二个根。我们可以通过调整我们的初始猜测找到这一确切值:
曲线拟合
假设我们有从被噪声污染的f中抽样到的数据:
如果我们知道函数形式(当前情况是x^2 + sin(x)),但是不知道幅度。我们可以通过最小二乘拟合拟合来找到幅度。首先我们定义一个用来拟合的函数:
然后我们可以使用scipy.optimize.curve_fit()来找到a和b:
现在我们找到了f的最小值和根并且对它使用了曲线拟合。我们将一切放在一个单独的图像中:
注意:Scipy>=0.11中提供所有最小化和根寻找算法的统一接口scipy.optimize.minimize(),scipy.optimize.minimize_scalar()和scipy.optimize.root()。它们允许通过method关键字方便地比较不同算法。
你可以在scipy.optimize中找到用来解决多维问题的相同功能的算法。
练习:曲线拟合温度数据
在阿拉斯加每个月的温度上下限,从一月开始,以摄氏单位给出。
练习:2维最小化
source code
[非线性最小二乘拟合:在点抽取地形激光雷达数据上的应用]
[Scipy:高端科学计算]
from: http://blog.csdn.net/pipisorry/article/details/51106570
ref: Optimization (scipy.optimize)
tutorial/optimize