翼度科技»论坛 编程开发 python 查看内容

【scipy 基础】--最优化

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
SciPy库的optimize模块主要用于执行各种优化任务。
优化是寻找特定函数的最小值或最大值的过程,通常用于机器学习、数据分析、工程和其他领域。
scipy.optimize提供了多种优化算法,包括梯度下降法、牛顿法、最小二乘法等,可以解决各种复杂的优化问题。
该模块还包含一些特定的函数,用于解决某些特定类型的优化问题,如多维非线性优化、约束优化、最小二乘问题等。
此外,scipy.optimize还提供了一些工具,如多线程支持、边界条件处理、数值稳定性措施等,以提高优化的效率和准确性。
1. 主要功能

最优化是数学学科中的一个重要研究领域,optimize模块包含的各类函数能够帮助我们节省大量的计算时间和精力。
类别说明优化包含标量函数优化,局部优化,全局优化等各类方法最小二乘法和曲线拟合包含求解最小二乘法问题,各种拟合曲线的方法求根包含多种求根的方法,比如布伦特方法,牛顿-拉夫森方法等10来种求根方法线性规划内置多种线性规划算法以及混合整数线性规划计算等分配问题解决线性和分配问题,包括二次分配和图匹配问题的近似解等工具函数包含一些通用的计算方法,比如有限差分近似,海森近似,线搜索等计算函数遗留函数即将被淘汰的一些函数,不建议再继续使用下面通过曲线拟合非线性方程组求解两个示例演示optimize模块的使用。
2. 曲线拟合示例

所谓曲线拟合,其实就是找到一个函数,能够尽可能的经过或接近一系列离散的点。
然后就可以用这个函数来预测离散点的变化趋势。
2.1. 最小二乘法

optimize模块的最小二乘法拟合曲线需要定义一个目标函数和一个残差函数
最小二乘法通过迭代寻找目标函数中参数的最优值,
残差函数是用来计算目标函数的返回值实际值之间的误差的。
首先,加载需要拟合的离散数据。
  1. import pandas as pd
  2. data = pd.read_csv("d:/share/data/A0A01.csv")
  3. data = data[data["zb"] == "A0A0101"]
  4. data = data.sort_values("sj")
  5. data.head()
复制代码

数据来源:https://databook.top/nation/A0A (其中的A0A01.csv)
然后,依据其中1978年~2022年居民人均可支配收入绘制散点图。
  1. from matplotlib.ticker import MultipleLocator
  2. import matplotlib.pyplot as plt
  3. ax = plt.subplot()
  4. ax.scatter(data["sjCN"], data["value"], marker='*', color='r')
  5. ax.xaxis.set_major_locator(MultipleLocator(4))
  6. ax.set_title("居民人均可支配收入(元)")
  7. plt.xticks(rotation=45)
  8. plt.show()
复制代码

最后,用optimize模块提供的最小二乘法拟合居民人均可支配收入的变化曲线。
  1. from scipy.optimize import least_squares
  2. # 目标函数
  3. def target_func(p, x):
  4.     return p[0]*np.exp(p[1]*x) + p[2]
  5. # 残差函数
  6. def residual(p, x, dy):
  7.     return target_func(p, x) - dy
  8. p0 = [1, 1, 0]
  9. x = range(len(data))
  10. y = data["value"]
  11. # 最小二乘法迭代目标函数的参数
  12. result = least_squares(residual, p0, args=(x, y))
  13. ax = plt.subplot()
  14. ax.xaxis.set_major_locator(MultipleLocator(4))
  15. ax.set_title("居民人均可支配收入(元)")
  16. ax.scatter(data["sjCN"], data["value"], marker='*', color='r')
  17. # 这里的result.x就是迭代后的最优参数
  18. ax.plot(x, target_func(result.x, x), color='g')
  19. plt.xticks(rotation=45)
  20. plt.show()
复制代码

图中绿色的曲线就是拟合的曲线,根据拟合出的曲线和目标函数,
就可以预测以后的居民人均可支配收入的变化情况。
2.2. curve_fit方法

最小二乘法需要定义目标函数残差函数,使用起来有些繁琐,optimize模块中还提供了一个curve_fit函数。
可以简化曲线拟合的过程。
  1. from scipy.optimize import curve_fit
  2. # 目标函数
  3. def curve_fit_func(x, p0, p1, p2):
  4.     return p0*np.exp(p1*x) + p2
  5. # fitp 就是计算出的目标函数的最优参数
  6. fitp, _ = curve_fit(curve_fit_func, x, y, [1, 1, 0])
  7. ax = plt.subplot()
  8. ax.xaxis.set_major_locator(MultipleLocator(4))
  9. ax.set_title("居民人均可支配收入(元)")
  10. ax.scatter(data["sjCN"], data["value"], marker='*', color='r')
  11. ax.plot(x, curve_fit_func(x, *fitp), color='b')
  12. plt.xticks(rotation=45)
  13. plt.show()
复制代码

蓝色的线就是拟合曲线,拟合结果和使用最小二乘法拟合出的是一样的,只是代码可以简化一些。
3. 非线性方程组求解示例

众所周知,手工求解非线性方程是非常困难的,如果经常遇到求解非线性方程的情况,optimize模块绝对能成为你的一个称手工具。
3.1. 非线性方程

使用optimize模块求解非线性方程非常简单。
比如方程:\(2^x+sin(x)-x^3=0\)
  1. from scipy.optimize import root
  2. f = lambda x: 2**x + np.sin(x) - x**3
  3. result = root(f, [1, 1], method='hybr')
  4. # result.x 是方程的解
  5. result.x
  6. # 运行结果:
  7. array([1.58829918, 1.58829918])
复制代码
实际使用时,将变量f对应的方程换成你的方程即可。
注意,求解方程的 root 方法的参数method,这个参数支持多种求解方程的方法,可以根据方程的特点选择不同的method。
支持的method列表可参考官方文档:https://docs.scipy.org/doc/scipy/reference/optimize.html#multidimensional
3.2. 非线性方程组

对于方程组,求解的方法如下:
比如方程组:\(\begin{cases}\begin{align*}x^2 +y-3 & =0 \\(x-2)^2+y-1 & =0\end{align*}\end{cases}\)
  1. fs = lambda x: np.array(
  2.     [
  3.         x[0] ** 2 + x[1] - 3,
  4.         (x[0] - 2) ** 2 + x[1] - 1,
  5.     ]
  6. )
  7. result = root(fs, [1, 1], method="hybr")
  8. result.x
  9. # 运行结果:
  10. array([1.5 , 0.75])
复制代码
方程组中方程个数多的话,直接添加到变量fs的数组中即可。
4. 总结

总的来说,scipy.optimize是一个强大且易用的优化工具箱,用于解决各种复杂的优化问题。
它对于需要优化算法的许多科学和工程领域都具有重要价值。
通过使用这个模块,用户可以节省大量时间和精力,同时还能保证优化的质量和准确性。

来源:https://www.cnblogs.com/wang_yb/p/17840165.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具