目录
机器学习流程
Step 1:A set of function -> 选择模型,一组w, b
Step 2:Goodness of function -> 评估模型,损失函数
Step 3:Pick the best function -> 选择argmin(w, b)的w, b
Step 1 -> 选择模型:线性模型
所以我们假设 线性模型 Linear model: y = b + ∑ w i x i y = b+\sum w_ix_i y=b+∑wixi
- x i x_i xi:各种特征(feature)
- w i w_i wi:各个特征的权重(weight)
- b b b:偏移量(bias)
Step 2 -> 模型评估:损失函数
用损失函数(Loss function)来评估模型的好坏:
L
(
f
)
=
∑
n
=
1
10
(
y
^
n
−
f
(
x
c
p
n
)
)
2
L(f) = \sum_{n=1}^{10} (\hat y^n- f(x_{cp}^n))^2
L(f)=n=1∑10(y^n−f(xcpn))2
L
(
w
,
b
)
=
∑
n
=
1
10
(
y
^
n
−
(
b
+
w
x
c
p
n
)
)
2
L(w, b) = \sum_{n=1}^{10}(\hat y^n- (b+wx_{cp}^n))^2
L(w,b)=n=1∑10(y^n−(b+wxcpn))2
Step 3 -> 最佳模型:梯度下降
Best function即是使得损失函数最小的一组参数(w ,b),即
f
∗
=
a
r
g
m
i
n
f
L
(
f
)
f* = arg min_fL(f)
f∗=argminfL(f)
w
∗
,
b
∗
=
a
r
g
m
i
n
w
,
b
L
(
w
,
b
)
=
arg
min
w
,
b
∑
n
=
1
10
(
y
^
n
−
(
b
+
w
⋅
x
c
p
n
)
)
2
w*, b* = arg min_{w,b}L(w, b) = \arg \min _{w, b} \sum_{n=1}^{10}\left(\hat{y}^{n}-\left(b+w \cdot x_{c p}^{n}\right)\right)^{2}
w∗,b∗=argminw,bL(w,b)=argw,bminn=1∑10(y^n−(b+w⋅xcpn))2
计算上式已得到最佳参数(w, b)需要用到梯度下降(gradient descent)
梯度下降(gradient descent)
梯度是
∇
L
=
[
∂
L
∂
w
∂
L
∂
b
]
\nabla L=\left[\begin{array}{l} \frac{\partial L}{\partial w} \\ \frac{\partial L}{\partial b} \end{array}\right]
∇L=[∂w∂L∂b∂L],梯度下降即沿着梯度方向下降寻找最小点。
梯度下降步骤:
- Step 1:随机选取一个初始值 w 0 , b 0 w_0, b_0 w0,b0
- Step 2:计算微分,也就是当前的斜率,根据斜率来判定移动的方向
大于0向左移动(减少w)
小于0向右移动(增加w) - Step 3:根据学习率移动
- 重复Step2和Step3,直到找到最低点
【注】:梯度下降存在一定的问题
问题1:找到局部最小点,而不是全局最小点(线性模型不存在这个问题,但是其他复杂模型会存在)
问题2:偏微分等于0
问题3:偏微分趋近于0
过拟合(Overfitting)
使用训练集和测试集的平均误差来验证模型的好坏
优化1:input更多的特征
在宝可梦研究中加入宝可梦种类的特征,并将它们合为一个线性方程,不需要的特征可以设为0。
优化2:input更多的参数
将血量(HP)、重量(Weight)、高度(Height)也加入到模型中
更多特征,更多input,数据量没有明显增加,仍旧导致overfitting
优化3:正则化(regularization)
更多特征,但是权重 ww 可能会使某些特征权值过高,仍旧导致overfitting,所以加入正则化
- w 越小,表示 functionfunction 较平滑的, functionfunction输出值与输入值相差不大
- 在很多应用场景中,并不是 ww 越小模型越平滑越好,但是经验值告诉我们 ww 越小大部分情况下都是好的。
【回归实例】
import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl
# matplotlib没有中文字体,动态解决
plt.rcParams['font.sans-serif'] = ['Simhei'] # 显示中文
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# ydata = b + w * xdata
x_data = [338., 333., 328., 207., 226., 25., 179., 60., 208., 606.]
y_data = [640., 633., 619., 393., 428., 27., 193., 66., 226., 1591.]
x_d = np.asarray(x_data)
y_d = np.asarray(y_data)
# 为画图准备等高线数据
x = np.arange(-200, -100, 1) # bias
y = np.arange(-5, 5, 0.1) # weight
Z = np.zeros((len(x), len(y)))
X, Y = np.meshgrid(x, y)
# loss
for i in range(len(x)):
for j in range(len(y)):
b = x[i]
w = y[j]
Z[j][i] = 0 # meshgrid吐出结果:y为行,x为列
for n in range(len(x_data)):
Z[j][i] += (y_data[n] - b - w * x_data[n]) ** 2
Z[j][i] /= len(x_data)
# linear regression
b=-120 # bias初始值
w=-4 # weight初始值
lr = 1 # 学习率
lr_b = 0
lr_w = 0
iteration = 100000 # 迭代次数
# 存储b, w和lossfunction的变化
b_history = [b]
w_history = [w]
loss_history = []
import time
start = time.time()
for i in range(iteration):
m = float(len(x_d))
y_hat = w * x_d +b
loss = np.dot(y_d - y_hat, y_d - y_hat) / m # 损失函数
grad_b = -2.0 * np.sum(y_d - y_hat) / m # 对b偏积分
grad_w = -2.0 * np.dot(y_d - y_hat, x_d) / m # 对w偏积分
# 特制b,w的学习率
lr_b += grad_b ** 2
lr_w += grad_w ** 2
# update param 梯度下降
b -= lr/np.sqrt(lr_b) * grad_b
w -= lr/np.sqrt(lr_w) * grad_w
b_history.append(b)
w_history.append(w)
loss_history.append(loss)
if i % 10000 == 0:
print("Step %i, w: %0.4f, b: %.4f, Loss: %.4f" % (i, w, b, loss))
end = time.time()
print("大约需要时间:",end-start)
Out:
Step 0, w: -3.0000, b: -119.0000, Loss: 3670819.0000
Step 10000, w: 2.5661, b: -152.5105, Loss: 10553.3404
Step 20000, w: 2.6185, b: -170.7118, Loss: 10281.2031
Step 30000, w: 2.6441, b: -179.6344, Loss: 10215.2508
Step 40000, w: 2.6569, b: -184.0578, Loss: 10199.0088
Step 50000, w: 2.6632, b: -186.2566, Loss: 10194.9935
Step 60000, w: 2.6663, b: -187.3503, Loss: 10193.9998
Step 70000, w: 2.6679, b: -187.8944, Loss: 10193.7539
Step 80000, w: 2.6687, b: -188.1651, Loss: 10193.6930
Step 90000, w: 2.6691, b: -188.2998, Loss: 10193.6779
大约需要时间: 1.5190024375915527
# 可视化
plt.contourf(x, y, Z, 50, alpha=0.5, cmap=plt.get_cmap('jet'))
plt.plot([-188.4], [2.67], 'x', ms=12, mew=3, color="orange") # 最优解位置
plt.plot(b_history, w_history, 'o-', ms=3, lw=1.5, color='black')
plt.xlim(-200, -100)
plt.ylim(-5, 5)
plt.xlabel(r'$b$')
plt.ylabel(r'$w$')
plt.title("线性回归")
plt.show()