精华内容
下载资源
问答
  • 训练过程 改善收敛性   梯度下降具有多种优点。它简单,它是局部的,即权重的改变只是用前后突出单元和误差(适合向后传播)的值。当使用在线训练时,它不需要存储训练集,并且可以自适应学习任务的变化。但是,...

    摘自《机器学习导论》

    训练过程

    改善收敛性

      梯度下降具有多种优点。它简单,它是局部的,即权重的改变只是用前后突出单元和误差(适合向后传播)的值。当使用在线训练时,它不需要存储训练集,并且可以自适应学习任务的变化。但是,就自身而言,梯度下降收敛很慢。当学习时间很重要时,可以使用更复杂的优化方法。有两种频繁使用的优化技术,可以显著改善梯度下降的性能。

    动量

      令 wi w i 为多层感知器任意层中的权重,包括偏倚。在每次参数更新时,连续的 Δwti Δ w i t 可能很不相同以致出现摆动,减缓收敛。t为时间指数,是批量学习的周期数和在线学习的迭代次数。基本想法是在当前的改变中考虑上一次的更新,去移动平均,好像因上次更新而存在的动量(momentum):

    Δwti=ηEtwi+αΔwt1i Δ w i t = − η ∂ E t ∂ w i + α Δ w i t − 1
      通常,a在0.5-1.0之间取值。当时用在线学习时,这种方法特别有用。我们将得到平均和光滑收敛轨迹的效果。缺点是需要额外存储过去的权重。

    自适应学习率

      在梯度下降中,学习因子 η η 决定参数的该变量。它通常在0.0-1.0之间取值,大部分情况小雨或等于0.2。为了更快收敛,可以让它自适应。学习开始时它保持较大,学习减慢时它也减小:

    Δη={+αbη           ifEt+τ<Etelse Δ η = { + α                       i f E t + τ < E t − b η e l s e
    这样,如果训练集上的误差减小,则 η η 增加一个常量;如果误差增大,则 η η 减小。由于E可能从一个周期到另一个周期震荡,所以最好用过去几个周期的平均值作为 Et E t

    过分训练

      随着训练周期的增加,训练机上的误差降低,但是当超过某一点时,验证集上的误差开始增加。
      由于非线性,误差函数可能有多个极小,而梯度下降收敛于最近的极小。为了能够评估期望的误差,通常以不同的初始权重开始。

    构造网络

      在某些应用中,我们可能相信输入具有局部结构。此时,再设计MLP时,并不是将隐层单元连接到所有输入单元,因为并非所有的输入都是相关的。另外,我们定义隐藏单元,它在输入空间上定义一个输入窗口,并且仅与输入的一个小的局部子集相连接。这样做减少了连接数,从而减少了自有参数的数目。
      同时,我们可以通过圈中共享(weight sharing)进一步减少参数的数目。

    线索

    局部结构的只是可以使得我们预先构造多层网络,并且使用权重共享使得他具有较少的参数。具有全连接层的MLP不具有这种结构,并且更难训练。如果将与应用相关的任何类型的知识都用与网络结构的构建中,那么这些知识称作线索(hint)。它们是我们知道的目标函数的性质,独立于训练实例。

    1. 可以使用线索创建虚拟实例。如图像的伸缩变换。
    2. 不变形可以作为预处理阶段实现。例如,光学字符阅读器可以有一个预处理步骤。将输入字符的图像关于尺寸和倾斜进行中心化和规范化。
    3. 线索可以纳入网络结构中。
    4. 也可以通过修改误差函数纳入线索。
    展开全文
  • caffe c++示例(mnist 多层感知机c++训练,测试)

    千次阅读 热门讨论 2018-10-07 15:39:53
    本文给出使用纯c++代码,使用mnist数据+多层感知机网络,训练数字分类问题。然后用C++调用训练好的模型测试分类。 solver.prototxt文件内容如下: net: &amp;quot;/home/xy/caffe_analys...

    caffe训练网络模型一般直接使用的caffe.bin: caffe train -solver solver.prototxt,其实这个命令的本质也是调用c++的Solver.

    本文给出使用纯c++代码,使用mnist数据+多层感知机网络,训练数字分类问题。然后用C++调用训练好的模型测试分类。

    solver.prototxt文件内容如下:

    net: "/home/xy/caffe_analysis/my_caffe/example/lenet.prototxt"
    test_iter: 1000
    test_interval: 100
    base_lr: 0.001
    lr_policy: "step"
    gamma: 0.1
    stepsize: 5000
    display: 1000
    max_iter: 20000
    momentum: 0.9
    weight_decay: 0.0005
    snapshot: 10000
    snapshot_prefix: "model"
    solver_mode: CPU
    

    注:网络名称虽然为lenet.prototxt,实际是多层感知机。

    训练网络如下:

    在这里插入图片描述

    name: "LeNet"
    layer {
      name: "mnist"
      #name: "data"
      type: "Data"
      top: "data"
      top: "label"
      include {
        phase: TRAIN
      }
      transform_param {
        scale: 0.00390625
      }
      data_param {
        source: "/home/xy/caffe-master/examples/mnist/mnist_train_lmdb"
        batch_size: 64
        backend: LMDB
      }
    }
    
    layer {
      name: "mnist"
      type: "Data"
      top: "data"
      top: "label"
      include {
        phase: TEST
      }
      transform_param {
        scale: 0.00390625
      }
      data_param {
        source: "/home/xy/caffe-master/examples/mnist/mnist_test_lmdb"
        batch_size: 100
        backend: LMDB
      }
    }
    
    
    layer {
      name: "fc1"
      type: "InnerProduct"
      # learning rate and decay multipliers for the weights
      param { lr_mult: 1 decay_mult: 1 }
      # learning rate and decay multipliers for the biases
      param { lr_mult: 2 decay_mult: 0 }
      inner_product_param {
        num_output: 300
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
          value: 0
        }
      }
      bottom: "data"
      top: "fc1"
    }
    
    layer {
      name: "relu1"
      type: "ReLU"
      bottom: "fc1"
      top: "fc1"
    }
    
    layer {
      name: "ip2"
      type: "InnerProduct"
      bottom: "fc1"
      top: "fc2"
      param {
        lr_mult: 1
      }
      param {
        lr_mult: 2
      }
      inner_product_param {
        num_output: 10
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
        }
      }
    }
    
    layer {
      name: "accuracy"
      type: "Accuracy"
      bottom: "fc2"
      bottom: "label"
      top: "accuracy"
      include {
        phase: TEST
      }
    }
    layer {
      name: "loss"
      type: "SoftmaxWithLoss"
      bottom: "fc2"
      bottom: "label"
      top: "loss"
    }
    

    训练代码如下:

    google::InitGoogleLogging("test_solver");
    FLAGS_alsologtostderr = 1;
    
    string base_dir = "/home/xy/caffe_analysis/my_caffe/example/";
    string path = base_dir + "mlp_solver.prototxt";
    SGDSolver<float> solver(path);
    
    // resuming from trained weights, 也可以加载已经训练好的模型
    string trained_weight_path = base_dir + "model_iter_20000.caffemodel";
    solver.net()->CopyTrainedLayersFrom(trained_weight_path);
    // 开始优化
    solver.Solve();
    

    训练过程如下:

    在这里插入图片描述

    接下来测试训练模型的效果的,代码如下:

    void test_net(){
        Caffe::set_mode(Caffe::CPU);
        string base_dir = "/home/xy/caffe_analysis/my_caffe/example/";
        string net_path = base_dir + "lenet_deploy.prototxt";
        string trained_path = base_dir + "model_iter_20000.caffemodel";
    
        Net<float> net(net_path, Phase::TEST);
        net.CopyTrainedLayersFrom(trained_path);
    
        CHECK_EQ(net.num_inputs(), 1) << "Network should have exactly one input.";
        CHECK_EQ(net.num_outputs(), 1) << "Network should have exactly one output.";
    
        // read Datum from file
        string datum_path = base_dir + "0.proto";
        Datum datum;
        ReadProtoFromBinaryFileOrDie(datum_path, &datum);
    
        // Datum convert
        TransformationParameter parameter;
        parameter.set_scale(0.00390625);
        DataTransformer<float> dataTransformer(parameter, Phase::TEST);
    
        Blob<float>* input_layer = net.input_blobs()[0];
    //    input_layer->Reshape(1, 1, 28, 28);//no need
        dataTransformer.Transform(datum, input_layer);
    
    //    net.Reshape();
        net.Forward();
        Blob<float>* output_layer = net.output_blobs()[0];
    
        const float* begin = output_layer->cpu_data();
        const float* end = begin + output_layer->channels();
    
        std::vector<float> ret(begin, end);
    
        for(auto item:ret)cout<<item<<" ";
        cout<<endl;
    
    }
    

    运行输出如下:可以看到0的概率最大。

    在这里插入图片描述

    测试inference的网络定义如下:

    在这里插入图片描述

    name: "LeNet"
    
    layer {
      name: "data"
      type: "Input"
      top: "data"
      input_param { shape: { dim: 1 dim: 1 dim: 28 dim: 28 } }
    }
    
    layer {
      name: "fc1"
      type: "InnerProduct"
      # learning rate and decay multipliers for the weights
      param { lr_mult: 1 decay_mult: 1 }
      # learning rate and decay multipliers for the biases
      param { lr_mult: 2 decay_mult: 0 }
      inner_product_param {
        num_output: 300
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
          value: 0
        }
      }
      bottom: "data"
      top: "fc1"
    }
    
    layer {
      name: "relu1"
      type: "ReLU"
      bottom: "fc1"
      top: "fc1"
    }
    
    layer {
      name: "ip2"
      type: "InnerProduct"
      bottom: "fc1"
      top: "fc2"
      param {
        lr_mult: 1
      }
      param {
        lr_mult: 2
      }
      inner_product_param {
        num_output: 10
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
        }
      }
    }
    
    layer {
      name: "prob"
      type: "Softmax"
      bottom: "fc2"
      top: "prob"
    }
    

    caffe系列源码分析介绍

    本系列深度学习框架caffe 源码分析主要内容如下:

    1. caffe源码分析-cmake 工程构建:

    caffe源码分析-cmake 工程构建主要内容:

    自己从头构建一遍工程,这样能让我更好的了解大型的项目的构建。当然原始的caffe的构建感觉还是比较复杂(主要是cmake),我这里仅仅使用cmake构建,而且简化点,当然最重要的是支持CLion直接运行调试(如果需要这个工程可以评论留下你的邮箱,我给你发送过去)。

    这里写图片描述

    2. caffe的数据内存分配类SyncedMemory, 以及类Blob数据传输的媒介.

    主要内容:
    caffe源码分析-SyncedMemory
    caffe源码分析-Blob
    其中Blob分析给出了其直接与opencv的图片相互转化以及操作,可以使得我们更好的理解Blob.

    3. caffe layer的源码分析,包括从整体上说明了layer类别以及其proto定义与核心函数.

    内容如下:
    caffe源码分析-layer
    caffe源码分析-ReLULayer
    caffe源码分析-inner_product_layer
    caffe源码分析-layer_factory

    首先分析了最简单的layer Relu,然后在是inner_product_layer全连接层, 最后是layer_factorycaffe中 以此工厂模式create各种Layer.

    4. 数据输入层,主要是多线程+BlockingQueue的方式读取数据训练:

    内容如下:
    caffe源码分析-BlockingQueue
    caffe源码分析-InternalThread
    caffe源码分析-DataReader

    5. IO处理例如读取proto文件转化为网络,以及网络参数的序列化

    内容如下:
    caffe源码分析-DataTransformer
    caffe源码分析-db, io

    6. 最后给出了使用纯C++结合多层感知机网络训练mnist的示例

    内容如下:

    caffe c++示例(mnist 多层感知机c++训练,测试)

    类似与caffe一样按照layer、solver、loss、net等模块构建的神经网络实现可以见下面这篇blog,相信看懂了这个python的代码理解caffe框架会更简单点.

    神经网络python实现


    最后如果需要cmake + CLion直接运行调试caffe的代码工程,可以评论留下你的邮箱,我给你发送过去.

    展开全文
  • 说明(what) 本篇博客主要有2个目的,第一,记录学习使用TensorFlow的操作流程;第二,将TensorFlow训练数据模型过程中的参数数据进行可视化记录。 ...2.训练过程中使用TensorBoard来可视化训练...

    说明(what)

    本篇博客主要有2个目的,第一,记录学习使用TensorFlow的操作流程;第二,将TensorFlow训练数据模型过程中的参数数据进行可视化记录。

    具体操作(how)

    实例描述

    1.使用TensorFlow搭建一个3层的神经网络(输入层,隐藏层,输出层)的模型训练经典的MNIST数据集,从而来预测手写体数字。
    2.训练过程中使用TensorBoard来可视化训练过程中参数数据
    实例的Github代码地址

    TensorFlow代码实现

    Step1 导入响应的库和加载数据集

    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    #以独热编码的方式加载数据集
    mnist = input_data.read_data_sets('./MNIST_data/',one_hot=True)

    Step2 模型相关的参数设置
    将模型相关的可能会变化的参数提前设置出来,方便后面统一更改

    in_unit = 784
    h1_unit = 300
    
    learningrate = 0.05  # 梯度下降法学习率
    dropout_keep_prob = 0.75  # dropout时保留神经元的比例,神经网络不为0的参数变为原理的1/dropout_keep_prob倍
    
    batch_size = 100  # 梯度下降法选取的batch的size
    max_iter = 3000  # 迭代次数
    
    sava_dir = '../data/'  # 存放数据结果
    log_dir = '../log/'  # 日志目录

    Step3 设置TensorFlow中的计算图
    1. 在TensorFlow启动session运行节点操作时,先设置好TensorFlow计算图,有利于全局把控计算图中的所有的节点操作。(TensorFlow中的计算图包括节点和边,其中节点为运算操作,而边代表数据的流动即张量,但是一些边没有数据流动表示节点运算操作之间的依赖关系;TensorFlow中的节点操作运行需要通过Session会话来启动,使用session.run()或节点操作对象调用eval()
    2. tf.placeholderTensorFlow中的占位符,作为外部数据(包括数据集和其他一些模型参数)的输入占位,当运行节点操作时候需要设置feed_dict参数来对占位符数据进行填充。
    3. 见下面NO3说明部分
    4. 在第一层隐藏层的输出后使用tf.nn.dropout再加了一层dropout
    5. 模型训练优化器选用的是AdamOptimizerloss函数是交叉熵,使用的是tf自带的tf.nn.softmax_cross_entropy_with_logits来计算真实值和预测值的交叉熵

    tf.reset_default_graph()
        train_graph = tf.Graph()
        with train_graph.as_default():
            # step 3.1 设置算法模型中的输入,使用占位符,占用输入的数据(什么情况下使用占位符,什么情况下设置tf变量)
            train_x = tf.placeholder(dtype=tf.float32,shape=[None,in_unit],name = 'train_x')
            train_y = tf.placeholder(dtype=tf.float32,shape=[None,10],name = 'train_y')
    
            # step 3.2构造神经网络
            # 创建第一层隐藏层
            hidden_layer1 = nn_layer(train_x,input_dim=in_unit,output_dim=h1_unit,layer_name='hider_layer1',act=tf.nn.relu)
    
            #在第一层隐藏层上创建一层 dropout层 —— 随机关闭一些hidden_layer1的神经元
            with tf.name_scope('dropout'):
                dropout_prob = tf.placeholder(dtype=tf.float32, name='dropout_prob')
                tf.summary.scalar('dropout_keep_probability',dropout_prob)
                hidden_layer1_dropout = tf.nn.dropout(hidden_layer1,dropout_prob)
    
            #创建输出层,包括10个类别,输出层的输入是hidden_layer1_dropout,输出是[1,10]
            y = nn_layer(hidden_layer1_dropout,h1_unit,10,layer_name='out_layer',act=tf.identity)
    
            # step 3.3 创建损失函数
            with tf.name_scope('loss'):
                cross_entropy_diff = tf.nn.softmax_cross_entropy_with_logits(labels=train_y, logits=y)
    
                with tf.name_scope('total'):
                    cross_entropy = tf.reduce_mean(cross_entropy_diff)
            tf.summary.scalar('loss', cross_entropy)
    
            # step 3.4 选择优化器训练并设计计算准确率的节点
            optimizer = tf.train.AdamOptimizer(learning_rate=learningrate)
            train_op = optimizer.minimize(cross_entropy)
    
            with tf.name_scope('accuracy'):
                with tf.name_scope('correct_prediction'):
                    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(train_y, 1))
                with tf.name_scope('accuracy'):
                    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
            tf.summary.scalar('accuracy', accuracy)

    NO3: 其中构建单层神经网络的操作封装于函数nn_layer,返回一个Tensor对象。weight_variable函数和bias_variable函数中使用tf.Variable来初始化网络层中对应的权重w和偏置项b. 其中tf.matmul(input_tensor,weight)+bias是该层网络的所有神经元的wx+b的向量表示,表示神经元的输入—g(wx+b),其中g为激活函数。

    def nn_layer(input_tensor,input_dim,output_dim,layer_name,act=tf.nn.relu):
        """
        建立神经网络层(一层),并返回该层网络层的输出的tensor对象
        :param input_tensor:特征数据
        :param input_dim:输入数据的维度大小
        :param output_dim:该层神经元的个数
        :param layer_name:命名空间
        :param act:神经元对应的激活函数
        """
        #设置命名空间
        with tf.name_scope(layer_name):
            #初始化权重,并记录权重变化
            with tf.name_scope('weights'):
                weight = weight_variable([input_dim,output_dim])
                variable_summeries(weight)# 记录权重变化
    
            with tf.name_scope('bias'):
                bias = bias_variable([output_dim])
                variable_summeries(bias)
    
            with tf.name_scope('linear_compute'):
                preact = tf.matmul(input_tensor,weight)+bias
                tf.summary.histogram('linear',preact)
    
            activeation = act(preact,name = 'activation')
            tf.summary.histogram('activation',activeation)
    
            return activeation
    def weight_variable(shape):
        """
        将每一层的神经网络的对应的权重参数w,初始化并封装到function中
        """
        inita_w = tf.truncated_normal(shape,stddev=0.1)
        return tf.Variable(inita_w,dtype=tf.float32)
    def bias_variable(shape):
        """
        将每一层的神经网络的对应的偏置项b,初始化并封装到function中
        """
        inita_b = tf.constant(0.1,shape=shape)
        return tf.Variable(inita_b)

    Step4 启动TensorFlow Session来实现计算图中的训练操作并将相应的Summary记录到日志文件
    1.初始化Session并设置Session对应的计算图,初始化TensorFlow的变量操作 tf.global_variables_initializer().run()
    2. 计算图中的节点运行方式有两种,方式一:session.run(),函数中设置好计算图中对应的节点操作,如session.run([train_op,cross_entropy,accuracy])其中train_op表示运行模型训练的操作,cross_entropy表示运行获取训练模型交叉熵的操作,accuracy表示获取模型运行的准确率操作,run函数返回的节点操作运行的对应结果。方式二,在tf.InteractiveSession初始化session情况下可以使用oper.eval()来运行操作,如train_op.eval()。该方式一次只能运行一个节点操作。

       session = tf.InteractiveSession(graph=train_graph)
        # step 4.1 合并summary并初始化所有变量
        merged = tf.summary.merge_all()
        train_writer = tf.summary.FileWriter(log_dir+'/train',graph=train_graph)
        test_writer = tf.summary.FileWriter(log_dir+'/test',graph=train_graph)
    
        tf.global_variables_initializer().run()
    
        # Step 4.2 训练模型并记录到TensorBoard
        for iter in range(max_iter):
            trainx_batch_x,train_batch_y = mnist.train.next_batch(batch_size)
            #迭代10次记录一下accuracy
            if iter % 10 == 0:
                summmary,acc,loss = session.run([merged,accuracy,cross_entropy],feed_dict={train_x:trainx_batch_x,train_y:train_batch_y,dropout_prob:1.0})
                test_writer.add_summary(summmary,iter)#写入日志
                print('loss at step %s: %s'%(iter,loss))
                print('Accuracy at step %s: %s'%(iter,acc))
            else:
                if iter % 100 == 0:
                    #记录tensor运行节点的信息
                    run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
                    run_metadata = tf.RunMetadata()
                    #将配置信息和记录运行信息的proto传入运行的过程,从而记录运行时每一个节点的时间、空间开销信息
                    summmary,_ = session.run([merged,train_op],
                                             feed_dict={train_x:trainx_batch_x,train_y:train_batch_y,dropout_prob:dropout_keep_prob},
                                             options=run_options,
                                             run_metadata=run_metadata)
                    #将节点运行时的信息写入日志文件
                    train_writer.add_run_metadata(run_metadata,'step %d' % iter)
                    train_writer.add_summary(summmary,iter)
                    pass
                else:
                    summmary,_ = session.run([merged,train_op],feed_dict={train_x:trainx_batch_x,train_y:train_batch_y,dropout_prob:dropout_keep_prob})
                    train_writer.add_summary(summmary,iter)
        train_writer.close()
        test_writer.close()
        session.close()

    TensorBoard可视化过程

    TensorBoard能记录的数据类型为:
    数据类型
    标量:SCALARS
    图片:IMAGES
    音频:AUDIO
    计算图:GRAPHS
    数据分布图:DISTRIBUTIONS
    直方图:HISTOGRAMS
    嵌入向量:EMBEDDINGS
    对上述数据的记录方式有:

    tf.summary.audio(name, tensor)
    tf.summary.scalar(name,tensor)
    tf.summary.image(name, tensor)
    tf.summary.histogram(name, tensor)
    #其中name表示生成的节点的名称。 也将作为TensorBoard中的一个系列名称。tensor为要记录的数据。
    #其中嵌入向量EMBEDDINGS的可视化,需要依赖于模型的保存,需要定义tf.train.Saver对象,再配置projector.ProjectorConfig对象。

    基本可视化步骤(摘自其他博客):
    1.建立一个Graph计算图,即想从该计算图中记录某些数据的信息并可视化。
    代码实现中的 Step 3 中的代码 为建立计算图的过程。
    train_graph = tf.Graph()
    2.确定要在Graph计算图中的哪些节点放置Summary Operations以用来记录信息。
    其中tf.name_scope(name)为给节点设置上下文,可以理解为节点的文件夹管理,一层包含一层的关系
    Step 3设计计算图中的建立神经网络的代码:

     #记录其中交叉熵的值
     tf.summary.scalar('loss', cross_entropy)
     #记录激活函数层的输出值
     tf.summary.histogram('activation',activeation)

    3.计算图中设计的Summary Operations并不会真正去执行计算记录,需要使用Session中的run去执行,或者被其他操作节点依赖执行。在TensorFlow代码实现Step中创建的Summary Operations没有被其他节点依赖,需要特地去运行Summary节点操作。Step 4 中通过代码merged = tf.summary.merge_all() 将所有的Summary Operations合并成一个节点,从而直接run该节点即可,也可以通过代码tf.summary.merge(input_list),合并指定的一些Summary Operations成一个节点再run
    4.使用tf.summary.FileWriter 将运行后输出的数据都保存到本地磁盘中。
    Step 4 中的代码

    #graph参数为指定要获取数据信息的计算图,对应着第一步。
    train_writer = tf.summary.FileWriter(log_dir+'/train',graph=train_graph)
    1. 运行整个程序,并在终端输入运行TensorBoard的指令,再打开web端查看可视化的结果
      命令:tensorboard --logdir='./ML/log/'
      tensorboard命令
      打开对应的网址 http://0.0.0.0:6006/
    展开全文
  • 多层感知机(MLP)简介

    万次阅读 多人点赞 2019-06-23 21:36:59
    一、多层感知机(MLP)原理简介 多层感知机(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

    展开全文
  • 但是单层感知机无法解决线性不可分的问题,要想解决线性不可分的问题,需要用多层感知机。 【多层感知机】 通用近似定理:如果一个多层感知机具有线性输出层和至少一层隐藏层,只要给予其足量的隐层神经元,它可以以...
  • tensorflow实现多层感知机

    千次阅读 2018-06-05 21:26:58
    在上一篇文章中,介绍了如何使用tensorflow来构建一个单层的神经网络,在训练集和测试集上的准确率达到了92%。这篇文章主要介绍使用tensorflow构建一个包含隐含层的神经网络,使得模型在...
  • 多层感知机:Multi-Layer Perceptron

    万次阅读 多人点赞 2017-11-07 21:33:06
    多层感知机(MLP)由感知机推广而来,最主要的特点是有多个神经元层,因此也叫深度神经网络(DNN: Deep Neural Networks)。
  • 参考:https://blog.csdn.net/u012162613/article/details/43221829 ... 一、什么是多层感知机多层感知机MLP,结构为:输入层——(1或n层)隐含层——输出层,层与层之间全连接(全连接的意思就是:上...
  • 02 简单的多层感知机

    2020-04-23 21:51:15
    本篇博客是在学习多层感知机原理的基础上,借助pytorch深度学习框架运行的一个简单的多层感知机模型,有助于自己对多层感知机模型原理的理解,以及熟练对pytorch工具的应用
  • 机器学习基础篇(十二)——多层感知机 一、概述 多层感知机(MLP:Multi-Layer Perceptron)由感知机(PLA: Perceptron Learning Algorithm)推广而来。它最主要的特点是有多个神经元层,因此也叫深度神经网络(DNN: ...
  • 多层感知机MLP

    千次阅读 2017-05-17 10:33:46
    关于感知机: ... 感知机是一种二类分类的线性分类器,其输入为实例的特征向量,输出为实例的类别,感知机属于判别模型,旨在求出将训练数据进行线性划分的分离超平面。  感知机最早是由Rosenblatt于195
  • TensorFlow2.0 学习笔记(二):多层感知机(MLP)

    千次阅读 多人点赞 2019-10-13 11:10:17
    文章目录专栏——TensorFlow学习笔记一、基础知识二、模型和层三、多层感知机(MLP)3.1、数据获取及预处理3.2、模型构建3.3、模型训练3.4、模型评估3.5、完整代码四、总结参考文章 一、基础知识 使用 TensorFlow ...
  • 感知机(Perceptron)和多层感知机(Multi-Layer Perceptron) 之前并未做过笔记,所以这篇文章是对以下内容回顾,对应: 第六周:(02)感知机 第六周:(03)多层感知机和反向传播 维基百科(en)...
  • 多层感知机(MLP)

    2020-03-12 21:56:28
    多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图: 从上图可以看到,...
  • MLP多层感知机(人工神经网络)原理及代码实现

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

    千次阅读 多人点赞 2018-09-21 20:12:13
    使用Tensor来写多层感知机 先做一个热身题目,我们使用Tensor构建一个两层神经网络 Tips:通常构建一个神经网络,我们有如下步骤 1、构建好网络模型 2、参数初始化 3、前向传播 4、计算损失 5、反向传播求出梯度 6、...
  • 一、感知机 在机器学习中,感知机(perceptron)是二分类的线性分类模型,属于监督学习算法。输入为实例的特征向量,输出为实例的类别(取+1和-1)。感知机对应于输入空间中将实例划分为两类的分离超平面。感知机...
  • TensorFlow上实现MLP多层感知机模型

    千次阅读 2017-03-26 10:04:03
    一、多层感知机简介 Softmax回归可以算是多分类问题logistic回归,它和神经网络的最大区别是没有隐含层。理论上只要隐含节点足够多,即时只有一个隐含层的神经网络也可以拟合任意函数,同时隐含层越多,越容易拟合...
  • 多层感知机(MLP)原理简介

    千次阅读 2019-03-09 21:23:54
    一、多层感知机(MLP)原理简介 多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,...
  • 深度学习 —— 多层感知机

    千次阅读 2017-06-01 19:54:31
    多层感知机 我们下一个要介绍的结构是单隐藏层的多层感知机(MLP)。MLP可以看成一个输入层由学习到的非线性转化phi进行转化的逻辑回归分类器。这种转化将输入数据投影到线性可分空间。这个中间层被称为隐藏层。单...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,623
精华内容 5,049
关键字:

多层感知机训练过程