深度学习(二),神经网络介绍与感知机——超详细公式推导及代码实例

                            公式代码图都是手敲,给个三连支持下呗(●´ω`●)欢迎讨论

一,神经网络(Neural Network)

    1.1 神经网络的概念

             神经网络简单地说,就是模仿人脑的自然神经系统构造和机理而建立的网络,其网络则是由一个又一个的神经单元组成。在真实场景的大脑神经元系统下,每一个神经元只有接收到足够大的电流刺激,才会向下发出信号。这可以理解每一个神经元有一个对应的激活的方法,比如说只有接收到的电流大于5毫安,才会向下传递。(看下面的图可能更好理解一点)

        用数学来说就是每一个真实的神经元都有对应的激活函数,上面的例子中该神经元的激活函数可以看做是,当x>5,y=1 ;否则y=0 的函数。

        而我们所建立的数学的神经网络模型中,每一个神经元的激活函数可没有那么简单了,一般有着各种各样的激活函数以应对复杂的多种非线性关系。

1.2 从神经网络看感知机

        先介绍一下,感知机,研究的函数也是  y = w0 + w1x1 + w2x2 ...+ wnxn, 如果我们的样本只有一个特征,那么他就是我们从小到大都很熟悉的形式 y = w0 + w1x ( 就是y = ax+b)。

        下面将用神经网络来展示一下这个结构,从而让大家对简单的神经网络开始有一些概念,下一篇我就开始讲多层感知机了。

          以有三个特征的样本为例,即我们的目标函数是(y = w0 + w1x1+w2x2+w3x3),w0是误差项,w1是样本在第一个特征的取值所对应要乘的的系数,以此类推。

           更具体一点,假设对于分辨眼前的动物是否是一只猫这个任务,我们的大脑里有三个神经单元负责这个任务,这三个神经单元分别接受的输入信号是,这个动物的是否有爪子,是否有耳朵,是否长毛。

        具体的辨别流程就应该是三步走

        1.我们眼睛捕捉到的信号,输入到这三个神经元,乘以神经元内存储的对应的系数;

        2.然后各自经过该神经元的激活函数判断(也有可能没有激活函数),来判断是否继续向下输出信号(用数字表示就是向下传1,还是0);

        3.然后这三个神经元的输出信号会汇总到一个神经元,该神经元再用它的激活函数判断之后,最后得出是否是猫的判断(比如假设当该汇总神经元的激活函数是只有当收集到的信号是3个1,就输出一个1,告诉你它是猫。)

        上述例子所对应的神经网络如下:

      

        上图就是感知机用神经网络的形式表达出来了(省略了参数优化部分),可以发现,它只有输入层,输出层两个层。实际上,在输入层和输出层之间如果我们再添任意个层,那么它就变成了多层感知机了,并且在输入输出两个层之间的所有层都叫做隐藏层

        实际上,梯度下降来优化参数权向量的过程也能用神经网络的形式画出来,但是留到多层感知机再具体讲可能更好一点。

        PS:如果有对线性回归熟悉的小伙伴肯定也会很眼熟,实际线性回归就可以看作是类似的只有输入输出层的单层神经网络,但损失函数是平方误差并且用最小二乘法求解参数。

二,感知机(Perceptron)

  2.1 介绍

        大名鼎鼎的感知机,是一个二分类模型,也是最早的AI模型之一。它的原理简单,便于理解,且实现简单,在线性分类问题上效果卓越,在60年代备受瞩目。但也正是因为它受到的期望过高,当潜在的一些问题暴露出来后(如无法拟合XOR函数,无法解决非线性问题),人们大失所望,直接导致了第一次的AI寒冬。

        不过它采用梯度下降的方式来对损失函数进行优化的方式,模拟神经网络运行的创思,成为了现在深度学习最重要的基础之一,同时也成为了学习神经网络的入门模型之一。

        与把线性分类任务拆分为两步的Fisher判别不同(请见我另一篇,LDA-Fisher线性判别),感知机是研究如何得到线性判别函数 g(x) = wx + w0的。

        机智的人可能会发现,它研究的函数,怎么跟线性回归长得那么像?其实不能说像,简直一模一样。

        关于线性回归和感知机,以下给出几个区分点:

        1. 线性回归一般是回归任务,而感知机是二分类任务;

        2.线性回归的计算函数y=ax+b所计算出来的值就是结果值,而感知机则是会根据计算出来的值是否大于0 ,来决定最后的取值为1还是-1(也有的版本是取1和0的)

        3.线性回归在限定损失函数是平方误差下,是可以直接得到解析解的,而感知机则不行,转而采用的梯度下降求解。

  2.2 公式推导

        下面的公式都是从数学角度来推的,并没有结合神经网络的图。你可以忘掉上面看到的图,当做重头从纯数学的角度理解感知机这一经典算法。两个角度来看待感知机,相互印证,相信你会有更深的理解。

        2.2.1 变量定义

          假设我们拥有n个d维的样本向量x, 并知晓它们每一个对应的真实标签(仅有两类).为了方便讨论,我们把向量x增加1维,变成增广的样本向量形式,如下:

            y = [ 1,  x1, x2, x3, ... , xd ]

         请注意,上面表示的仅仅是一个样本,n个样本的总数据集用矩阵表示的话应该是n个上面的y作为行向量。而x1代表该样本在第一个特征的取值,其他的同理。

        所以下面当我们提到y1的时候,你要知道就是原来数据集里的第一个样本 增广了一列1. 

        之所以要这么做,是因为我们将要训练的权重向量会定义为:

           a = [w0, w1, w2, w3,..., wd]

   

最终的线性判别函数就变为:

        g(y) = a y^T (实在搞不懂怎么在右上角打小T)

        这样就看起来十分简洁了。

  2.2.2 线性可分

        下面给出判断样本集是否线性可分的定义:

        对于一组样本 y1,y2,y3,...yn,若存在权向量a, 使得对于任一样本有:

       

                当yi 属于类别C1时,g(yi) < 0;

                当yi属于类别C2时,g(yi) < 0;

       

        则称该数据集是线性可分的。

         如下图所示,左边明显是线性可分的,我们可以用一条斜线就分开了两类数据。右边则是非线性可分的情况。

                     

        更进一步的,让我们对样本y的表达式再做如下改动

                 

    2.2.3 损失函数 

                通过定义好损失函数之后,就可以利用梯度下降来求解出目标权重向量a了。

                          

                有的观察仔细的可能会发现,判别函数计算结果是0的样本也是被加入到损失函数的计算中去了,这是因为我们的分类准则只有大于0或者小于0的时候才会分到某一类中,如果计算结果是0,那么代表的是分类失败。

                显然,当Loss(a) = 0时,所对应的权向量a就是满足我们目标,把数据集线性分开了的解向量。所以我们的优化目标也就是把Loss(a)的值最小化。

     2.2.4 梯度下降

                把Loss(a)最小化的方式我们选择用梯度下降来求解,也就是不断更新a的值,即 把当前t时刻的a权向量的值 加上 目标函数的负梯度方向的一个修正量 从而得到 下一个时刻t+1的a权向量。

                        

        2.2.5 算法步骤: 

        每次只修正1个样本,所以等价于批量为1的随机梯度下降的只有一层的神经网络。

  1.    任意选择初始的权向量a(0), 里面的0就是当前时刻t为0;
  2.   考察样本Y0, 若 g(Y0) <=0, 则 a(t+1) = a(t) + pY0 ,否则继续遍历样本
  3.    重复第2步,知道所有样本都有g(Y) > 0, 也就是Loss(a)=0

    2.2.6 关于余量

      原本我们的对一个样本的判别条件是,如果g(y) >0,那么就认为它属于第一类。但是如果结果只是0.001呢?虽然也是大于0,但是也给它分为第一类,是不是有点不太稳,尤其是我们的模型还存在偏差,还要考虑泛化性能的情况下。

        所以为了提高置信度,一般会设置一个余量b, 使得只有g(y) > b, 才认为是第一类。这么做也就是压缩了两个类别之间的解向量的可取范围,使你能够取到的解向量更少,也更加精准了。但同时也更加难以去找到这个解向量了,计算量会变大。 所以这个余量b也是挺重要的一个超参数,需要仔细衡量。

2.3 代码实例        

import numpy as np

def perceptron_fit(X: np.array, y: np.array, n_iter=1000, learning_rate=0.01):
    '''
    训练感知机模型
    X: 输入特征数组 shape: [n_samples, n_features]
    y: 类别数组,类别标签为1或-1 shape: [n_samples]
    n_iter: 迭代次数
    learning_rate: 学习率
    '''
    # 初始化权重向量,添加偏置项
    w = np.zeros(X.shape[1] + 1)
    # 添加偏置项到X中
    X = np.hstack([np.ones((X.shape[0], 1)), X])
    
    # 迭代训练模型
    for _ in range(n_iter):
        for xi, target in zip(X, y):
            # 计算预测值
            prediction = np.dot(xi, w)
            # 检查预测值是否正确分类
            if target * prediction <= 0:
                # 更新权重
                w += learning_rate * target * xi
    return w

def perceptron_predict(X: np.array, w: np.array):
    '''
    使用训练好的感知机模型进行预测
    X: 输入特征数组 shape: [n_samples, n_features]
    w: 训练好的权重数组 shape: [n_features + 1]
    '''
    # 添加偏置项到X中
    X = np.hstack([np.ones((X.shape[0], 1)), X])
    # 计算预测值
    predictions = np.dot(X, w)
    # 应用激活函数(sign函数)
    predictions = np.where(predictions > 0, 1, -1)
    return predictions

# 示例使用感知机模型
# X, y 为数据集的特征和标签,其中y的取值为1或-1
# w = perceptron_fit(X, y)
# predictions = perceptron_predict(X, w)

        我这里只是简单的给了算法的过程代码。

        使用这个模型更加要关注的是训练前的数据预处理,比如把特征都缩放到同一个范围这对感知机这种采取梯度下降的模型的收敛速度起到很大的影响,还有确保你的数据集是线性可分的,才会取到比较好的效果。

  • 31
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值