本文学习内容来自:《TensorFlow深度学习应用实践》
最小二乘法算法介绍
LS算法是一种数学优化技术,也是一种机器学习常用算法。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间的误差的平方和为最小。最小二乘法还可用于曲线拟合,其它一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。
这里以一个变量为例。
从图可以看到,若干个点依次分布在向量空间中,如果希望找出一条直线和这些点达到最佳匹配,那么最简单的一个方法就是希望这些点到直线的值最小,即下面最小二乘法实现公式最小:
这里直接应用的是真实值与计算值之间的差的平方和,具体而言,这种差值有个专门的名称称为“残差”。基于此,表达残差的方式有以下三种:
- 范数:残差绝对值的最大值
- L1-范数:绝对残差和
- L2-范数:残差平方和
也可以看到,所谓的最小二乘法也就是L2范数的一个具体应用。通俗地说,就是看模型计算的结果与真实值之间的相似性。
因此,最小二乘法的定义可由如下公式定义:
对于给定的数据
,在确定的假设空间
中,求解
,使得残差
的L2-范数最小。
这里的
实际上是一条多项式曲线:
这么继续讨论下去,所谓的最小二乘法就是找到这么一组权重 ,使得 最小。
如何使最小二乘法最小?对于求出最小二乘法的结果,通过数学上的微积分处理方法,这是一个求极值的问题。这里只需要对权值依次求偏导数,最后令偏导数为0,即可求出极值点。
python scipy库的 leastsq
python的科学计算包scipy里提供了leastq函数,可以求出任意的需要拟合的函数的参数。
leastsq(func, x0, args=(), Dfun=None, full_output=0, col_deriv=0, ftol=1.49012e-08, xtol=1.49012e-08, gtol=0.0, maxfev=0, epsfcn=0.0, factor=100, diag=None, warning=True)
一般只需要指定前三个参数就可以了。
- func 自己定义的一个计算误差的函数
- x0 计算的初始参数值
- args 是指定func的其它参数
示例程序
##最小二乘法
import numpy as np # 科学计算库
import matplotlib.pyplot as plt # 绘图库
from scipy.optimize import leastsq # 引入最小二乘法算法
'''
设置样本数据,真实数据需要在这里处理
'''
# 样本数据(Xi,Yi),需要转换成数组(列表)形式
Xi = np.array([6.19, 2.51, 7.29, 7.01, 5.7, 2.66, 3.98, 2.5, 9.1, 4.2])
Yi = np.array([5.25, 2.83, 6.41, 6.71, 5.1, 4.23, 5.05, 1.98, 10.5, 6.3])
'''
设定拟合函数和偏差函数
函数的形状确定过程:
1.先画样本图像
2.根据样本图像大致形状确定函数形式(直线、抛物线、正弦余弦等)
'''
# 需要拟合的函数func :指定函数的形状
def func(p, x):
k, b = p
return k*x+b
# 偏差函数:x,y都是列表:这里的x,y更上面的Xi,Yi中是一一对应的
def error(p, x, y):
return func(p, x)-y
'''
主要部分:附带部分说明
1.leastsq函数的返回值tuple,第一个元素是求解结果,第二个是求解的代价值(个人理解)
2.官网的原话(第二个值):Value of the cost function at the solution
3.实例:Para=>(array([ 0.61349535, 1.79409255]), 3)
4.返回值元组中第一个值的数量跟需要求解的参数的数量一致
'''
# k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1]
p0 = [1, 20]
# 把error函数中除了p0以外的参数打包到args中(使用要求)
Para = leastsq(error, p0, args=(Xi, Yi))
# 读取结果
k, b = Para[0]
print("k=", k, "b=", b)
print("cost:"+str(Para[1]))
print("求解的拟合直线为:")
print("y="+str(round(k, 2))+"x+"+str(round(b, 2)))
'''
绘图,看拟合效果.
matplotlib默认不支持中文,label设置中文的话需要另行设置
如果报错,改成英文就可以
'''
# 画样本点
plt.figure(figsize=(8, 6)) # 指定图像比例: 8:6
plt.scatter(Xi, Yi, color="green", label="样本数据", linewidth=2)
# 画拟合直线
x = np.linspace(0, 12, 100) # 在0-15直接画100个连续点
y = k*x+b # 函数式
plt.plot(x, y, color="red", label="拟合直线", linewidth=2)
plt.legend(loc='lower right') # 绘制图例
plt.show()
运行结果:
代码来自:
https://www.cnblogs.com/lc1217/p/6514734.html
另外抛物线拟合示例:
http://www.cnblogs.com/lc1217/p/6519860.html