利用 Numpy 实现简单的机器学习算法

线性回归(Linear Regression) 可能是最流行的机器学习算法。线性回归就是要找一条直线,并且让这条直线尽可能地拟合散点图中的数据点。

前言

线性回归作为高中数学统计题比较重要的内容,先对其原理与推导过程不做详细讨论,重点通过代码来运用 python 模块实现线性回归算法。

线性回归算法的简单介绍

线性模型:给定由 d 个属性描述的示例,线性模型试图学得一个通过属性的线性组合来进行预测的函数。

线性回归试图学得一个线性模型以尽可能准确的预测实值输出标记,公式: $ f(x) = w^Tx+b $
$ f(x_i) = wx_i + b $,使得 $ f(x_i) ≈ y_i $

实现线性回归算法的目标与方法

我们的任务就是求出 w 和 b,可用均方误差最小化的方法,基于均方误差最小化来进行模型求解的方法称为最小二乘法,在线性回归中,最小二乘法就是试图找到一条直线,使得所有样本数据点到达直线的欧氏距离最小。总距离是所有数据点的垂直距离的平方和。其思想是通过最小化这个平方误差或距离来拟合模型。

代码具体实现过程

定义线性回归函数

  • np.mean()函数主要起对矩阵求均值的作用
  • for 循环中利用最小二乘法的基本公式求出分子与分母,进而求出回归直线的斜率
  • 值得注意的是分母转化为浮点数来保证计算的精确性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def fitSLR(X, Y):
  X_avg = np.mean(X)  # 求取括号内数组矩阵的均值
  Y_avg = np.mean(Y)
  n = len(X)  # 得到括号内列表长度即元素的个数
  # 定义分子与分母
  fen_zi = 0
  fen_mu = 0
  # 核心算法
  for i in range(0, n):
      fen_zi += (X[i] - X_avg) * (Y[i] - Y_avg)
      fen_mu += (X[i] - X_avg) ** 2
  b1 = fen_zi / float(fen_mu)  # 计算w,即直线的斜率
  b0 = Y_avg - b1 * X_avg
  return b0, b1

引入具体的数据

1
2
X = [1.5, 0.8, 2.6, 1.0, 0.6, 2.8, 1.2, 0.9, 0.4, 1.3, 1.2, 2.0, 1.6, 1.8, 2.2]
Y = [3.1, 1.9, 4.2, 2.3, 1.6, 4.9, 2.8, 2.1, 1.4, 2.4, 2.4, 3.8, 3.0, 3.4, 4.0]

调用函数计算出斜率与截距

1
2
3
b0, b1 = fitSLR(X, Y)
print('w = ', b1)
print('b = ', b0)

生成画板,画图图像

  • 两点确定一条直线作出回归直线
  • plt.plot()'r'代表回归直线是红色的意思
1
2
3
4
5
6
7
8
9
10
11
# 生成画板
plt.figure()
# 画散点图
plt.scatter(X, Y)
X_min = min(X)
X_max = max(X)
Y_min = b0 + b1 * X_min
Y_max = b0 + b1 * X_max

plt.plot([X_min, X_max], [Y_min, Y_max], 'r')
plt.show()

画出图像


完整代码:

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
import numpy as np
from matplotlib import pyplot as plt


def fitSLR(X, Y):
    X_avg = np.mean(X)  # 求取括号内数组矩阵的均值
    Y_avg = np.mean(Y)
    n = len(X)  # 得到括号内列表长度即元素的个数
    # 定义分子与分母
    fen_zi = 0
    fen_mu = 0
    # 核心算法
    for i in range(0, n):
        fen_zi += (X[i] - X_avg) * (Y[i] - Y_avg)
        fen_mu += (X[i] - X_avg) ** 2
    b1 = fen_zi / float(fen_mu)  # 计算w,即直线的斜率
    b0 = Y_avg - b1 * X_avg
    return b0, b1


# 定义X,Y列表
X = [1.5, 0.8, 2.6, 1.0, 0.6, 2.8, 1.2, 0.9, 0.4, 1.3, 1.2, 2.0, 1.6, 1.8, 2.2]
Y = [3.1, 1.9, 4.2, 2.3, 1.6, 4.9, 2.8, 2.1, 1.4, 2.4, 2.4, 3.8, 3.0, 3.4, 4.0]

b0, b1 = fitSLR(X, Y)
print('w = ', b1)
print('b = ', b0)

# 生成画板
plt.figure()
# 画散点图
plt.scatter(X, Y)
X_min = min(X)
X_max = max(X)
Y_min = b0 + b1 * X_min
Y_max = b0 + b1 * X_max

plt.plot([X_min, X_max], [Y_min, Y_max], 'r')
plt.show()