前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >入门机器学习(二)-------线性单元和梯度下降及其代码实现(代码实现)

入门机器学习(二)-------线性单元和梯度下降及其代码实现(代码实现)

作者头像
andrew_a
发布2019-07-30 15:03:45
5030
发布2019-07-30 15:03:45
举报

通过上一篇文章,我们学会了一个简单的感知器,了解了阶跃函数(更喜欢叫二分类,简单明了哈哈),还有训练感知器的感知器规则。在这里学习另一种感知器——线性单元,通过此线性单元来了解机器学习的一些基本概念, 比如模型,目标函数,算法优化等。以此来简单了解机器学习。

一、线性单元

对与上一节说讲的感知器,在对线性不可分的数据集,之前的感知器规则是无法收敛的,在此时是无法来训练感知器的,所以在为了解决这个问题时,找到了一个可导线性函数来替代感知器的阶跃函数,这种感知器就叫线性单元。线性单元在面对线性不可分的数据集时,会收敛到一个最佳的近似值。

在这里我们假设一个简单的线性单元的激活函数f: f(x) = x

该线性单元表示如下:

对比上一节的:

替换了激活函数f之后, 线性单元返回的就是一个实数值了,而不是二分类0,1了,所以线性单元是用来解决回归问题而不是分类的

二、线性单元模型

说的是模型其实就是函数(ps: 我感觉是这样,模型说起来高大上一点~~哈哈)。

在实际的现实生活中,我们根据的输入的x值来预测输出y的算法。比如,x可以是一个人的工作年限, y是他的月薪, 我们可以根据某种算法来根据一个人的工作年限来预测他的收入。比如:y = h(x) = w*x +b

函数 h(x) 为假设, 而w, b 是他的参数。 假设w = 1000, b= 500, x为一个人的工作年限,代入上面的模型,预测出他的月薪为5500。这样的模型有点不靠谱,,因为没考虑其他的因素,考虑的只是工作年限,当把工作年限,行业,公司,职级这些信息,称之为特征。对于一个工作了3年的,在IT行业,阿里工作,职级T3的人, 可以用特征向量来表示

X = (3, IT, 阿里,T3)

此时的输入X变成了一个具备四个特征的向量,相对的,只有一个参数w就不可以了,还需要3个参数,就一共4个参数(w1, w2,w3,w4)数字是下标,每个特征对应一个参数。此时的模型就成了:

y = h(x) = w1 * x1+ w2 *x2 + w3 * x3 + w4 * x4 + b

x1: 工作年限 x2: 对应的行业

x3: 对应的公司 x4: 对应职级

此时,令w0等于b, w0对应特征x0, 因为x0并不存在, 我们可以令x0 = 1,即:

b = w0 * x0 其中 x0 = 1

这样上面的公式就变成下面的了:

y = h(x) = w1 * x1+ w2 *x2 + w3 * x3 + w4 * x4 + b (1)

=w0 * x0 + w1 * x1+ w2 *x2 + w3 * x3 + w4 * x4 (2)

写成向量的模式:

上面的式子,函数模型就称为线性模型, 输出y就是输入特征x1, x2, x3,...的线性组合

三、监督学习和无监督学习

有了模型了, 但是如何训练该模型??,参数w到底该如何选取??

监督学习:它是机器学习的一类学习方法,它是为了训练一个模型,提供了一大堆的样本,这些样本包括输入的特征X,也包应的输出y(y也叫做标记, label)。也就是说,我们要知道很多人的数据,他们都有这些特征:工作年限,行业,公司,职级,以及他们的收入。我们用这些样本来训练模型, 让模型知道每个输入的特征(X), 也知道对应问题的答案(标记y)。模型通过这些样本(足够多),来总结规律,然后来预测那些没有看到过的输入(X),所对应的答案。

无监督学习:这种方法的训练样本中只有X没有y, 模型可以总结出特征x的一些规律,但是无法知道其对应的答案y。(即你给出输入x, 会有一个输出y, 但是你不知道这个y的值是不是对的)

很多时候,有x又有y的样本很少的, 大部分样本只有x。比如在语音到文本(STT)的识别任务中, x是语音, y是该段语音对应的文本。语音我们可以获取大量的数据,但是把语音转化为文本,并标注上对应的文字则是非常费时间的。此时为了弥补标注样本的不足, 我们可以用无监督学习方法先做一些聚类,让模型总结出哪些音节是相似的,然后在用少量的带标注的训练样本,告诉模型其中一些音节对应的文字。此时模型就可以把相似的音节都对应到相似的文字上,完成模型的训练。

