最近忽然对机器学习方面比较感兴趣,于是接触了一下,一眼望过去感觉对我这种学渣太不友好了,不过深入了解了一下发现其实并不难,这里总结一下学习最小二乘法的拟合直线和样本点图。
关于最小二乘法
最小二乘法是机器学习中最基本的数学优化方法之一。例如,线性回归中拟合参数求解,一般就会使用到最小二乘法,其过程如下:
对于线性方程:
其中,w1为自变量对应的系数,w0常数也就是截距项。此时,如果我们令其平方损失函数为:
为了求出平方损失函数的最小值,即对上式进行求偏导数:
最终通过令偏导数等于 0 来得到参数的取值为:
其中,xi和yi分别对应着第i个样本数据的特征xi和yi取值。
代码实现
虽然这一大堆看起来很麻烦,不过分析一下,关于这个线性方程我们要求的就只有w1,w0的值而已。因为这里比较简单,所以没有用到第三方库来求xi和yi的值,通过自己手动实现。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import matplotlib.pyplot as plt
import numpy as np
def linear_plot():
# 一个随机的样本数据
data = [
[5.06, 5.79], [4.92, 6.61], [4.67, 5.48], [4.56, 6.11], [4.26, 6.39],
[4.07, 4.84], [4.01, 4.16], [4.01, 5.55], [3.66, 5.05], [3.43, 4.34],
[3.12, 3.24], [3.02, 4.80], [2.87, 4.01], [2.64, 3.17], [2.48, 1.61],
[2.48, 2.62], [2.02, 2.50], [1.95, 3.59], [1.79, 1.49], [1.54, 2.10]
]
# 用numpy来将样本数据的x,y分离开来
Xi = np.array([])
Yi = np.array([])
lenn = len(data)
sumX = 0.0
sumY = 0.0
sumXY = 0.0
sumX2 = 0.0
# 手动计算w0,w1的值
for i in range(lenn):
print(data[i])
Xi = np.append(Xi, data[i][0])
Yi = np.append(Yi, data[i][1])
sumX += data[i][0]
sumY += data[i][1]
sumXY += data[i][0] * data[i][1]
sumX2 += data[i][0] * data[i][0]
# 这里保留5位小数
w0 = round((sumX2 * sumY - sumX * sumXY) / (lenn * sumX2 - (sumX * sumX)), 5)
w1 = round((lenn * sumXY - sumX * sumY) / (lenn * sumX2 - (sumX * sumX)), 5)
'''
print(w0)
print(w1)
print(Xi)
print(Yi)
'''
# 开始绘制样本点图
fig = plt.figure()
# 指定字体,不然中文会出错
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.scatter(Xi, Yi, color="green", label='样本数据', linewidth=2)
plt.plot(w1, w0)
x = np.linspace(0, 8)
y = w0 + w1 * x
# 绘制拟合直线
plt.plot(x, y, color="red", label='拟合直线', linewidth=2)
plt.legend(loc='lower right') # 绘制图例
plt.show()
linear_plot()
结果如图: