精华内容
下载资源
问答
  • 多层感知机

    千次阅读 2016-01-14 20:07:42
    1、单输出多层感知机 在单层感知机的基础上增加若干个(本文增加一个)隐层,得到多层感知机(Multi Perceptron Machine,MLP)。结构如图所示: (单输出多层感知机) 图中各变量满足公式:

    1、单输出多层感知机

    在单层感知机的基础上增加若干个(本文增加一个)隐层,得到多层感知机(Multi Perceptron Machine,MLP)。结构如图所示:

    (单输出多层感知机)


    图中各变量满足公式:



      


    假如现在有一个样本[(x1x2),T],用该样本训练网络时,网络优化的目标为lossFun最小。lossFun是一个关于变量w和v多元函数。网络的训练又变成多元函数求极值的问题。

    v1的梯度:

      

    同理可得vi的梯度:


    w11的梯度:

     

    同理,可得wij的梯度:


    通过上述方法算得单输出多层感知机的各连接权重w和v的梯度,只要按照w和v的梯度下降方向更新网络就能完成网络训练。


    2、多输出多层感知机

    在前面介绍的神经网络输出节点都是一个,如果遇到多分类问题,我们便需要多输出的神经网络。下图为一个多输出多层感知机。


                                                                                                              (多输出多层感知机)

    在上图的网络中,各变量满足公式:

     

    通过数学求导,得到lossFun对vjk的梯度:



    求导得到lossFun对wij的梯度:

    在求出权重梯度之后,只要按照梯度下降的方向更新连接权重就可以完成网络的训练。

    我们总结出:对于末层神经元,输出错误定义为:

     

    对于非末层神经元,输出错误如Err(y)由与其相连的后层神经元的输入错误Err(Z)加权求和得到,如下公式所示:



    一个神经元的输入错误Err(Y)与输出错误Err(y)满足公式:


      

    一条连接权重的更新量为该条连接前层神经元的输出乘以后层神经元的输入错误信号,如下公式所示。

      

    展开全文
  • MLP多层感知机(人工神经网络)原理及代码实现

    万次阅读 多人点赞 2018-07-05 11:23:19
    一、多层感知机(MLP)原理简介多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如...

    一、多层感知机(MLP)原理简介

    多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图:



    从上图可以看到,多层感知机层与层之间是全连接的(全连接的意思就是:上一层的任何一个神经元与下一层的所有神经元都有连接)。多层感知机最底层是输入层,中间是隐藏层,最后是输出层。


    输入层没什么好说,你输入什么就是什么,比如输入是一个n维向量,就有n个神经元。

    隐藏层的神经元怎么得来?首先它与输入层是全连接的,假设输入层用向量X表示,则隐藏层的输出就是

    f(W1X+b1),W1是权重(也叫连接系数),b1是偏置,函数f 可以是常用的sigmoid函数或者tanh函数:


           


    最后就是输出层,输出层与隐藏层是什么关系?其实隐藏层到输出层可以看成是一个多类别的逻辑回归,也即softmax回归,所以输出层的输出就是softmax(W2X1+b2),X1表示隐藏层的输出f(W1X+b1)


    MLP整个模型就是这样子的,上面说的这个三层的MLP用公式总结起来就是,函数G是softmax



    因此,MLP所有的参数就是各个层之间的连接权重以及偏置,包括W1、b1、W2、b2。对于一个具体的问题,怎么确定这些参数?求解最佳的参数是一个最优化问题,解决最优化问题,最简单的就是梯度下降法了(SGD):首先随机初始化所有参数,然后迭代地训练,不断地计算梯度和更新参数,直到满足某个条件为止(比如误差足够小、迭代次数足够多时)。这个过程涉及到代价函数、规则化(Regularization)、学习速率(learning rate)、梯度计算等,本文不详细讨论,读者可以参考本文顶部给出的两个链接。


    了解了MLP的基本模型,下面进入代码实现部分。



    二、多层感知机(MLP)代码详细解读(基于python+theano)


    再次说明,代码来自:Multilayer Perceptron,本文只是做一个详细解读,如有错误,请不吝指出。

    这个代码实现的是一个三层的感知机,但是理解了代码之后,实现n层感知机都不是问题,所以只需理解好这个三层的MLP模型即可。概括地说,MLP的输入层X其实就是我们的训练数据,所以输入层不用实现,剩下的就是“输入层到隐含层”,“隐含层到输出层”这两部分。上面介绍原理时已经说到了,“输入层到隐含层”就是一个全连接的层,在下面的代码中我们把这一部分定义为HiddenLayer。“隐含层到输出层”就是一个分类器softmax回归(也有人叫逻辑回归),在下面的代码中我们把这一部分定义为LogisticRegression。

    代码详解开始:

    (1)导入必要的python模块

    主要是numpy、theano,以及python自带的os、sys、time模块,这些模块的使用在下面的程序中会看到。

    import os
    import sys
    import time
     
    import numpy
     
    import theano
    import theano.tensor as T

    (2)定义MLP模型(HiddenLayer+LogisticRegression)

    这一部分定义MLP的基本“构件”,即上文一直在提的HiddenLayer和LogisticRegression

    • HiddenLayer
    隐含层我们需要定义连接系数W、偏置b,输入、输出,具体的代码以及解读如下:

    class HiddenLayer(object):
        def __init__(self, rng, input, n_in, n_out, W=None, b=None,
                     activation=T.tanh):
            """
    注释:
    这是定义隐藏层的类,首先明确:隐藏层的输入即input,输出即隐藏层的神经元个数。输入层与隐藏层是全连接的。
    假设输入是n_in维的向量(也可以说时n_in个神经元),隐藏层有n_out个神经元,则因为是全连接,
    一共有n_in*n_out个权重,故W大小时(n_in,n_out),n_in行n_out列,每一列对应隐藏层的每一个神经元的连接权重。
    b是偏置,隐藏层有n_out个神经元,故b时n_out维向量。
    rng即随机数生成器,numpy.random.RandomState,用于初始化W。
    input训练模型所用到的所有输入,并不是MLP的输入层,MLP的输入层的神经元个数时n_in,而这里的参数input大小是(n_example,n_in),每一行一个样本,即每一行作为MLP的输入层。
    activation:激活函数,这里定义为函数tanh
            """
            
            self.input = input   #类HiddenLayer的input即所传递进来的input
     
    """
    注释:
    代码要兼容GPU,则W、b必须使用 dtype=theano.config.floatX,并且定义为theano.shared
    另外,W的初始化有个规则:如果使用tanh函数,则在-sqrt(6./(n_in+n_hidden))到sqrt(6./(n_in+n_hidden))之间均匀
    抽取数值来初始化W,若时sigmoid函数,则以上再乘4倍。
    """
    #如果W未初始化,则根据上述方法初始化。
    #加入这个判断的原因是:有时候我们可以用训练好的参数来初始化W,见我的上一篇文章。
            if W is None:
                W_values = numpy.asarray(
                    rng.uniform(
                        low=-numpy.sqrt(6. / (n_in + n_out)),
                        high=numpy.sqrt(6. / (n_in + n_out)),
                        size=(n_in, n_out)
                    ),
                    dtype=theano.config.floatX
                )
                if activation == theano.tensor.nnet.sigmoid:
                    W_values *= 4
                W = theano.shared(value=W_values, name='W', borrow=True)
     
            if b is None:
                b_values = numpy.zeros((n_out,), dtype=theano.config.floatX)
                b = theano.shared(value=b_values, name='b', borrow=True)
     
    #用上面定义的W、b来初始化类HiddenLayer的W、b
            self.W = W
            self.b = b
     
    #隐含层的输出
            lin_output = T.dot(input, self.W) + self.b
            self.output = (
                lin_output if activation is None
                else activation(lin_output)
            )
     
    #隐含层的参数
            self.params = [self.W, self.b]
    • LogisticRegression

    逻辑回归(softmax回归),代码详解如下。

    (如果你想详细了解softmax回归,可以参考: DeepLearning tutorial(1)Softmax回归原理简介+代码详解

    """
    定义分类层,Softmax回归
    在deeplearning tutorial中,直接将LogisticRegression视为Softmax,
    而我们所认识的二类别的逻辑回归就是当n_out=2时的LogisticRegression
    """
    #参数说明:
    #input,大小就是(n_example,n_in),其中n_example是一个batch的大小,
    #因为我们训练时用的是Minibatch SGD,因此input这样定义
    #n_in,即上一层(隐含层)的输出
    #n_out,输出的类别数 
    class LogisticRegression(object):
        def __init__(self, input, n_in, n_out):
     
    #W大小是n_in行n_out列,b为n_out维向量。即:每个输出对应W的一列以及b的一个元素。  
            self.W = theano.shared(
                value=numpy.zeros(
                    (n_in, n_out),
                    dtype=theano.config.floatX
                ),
                name='W',
                borrow=True
            )
     
            self.b = theano.shared(
                value=numpy.zeros(
                    (n_out,),
                    dtype=theano.config.floatX
                ),
                name='b',
                borrow=True
            )
     
    #input是(n_example,n_in),W是(n_in,n_out),点乘得到(n_example,n_out),加上偏置b,
    #再作为T.nnet.softmax的输入,得到p_y_given_x
    #故p_y_given_x每一行代表每一个样本被估计为各类别的概率    
    #PS:b是n_out维向量,与(n_example,n_out)矩阵相加,内部其实是先复制n_example个b,
    #然后(n_example,n_out)矩阵的每一行都加b
            self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
     
    #argmax返回最大值下标,因为本例数据集是MNIST,下标刚好就是类别。axis=1表示按行操作。
            self.y_pred = T.argmax(self.p_y_given_x, axis=1)
     
    #params,LogisticRegression的参数     
            self.params = [self.W, self.b]

    ok!这两个基本“构件”做好了,现在我们可以将它们“组装”在一起。

    我们要三层的MLP,则只需要HiddenLayer+LogisticRegression,

    如果要四层的MLP,则为HiddenLayer+HiddenLayer+LogisticRegression........以此类推。

    下面是三层的MLP:

    #3层的MLP
    class MLP(object):
        def __init__(self, rng, input, n_in, n_hidden, n_out):
            
            self.hiddenLayer = HiddenLayer(
                rng=rng,
                input=input,
                n_in=n_in,
                n_out=n_hidden,
                activation=T.tanh
            )
     
    #将隐含层hiddenLayer的输出作为分类层logRegressionLayer的输入,这样就把它们连接了
            self.logRegressionLayer = LogisticRegression(
                input=self.hiddenLayer.output,
                n_in=n_hidden,
                n_out=n_out
            )
     
     
    #以上已经定义好MLP的基本结构,下面是MLP模型的其他参数或者函数
     
    #规则化项:常见的L1、L2_sqr
            self.L1 = (
                abs(self.hiddenLayer.W).sum()
                + abs(self.logRegressionLayer.W).sum()
            )
     
            self.L2_sqr = (
                (self.hiddenLayer.W ** 2).sum()
                + (self.logRegressionLayer.W ** 2).sum()
            )
     
     
    #损失函数Nll(也叫代价函数)
            self.negative_log_likelihood = (
                self.logRegressionLayer.negative_log_likelihood
            )
     
    #误差      
            self.errors = self.logRegressionLayer.errors
     
    #MLP的参数
            self.params = self.hiddenLayer.params + self.logRegressionLayer.params
            # end-snippet-3

    MLP类里面除了隐含层和分类层,还定义了损失函数、规则化项,这是在求解优化算法时用到的。


    (3)将MLP应用于MNIST(手写数字识别)

    上面定义好了一个三层的MLP,接下来使用它在MNIST数据集上分类,MNIST是一个手写数字0~9的数据集。

    首先定义加载数据 mnist.pkl.gz 的函数load_data():

    """
    加载MNIST数据集
    """
    def load_data(dataset):
        # dataset是数据集的路径,程序首先检测该路径下有没有MNIST数据集,没有的话就下载MNIST数据集
        #这一部分就不解释了,与softmax回归算法无关。
        data_dir, data_file = os.path.split(dataset)
        if data_dir == "" and not os.path.isfile(dataset):
            # Check if dataset is in the data directory.
            new_path = os.path.join(
                os.path.split(__file__)[0],
                "..",
                "data",
                dataset
            )
            if os.path.isfile(new_path) or data_file == 'mnist.pkl.gz':
                dataset = new_path
     
        if (not os.path.isfile(dataset)) and data_file == 'mnist.pkl.gz':
            import urllib
            origin = (
                'http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz'
            )
            print 'Downloading data from %s' % origin
            urllib.urlretrieve(origin, dataset)
     
        print '... loading data'
    #以上是检测并下载数据集mnist.pkl.gz,不是本文重点。下面才是load_data的开始
        
    #从"mnist.pkl.gz"里加载train_set, valid_set, test_set,它们都是包括label的
    #主要用到python里的gzip.open()函数,以及 cPickle.load()。
    #‘rb’表示以二进制可读的方式打开文件
        f = gzip.open(dataset, 'rb')
        train_set, valid_set, test_set = cPickle.load(f)
        f.close()
       
     
    #将数据设置成shared variables,主要时为了GPU加速,只有shared variables才能存到GPU memory中
    #GPU里数据类型只能是float。而data_y是类别,所以最后又转换为int返回
        def shared_dataset(data_xy, borrow=True):
            data_x, data_y = data_xy
            shared_x = theano.shared(numpy.asarray(data_x,
                                                   dtype=theano.config.floatX),
                                     borrow=borrow)
            shared_y = theano.shared(numpy.asarray(data_y,
                                                   dtype=theano.config.floatX),
                                     borrow=borrow)
            return shared_x, T.cast(shared_y, 'int32')
     
     
        test_set_x, test_set_y = shared_dataset(test_set)
        valid_set_x, valid_set_y = shared_dataset(valid_set)
        train_set_x, train_set_y = shared_dataset(train_set)
     
        rval = [(train_set_x, train_set_y), (valid_set_x, valid_set_y),
                (test_set_x, test_set_y)]
        return rval
    加载了数据,可以开始训练这个模型了,以下就是主体函数test_mlp(),将MLP用在MNIST上:

    #test_mlp是一个应用实例,用梯度下降来优化MLP,针对MNIST数据集
    def test_mlp(learning_rate=0.01, L1_reg=0.00, L2_reg=0.0001, n_epochs=10,
                 dataset='mnist.pkl.gz', batch_size=20, n_hidden=500):
        """
    注释:
    learning_rate学习速率,梯度前的系数。
    L1_reg、L2_reg:正则化项前的系数,权衡正则化项与Nll项的比重
    代价函数=Nll+L1_reg*L1或者L2_reg*L2_sqr
    n_epochs:迭代的最大次数(即训练步数),用于结束优化过程
    dataset:训练数据的路径
    n_hidden:隐藏层神经元个数
    batch_size=20,即每训练完20个样本才计算梯度并更新参数
       """
     
    #加载数据集,并分为训练集、验证集、测试集。
        datasets = load_data(dataset)
        train_set_x, train_set_y = datasets[0]
        valid_set_x, valid_set_y = datasets[1]
        test_set_x, test_set_y = datasets[2]
     
     
    #shape[0]获得行数,一行代表一个样本,故获取的是样本数,除以batch_size可以得到有多少个batch
        n_train_batches = train_set_x.get_value(borrow=True).shape[0] / batch_size
        n_valid_batches = valid_set_x.get_value(borrow=True).shape[0] / batch_size
        n_test_batches = test_set_x.get_value(borrow=True).shape[0] / batch_size
     
        ######################
        # BUILD ACTUAL MODEL #
        ######################
        print '... building the model'
     
    #index表示batch的下标,标量
    #x表示数据集
    #y表示类别,一维向量
        index = T.lscalar()  
        x = T.matrix('x') 
        y = T.ivector('y')  
                           
     
        rng = numpy.random.RandomState(1234)
    #生成一个MLP,命名为classifier
        classifier = MLP(
            rng=rng,
            input=x,
            n_in=28 * 28,
            n_hidden=n_hidden,
            n_out=10
        )
     
    #代价函数,有规则化项
    #用y来初始化,而其实还有一个隐含的参数x在classifier中
        cost = (
            classifier.negative_log_likelihood(y)
            + L1_reg * classifier.L1
            + L2_reg * classifier.L2_sqr
        )
     
     
    #这里必须说明一下theano的function函数,givens是字典,其中的x、y是key,冒号后面是它们的value。
    #在function被调用时,x、y将被具体地替换为它们的value,而value里的参数index就是inputs=[index]这里给出。
    #下面举个例子:
    #比如test_model(1),首先根据index=1具体化x为test_set_x[1 * batch_size: (1 + 1) * batch_size],
    #具体化y为test_set_y[1 * batch_size: (1 + 1) * batch_size]。然后函数计算outputs=classifier.errors(y),
    #这里面有参数y和隐含的x,所以就将givens里面具体化的x、y传递进去。
        test_model = theano.function(
            inputs=[index],
            outputs=classifier.errors(y),
            givens={
                x: test_set_x[index * batch_size:(index + 1) * batch_size],
                y: test_set_y[index * batch_size:(index + 1) * batch_size]
            }
        )
     
        validate_model = theano.function(
            inputs=[index],
            outputs=classifier.errors(y),
            givens={
                x: valid_set_x[index * batch_size:(index + 1) * batch_size],
                y: valid_set_y[index * batch_size:(index + 1) * batch_size]
            }
        )
     
    #cost函数对各个参数的偏导数值,即梯度,存于gparams
        gparams = [T.grad(cost, param) for param in classifier.params]
        
    #参数更新规则
    #updates[(),(),()....],每个括号里面都是(param, param - learning_rate * gparam),即每个参数以及它的更新公式
        updates = [
            (param, param - learning_rate * gparam)
            for param, gparam in zip(classifier.params, gparams)
        ]
     
        train_model = theano.function(
            inputs=[index],
            outputs=cost,
            updates=updates,
            givens={
                x: train_set_x[index * batch_size: (index + 1) * batch_size],
                y: train_set_y[index * batch_size: (index + 1) * batch_size]
            }
        )
     
     
        ###############
        # 开始训练模型 #
        ###############
        print '... training'
        
     
     
        patience = 10000  
        patience_increase = 2  
    #提高的阈值,在验证误差减小到之前的0.995倍时,会更新best_validation_loss  
        improvement_threshold = 0.995  
    #这样设置validation_frequency可以保证每一次epoch都会在验证集上测试。  
        validation_frequency = min(n_train_batches, patience / 2)
      
     
        best_validation_loss = numpy.inf
        best_iter = 0
        test_score = 0.
        start_time = time.clock()
        
    #epoch即训练步数,每个epoch都会遍历所有训练数据
        epoch = 0
        done_looping = False
     
     
    #下面就是训练过程了,while循环控制的时步数epoch,一个epoch会遍历所有的batch,即所有的图片。
    #for循环是遍历一个个batch,一次一个batch地训练。for循环体里会用train_model(minibatch_index)去训练模型,
    #train_model里面的updatas会更新各个参数。
    #for循环里面会累加训练过的batch数iter,当iter是validation_frequency倍数时则会在验证集上测试,
    #如果验证集的损失this_validation_loss小于之前最佳的损失best_validation_loss,
    #则更新best_validation_loss和best_iter,同时在testset上测试。
    #如果验证集的损失this_validation_loss小于best_validation_loss*improvement_threshold时则更新patience。
    #当达到最大步数n_epoch时,或者patience<iter时,结束训练
        while (epoch < n_epochs) and (not done_looping):
            epoch = epoch + 1
            for minibatch_index in xrange(n_train_batches):#训练时一个batch一个batch进行的
     
                minibatch_avg_cost = train_model(minibatch_index)
                # 已训练过的minibatch数,即迭代次数iter
                iter = (epoch - 1) * n_train_batches + minibatch_index
    #训练过的minibatch数是validation_frequency倍数,则进行交叉验证
                if (iter + 1) % validation_frequency == 0:
                    # compute zero-one loss on validation set
                    validation_losses = [validate_model(i) for i
                                         in xrange(n_valid_batches)]
                    this_validation_loss = numpy.mean(validation_losses)
     
                    print(
                        'epoch %i, minibatch %i/%i, validation error %f %%' %
                        (
                            epoch,
                            minibatch_index + 1,
                            n_train_batches,
                            this_validation_loss * 100.
                        )
                    )
    #当前验证误差比之前的都小,则更新best_validation_loss,以及对应的best_iter,并且在tsetdata上进行test
                    if this_validation_loss < best_validation_loss:
                        if (
                            this_validation_loss < best_validation_loss *
                            improvement_threshold
                        ):
                            patience = max(patience, iter * patience_increase)
     
                        best_validation_loss = this_validation_loss
                        best_iter = iter
     
                        test_losses = [test_model(i) for i
                                       in xrange(n_test_batches)]
                        test_score = numpy.mean(test_losses)
     
                        print(('     epoch %i, minibatch %i/%i, test error of '
                               'best model %f %%') %
                              (epoch, minibatch_index + 1, n_train_batches,
                               test_score * 100.))
    #patience小于等于iter,则终止训练
                if patience <= iter:
                    done_looping = True
                    break
     
        end_time = time.clock()
        print(('Optimization complete. Best validation score of %f %% '
               'obtained at iteration %i, with test performance %f %%') %
              (best_validation_loss * 100., best_iter + 1, test_score * 100.))
        print >> sys.stderr, ('The code for file ' +
                              os.path.split(__file__)[1] +
                              ' ran for %.2fm' % ((end_time - start_time) / 60.))

    个人理解:

          单个感知器本身是希望通过一个切面或者切线来把数据集分开,这是线性可分的,针对线性不可分或者说非线性问题,它无法解决,可以用多层感知器实现非线性的切分,这就是MLP,如下公式,当然这只是两层的,我们可以继续接很多层。

                                            

          从公式可以看出,MLP多层感知器其实就是一个普通的人工神经网络,人工神经网络中全连接,其实就是一种线性的组合关系,而多层感知器其实就是多个全连接层的组合而已。

    参考文章:

    原理参考:https://blog.csdn.net/liuyukuan/article/details/72934383

    文章原文:https://blog.csdn.net/u012162613/article/details/43221829




    展开全文
  • 多层感知机理解

    2021-04-26 10:26:54
    好在我对神经网络的了解是从卷积神经网络开始的,对基本的原理和模型已经有了了解,所以学习起来相对容易,先看多层感知机的模型: 1.网络的连接及输出: 1.最左边就是我们的输入层了,算是网络的第0层,通常是一...

    一.网络的原理和结构

    多层感知器(Muti-Layer Percetron)和卷积网络(Convolutional Neural Network)。这两种网络都属于前馈型网络(Feedforward network),其中多层感知器(MLP)是最简单也是最常见的一种神经网络结构,它是所有其他神经网络结构的基础,

    好在我对神经网络的了解是从卷积神经网络开始的,对基本的原理和模型已经有了了解,所以学习起来相对容易,先看多层感知机的模型:
    在这里插入图片描述
    如何设计一个网络,输入代表像素的值,输出0-9之间的一个正确的数字
    在这里插入图片描述
    在这里插入图片描述
    先把神经元当做数字
    在这里插入图片描述
    在这里插入图片描述
    每个神经元里面是我们要提取的特征值,即像素的灰度值,0表示纯黑,1 表示纯白
    在这里插入图片描述

    这784个神经元组成了第一层,即神经网络的输入层

    网络的最后一层是输出层,输出的是可能的概率,哪个概率最大,就代表识别的结果是哪个数字
    在这里插入图片描述

    网络的中间是隐藏层,包含这一些算法
    在这里插入图片描述
    比如网络的第三层,我们已经提取到局部的特征,只需要考虑将局部特征组合起来有多少 可能组成某一个数字
    在这里插入图片描述

    在这里插入图片描述
    那再往前推,前面的一层网络就要能提取出更小的局部特征,把他们组合起来
    在这里插入图片描述
    通过权重值w,来提取我们关注的区域的值
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这个加权和,再通过激活函数映射到[0,1]的区间

    在这里插入图片描述
    而通过偏置值,控制加权和不过早的激发

    在这里插入图片描述
    将加权和减去一个数,不让不必要的神经元激活,
    在这里插入图片描述
    权重代表我们关注什么样的图案,而偏置值代表加权和有多大激活神经元才有意义

    在网络的第二层,每一个神经元都和上一层的784个神经元保持全连接
    在这里插入图片描述

    每个神经元都带一个权重和偏置值
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    用向量表示
    在这里插入图片描述
    所以,网络中每一个神经元更像一个函数,接收输入,输出0-1的值
    在这里插入图片描述

    进而整个网络也可以看成一个函数,接收输入,输出一个结果
    在这里插入图片描述

    在这里插入图片描述

    二.网络如何学习

    在网络训练的时候,我们需要定义一个代价函数,来告诉网络与正确值的差距在这里插入图片描述
    定义正确值1,其他为0,将网络输出的结果与实际结果相减,再将他们差的平方加起来,得到一个损失值
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    代价函数输出单个数值,来评价整个网络中的权重和偏置值与正确结果的差距
    在这里插入图片描述
    网络需要知道如何调整这些输入参数使输出接近正确的结果

    以二维图像为例

    随便 选一个输入值,然后考虑向左还是向右
    在这里插入图片描述

    计算斜率,斜率为正,表示函数是上升,那么我们梯度的反方向即向左

    斜率为负,表示梯度是下降的,我们继续往右找到最低点
    在这里插入图片描述

    在每一点这样重复的计算斜率,直到找到局部最低点
    在这里插入图片描述
    在这里插入图片描述
    在三维空间如何计算
    在这里插入图片描述
    同样也是计算梯度,沿梯度的反方向下降一小步

    在这里插入图片描述

    梯度如何计算:

    梯度,就是封装了所有偏导的向量
    在这里插入图片描述

    在这里插入图片描述

    这样我们就有了一个权重向量和一个反向梯度向量

    在这里插入图片描述
    将两个向量的对应的每一项相加,得到新的权重,再更新权重,如此循环
    在这里插入图片描述
    同时,代价值的绝对值表示每个w和B的重要程度
    在这里插入图片描述
    假如有一个函数的在点[1,1]的梯度向量是[31]\begin{bmatrix} 3\\1\\ \end{bmatrix}
    在这里插入图片描述
    在这里插入图片描述
    也可以理解为改变x对函数影响更大

    在这里插入图片描述

    这样来看,网络的代价函数是把权重和偏置作为输入

    在这里插入图片描述

    三.反向传播法

    通过代价函数我们得到了误差值

    然后需要把所有样本的误差值平均值

    在这里插入图片描述

    我们求出的负梯度,同时反映了代价函数值的重要程度,
    在这里插入图片描述
    比如样本2,网络输出的值与正确的值差距较大,如何增大这个输出呢

    如何让这个结果变大

    我们知道这个结果是上一层的输出+权重+偏置再通过激活函数得到的

    那么有三个方法

    *增大上一层的输出

    *增加权重

    *增加偏置值

    在这里插入图片描述
    如何增加权重

    比较亮的神经元,对应的权重对结果影响相对更大,所以增加相对亮的神经元,训练的效率会更高
    在这里插入图片描述
    所以当反向传播的时候,不仅要看高边哪些权重,还要看改变那些权重性价比高
    在这里插入图片描述
    如何改变上一层的输出

    和更改权重一样,如果我们需要结果更大的时候,依据权重的大小,对上一层的结果做出呈比例的改变
    在这里插入图片描述
    结果2期待上一层的值如何改变,比如增大

    结果3期待上一层的值如何改变,比如减小

    我们把这些期待全部加起来,作为如何改变上一层的值的指示

    如此往复循环,达到训练的效果

    这就是反向传播的理念
    在这里插入图片描述

    展开全文
  • 多层感知机(MLP)简介

    万次阅读 多人点赞 2019-06-23 21:36:59
    多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图: ...

    一、多层感知机(MLP)原理简介

                 多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图:

                                           

     

               从上图可以看到,多层感知机层与层之间是全连接的。多层感知机最底层是输入层,中间是隐藏层,最后是输出层。 

    隐藏层的神经元怎么得来?首先它与输入层是全连接的,假设输入层用向量X表示,则隐藏层的输出就是 f (W1X+b1),W1是权重(也叫连接系数),b1是偏置,函数f 可以是常用的sigmoid函数或者tanh函数:

     注:神经网络中的Sigmoid型激活函数:

           1.  为嘛使用激活函数?

                a. 不使用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合。

                b. 使用激活函数,能够给神经元引入非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以利用到更多的非线性模型中。

     激活函数需要具备以下几点性质:

                1. 连续并可导(允许少数点上不可导)的非线性函数。可导的激活函数可以直接利用数值优化的方法来学习网络参                    数。
                2. 激活函数及其导函数要尽可能的简单,有利于提高网络计算效率。
               3. 激活函数的导函数的值域要在一个合适的区间内,不能太大也不能太小,否则会影响训练的效率和稳定性。 

          2. sigmod 函数

                                                    

                        

    导数为:

                                

                     

      3 . Tanh 函数

                                                         

                                                    

                

    取值范围为[-1,1]

    tanh在特征相差明显时的效果会很好,在循环过程中会不断扩大特征效果。

    与sigmod的区别是 tanh 是0 的均值,因此在实际应用中tanh会比sigmod更好。

    在具体应用中,tanh函数相比于Sigmoid函数往往更具有优越性,这主要是因为Sigmoid函数在输入处于[-1,1]之间时,函数值变 化敏感,一旦接近或者超出区间就失去敏感性,处于饱和状态。

     

           最后就是输出层,输出层与隐藏层是什么关系?

          其实隐藏层到输出层可以看成是一个多类别的逻辑回归,也即softmax回归,所以输出层的输出就是softmax(W2X1+b2),X1表示隐藏层的输出f(W1X+b1)。

           MLP整个模型就是这样子的,上面说的这个三层的MLP用公式总结起来就是,函数G是softmax。

            因此,MLP所有的参数就是各个层之间的连接权重以及偏置,包括W1、b1、W2、b2。对于一个具体的问题,怎么确定这些参数?求解最佳的参数是一个最优化问题,解决最优化问题,最简单的就是梯度下降法了(SGD):首先随机初始化所有参数,然后迭代地训练,不断地计算梯度和更新参数,直到满足某个条件为止(比如误差足够小、迭代次数足够多时)。这个过程涉及到代价函数、规则化(Regularization)、学习速率(learning rate)、梯度计算等,本文不详细讨论,读者可以参考本文底部给出的两个链接。

    了解了MLP的基本模型,下面进入代码实现部分。

    二、多层感知机(MLP)代码详细解读(基于python+theano)

            代码来自:Multilayer Perceptron,本文只是做一个详细解读,如有错误,请不吝指出。

           这个代码实现的是一个三层的感知机,但是理解了代码之后,实现n层感知机都不是问题,所以只需理解好这个三层的MLP模型即可。概括地说,MLP的输入层X其实就是我们的训练数据,所以输入层不用实现,剩下的就是“输入层到隐含层”,“隐含层到输出层”这两部分。上面介绍原理时已经说到了,“输入层到隐含层”就是一个全连接的层,在下面的代码中我们把这一部分定义为HiddenLayer。“隐含层到输出层”就是一个分类器softmax回归,在下面的代码中我们把这一部分定义为logisticRegression。

    代码详解开始:

    (1)导入必要的python模块
    主要是numpy、theano,以及python自带的os、sys、time模块,这些模块的使用在下面的程序中会看到。

    import os
    import sysimport time
     
    import numpy
     
    import theano
    import theano.tensor as T
    
    

    (2)定义MLP模型(HiddenLayer+LogisticRegression)
    这一部分定义MLP的基本“构件”,即上文一直在提的HiddenLayer和LogisticRegression

    HiddenLayer
    隐含层我们需要定义连接系数W、偏置b,输入、输出,具体的代码以及解读如下:
     

    class HiddenLayer(object):
        def __init__(self, rng, input, n_in, n_out, W=None, b=None,
                     activation=T.tanh):
            """
    注释:
    这是定义隐藏层的类,首先明确:隐藏层的输入即input,输出即隐藏层的神经元个数。输入层与隐藏层是全连接的。
    假设输入是n_in维的向量(也可以说时n_in个神经元),隐藏层有n_out个神经元,则因为是全连接,
    一共有n_in*n_out个权重,故W大小时(n_in,n_out),n_in行n_out列,每一列对应隐藏层的每一个神经元的连接权重。
    b是偏置,隐藏层有n_out个神经元,故b时n_out维向量。
    rng即随机数生成器,numpy.random.RandomState,用于初始化W。
    input训练模型所用到的所有输入,并不是MLP的输入层,MLP的输入层的神经元个数时n_in,而这里的参数input大小是(n_example,n_in),每一行一个样本,即每一行作为MLP的输入层。
    activation:激活函数,这里定义为函数tanh
            """
            
            self.input = input   #类HiddenLayer的input即所传递进来的input
     
    """
    注释:
    代码要兼容GPU,则W、b必须使用 dtype=theano.config.floatX,并且定义为theano.shared
    另外,W的初始化有个规则:如果使用tanh函数,则在-sqrt(6./(n_in+n_hidden))到sqrt(6./(n_in+n_hidden))之间均匀
    抽取数值来初始化W,若时sigmoid函数,则以上再乘4倍。
    """
    #如果W未初始化,则根据上述方法初始化。
    #加入这个判断的原因是:有时候我们可以用训练好的参数来初始化W
            if W is None:
                W_values = numpy.asarray(
                    rng.uniform(
                        low=-numpy.sqrt(6. / (n_in + n_out)),
                        high=numpy.sqrt(6. / (n_in + n_out)),
                        size=(n_in, n_out)
                    ),
                    dtype=theano.config.floatX
                )
                if activation == theano.tensor.nnet.sigmoid:
                    W_values *= 4
                W = theano.shared(value=W_values, name='W', borrow=True)
     
            if b is None:
                b_values = numpy.zeros((n_out,), dtype=theano.config.floatX)
                b = theano.shared(value=b_values, name='b', borrow=True)
     
    #用上面定义的W、b来初始化类HiddenLayer的W、b
            self.W = W
            self.b = b
     
    #隐含层的输出
            lin_output = T.dot(input, self.W) + self.b
            self.output = (
                lin_output if activation is None
                else activation(lin_output)
            )
     
    #隐含层的参数
            self.params = [self.W, self.b]
    

     LogisticRegression

      逻辑回归(softmax回归),代码详解如下。

    """
    定义分类层,Softmax回归
    在deeplearning tutorial中,直接将LogisticRegression视为Softmax,
    而我们所认识的二类别的逻辑回归就是当n_out=2时的LogisticRegression
    """
    #参数说明:
    #input,大小就是(n_example,n_in),其中n_example是一个batch的大小,
    #因为我们训练时用的是Minibatch SGD,因此input这样定义
    #n_in,即上一层(隐含层)的输出
    #n_out,输出的类别数 
    class LogisticRegression(object):
        def __init__(self, input, n_in, n_out):
     
    #W大小是n_in行n_out列,b为n_out维向量。即:每个输出对应W的一列以及b的一个元素。  
            self.W = theano.shared(
                value=numpy.zeros(
                    (n_in, n_out),
                    dtype=theano.config.floatX
                ),
                name='W',
                borrow=True
            )
     
            self.b = theano.shared(
                value=numpy.zeros(
                    (n_out,),
                    dtype=theano.config.floatX
                ),
                name='b',
                borrow=True
            )
     
    #input是(n_example,n_in),W是(n_in,n_out),点乘得到(n_example,n_out),加上偏置b,
    #再作为T.nnet.softmax的输入,得到p_y_given_x
    #故p_y_given_x每一行代表每一个样本被估计为各类别的概率    
    #PS:b是n_out维向量,与(n_example,n_out)矩阵相加,内部其实是先复制n_example个b,
    #然后(n_example,n_out)矩阵的每一行都加b
            self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
     
    #argmax返回最大值下标,因为本例数据集是MNIST,下标刚好就是类别。axis=1表示按行操作。
            self.y_pred = T.argmax(self.p_y_given_x, axis=1)
     
    #params,LogisticRegression的参数     
            self.params = [self.W, self.b]
    

     

    ok!这两个基本“构件”做好了,现在我们可以将它们“组装”在一起。

    我们要三层的MLP,则只需要HiddenLayer+LogisticRegression,

    如果要四层的MLP,则为HiddenLayer+HiddenLayer+LogisticRegression........以此类推。

    下面是三层的MLP:
     

    #3层的MLP
    class MLP(object):
        def __init__(self, rng, input, n_in, n_hidden, n_out):
            
            self.hiddenLayer = HiddenLayer(
                rng=rng,
                input=input,
                n_in=n_in,
                n_out=n_hidden,
                activation=T.tanh
            )
     
    #将隐含层hiddenLayer的输出作为分类层logRegressionLayer的输入,这样就把它们连接了
            self.logRegressionLayer = LogisticRegression(
                input=self.hiddenLayer.output,
                n_in=n_hidden,
                n_out=n_out
            )
     
     
    #以上已经定义好MLP的基本结构,下面是MLP模型的其他参数或者函数
     
    #规则化项:常见的L1、L2_sqr
            self.L1 = (
                abs(self.hiddenLayer.W).sum()
                + abs(self.logRegressionLayer.W).sum()
            )
     
            self.L2_sqr = (
                (self.hiddenLayer.W ** 2).sum()
                + (self.logRegressionLayer.W ** 2).sum()
            )
     
     
    #损失函数Nll(也叫代价函数)
            self.negative_log_likelihood = (
                self.logRegressionLayer.negative_log_likelihood
            )
     
    #误差      
            self.errors = self.logRegressionLayer.errors
     
    #MLP的参数
            self.params = self.hiddenLayer.params + self.logRegressionLayer.params
            # end-snippet-3
    

     MLP类里面除了隐含层和分类层,还定义了损失函数、规则化项,这是在求解优化算法时用到的。

    Ref:

     1.  https://blog.csdn.net/m0_38045485/article/details/81749385

     2. https://blog.csdn.net/u012162613/article/details/43221829

        经详细注释的代码:放在github地址上https://github.com/wepe/MachineLearning/tree/master/DeepLearning Tutorials/mlp

    展开全文
  • 感知机与多层感知机

    千次阅读 2019-01-31 10:02:50
    1.感知机与多层感知机 1.1 门 与门:实现逻辑“乘”运算 y=AB 与门真值表 A B y 0 0 0 0 1 0 1 0 0 1 1 1 非门:实现逻辑非,一对一输出 非门真值表 A y 0 1 1 0 或门:实现逻辑“和”...
  •  多层感知机与之前的Softmax Regression的区别是多了一层隐藏层,但是,本质上还是FCN(全连接神经网络),与卷积神经网络还是有差距的。 下面上代码: from tensorflow.examples.tutorials.mnist import input_...
  • 多层感知机与神经网络学习总结

    千次阅读 2019-07-16 17:32:19
    这篇博客主要总结多层感知机(MLP)的一些知识要点,MLP也就是DNN(深度神经网络),是深度学习的基础。(原创 https://blog.csdn.net/baidu_33718858/article/details/84972537) 主要的参考文献来自于: ...
  • 多层感知机在单层神经网络的基础上引入了一个或多个隐藏层(hidden layer).隐藏层位于输入层和输出层之间。 如下图所示: 上图所示的多层感知机中,输入和输出个数分别为4和3,中间的隐藏层中包含了5个隐藏单元...
  • 多层感知机不等于神经网络

    千次阅读 2019-01-12 20:53:38
    在前一章节(https://blog.csdn.net/u012132349/article/details/86166324),我们介绍了感知机可以实现与门... 今天我们将介绍感知机的局限性(严格说是单层感知机的局限性)。这里我们想用感知机实现异或门,所谓异...
  • 以手写体识别为例子来讲一下基本结构,和实践中的基本使用思想。这是推广到更加复杂任务上的基础。
  • MLP(多层感知器)神经网络https://blog.csdn.net/liuyukuan/article/details/72934383 ...多层感知机MLP,结构为:输入层——(1或n层)隐含层——输出层,层与层之间全连接(全连接的意思就是:上...
  • 前一篇文章中我们提到单层感知机网络被局限在解决传统的是非问题,当面对异或这类问题时则显得无能为力,为了解决这一问题,人们通过增加网络层数来提升神经网络解决问题的能力。这就是我们今天要讲到的多层感知机...
  • 文章目录激活函数绘制激活函数绘制激活函数相应的导数多层感知机网络结构图pytorch简洁实现Softmax知识点1.torchvision的用法2.torch对维度操作 激活函数 目的:增加网络的非线性拟合的能力 绘制激活函数 #定义一个...
  • 全连接网络(FC)、前馈神经网络(BP)、多层感知机(MLP)三种称呼实质是一样的。以全连接网络为例讲解训练过程。 全连接网络实际上可以看作由多个隐藏层(dense)组成的网络模型,隐藏层的每个节点都与上一层所有...
  • 多层感知机:Multi-Layer Perceptron

    万次阅读 多人点赞 2017-11-07 21:33:06
    多层感知机(MLP)由感知机推广而来,最主要的特点是有多个神经元层,因此也叫深度神经网络(DNN: Deep Neural Networks)。
  • 多层感知机MLP

    2019-09-25 13:38:00
    神经网络的构建块是人工神经元。 这些是具有加权输入信号并使用激活功能产生输出信号的简单计算单元。 输出和输入之间学习到一个线性关系,得到中间输出结果: 接着是一个神经元激活函数: 激活函数是输入...
  • 所以才会有多层感知机的出现,它由一个输入层,一个输入层和多个隐藏层组成。神经网络和前面介绍的感知机有很多共同点。这里,我们主要以两者 的差异为中心,来介绍神经网络结构 。 在观察神经网络中信号的传递...
  • 多层感知机模型讲解

    千次阅读 2020-01-13 12:44:16
    具有多层输出的感知机如下图所示: 图中节点上的符号表示的含义是: xk1x^1_kxk1​代表第1层上的第k个节点 Ok1O^1_kOk1​同样代表第1层上的第k个节点 若能求出∇E∇wjk\frac{\nabla E}{\nabla w_{jk}}∇wjk​∇E​...
  • 继上文的集成学习模型之后,本文实践使用的pyspark提供的多层感知机神经网络模型,这是一种比较简单但是却又很重要的神经网络模型。MLP是一种前向结构的人工神经网络,映射一组输入向量到一组输出向量。MLP可以被...
  • 多层感知机(MLP)

    千次阅读 2021-01-26 22:00:00
    1.多层感知机(MLP)是深度神经网络(DNN)的基础算法,有时候提起DNN就是指MLP2.感知机跟SVM优化的目标一致,损失函数不同(前者分母限制为1,后者分子限制为1)3.神经网络由...
  • Tensorflow实战4:多层感知机

    千次阅读 2017-03-30 20:14:01
    多层感知机(Multi-Layer Perceptron, MLP),又叫做多层神经网络。如果使用的是没有隐含层的神经网络,那么这样的神经网络只能解决一些线性可分的问题,但是在实际的生活中,很多问题并不是线性可分的,例如XOR函数...
  • 概念理解 感知机 感知机(perceptron)是二分类的线性分类模型,输入为实例的特征向量,输出为实例的类别(取+1和-1)。感知机对应于输入空间中将实例划分为两类的分离超...多层感知机 多层感知器(Multilayer P...
  • 一、感知机的简介 在前面我们实现了一个softmax regression,也可以说是一个多分类问题的logistic regression。它和传统意义上的神经网络最大的区别就是没有隐藏层。在一个神经网络中,包含输入层、隐含层和输出层...
  • 多层感知机一,多层感知机1.1 现在已有的门电路组合1.2 异或门的实现二,从与非门到计算机三,总结 一,多层感知机   在上一篇深度学习——感知机(perceptron)图文详解中我们已经讨论完了简单感知机的原理和实现...
  • \quad \quad多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图: \quad \...
  • 多层感知机预测两个值 学习深度学习 目前,我在Jason Brownlee的《 Python深度学习》一书的帮助下学习了深度学习基础知识。 它为构建各种类型的深度学习网络(如CNN,RNN等)提供了良好的实践覆盖。运行本书中的每...
  • tensorflow实现多层感知机

    千次阅读 2018-04-09 10:58:48
    它和传统意义上的神经网络的最大区别是没有隐含层。 对于神经网络来说,引入非线性隐含层后,理论上只要隐含节点足够多,即使只有一个隐含层的神经网络也可以拟合任意函数。同时隐含层越多,越容易拟合复杂函数。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,257
精华内容 6,102
关键字:

多层感知机网络结构