四、线性单元的目标函数

只考虑监督学习

在监督学习下, 对与一个样本,我们知道它的特征X,以及标记y。同时根据模型h(x)计算得到输出

。这里的y表示的是训练样本里面的标记,也就是实际值;带上划线的

表示模型计算出来的预测值。如果y和

的值特别接近,则该模型就很好了。那么如何来表示

和y的值相近,我们可以用

和y的差的平凡和的1/2来表示:

e: 单个样本误差(1/2方便计算

训练数据中会有很多样本,当有N个时,我们可以用训练样本中所有样本的误差的和,来表示模型的误差E,如下:

上面的

表示第一个样本的误差,后续表示第二个,一直到最后一个。。。。。

写成和的形式:

上式2中,

表示第i个训练样本的特征

表示第i个样本的标记,在这里可以用元组

表示第i个训练样本

则是模型对第i个样本的预测值。对于一个训练集数据来说,当误差越小的时候,模型越好,对于特定的训练数据集来说,

的值都是已知的, 所以对于式子2来说就变成了参数w的函数。

综上所述,模型的训练,实际上就是取到合适的w,使得式子2的值最小。取最小值,就变成了数学上的优化问题,而E(w)就是优化目标,为我们的目标函数

四、梯度下降优化算法

在学数学的时候,我们通过求函数的极值。就y=f(x) 的极值点,就是求它的导数

的那个店。所以我们可以通过解方程

,来得到函数的极值点

对于计算机来说,它通过自己的计算来把极值点找出来。如下:

首先我们随便选择一个点,假设改点为x0点,接下来每次迭代修改x为x1, x2, x3, ......经过很多次的迭代,到达函数的最小值点。

我们每次修改x的值,都需要往函数最小值的方向前进,就需要向函数y = f(x)的梯度相反方向来修改x。 梯度:是一个向量,它指向函数值上升最快的方向。所以梯度的反方向就是函数值下降最快的方向。所以每次沿着梯度反方向去修改x的值,就可以走到函数的最小值附近,之所以是最小值附近而不是最小值点,是因为每次移动的步长不会会恰到好处,有可能最后一次迭代走远了直接越过了最小值点。步长的选取:选择小了,那么就会迭代很多轮才能走到最小值附近;如果选择大了,那可能就会越过最小值很远,收敛不到一个好的点上。

给出梯度下降算法:

梯度算子

:指的是f(x)的梯度

步长(学习速率)

对应的上面的目标函数(式子2)可以改写成:

梯度下降算法可改写成:

同时如果求取最大值, 就可以使用梯度上升算法,它的参数修改规则如下:

此时需要求取

然后代入

得到线性单元的参数规则。

求取到的目标函数

的梯度是:

最终的线性单元的参数修改规则如下:

此时就可以用该函数来写出训练线性单元的代码了。

需要说明的是,如果每个样本有M个特征,则上式中x, w的都是M+1维向量(因为我们加上了一个恒为1的虚拟特征x0,参考前面的内容),而y是标量。用数学符号表示,就是

也即, w, x是M+1维列向量,式子3可以写成

五、目标函数

的推导

学过数学的同志,知道的不知道的,在这里告诉大家, 函数的梯度的定义就是相对于各个变量的偏导数

如下:

下来求解11, 首先导数的和就等于和的导数(细节不说了,自行百度,累死快~~),所以先把求和符号

里面的导数求出来,在相加如下:

求导,如下:

通过上面的我们知道,y是与w无关的常数,而

通过连式法则来求导(复合函数的求导):

分别计算上式等号右边的两个偏导数

代入,求和

里面的偏导数是:

mamaya~~终于完了,leiskr个。

六、随机梯度下降算法(Stochastic Gradient Descent, SGD)

如果更具第四节中的式子3来训练模型(DGD),在每次迭代W时, 要遍历数据中的所有样本,称这种叫做批梯度下降Batch Gradient Descent)。

但是当样本特别特别大的时候,数据量达到百万到数亿的时候,常常用的是SDG算法。在SGD算法中,每次更新w的迭代,只计算一个样本。这样对于一个具有数百万样本的训练数据,完成一次遍历就会对w更新数百万次,效率大大提升。由于样本的噪音和随机性,每次更新w并不一定按照减少E的方向。然而,虽然存在一定随机性,大量的更新总体上沿着减少E的方向前进的,因此最后也能收敛到最小值附近。下图展示了SGD和BGD的区别:

