什么是线性单元
当数据集不是线性可分的时候,感知器可能无法收敛。于是用一个可导的线性函数来替代感知器的阶跃函数,这种感知器就叫做线性单元。线性单元在面对线性不可分的数据集时,会收敛到一个最佳近似上。

这里的activation function是一个线性函数,而非之前的阶跃函数。
这样,线性单元将返回一个实数值而非0,1分类。
因此,线性单元用来解决回归问题而非分类问题。
线性单元的模型
y=h(x)=ω1∗x1+ω2∗x2+⋯+ωn∗xn+b
函数h(x)叫做假设。令b=ω0,同时令ω0对应特征x0。这里的x0永远为1。即b=ω0∗x0,其中x0=1。则:
y=h(x)=ω0∗x0+ω1∗x1+⋯+ωn∗xn=ωTx
这样的模型就叫做线性模型,因为输出y是输入特征x1,x2,x3⋯的线性组合。
监督学习和无监督学习
- 监督学习:每个训练样本既包括输入特征x,也包括对应输出y(label)
- 无监督学习:训练样本只有x,没有y。
既有x又有y的样本是很少的,我们可以先用无监督学习做一些聚类,再用少量的带标注的样本告诉模型,模型就可以完成训练。
线性单元的目标函数
对于一个监督学习,用y表示样本的标记,即实际值。用yˉ表示模型计算出来的预测值。
误差e叫做单个样本的误差
e=21(y−yˉ)2
所有样本的误差和叫做E
E=i=1∑ne(i)=21i=1∑n(y(i)−yˉ(i))2
其中
yˉ(i)=h(x(i))=ωTx(i)
用元组(x(i),y(i))表示第i训练样本,yˉ则是模型对第i样本的预测值。
可见对于特定的数据集来说,(x(i),y(i))都是已知的,所以E实际上是对ω的函数。模型的训练实际上就是求合适的ω,使得E(ω)取得最小值,这叫做优化问题,而E(ω)就是优化的目标,称为目标函数。
梯度下降优化算法
每次都向函数y=f(x)的梯度的相反方向来修改x,这样每次函数都能往最小值的方向前进。对于函数E(ω)=21∑i=1n(y(i)−yˉ(i))2:
∇E(ω)=∂ω∂E(ω)=∂ω∂21i=1∑n(y(i)−yˉ(i))2=21i=1∑n∂ω∂(y(i)−yˉ(i))2,
其中,
∂ω∂(y(i)−yˉ(i))2=∂yˉ∂(y(i)−yˉ(i))2⋅∂ω∂yˉ.
而
∂yˉ∂(y(i)−yˉ(i))2=−2y(i)+2yˉ(i),∂ω∂yˉ=∂ω∂ωTx=x.
代入,得
∇E(ω)=−i=1∑n(y(i)−yˉ(i))x
所以,
ωnew=ωold+ηi=1∑n(y(i)−yˉ(i))x(i)
注意,如果每个样本有M个特征,则上式中的x,ω都是M+1维向量(加上了x0),y是标量。
随机梯度下降算法
每次更新ω的迭代,要遍历训练数据中的所有样本进行计算,这种算法叫批梯度下降(Batch Gradient Descent, BGD)。
实用的算法是随机梯度下降(Stochastic Gradient Descent, SGD),每次ω的迭代只计算一个样本,效率大大提升。但存在随机性,每次更新ω并不一定按照减小E的方向,不过大量的更新总体上会沿着减少E的方向前进。SGD不仅效率高,其随机性有助于找到非凸函数的最小值,从而获得更好的模型。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| from perceptron import Perceptron
f = lambda x: x
class LinearUnit(Perceptron): """ 继承Perceptron类 """ def __init__(self, input_num): Perceptron.__init__(self, input_num, f)
def get_training_dataset(): input_vecs = [[5], [3], [8], [1.4], [10.1]] labels = [5500, 2300, 7600, 1800, 11400] return input_vecs, labels
def train_linear_unit(): lu = LinearUnit(1) 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:%.2f' % linear_unit.predict([3.4])) print('Work 15 years:%.2f' % linear_unit.predict([15])) print('Work 1.5 years:%.2f' % linear_unit.predict([1.5])) print('Work 6.3 years:%.2f' % linear_unit.predict([6.3]))
|