• CNN基础


    CNN一般结构

    卷积层作用:

    1. 提取不同维度的特征,组合不同维度特征,其本质是卷积核,因此,学习一个有效的总卷积核是训练卷积层主要工作
      2)寻找不同位置,不同大小的特征
    2. 根据卷积核参数计算上下层blob之前维度关系
    input => conv => output:
    out = (W-F+2*P)/S + 1
    W:input的尺寸
    F:kernel的尺寸
    S:步长
    P:padding的数量
    

    非线性层

    控制对不同特征特征信号所应当作出的反应
    如,RELU:

    [f(x)=max(0,x) ]

    1. 对低强度特征信息不做反应,超过阈值后,强度越大,反应相应越大
    2. 阈值一般为0,因此样本数据与特征也尽量零均值,这可能是训练数据归一化及batchnormalization的原因

    池化层

    1. 降采样:将高维特征稀疏为低维特征
      2)可以增强模型对特征畸变的鲁棒性,如手写数字笔记不工整

    dropout:

    打破网络的对称性,使网络结构不断重构,防止网络过拟合;
    具体实现直接看源码dropout_layer.cppdropout_layer.hpp
    前传过程中,bottom计算出的部分特征不参与前传过程的计算

    void DropoutLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
      const Dtype* bottom_data = bottom[0]->cpu_data();
      Dtype* top_data = top[0]->mutable_cpu_data();
      unsigned int* mask = rand_vec_.mutable_cpu_data();    //从cpu中取一段可读写的内存,返回指针mask
      const int count = bottom[0]->count();                               //mutable_cpu_data表示可读写的内存,而cpu_data表示只读内存
      if (this->phase_ == TRAIN) {
        // Create random numbers
        caffe_rng_bernoulli(count, 1. - threshold_, mask);    //将mask内容部分以伯努利概率置为0,置0的概率与threshold有关
        for (int i = 0; i < count; ++i) {
          top_data[i] = bottom_data[i] * mask[i] * scale_;    //用mask掩码将bottom_data中部分特征设为死结点,不参与前传中loss的计算
        }
      } else {
        caffe_copy(bottom[0]->count(), bottom_data, top_data);
      }
    }
    

    在反传过程中,上层梯度回传时至下层时,同样会一部分被mask屏蔽,而且这个maskg前传一致,保证了前传与反传过程看到的网络结构是一致的

    template <typename Dtype>
    void DropoutLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
      if (propagate_down[0]) {
        const Dtype* top_diff = top[0]->cpu_diff();
        Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
        if (this->phase_ == TRAIN) {
          const unsigned int* mask = rand_vec_.cpu_data();    //将前传时写入mask内容重新赋值mask指针
          const int count = bottom[0]->count();
          for (int i = 0; i < count; ++i) {
            bottom_diff[i] = top_diff[i] * mask[i] * scale_;    //同样,反传过程也屏蔽了部分梯度,这样在一次前传与反传过程中所看见的网络结构实际就相同了,                                                                              
          }                                                                         //得到bottom梯度后会给cpu或gpu进行solver的update
        } else {
          caffe_copy(top[0]->count(), top_diff, bottom_diff);
        }
      }
    }
    

    其中,mask初始化用到了一个 caffe_rng_bernoulli,在这篇文章中提到,其实它主要调用了boost::bernoulli_distribution,将向量初始化为一定比例的1其余为0

    参考

    dropout_layer

  • 相关阅读:
    javascript检测浏览器插件
    登陆注册数据库设计与任务分配
    做网站的一些定律原理和效应
    为什么我们应该像盖房子那样写程序?
    最近项目中遇到的一些设计问题
    反向代理缓存
    《你必须知道的.NET》读书笔记
    锋利的Jquery读书笔记
    将pdf转成jpg格式
    《你必须知道的.NET》第五章读书笔记
  • 原文地址:https://www.cnblogs.com/fariver/p/6839665.html
Copyright © 2020-2023  润新知