如上图, 椭圆表示的是函数值的等高线,椭圆中心是函数的最小值点。红色是BGD的逼近曲线,而紫色是SGD的逼近曲线。我们可以看到BGD是一种向着最低点前进的, 虽然SDG波动较大,但最终在总体上任然是向着最低点逼近的。

最后需要说明的是,SGD不仅仅效率高,而且随机性有时候反而是好事。今天的目标函数是一个『凸函数』,沿着梯度反方向就能找到全局唯一的最小值。然而对于非凸函数来说,存在许多局部最小值。随机性有助于我们逃离某些很糟糕的局部最小值,从而获得一个更好的模型。

七、实现线性单元

对比之前的感知器模型:

通过上图比较,发现除了激活函数f不同之外,两者的模型和训练规则是一样的(在上表中,线性单元的优化算法是SDG算法)。所以此时我们只需要把感知器的激活函数进行替换即可。

通过继承上节的Perceptron,来实现线性单元:

代码语言:javascript
复制
# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time    : 2019/4/29 15:23
# @Author  : xhh
# @Desc    :  
# @File    : test_linearModel.py
# @Software: PyCharm
from test_perceptorn import Perceptron


# 定义激活函数
f = lambda x: x

class LinearUnit(Perceptron):
    def __init__(self, input_num):
        """
        初始化线性单元,设置输入参数的个数
        :param input_num:
        """
        Perceptron.__init__(self, input_num,f)

模拟一些数据,来测试:

代码语言:javascript
复制
def get_training_dataset():
    """
    假设5个人的收入数据
    :return:
    """
    # 构建训练数据
    # 输入向量列表,每一项都是工作年限
    input_vecs = [[5],[3],[8],[1.4],[10.1]]
    # 期望的输出列表,月薪,注意要与输入一一对应
    labels = [5500, 2300, 7600,1800,11400]
    return input_vecs, labels

def train_linear_unit():
    """
    使用数据训练线性单元
    :return:
    """
    # 创建感知器,输入参数的特征为1(工作年限)
    lu = LinearUnit(1)

    # 训练,迭代10轮,学习速率为0.01
    input_vecs, labels = get_training_dataset()
    lu.train(input_vecs, labels, 10, 0.01)

    # 返回训练好的线性单元
    return lu

def plot(linear_unit):
    import matplotlib.pyplot as plt
    input_vecs, labels = get_training_dataset()
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(map(lambda x:x[0], input_vecs), labels)
    weights = linear_unit.weight
    bias = linear_unit.bias
    x = range(0, 12, 1)
    y = map(lambda x:weights[0] * x + bias, x)
    ax.plot(x, y)
    plt.show()


if __name__ == '__main__':
    """
    训练线性单元
    """
    linear_unit = train_linear_unit()
    # 打印训练获得的权重
    print(linear_unit)
    # 测试
    print('工作3.6年,月收入 = %.2f'% linear_unit.predict([3.4]))
    print('工作10年,月收入 = %.2f'% linear_unit.predict([10]))
    print('工作6.3年,月收入 = %.2f'% linear_unit.predict([6.3]))
    plot(linear_unit)

运行结果如下:

拟合的直线如下图:

总结:

通过上面所写的,得出机器学习算法其实只要两部分:

1、模型 从输入特征x预测输出y的函数h(x)

2、目标函数 目标函数取最小(最大)值时所对应的参数值,就是模型的参数的最优值。但通常我们只能获取得到目标函数的局部最小(最大)值,因此我们只能得到模型参数的局部最优值

3、接下来,用优化算法去求取目标函数的最小(最大)值、【随机】梯度{下降|上升}算法就是一个优化算法。针对一个目标函数,不同的优化算法会推出不同的训练规则

参考资料:

  1. Tom M. Mitchell, "机器学习", 曾华军等译, 机械工业出版社

https://www.zybuluo.com/hanbingtao/note/448086

大家可以关注我和我小伙伴的公众号~~~这里有我和我的小伙伴不定时的更新一些python技术资料哦!!大家也可以留言,讨论一下技术问题,希望大家多多支持,关注一下啦,谢谢大家啦~~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python爬虫scrapy 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档