经过上一篇章的学习,我们得知了有很多种深度学习,比如监督学习,无监督学习,强化学习等,监督学习算是深度学习的入门第一手,所以我们先学习监督学习中的回归
定义
:前期学习(通过很多正确的输入和输出——>找到一个函数function),然后再输入特征x,输出一个结果。
步骤
:
1.先选择模型
2.通过损失函数判断和结果的接近程度
3.通过梯度下降不断修正模型
单个特征:
y = b + w x y = b + wx y=b+wx
多个特征:
y = b + ∑ w i x i y = b + \sum {{w_i}{x_i}} y=b+∑wixi
x:各种特征;w:各个特征的权重; b:偏移量。
多个特征——>联系到向量和矩阵,可以方便计算。
作用:通过损失函数来评判模型的好坏
损失函数有很多种,一般是用均方误差和交叉熵误差等。
均方误差
E = 1 2 ∑ k ( y k − t k ) 2 E = \frac{1}{2}\sum\limits_k {{{({y_k} - {t_k})}^2}} E=21k∑(yk−tk)2
其中, E {E} E针对单个数据的损失函数, y k {y_k} yk表示神经网络的输出, t k {t_k} tk表示监督数据,k表示数据的维数。
交叉熵误差
E = − ∑ k t k log y k E = - \sum\limits_k {{t_k}\log {y_k}} E=−k∑tklogyk
其中, E {E} E针对单个数据的损失函数, y k {y_k} yk表示神经网络的输出, t k {t_k} tk表示正确解标签,只有正确解标签处的值才为1,其他都为0.
在老师讲课过程中,主要以均方误差来表示损失函数。
例如:统计10组原始数据 ( y ^ − f ( x n c p ) ) 2 {(\hat y - f({x^n}_{cp}))^2} (y^−f(xncp))2之和,和越小越好。
意思就是算出预测出来的值和真实的值的差越小越好。
L ( f ) = ∑ n = 1 10 ( y ^ n − f ( x n c p ) ) 2 L(f) = \sum\limits_{n = 1}^{10} {{{({{\hat y}^n} - f({x^n}_{cp}))}^2}} L(f)=n=1∑10(y^n−f(xncp))2
f ( x ) = y f(x) = y f(x)=y
y = b + w x c p y = b + w{x_{cp}} y=b+wxcp
将上文的三个式子总和可得最终损失函数Loss function:
L ( w , b ) = ∑ n = 1 10 ( y ^ n − f ( b + w x c p n ) ) 2 L(w,b) = \sum\limits_{n = 1}^{10} {{{({{\hat y}^n} - f(b + w{x_{cp}}^n))}^2}} L(w,b)=n=1∑10(y^n−f(b+wxcpn))2
拓展:此处 f ( x ) = y f(x) = y f(x)=y较为省略,更应该的是此处加一个激活函数,应更正为 f ( x ) = h ( y ) f(x) =h(y) f(x)=h(y)
为了使损失函数最小,结果更优,我们需要不断调整参数 ( w , b ) (w,b) (w,b),这里我们就用到梯度下降的方法。
先从只有一个参数w入手,任何可微分的L都可以
w ∗ = arg min x L ( w ) {w^*} = \arg \mathop {\min }\limits_x L(w) w∗=argxminL(w)
1.随机选出一个初始的点w0;
2.然后再计算切线斜率 d L d w ∣ w = w 0 \frac{{d{\rm{L}}}}{{d{\rm{w}}}}{|_{{\rm{w}} = {{\rm{w}}_0}}} dwdL∣w=w0,然后大于0往左移动,小于零往右移动。
3.跨步距离——学习率 η \eta η:事先定好的数值
4.移动: − η d L d w ∣ w = w 0 -\eta \frac{{d{\rm{L}}}}{{d{\rm{w}}}}{|_{{\rm{w}} = {{\rm{w}}_0}}} −ηdwdL∣w=w0
5.更新w0——> ω n + 1 = ω n − η d L d w ∣ w = w 0 {\omega _{n + 1}} = {\omega _n} - \eta \frac{{d{\rm{L}}}}{{d{\rm{w}}}}{|_{{\rm{w}} = {{\rm{w}}_0}}} ωn+1=ωn−ηdwdL∣w=w0
6.重复234.直到找到最低点
但是找到的只能说找到局部最小值而不是全局最小值。
两个参数:
同理,只不过是把导数变成偏导数。
∇ L = [ ∂ L ∂ w ∂ L ∂ b ] g r a d i e n t \nabla L = {\left[ {\begin{matrix}{} {\frac{{\partial L}}{{\partial w}}}\\ {\frac{{\partial L}}{{\partial b}}} \end{matrix}} \right]_{gradient}} ∇L=[∂w∂L∂b∂L]gradient
可以想想一个山坡,然后向最低的方向滚,然后通过往偏导方向走,那肯定是数值下降最快的方向。
但找到局部最优解,不一定是全局最优解。
但如果是在线性模型中,那肯定是局部最优解就是全局最优解。
当有很多个数据点的时候,去拟合这个函数值。一元N次线性模型一般较为强大。
但是我们可以看到,并不是次数越高,就拟合效果越好,有时候过于追求每个点的精度,反而丢失了全局,造成过拟合
问题。
将四个线性模型合并到一个线性模型中,只需要将对应模型板块的 δ \delta δ为1,不对应的为0,就可以避免混入其他线性模型中。
所以对于上文的线性拟合,如果知道其种类,把它分成三个线性模型,说不定可以得到更加精确的模型。
设更多参数,加入更多input—>容易过拟合;
怎么办?
1.可以删掉相关性较小的input
2.加入正则化,重新定义我们的loss function
L = ∑ n ( y ^ n − ( b + ∑ w i x i ) ) 2 + λ ∑ ( w i ) 2 L = \sum\limits_n {{{({{\hat y}^n} - (b + \sum {{w_i}{x_i}} ))}^2} + \lambda \sum {{{({w_i})}^2}} } L=n∑(y^n−(b+∑wixi))2+λ∑(wi)2
加入 λ ∑ ( w i ) 2 {\lambda \sum {{{({w_i})}^2}} } λ∑(wi)2说明期望w越小越好
w越小越好——>比较平滑的——>output对输入的变化是不太敏感的。比较稳定——>可以避免一些干扰项的影响
λ \lambda λ越大的时候,说明我们越考虑函数的平滑。但也不能太平滑,所以我们需要不断的调整 λ \lambda λ
我于是对代码进行了研读。
用numpy的np.asarray来使列表变为数组。
我能理解lr的不断变动或许效果不是很好
所以将lr_b和lr_w分开
但我不大理解学习率用这种方式特化:
lr_b = lr_b + b_grad ** 2
lr_w = lr_w + w_grad ** 2
我想提前了解一下这种特化学习率的方法。
后经队长的指导,我了解到了原来是Adagrad方面的知识。
如果学习率固定,那针对不同的地方,学习率可能作用效果不同。
大致就是:
随着迭代次数增加,让学习率变小
初始迭代时,使用较大的学习率加速下降
迭代几次后,减小学习率防止振荡和越过
当然adagrad的相关知识之后也会学到,但是通过代码的调整,我提前了解到了adagrad的作用。在此感谢队长和相关伙伴的指导。
import numpy as np
import matplotlib.pyplot as plt
import time
from pylab import mpl
# matplotlib没有中文字体,动态解决
plt.rcParams['font.sans-serif'] = ['Simhei'] # 显示中文
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
#x_data正确输入数据 y_data 正确输出数据
x_data = [338., 333., 328., 207., 226., 25., 179., 60., 208., 606.]
y_data = [640., 633., 619., 393., 428., 27., 193., 66., 226., 1591.]
#用numpy将列表转化为数组
x_d = np.asarray(x_data)
y_d = np.asarray(y_data)
x = np.arange(-200, -100, 1)
y = np.arange(-5, 5, 0.1)
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)
# 线性回归
b = -120
w = -4
lr = 1
#迭代次数
iteration = 100000
b_history = [b]
w_history = [w]
#把w和b的学习率分来
lr_b = 0
lr_w = 0
start = time.time()
for i in range(iteration):
b_grad = 0.0
w_grad = 0.0
for n in range(len(x_data)):
b_grad = b_grad - 2.0 * (y_data[n] - n - w * x_data[n]) * 1.0
w_grad = w_grad - 2.0 * (y_data[n] - n - w * x_data[n]) * x_data[n]
#不理解???lr_b的变动
lr_b = lr_b + b_grad ** 2
lr_w = lr_w + w_grad ** 2
# update param
b -= lr / np.sqrt(lr_b) * b_grad
w -= lr / np.sqrt(lr_w) * w_grad
b_history.append(b)
w_history.append(w)
# plot the figure
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()
提示:今天主要学习了回归里面的线性模型,损失函数,还有梯度下降。还学到了过拟合以及防止过拟合的正则化。但其讲的时候省略了激活函数这一块知识。还研读了一下其代码,在他人的帮助下提前对adagrqd对知识有了一定的了解。