1.最小二乘法的原理及实现
笔记来源于《白话机器学习的数学》
1.1 最小二乘法的原理
预测一个变量
x
x
x与一个变量
y
y
y的关系
例如:广告费
x
x
x与点击量
y
y
y
用直线拟合数据
1.2 最小二乘法的实现
广告费x和点击量y,找到一条直线表达式,输入广告费来预测点击量
训练数据如下:
import numpy as np
import matplotlib.pyplot as plt
# 读入训练数据
train = np.loadtxt('click.csv', delimiter=',', dtype='int', skiprows=1)
train_x = train[:,0]
train_y = train[:,1]
数据预处理步骤之一:对训练数据进行标准化 / 归一化,目的使得参数收敛会更快
计算出数据中所有x的均值
μ
\mu
μ和标准差
σ
\sigma
σ,每个数值x按照下列式子进行标准化,数据y也进行类似标准化
# 标准化
mu = train_x.mean()
sigma = train_x.std()
def standardize(x):
return (x - mu) / sigma
train_z = standardize(train_x)
# 展示标准化后的数据
plt.plot(train_z, train_y, 'o')
plt.show()
横轴范围变为了[-2,2]
假设函数
f
θ
(
x
)
f_{\theta}(x)
fθ(x)、目标函数
E
(
θ
)
E(\theta)
E(θ)
# 参数初始化
theta0 = np.random.rand()
theta1 = np.random.rand()
# 预测函数
def f(x):
return theta0 + theta1 * x
# 目标函数
def E(x, y):
return 0.5 * np.sum((y - f(x)) ** 2)
# 学习率
ETA = 1e-3
# 初始化误差的差值,作为循环结束依据
diff = 1
# 初始化更新次数
count = 0
梯度下降法对目标函数进行优化
参数更新表达式
# 直到误差的差值小于 0.01 为止,重复参数更新
error = E(train_z, train_y)
while diff > 1e-2:
# 更新结果保存到临时变量
tmp_theta0 = theta0 - ETA * np.sum((f(train_z) - train_y))
tmp_theta1 = theta1 - ETA * np.sum((f(train_z) - train_y) * train_z)
# 更新参数
theta0 = tmp_theta0
theta1 = tmp_theta1
# 计算与上一次误差的差值
current_error = E(train_z, train_y)
diff = error - current_error
error = current_error
# 输出日志
count += 1
log = '第 {} 次 : theta0 = {:.3f}, theta1 = {:.3f}, 差值 = {:.4f}'
print(log.format(count, theta0, theta1, diff))
# 绘图确认
x = np.linspace(-3, 3, 100)
plt.plot(train_z, train_y, 'o')
plt.plot(x, f(x))
plt.show()
对目标函数的优化方法:
最速下降法(梯度下降法/Gradient Descent) 对所有训练数据都重复进行计算
梯度下降法的问题是训练数据越多,循环次数越多,计算时间越长,选用随机数作为初始值,每次初始值都会变,进而导致陷入局部最优解的问题
在GD算法中,每次的梯度都是从所有样本中累计获取的,这种情况最容易导致梯度方向过于稳定一致,且更新次数过少,容易陷入局部最优–摘自:防止梯度下降陷入局部最优的三种方法
随机梯度下降法(Stochastic GD)随机选择一个训练数据,并使用它来更新参数
k是被随机选中的数据索引
θ
j
:
=
θ
j
−
η
(
f
θ
(
x
(
k
)
)
−
y
(
k
)
)
x
j
(
k
)
\theta_j:=\theta_j-\eta\big(f_{\boldsymbol{\theta}}(\boldsymbol{x}^{(k)})-y^{(k)}\big)x_j^{(k)}
θj:=θj−η(fθ(x(k))−y(k))xj(k)
注意这里没有求和,因为只使用了一个训练数据
为什么随机梯度下降法不容易陷入局部最优?
stochastic GD是GD的另一种极端更新方式,其每次都只使用一个样本进行参数更新,这样更新次数大大增加,更新参数时使用的又是选择数据时的梯度,每次梯度方向不同,也就不容易陷入局部最优。–摘自:防止梯度下降陷入局部最优的三种方法
小批量梯度下降法(Mini-Batch GD)随机选择m个训练数据来更新参数
θ
j
:
=
θ
j
−
η
∑
k
∈
K
(
f
θ
(
x
(
k
)
)
−
y
(
k
)
)
x
j
(
k
)
\theta_j:=\theta_j-\eta\sum_{k\in K}\big(f_{\boldsymbol{\theta}}(\boldsymbol{x}^{(k)})-y^{(k)}\big)x_j^{(k)}
θj:=θj−ηk∈K∑(fθ(x(k))−y(k))xj(k)
∑
k
∈
K
\sum_{k\in K}
∑k∈K代表将集合K中的所有元素相加
Mini-Batch GD便是两种极端的折中,即每次更新使用一小批样本进行参数更新。Mini-Batch GD是目前最常用的优化算法,严格意义上Mini-Batch GD也叫做stochastic GD,所以很多深度学习框架上都叫做SGD。–摘自:防止梯度下降陷入局部最优的三种方法
动量(Momentum)
动量也是GD中常用的方式之一,SGD的更新方式虽然有效,但每次只依赖于当前批样本的梯度方向,这样的梯度方向依然很可能很随机。动量就是用来减少随机,增加稳定性。其思想是模仿物理学的动量方式,每次更新前加入部分上一次的梯度量,这样整个梯度方向就不容易过于随机。一些常见情况时,如上次梯度过大,导致进入局部最小点时,下一次更新能很容易借助上次的大梯度跳出局部最小点。–摘自:防止梯度下降陷入局部最优的三种方法
无论使用哪种优化方法对目标函数进行优化,我们都必须考虑学习率 η \eta η设置为合适的值很重要,这个问题比较难,可以通过反复尝试来找到合适的值