zoukankan      html  css  js  c++  java
  • 一.单层感知器

    单层感知器属于单层前向网络,即除输入层和输出层之外,只拥有一层神经元节点。

      特点:输入数据从输入层经过隐藏层向输出层逐层传播,相邻两层的神经元之间相互连接,同一层的神经元之间没有连接。

      感知器(perception)是由美国学者F.Rosenblatt提出的。与最早提出的MP模型不同,神经元突触权值可变,因此可以通过一定规则进行学习。可以快速、可靠地解决线性可分的问题。

    1.单层感知器的结构

      单层感知器由一个线性组合器和一个二值阈值元件组成。输入向量的各个分量先与权值相乘,然后在线性组合器中进行叠加,得到一个标量结果,其输出是线性组合结果经过一个二值阈值函数。二值阈值元件通常是一个上升函数,典型功能是非负数映射为1,负数映射为0或负一。

      输入是一个N维向量 x=[x1,x2,...,xn],其中每一个分量对应一个权值wi,隐含层输出叠加为一个标量值:

    随后在二值阈值元件中对得到的v值进行判断,产生二值输出:

                              

    可以将数据分为两类。实际应用中,还加入偏置,值恒为1,权值为b。这时,y输出为:

                      

    把偏置值当作特殊权值:

     

     单层感知器结构图:

                    

     单层感知器进行模式识别的超平面由下式决定:

                        

    当维数N=2时,输入向量可以表示为平面直角坐标系中的一个点。此时分类超平面是一条直线:

                        

    这样就可以将点沿直线划分成两类。

    2.单层感知器的学习算法

    (1)定义变量和参数,这里的n是迭代次数。N是N维输入,将其中的偏置也作为输入,不过其值恒为1,。

      x(n)=N+1维输入向量=[+1,x1(n),x2(n),...,xN(n)]T

      w(n)=N+1维权值向量=[b(n),w1(n),w2(n),...,wN(n)]T

      b(n)=偏置

      y(n)=实际输出

      d(n)=期望输出

      η(n)=学习率参数,是一个比1小的正常数

    所以线性组合器的输出为:v(n)=wT(n)x(n)

    (2)初始化。n=0,将权值向量w设置为随机值或全零值。

    (3)激活。输入训练样本,对每个训练样本x(n)=[+1,x1(n),x2(n),...,xN(n)]T,指定其期望输出d。即若x属于l1,则d=1,若x属于l2,则d属于-1(或者0)。

    (4)计算实际输出。        y(n)=sgn(wT(n)x(n))

    (5)更新权值向量         w(n+1)=w(n)+η[d(n)-y(n)]x(n)

    感知器的学习规则:学习信号等于神经元期望输出与实际输出之差:

    dj为期望的输出,oj为实际的输出。
    W代表特征向量或者是矩阵。T代表矩阵的转置,X为输入信号或者是训练数据集中的一个m维样本


     
    权值调整公式为:
     

    公式右侧前面的符号η为学习率。权值调整值为学习率乘以误差乘以输入信号(X)。
    当实际输出与期望值相同时,权值不需要调整,在有误差存在的情况下,并且期望值与实际输出值为1或者-1,此时权值调整公式可以简化为:

    每一次带入一个数据进行迭代,而不是带入所有数据(为什么呢,感觉带入所有数据进行运算会好很多)其实也能一批数据全部直接带入计算,只不过现在的我还不太懂为什么可以这样。此问题留待日后回答。

    这里

                    

                    0<η<1

    为什么权值更新会是这样呢:我认为可以这样理解,当y与d相同时,分类正确,权值不用更新。

    当y与d不同时 : w(n+1)*x(n)=w(n)*x(n)+η[d(n)-y(n)]x(n)*x(n) 即当d为1而y为-1时,整体的w(n+1)*x(n)增加的,当d为-1而y为1时,整体是往-1的方向变化的,所以w(n+1)权值会使得整体往正确的分类走。但是这个权值更新公式怎么来的就还不知道了。

    (6)判断。若满足收敛条件,则算法结束,若不满足,n++,转到第(3)步。

    收敛条件:当权值向量w已经能正确实现分类时,算法就收敛了,此时网络误差为零。收敛条件通常可以是:

        误差小于某个预先设定的较小的值ε。即

                      |d(n)-y(n)|<ε

        两次迭代之间的权值变化已经很小,即

                      |w(n+1)-w(n)|<ε

    为防止偶然因素导致的提取收敛,前两个条件还可以改进为连续若干次误差或者权值变化小于某个值。

        设定最大迭代次数M,当迭代了M次就停止迭代。

        需事先通过经验设定学习率η,不应该过大,以便为输入向量提供一个比较稳定的权值估计。不应过小,以便使权值能根据输入的向量x实时变化,体现误差对权值的修正作用。

    • 学习率大于零,小于等于1
    • 学习率太大,容易造成权值调整不稳定。
    • 学习率太小,权值调整太慢,迭代次数太多。
    • 学习率一般选择可变的,类似于调节显微镜一样,开始时步长比较大,后面步长比较小。

        它只对线性可分的问题收敛,通过学习调整权值,最终找到合适的决策面,实现正确分类。

    单层感知器在研究线性不可分的问题中:可以追求尽量正确的分类,定义一个误差准则,在不同的超平面中选择一个最优超平面,,使得误差最小,实现近似分类。

    3.感知器的局限性

    • 感知器的激活函数使用阈值函数,使得输出只能取两个值(-1/1或0/1)
    • 只对线性可分的问题收敛
    • 如果输入样本存在奇异样本,则网络需要花费很长时间。(奇异样本是数值上远远偏离其他样本的数据)
    • 感知器的学习算法只对单层有效,因此无法套用其规则设计多层感知器。
    •  感知器算法的另一个缺陷是,一旦所有样本均被正确分类,它就会停止更新权值,这看起来有些矛盾。直觉告诉我们,具有大间隔的决策面比感知器的决策面具有更好的分类误差。但是诸如“Support Vector Machines”之类的大间隔分类器不在本次讨论范围。

    4.Python实现感知器算法

     这是整个感知器算法的代码

    #! /usr/bin/env python
    # -*- coding:utf-8 -*-
    import numpy as np
    import pandas as pd
    
    
    def sgn(x):     # the sgn function
        if x >= 0:
            return 1
        else:
            return -1
    
    
    class Perception(object):
        """
        This is the Perception of the Neural Newtork.
        """
        def __init__(self, input_data, input_label, learning_rate=0.2, iter_times=500):
            """
    
            :param input_data: is the np.array type and size is [m, n] which m is number of data, n is the length of a input
            :param input_label: is the np.array type and size is [1, m] which m is number of data
            :param learning_rate:
            :param iter_times:
            """
            self.datas = np.ones((input_data.shape[0], input_data.shape[1] + 1))
            self.datas[:, 1:] = input_data
            self.label = input_label
            self.weights = (np.random.random(size=self.datas.shape[1]) - 0.5) * 2    # make the weights in [-1, 1]
            self.learning_rate = learning_rate
            self.iter_times = iter_times
            for i in range(self.iter_times):
                for j in range(self.datas.shape[0]):
                    y = sgn(np.dot(self.datas[j], self.weights.T))
                    new_w = self.weights + learning_rate * (self.label[j] - y) * self.datas[j]
                    self.weights = new_w
                if sum(abs(self.label - [sgn(x) for x in np.dot(self.datas, self.weights)])) <= 0.0001:    # if |y(n) - d(n)| <=0.00001, break
                    print("The perception is work well!")
                    break
            print("The real data output: ", self.label)
            print("Perception output is :", np.array([sgn(x) for x in np.dot(self.datas, self.weights.T)]))

    用感知器算法实际处理一些数据

    #! /usr/bin/env python
    # -*- coding:utf-8 -*-
    import numpy as np
    import pandas as pd
    
    
    def sgn(x):     # the sgn function
        if x >= 0:
            return 1
        else:
            return -1
    
    
    class Perception(object):
        """
        This is the Perception of the Neural Newtork.
        I implement the algorithm by myself.
        """
        def __init__(self, input_data, input_label, learning_rate=0.2, iter_times=500):
            """
    
            :param input_data: is the np.array type and size is [m, n] which m is number of data, n is the length of a input
            :param input_label: is the np.array type and size is [1, m] which m is number of data
            :param learning_rate:
            :param iter_times:
            """
            self.datas = np.ones((input_data.shape[0], input_data.shape[1] + 1))
            self.datas[:, 1:] = input_data
            self.label = input_label
            self.weights = (np.random.random(size=self.datas.shape[1]) - 0.5) * 2    # make the weights in [-1, 1]
            self.learning_rate = learning_rate
            self.iter_times = iter_times
            for i in range(self.iter_times):
                for j in range(self.datas.shape[0]):
                    y = sgn(np.dot(self.datas[j], self.weights.T))
                    new_w = self.weights + learning_rate * (self.label[j] - y) * self.datas[j]
                    self.weights = new_w
                if sum(abs(self.label - [sgn(x) for x in np.dot(self.datas, self.weights)])) <= 0.0001:    # if |y(n) - d(n)| <=0.00001, break
                    print("The perception is work well!")
                    break
            print("The real data output: ", self.label)
            print("Perception output is :", np.array([sgn(x) for x in np.dot(self.datas, self.weights.T)]))
    
    
    def main():
        df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)
    
        y = df.iloc[0:100, 4].values
        y = np.where(y == 'Iris-setosa', -1, 1)
        X = df.iloc[0:100, [0, 2]].values
        Perception(X, y)
    
    
    if __name__ == '__main__':
        main()

    代码还有许多不完善的第一,以后还会一直改进。

  • 相关阅读:
    ZOJ 3765 Lights (zju March I)伸展树Splay
    UVA 11922 伸展树Splay 第一题
    UVALive 4794 Sharing Chocolate DP
    ZOJ 3757 Alice and Bod 模拟
    UVALive 3983 捡垃圾的机器人 DP
    UVA 10891 SUM游戏 DP
    poj 1328 Radar Installatio【贪心】
    poj 3264 Balanced Lineup【RMQ-ST查询区间最大最小值之差 +模板应用】
    【转】RMQ-ST算法详解
    poj 3083 Children of the Candy Corn 【条件约束dfs搜索 + bfs搜索】【复习搜索题目一定要看这道题目】
  • 原文地址:https://www.cnblogs.com/pythonlearing/p/9947051.html
Copyright © 2011-2022 走看看