利用scipy求解方程组、拟合直线、圆、椭圆、抛物线

本文介绍了scipy.optimize库在Python中进行优化、函数拟合和方程求解的几种常用方法,如minimize用于通用优化,curve_fit用于曲线拟合,以及fsolve和least_squares处理特定类型的优化问题。通过实例展示了如何使用这些工具来拟合直线、圆、椭圆,以及解决非线性方程组。
摘要由CSDN通过智能技术生成

scipy.optimize作为优化模块可以实现任意曲线拟合,方程求根、非线性方程组求解、自定义代价函数求解等功能,下面给出了optimize中常用的几个子模块:
minimize:需要自己构建代价函数(有时也称损失函数,目标函数等),理论上可以求解任意最优化问题
curve_fit:可以拟合任意的显式函数曲线,对于隐式函数曲线不能拟合
fsolve:方程根、求解适定方程组,需要满足未知数数量等于方程数量
least_squares、leastsq:这两个可以用于求解最小二乘问题
root:求解方程根
minimize模块灵活度最多,功能最为强大,理论上上述子模块都可以看作minimize的特例:下面分别给出使用案例:
使用minimize拟合直线、圆、椭圆,使用fsolve、least_squares求解方程组,使用curve_fit拟合抛物线

from scipy.optimize import minimize
from scipy.optimize import curve_fit
from scipy.optimize import fsolve
from scipy.optimize import least_squares
from scipy.optimize import leastsq
from matplotlib import pyplot as plt
import numpy as np
import math
def line_fun(params,x,y):
    a,b=params
    return np.sum(np.square(x*a+b-y))

def circle_fun(params,x,y):
    #圆的一般方程:x^2+y^2+ax+by+c=0
    a,b,c=params
    return np.sum(np.square(x*x+y*y+a*x+b*y+c))

def ellipse_model2d(params, x, y):
    #椭圆一般方程:A * x ** 2 + B * y ** 2 + C * x * y + D * x + E * y + F=0
    A, B, C, D, E, F= params
    error=A * x ** 2 + B * y ** 2 + C * x * y + D * x + E * y + F
    squares = np.square(error)  # 将数组a每个元素平方
    sum_of_squares = np.sum(squares)  # 对平方后的数组求和
    return sum_of_squares


#超定方程组
def non_linear_equations(var):
    x = var[0]
    y = var[1]
    Func= np.empty((3))
    Func[0] = x**2+y-5
    Func[1] = x+y-3
    Func[2] = 4*x+y**2-9
    return Func

#适定方程组
def non_linear_equations2(var):
    x = var[0]
    y = var[1]
    Func= np.empty((2))
    Func[0] = x**2+y-5
    Func[1] = x+y-3
    return Func


def curve_line(x, a, b):
    return a*x**2+b*x+10


# 按间距中的绿色按钮以运行脚本。
if __name__ == '__main__':

    #生成直线数据
    x = np.linspace(-20, 20, 100)

    y = x * 2 + 1
    # plt.scatter(x,y)
    # plt.show()
    x0 = np.array([1.0, 0.8])
    #求解直线方程,当然这里也可以用curve_fit模块
    result = minimize(line_fun, x0, args=(x, y))
    print(r"line ab:", result.x)

    # 生成圆数据
    m = np.linspace(0, 2 * math.pi, 100)
    a = 3
    b = -6
    r = 5
    x = a + r * np.cos(m)
    y = b + r * np.sin(m)
    figure, axes = plt.subplots(1)
    axes.plot(x, y)
    axes.set_aspect(1)
    plt.show()
    #拟合圆
    result = minimize(circle_fun, np.ones(3), args=(x, y))
    print(r"circle abc:", result.x)

    #ellipse
    #data
    theta_samples = np.linspace(0, 20, 100)
    # 椭圆方位角
    alpha_samples = -45.0 / 180.0 * np.pi
    # 长轴长度
    a_samples = 1.0
    # 短轴长度
    b_samples = 2.0
    # 样本x 序列,并叠加正态分布的随机值
    x_samples = a_samples * np.cos(theta_samples) * np.cos(alpha_samples) \
                - b_samples * np.sin(theta_samples) * np.sin(alpha_samples) +1\
               # + np.random.randn(100) * 0.05 * a_samples
    # 样本y 序列 ,并叠加正态分布的随机值
    y_samples = b_samples * np.sin(theta_samples) * np.cos(alpha_samples) \
                + a_samples * np.cos(theta_samples) * np.sin(alpha_samples) +2\
               # + np.random.randn(100) * 0.05 * b_samples
    z_samples=np.zeros(100)
    plt.axes([0.16, 0.15, 0.75, 0.75])
    plt.scatter(x_samples, y_samples, color="magenta", marker="+",
                zorder=1, s=80, label="samples")
    plt.show()
    #fit ellipse
    result=minimize(ellipse_model2d,np.ones(6),args=(x_samples,y_samples))
    print("ellipse abcdef:",result.x)

    #solve non_linear_equations
    a = np.array([0.0,0])
    b = least_squares(non_linear_equations, a)
    print("non_linear_equations x0,x1:", b.x)
    a = np.array([0.0,0])
    b = fsolve(non_linear_equations2, a)#方程数量和未知数数量要保持一致
    print("non_linear_equations x0,x1:",b)

    #fit curve_line
    # 这部分生成样本点,对函数值加上高斯噪声作为样本点
    xdata = np.linspace(-5, 5, 50)
    #
    # a=2.5, b=1.3
    y = curve_line(xdata, 2.5, 1.3)

    np.random.seed(1)
    err_stdev = 0.2
    # 生成均值为0,标准差为err_stdev为0.2的高斯噪声
    y_noise = err_stdev * np.random.normal(size=len(xdata))
    ydata = y + y_noise
    plt.scatter(xdata, ydata, label='data')

    # 利用curve_fit作简单的拟合,popt为拟合得到的参数,pcov是参数的协方差矩阵
    popt_1, pcov = curve_fit(curve_line, xdata, ydata)
    print("curve_line_result:",popt_1)
    plt.plot(xdata, curve_line(xdata, *popt_1), 'r-', label='fit_1')
    plt.show()


结果:

line ab: [1.99999999 0.99999999]
circle abc: [-6.00000001 11.99999997 19.99999983]
ellipse abcdef: [-0.04833563 -0.04833556  0.05800266 -0.01933401  0.13533947 -0.04833538]
non_linear_equations x0,x1: [2. 1.]
non_linear_equations x0,x1: [-1.  4.]
curve_line_result: [2.50137612 1.30813455]

椭圆拟合结果:
在这里插入图片描述

抛物线拟合结果:
在这里插入图片描述

参考:
1
2
3
4
5
6

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值