SciPy 优化
章节
优化是指在某些约束条件下,求解目标函数最优解的过程。机器学习、人工智能中的绝大部分问题都会涉及到求解优化问题。
SciPy的optimize模块提供了许多常用的数值优化算法,一些经典的优化算法包括线性回归、函数极值和根的求解以及确定两函数交点的坐标等。
导入scipy.optimize模块,如下所示:
from scipy import optimize
标量函数极值求解
fmin_bfgs方法
函数f(x)是一个抛物线,求它的极小值:
$$
f(x) = x^2 + 2x + 9
$$
我们先画出函数曲线:
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
# 定义函数
def f(x):
return x**2 + 2*x + 9
# x取值:-10到10之间,间隔0.1
x = np.arange(-10, 10, 0.1)
# 画出函数曲线
plt.plot(x, f(x))
# plt.savefig('./opt2-1.png') # 保存要显示的图片
plt.show()
计算该函数最小值的有效方法之一是使用带起点的BFGS算法。该算法从参数给定的起始点计算函数的梯度下降,并输出梯度为零、二阶导数为正的极小值。BFGS算法是由Broyden,Fletcher,Goldfarb,Shanno四个人分别提出的,故称为BFGS校正。
示例
使用BFGS函数,找出抛物线函数的最小值:
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
# 定义函数
def f(x):
return x**2 + 2*x + 9
# x取值:-10到10之间,间隔0.1
x = np.arange(-10, 10, 0.1)
# 画出函数曲线
plt.plot(x, f(x))
# 第一个参数是函数名,第二个参数是梯度下降的起点。返回值是函数最小值的x值(ndarray数组)
xopt = optimize.fmin_bfgs(f, 0)
xmin = xopt[0] # x值
ymin = f(xmin) # y值,即函数最小值
print('xmin: ', xmin)
print('ymin: ', ymin)
# 画出最小值的点, s=20设置点的大小,c='r'设置点的颜色
plt.scatter(xmin, ymin, s=20, c='r')
#plt.savefig('./opt3-1.png') # 保存要显示的图片
plt.show()
输出
Optimization terminated successfully.
Current function value: 8.000000
Iterations: 2
Function evaluations: 9
Gradient evaluations: 3
xmin: -1.00000000944232
ymin: 8.0
fmin_bfgs
有个问题,当函数有局部最小值,该算法会因起始点不同,找到这些局部最小而不是全局最小。
让我们看另一个函数,该函数有多个局部最小值:
$$
g(x) = x^2 + 20sin(x)
$$
画出该函数的曲线:
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
# 定义函数
def g(x):
return x**2 + 20*np.sin(x)
# x取值:-10到10之间,间隔0.1
x = np.arange(-10, 10, 0.1)
# 画出函数曲线
plt.plot(x, g(x))
# plt.savefig('./opt4-1.png') # 保存要显示的图片
plt.show()
函数曲线
可以看到,该函数有多个底部。如果初始值设置不当,获得的最小值有可能只是局部最小值。
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
# 定义函数
def g(x):
return x**2 + 20*np.sin(x)
# x取值:-10到10之间,间隔0.1
x = np.arange(-10, 10, 0.1)
# 画出函数曲线
plt.plot(x, g(x))
# 第一个参数是函数名,第二个参数是梯度下降的起点。返回值是函数最小值的x值(ndarray数组)
# 可以看到5.0附近有个局部最小,把初始值设置为7, 返回的应该是这个局部最小值。
xopt = optimize.fmin_bfgs(g, 7)
xmin = xopt[0] # x值
ymin = g(xmin) # y值,即函数最小值
print('xmin: ', xmin)
print('ymin: ', ymin)
# 画出最小值的点, s=20设置点的大小,c='r'设置点的颜色
plt.scatter(xmin, ymin, s=20, c='r')
#plt.savefig('./opt5-1.png') # 保存要显示的图片
plt.show()
输出
Optimization terminated successfully.
Current function value: 0.158258
Iterations: 3
Function evaluations: 27
Gradient evaluations: 9
xmin: 4.271095444673479
ymin: 0.15825752683190686
可以看到5.0附近有个局部最小,把初始值设置为7, 返回的是这个局部最小值。
如果把初始值设置为0,应该就能返回真正的全局最小值:
basinhopping 方法
对于这种情况,可以使用scipy.optimize提供的basinhopping()
方法。该方法把局部优化方法与起始点随机抽样相结合,求出全局最小值,代价是耗费更多计算资源。
调用语法
optimize.basinhopping(func, x0)
- func 目标函数
- x0 初始值
示例
import numpy as np
from scipy import optimize
# 定义函数
def g(x):
return x**2 + 20*np.sin(x)
# 求取最小值,初始值为7
ret = optimize.basinhopping(g, 7)
print(ret)
输出
fun: 0.15825752683178962
lowest_optimization_result: fun: 0.15825752683178962
hess_inv: array([[0.04975718]])
jac: array([4.76837158e-07])
message: 'Optimization terminated successfully.'
nfev: 12
nit: 2
njev: 4
status: 0
success: True
x: array([4.27109533])
message: ['requested number of basinhopping iterations completed successfully']
minimization_failures: 0
nfev: 1641
nit: 100
njev: 547
x: array([4.27109533])
可以看到全局最小值被正确找出:fun: 0.15825752683178962
,x: array([4.27109533])
scipy.optimize.brute函数蛮力法也可用于全局优化,但效率较低。蛮力方法的语法为:
scipy.optimize.brute(f, 0)
fminbound
要求取一定范围之内的函数最小值,可使用fminbound方法。
调用语法
optimize.fminbound(func, x1, x2)
- func 目标函数
- x1, x2 范围边界
示例
import numpy as np
from scipy import optimize
# 定义函数
def g(x):
return x**2 + 20*np.sin(x)
# 求取-10到-5之间的函数最小值。full_output=True表示返回详细信息。
ret = optimize.fminbound(g, -10, -5, full_output=True)
print(ret)
输出
(-7.068891380019064, 35.82273589215206, 0, 12)
函数最小值是:35.82273589215206,对应的x值:-7.068891380019064。
函数求解
对于一个函数f(x),当f(x) = 0,求取x的值,即为函数求解。这种情况,可以使用fsolve()函数。
调用语法
optimize.fsolve(func, x0)
- func 目标函数
- x0 初始值
解单个方程
示例
解单个方程:
import numpy as np
from scipy import optimize
# 定义函数
def g(x):
return x**2 + 20*np.sin(x)
# 函数求解
ret = optimize.fsolve(g, 2)
print(ret)
输出
[0.]
解出的根值是:0
解方程组
如果要对如下方程组求解:
$$
f1(u1,u2,u3) = 0 \
f2(u1,u2,u3) = 0 \
f3(u1,u2,u3) = 0
$$
func可以定义为:
def func(x):
u1,u2,u3 = x
return [f1(u1,u2,u3), f2(u1,u2,u3), f3(u1,u2,u3)]
示例
解方程组:
$$
4x + 9 = 0 \
3y^2 - sin(yz) = 0 \
yz - 2.5 = 0
$$
from scipy.optimize import fsolve
from math import sin,cos
def f(x):
x0 = float(x[0])
x1 = float(x[1])
x2 = float(x[2])
return [
4*x1 + 9,
3*x0*x0 - sin(x1*x2),
x1*x2 - 2.5
]
result = fsolve(f, [1,1,1])
print (result)
输出
[-0.44664383 -2.25 -1.11111111]
拟合
curve_fit
假设有一批数据样本,要创建这些样本数据的拟合曲线/函数,可以使用Scipy.optimize模块的curve_fit()
函数。
调用形式
optimize.curve_fit(func, x1, y1)
- func 目标函数
- x1, y1 样本数据
我们将使用下面的函数来演示曲线拟合:
$$
f(x) = 50cos(x) + 2
$$
示例
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
# 函数模型用于生成数据
def g(x, a, b):
return a*np.cos(x) + b
# 产生含噪声的样本数据
x_data = np.linspace(-5, 5, 100) # 采样点
y_data = g(x_data, 50, 2) + 5*np.random.randn(x_data.size) # 加入随机数作为噪声
# 使用curve_fit()函数来估计a和b的值
variables, variables_covariance = optimize.curve_fit(g, x_data, y_data)
# 输出结果
print('\n求出的系数a, b: ')
print(variables)
print('\nvariables_covariance: ')
print(variables_covariance)
输出
求出的系数a, b:
[49.66367999 2.09557981]
variables_covariance:
[[0.55593391 0.10388677]
[0.10388677 0.26071478]]
variables是给定模型的最优参数,variables_covariance可用于检查拟合情况,其对角线元素值表示每个参数的方差。可以看到我们正确求出了系数值。
绘制曲线:
import matplotlib.pyplot as plt
y = g(x_data, variables[0], variables[1])
plt.plot(x_data, y_data, 'o', color="green", label = "Samples")
plt.plot(x_data, y, color="red", label = "Fit")
plt.legend(loc = "best")
#plt.savefig('./opt10-1.png') # 保存要显示的图片
plt.show()
生成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-98kPUfcs-1571731570441)(https://www.qikegu.com/wp-content/uploads/2019/07/opt10-1.png)]
leastsq()函数
最小二乘法是非常经典的数值优化算法,通过最小化误差的平方和来寻找最符合数据的曲线。
optimize模块提供了实现最小二乘拟合算法的函数leastsq(),leastsq是least square的简写,即最小二乘法。
调用形式
optimize.leastsq(func, x0, args=())
- func 计算误差的函数
- x0 是计算的初始参数值
- args 是指定func的其他参数
示例
import numpy as np
from scipy import optimize
# 样本数据
X = np.array([160,165,158,172,159,176,160,162,171]
Y = np.array([58,63,57,65,62,66,58,59,62])
# 偏差函数, 计算以p为参数的直线和原始数据之间的误差
def residuals(p):
k, b = p
return Y-(k*X+b)
# leastsq()使得residuals()的输出数组的平方和最小,参数的初始值为[1, 0]
ret = optimize.leastsq(residuals, [1, 10])
k, b = ret[0]
print("k = ", k, "b = ", b)
输出
k = 0.4211697393502931 b = -8.288302606523974
绘制曲线:
import matplotlib.pyplot as plt
#画样本点
plt.figure(figsize=(8, 6)) ##指定图像比例: 8:6
plt.scatter(X, Y, color="green", label="Samples", linewidth=2)
#画拟合直线
x = np.linspace(150, 190, 100) ##在150-190直接画100个连续点
y = k*x + b ##函数式
plt.plot(x,y,color="red", label="Fit",linewidth=2)
plt.legend() #绘制图例
plt.savefig('./opt11-1.png') # 保存要显示的图片
plt.show()
输出
SciPy 优化的更多相关文章
- python scipy优化器模块(optimize)
pyhton数据处理与分析之scipy优化器及不同函数求根 1.Scipy的优化器模块optimize可以用来求取不同函数在多个约束条件下的最优化问题,也可以用来求取函数在某一点附近的根和对应的函数值 ...
- scipy优化器optimizer
#optimazer优化器 from scipy.optimize import minimize def rosem(x): return sum(100.0*(x[1:]-x[:-1])**2.0 ...
- Scipy优化算法--scipy.optimize.fmin_tnc()/minimize()
scipy中的optimize子包中提供了常用的最优化算法函数实现,我们可以直接调用这些函数完成我们的优化问题. scipy.optimize包提供了几种常用的优化算法. 该模块包含以下几个方面 使用 ...
- 第4天:scipy库
一.SciPy库概述 1.numpy提供向量和矩阵的相关操作,高级计算器 2.SciPy在统计.优化.插值.数值积分.视频转换等,涵盖基础科学计算相关问题. (额,对统计和概率,数理完全一窍不通) 3 ...
- SciPy 信号处理
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
- SciPy 统计
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
- SciPy 线性代数
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
- SciPy 图像处理
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
- SciPy 积分
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
随机推荐
- JS 上传图片压缩,原比例压缩
复制 粘贴 改吧改吧就可用,原生js var fileObj = file.file;//原文件 file是我用vue-vant里的组件,里边有file(原文件)和content(base64) 其它 ...
- 关于Debug Assertion Failed问题
书上代码: #include<stdio.h> #include<stdlib.h> /* 提供malloc().free()函数 */ #include<string. ...
- sftp和FTP
sftp 是一个交互式安全文件传输协议的传输程式.它类似于 ftp也叫internet网络文件协议, 但它进行加密传输,比FTP有更高的安全性.下边就简单介绍一下如何远程连接主机,进行文件的上传和下 ...
- JavaScript - map和parseInt的坑
问题: var arrs = ['1', '2', '3']; var r = arrs.map(parseInt); alert(r);//1,NaN,NaN map arr.map(functio ...
- SpringBoot笔记二:整合篇
Spring Boot与缓存 jsr-107 Java Caching定义了5个核心接口分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry. ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:引导主体副本
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 报错PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
今天在调用第三方HTTPS接口的时候,一直显示这个报错,然后百度很久,有2种解决方法,一个是说自己手动去导入,第二种用代码忽略证书验证.我用二种方式, 复制即用, public void test2( ...
- Netcat - 网络工具中的瑞士军刀
nc的一些小应用,慢更新.... 1.一个简单的聊天工具,Client1和Client2之间,Client1安装了nc,监听8888端口,Client2用telnet Client1的8888端口即可 ...
- 3_01_MSSQL课程_Ado.Net_连接数据库
1. Ado.Net 是一组微软的c#操作数据库的类库. 2.开发人员将界面上的数据(用户的操作和输入的数据)存储到数据库当中.. 3.数据库访问的驱动.即:应用程序和数据库的桥梁. 4.驱动层. S ...
- tensorflow变量的使用(02-2)
import tensorflow as tf x=tf.Variable([1,2]) a=tf.constant([3,3]) sub=tf.subtract(x,a) #增加一个减法op add ...