人工智能小白日记 DL算法学习之2 线性单元和梯度下降
前言
开始了解线性单元和梯度下降算法,参考
https://www.zybuluo.com/hanbingtao/note/448086
正文内容
1 线性单元
问题:当面对的数据集不是线性可分的时候,『感知器规则』可能无法收敛,这意味着我们永远也无法完成一个感知器的训练。
方案:使用一个可导的线性函数来替代感知器的阶跃函数,这种感知器就叫做线性单元。线性单元在面对线性不可分的数据集时,会收敛到一个最佳的近似上。
比如激活函数为f(x) = x , 那么该线性单元的输出不再是0,1,而是一个数值。所以线性单元用来解决回归问题而不是分类问题。
线性回归问题前面已经见过了,加州房价预测之类的。其模型最终可表示为
令
则可以简化为
2 线性回归的目标函数
对于线性回归问题,其预测值与实际值之间会产生一定的误差,这种误差越小,则预测越准确。对此,就有了一套针对误差减小的优化思路。
用于计算误差的方法也很多,线性回归单个样本的误差函数可表示为
整个模型的误差则可认为是
由此可见,模型的训练,实际上就是求取到合适的,使E(w)取得最小值。E(w)也称之为目标函数
3 梯度下降优化算法
E(w)是一个关于w的一元二次方程,在平面几何上的表示如下:
为了得到函数的最小值,其实就是得到E’(w) = 0 时 ,w的值。
从图中所示, 当斜率E’(w) < 0 时,需要将w向右边移动 ;
当斜率E’(w) > 0 时,需要将w向左边移动 ;
因此 ,梯度优化公式可表达为:
w = w - η*E’(w) , 其中η为学习速率。
由于
现对令其对w求导,y是标签值为w无关的常量,而
所以可以通过链式求导法转换为
下一步
带入梯度优化公式中最后得到
由于w和x都是向量,最后的表达式实际上是这样的
4 随机梯度下降算法(Stochastic Gradient Descent, SGD)
批梯度下降(Batch Gradient Descent):每次更新的迭代,要遍历训练数据中所有的样本进行计算。
而SGD算法,每次更新的迭代,只计算一个样本。由于样本的噪音和随机性,每次更新并不一定按照减少的方向。然而,虽然存在一定随机性,大量的更新总体上沿着减少的方向前进的,因此最后也能收敛到最小值附近。
**优点:**SGD不仅仅效率高,而且随机性有时候反而是好事。今天的目标函数是一个『凸函数』,沿着梯度反方向就能找到全局唯一的最小值。然而对于非凸函数来说,存在许多局部最小值。随机性有助于我们逃离某些很糟糕的局部最小值,从而获得一个更好的模型。
5 实现线性单元
与感知器进行比较
除了激活函数需要变化其他不变.
因此,继承上一节的感知器
from lesson1_perceptron import Perceptron
#激活函数
f = lambda x:x
class LinearUnit(Perceptron):
def __init__(self,input_num):
Perceptron.__init__(self,input_num,f)
然后调用
def get_training_dataset():
'''
捏造5个人的收入数据
'''
# 构建训练数据
# 输入向量列表,每一项是工作年限
input_vecs = [[5], [3], [8], [1.4], [10.1]]
# 期望的输出列表,月薪,注意要与输入一一对应
labels = [5500, 2300, 7600, 1800, 11400]
return input_vecs, labels
def train_linear_unit():
'''
使用数据训练线性单元
'''
# 创建感知器,输入参数的特征数为1(工作年限)
lu = LinearUnit(1)
# 训练,迭代10轮, 学习速率为0.01
input_vecs, labels = get_training_dataset()
lu.train(input_vecs, labels, 10, 0.01)
#返回训练好的线性单元
return lu
if __name__ == '__main__':
'''训练线性单元'''
linear_unit = train_linear_unit()
# 打印训练获得的权重
print (linear_unit)
# 测试
print ('Work 3.4 years, monthly salary = %.2f' % linear_unit.predict([3.4]))
print ('Work 15 years, monthly salary = %.2f' % linear_unit.predict([15]))
print ('Work 1.5 years, monthly salary = %.2f' % linear_unit.predict([1.5]))
print ('Work 6.3 years, monthly salary = %.2f' % linear_unit.predict([6.3]))
运行结果如下
小结
原文最后部分的小结直接搬过来了,总结的很到位:
“事实上,一个机器学习算法其实只有两部分
- 模型 从输入特征预测输入的那个函数
- 目标函数 目标函数取最小(最大)值时所对应的参数值,就是模型的参数的最优值。很多时候我们只能获得目标函数的局部最小(最大)值,因此也只能得到模型参数的局部最优值。
因此,如果你想最简洁的介绍一个算法,列出这两个函数就行了。
接下来,你会用优化算法去求取目标函数的最小(最大)值。[随机]梯度{下降|上升}算法就是一个优化算法。针对同一个目标函数,不同的优化算法会推导出不同的训练规则。”