1.多项式回归的原理及实现
笔记来源于《白话机器学习的数学》
1.1 多项式回归的原理
预测一个变量
x
x
x与一个变量
y
y
y的关系
例如:广告费
x
x
x与点击量
y
y
y
用曲线拟合数据
求导过程类比本人之前的博客进行推导,相关笔记:最小二乘法的原理及实现
n次曲线
f
θ
(
x
)
=
θ
0
+
θ
1
x
+
θ
2
x
2
+
⋯
+
θ
n
x
n
f_{\theta}(x)=\theta_0+\theta_1x+\theta_2x^2+\cdots+\theta_nx^n
fθ(x)=θ0+θ1x+θ2x2+⋯+θnxn
尽管次数越高对训练数据拟合越精确(过拟合)但我们的目的是用这个拟合曲线去预测训练数据之外的数据,需要这个曲线或模型具备泛化能力,而不是仅仅代表训练数据,过拟合使得模型不再具有代表性了,不能预测一般情形了
1.2 多项式回归的实现
广告费
x
x
x与点击量
y
y
y
import numpy as np
import matplotlib.pyplot as plt
# 读入训练数据
train = np.loadtxt('~/Downloads/sourcecode-cn/click.csv', delimiter=',', dtype='int', skiprows=1)
train_x = train[:,0] # 第一列
train_y = train[:,1] # 第二列
数据预处理步骤之一:对训练数据进行标准化 / 归一化,目的使得参数收敛会更快
计算出数据中所有x的均值
μ
\mu
μ 和标准差
σ
\sigma
σ,每个数值x按照下列式子进行标准化
# 标准化
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()
# 参数初始化
theta = np.random.rand(3)
# 创建训练数据的矩阵
def to_matrix(x):
return np.vstack([np.ones(x.size), x, x ** 2]).T
X = to_matrix(train_z)
由于训练数据有很多,所以我们把 1 行数据当作 1 个训练数据,以矩阵的形式来处理会更好。
# 预测函数
def f(x):
return np.dot(x, theta)
# 目标函数
def E(x, y):
return 0.5 * np.sum((y - f(x)) ** 2)
# 学习率
ETA = 1e-3
# 初始化误差的差值,随后作为循环结束判断依据
diff = 1
# 初始化更新次数
count = 0
参数的更新表达式(注意更新参数时所有参数必须同步更新,确保梯度方向保持稳定)
因为此例有三个参数
θ
0
、
θ
1
、
θ
2
\theta_0、\theta_1、\theta_2
θ0、θ1、θ2,
法一:在循环体中直接用三个式子更新三个参数
法二:将参数更新式后半部分写为矩阵形式,一个式子更新三个参数
使用梯度下降法
# 直到误差的差值小于 0.01 为止,重复参数更新
error = E(X, train_y)
while diff > 1e-2:
# 更新结果保存到临时变量
# 这里使用矩阵直接计算出所有参数,而不是每个参数进行更新迭代
theta = theta - ETA * np.dot(f(X) - train_y, X)
# 计算与上一次误差的差值
current_error = E(X, train_y)
diff = error - current_error
error = current_error
# 输出日志
count += 1
log = '第 {} 次 : theta = {}, 差值 = {:.4f}'
print(log.format(count, theta, diff))
# 绘图确认
x = np.linspace(-3, 3, 100)
plt.plot(train_z, train_y, 'o')
plt.plot(x, f(to_matrix(x)))
plt.show()
以重复次数为横轴,均方误差为纵轴绘图,随着迭代次数的增多,均方误差逐渐下降
# 均方误差
def MSE(x, y):
return (1 / x.shape[0]) * np.sum((y-f(x))**2)
# 用随机值初始化参数
theta = np.random.rand(3)
# MSE的历史记录
errors = []
# 误差的差值
diff = 1
# 重复学习
errors.append(MSE(X, train_y))
while diff > 1e-2:
theta = theta - ETA * np.dot(f(X) - train_y, X)
errors.append(MSE(X, train_y))
diff = errors[-2] - errors[-1]
# 绘制误差变化图
x = np.arange(len(errors))
plt.plot(x, errors)
plt.show()
上述过程采用了梯度下降法(使用所有训练数据)对目标函数进行优化,接下来我们使用随机梯度下降法(只使用一个训练数据)对目标函数进行优化
n次随机梯度下降(耗时相对短)等价于1次梯度下降(耗时相对长)
上图中
k
k
k 是随机的
import numpy as np
import matplotlib.pyplot as plt
# 读入训练数据
train = np.loadtxt('~/Downloads/sourcecode-cn/click.csv', delimiter=',', dtype='int', skiprows=1)
train_x = train[:,0]
train_y = train[:,1]
# 标准化
mu = train_x.mean()
sigma = train_x.std()
def standardize(x):
return (x - mu) / sigma
train_z = standardize(train_x)
# 参数初始化
theta = np.random.rand(3)
# 创建训练数据的矩阵
def to_matrix(x):
return np.vstack([np.ones(x.size), x, x ** 2]).T
X = to_matrix(train_z)
# 预测函数
def f(x):
return np.dot(x, theta)
# 均方误差
def MSE(x, y):
return (1 / x.shape[0]) * np.sum((y - f(x)) ** 2)
# 学习率
ETA = 1e-3
# 误差的差值
diff = 1
# 更新次数
count = 0
# 重复学习
error = MSE(X, train_y)
while diff > 1e-2:
# 使用随机梯度下降法更新参数
p = np.random.permutation(X.shape[0]) # 随机p
for x, y in zip(X[p,:], train_y[p]): # 选择第p行的训练数据(此例中一个x,一个y)对参数进行更新
theta = theta - ETA * (f(x) - y) * x
# 计算与上一次误差的差值
current_error = MSE(X, train_y)
diff = error - current_error
error = current_error
# 输出日志
count += 1
log = '第 {} 次 : theta = {}, 差值 = {:.4f}'
print(log.format(count, theta, diff))
# 绘图确认
x = np.linspace(-3, 3, 100)
plt.plot(train_z, train_y, 'o')
plt.plot(x, f(to_matrix(x)))
plt.show()
2.多重回归的原理
2.1 多重回归的原理
预测多个变量
x
x
x与一个变量
y
y
y的关系
例如:广告费
x
1
x_1
x1、广告展示位置
x
2
x_2
x2、广告版面大小
x
3
x_3
x3与点击量
y
y
y
f
θ
(
x
1
,
⋯
,
x
n
)
=
θ
0
+
θ
1
x
1
+
θ
2
x
2
+
⋯
+
θ
n
x
n
f_{\theta}(x_1,\cdots,x_n)=\theta_0+\theta_1x_1+\theta_2x_2+\cdots+\theta_nx_n
fθ(x1,⋯,xn)=θ0+θ1x1+θ2x2+⋯+θnxn
θ
=
[
θ
0
θ
1
⋮
θ
n
]
、
x
=
[
x
0
x
1
⋮
x
n
]
(
x
0
=
1
)
\boldsymbol{\theta}= \left [ \begin{matrix} \theta_0\\ \theta_1 \\ \vdots\\ \theta_n \end{matrix} \right ] 、 \boldsymbol{x}= \left [ \begin{matrix} x_0\\ x_1 \\ \vdots\\ x_n \end{matrix} \right ](x_0=1)
θ=
θ0θ1⋮θn
、x=
x0x1⋮xn
(x0=1)
f
θ
(
x
)
=
θ
T
x
=
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
+
⋯
+
θ
n
x
n
f_{\boldsymbol{\theta}}(\boldsymbol{x})=\boldsymbol{\theta}^T\boldsymbol{x}=\theta_0x_0+\theta_1x_1+\theta_2x_2+\cdots+\theta_nx_n
fθ(x)=θTx=θ0x0+θ1x1+θ2x2+⋯+θnxn
θ
j
:
=
θ
j
−
η
∑
i
=
1
n
(
f
θ
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
\theta_j:=\theta_j-\eta\sum_{i=1}^n\big(f_{\boldsymbol{\theta}}(\boldsymbol{x}^{(i)})-y^{(i)}\big)x_j^{(i)}
θj:=θj−ηi=1∑n(fθ(x(i))−y(i))xj(i)
上述表达式使用了所有训练数据
需要注意的是数据预处理时需要对所有变量x进行标准化
计算变量
x
1
x_1
x1所有数值的均值和标准差,利用下式对变量
x
1
x_1
x1所有数值进行标准化,其他类似
训练过程与多项式回归类似,唯一不同的是预测函数不同