Caffe源码阅读(1) 全连接层

发表于 2014-09-15   |  

今天看全连接层的实现。
主要看的是https://github.com/BVLC/caffe/blob/master/src/caffe/layers/inner_product_layer.cpp

主要是三个方法,setup,forward,backward

  • setup 初始化网络参数,包括了w和b
  • forward 前向传播的实现
  • backward 后向传播的实现

setup

主体的思路,作者的注释给的很清晰。
主要是要弄清楚一些变量对应的含义

1
2
3
M_ 表示的样本数
K_ 表示单个样本的特征长度
N_ 表示输出神经元的个数

为了打字方便,以下省略下划线,缩写为M,K,N

forward

实现的功能就是 y=wx+b

1
2
3
4
x为输入,维度 MxK
y为输出,维度 Nx1
w为权重,维度 NxK
b为偏置,维度 Nx1

具体到代码实现,用的是这个函数caffe_cpu_gemm,具体的函数头为

1
2
3
4
void caffe_cpu_gemm<float>(const CBLAS_TRANSPOSE TransA,
const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K,
const float alpha, const float* A, const float* B, const float beta,
float* C)

略长,整理它的功能其实很直观,即C←αA×B+βC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const CBLAS_TRANSPOSE TransA  # A是否转置
const CBLAS_TRANSPOSE TransB # B是否转置 # 这部分都比较直观不用解释了
const int M
const int N
const int K
const float alpha
const float* A
const float* B
const float beta,
float* C # 其中A维度是MxK,B维度是KxN,C维度为MxN

从实际代码来算,全连接层的forward包括了两步:

1
2
3
4
5
6
7
8
# 这一步表示 y←wx,或者说是y←xw'
caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasTrans, M_, N_, K_, (Dtype)1.,
bottom_data, weight, (Dtype)0., top_data);
# 这一步表示 y←y+b
caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, M_, N_, 1, (Dtype)1.,
bias_multiplier_.cpu_data(),
this->blobs_[1]->cpu_data(), (Dtype)1., top_data);
# 所以两步连起来就等价于y=wx+b

backward

分成三步:

  • 更新w
  • 更新b
  • 计算delta

用公式来说是下面三条:

一步步来,先来第一步,更新w,对应代码是:

1
2
caffe_cpu_gemm<Dtype>(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1.,
top_diff, bottom_data, (Dtype)0., this->blobs_[0]->mutable_cpu_diff());

对照公式,有

1
2
3
需要更新的w的梯度的维度是NxK
公式中的a^(l)_j对应的是bottom_data,维度是KxM
公式中的\delta_(l+1)_i对应的是top_diff,维度是NxM

然后是第二步,更新b,对应代码是:

1
2
3
caffe_cpu_gemv<Dtype>(CblasTrans, M_, N_, (Dtype)1., top_diff,
bias_multiplier_.cpu_data(), (Dtype)0.,
this->blobs_[1]->mutable_cpu_diff());

这里用到了caffe_cpu_gemv,简单来说跟上面的caffe_cpu_gemm类似,不过前者是计算矩阵和向量之间的乘法的(从英文命名可以分辨,v for vector, m for matrix)。函数头:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void caffe_cpu_gemv<float>(const CBLAS_TRANSPOSE TransA, const int M,
const int N, const float alpha, const float* A, const float* x,
const float beta, float* y) # 实现的功能类似 Y←αAX + βY
# 其中A的维度为 MxN
# X是一个向量,维度为 Nx1
# Y是结果 ,也是一个向量,维度为Mx1 const CBLAS_TRANSPOSE TransA # 是否对A进行转置 # 下面的参数很直观,不描述了
const int M
const int N
const float alpha
const float* A
const float* x
const float beta
float* y

绕回到具体的代码实现。。如何更新b?根据公式b的梯度直接就是delta

1
2
3
4
# 所以对应的代码其实就是将top_diff转置后就可以了(忽略乘上bias_multiplier这步)
caffe_cpu_gemv<Dtype>(CblasTrans, M_, N_, (Dtype)1., top_diff,
bias_multiplier_.cpu_data(), (Dtype)0.,
this->blobs_[1]->mutable_cpu_diff());

第三步是计算delta,对应公式

这里面可以忽略掉最后一项f’,因为在caffe实现中,这是由Relu layer来实现的,这里只需要实现括号里面的累加就好了,这个累加其实可以等价于矩阵乘法

1
2
3
4
5
6
7
caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, M_, K_, N_, (Dtype)1.,
top_diff, this->blobs_[0]->cpu_data(), (Dtype)0.,
(*bottom)[0]->mutable_cpu_diff()); # top_diff为\delta^(l+1)_j 维度 MxN
# this->blobs_[0]->cpu_data()为W^(l)_ji 维度 NxK
# (*bottom)[0]->mutable_cpu_diff()是要计算的结果,也就是\delta^(l)_i 维度是MxK

附录

又及,这里具体计算矩阵相乘用的是blas的功能,描述页面我参考的是:https://developer.apple.com/library/mac/documentation/Accelerate/Reference/BLAS_Ref/Reference/reference.html#//apple_ref/c/func/cblas_sgemm

Caffe源码阅读(1) 全连接层的更多相关文章

  1. caffe源码阅读

    参考网址:https://www.cnblogs.com/louyihang-loves-baiyan/p/5149628.html 1.caffe代码层次熟悉blob,layer,net,solve ...

  2. caffe源码阅读(1)_整体框架和简介(摘录)

    原文链接:https://www.zhihu.com/question/27982282 1.Caffe代码层次.回答里面有人说熟悉Blob,Layer,Net,Solver这样的几大类,我比较赞同. ...

  3. caffe源码阅读(1)-数据流Blob

    Blob是Caffe中层之间数据流通的单位,各个layer之间的数据通过Blob传递.在看Blob源码之前,先看一下CPU和GPU内存之间的数据同步类SyncedMemory:使用GPU运算时,数据要 ...

  4. caffe源码阅读(3)-Datalayer

    DataLayer是把数据从文件导入到网络的层,从网络定义prototxt文件可以看一下数据层定义 layer { name: "data" type: "Data&qu ...

  5. caffe源码阅读(2)-Layer

    神经网络是由层组成的,深度神经网络就是层数多了.layer对应神经网络的层.数据以Blob的形式,在不同的layer之间流动.caffe定义的神经网络已protobuf形式定义.例如: layer { ...

  6. caffe源码阅读(一)convert_imageset.cpp注释

    PS:本系列为本人初步学习caffe所记,由于理解尚浅,其中多有不足之处和错误之处,有待改正. 一.实现方法 首先,将文件名与它对应的标签用 std::pair 存储起来,其中first存储文件名,s ...

  7. caffe 源码阅读

    bvlc:Berkeley Vision and Learning Center. 1. 目录结构 models(四个文件夹均有四个文件构成,deploy.prototxt, readme.md, s ...

  8. caffe源码 全连接层

    图示全连接层 如上图所示,该全链接层输入n * 4,输出为n * 2,n为batch 该层有两个参数W和B,W为系数,B为偏置项 该层的函数为F(x) = W*x + B,则W为4 * 2的矩阵,B ...

  9. 源码阅读经验谈-slim,darknet,labelimg,caffe(1)

    本文首先谈自己的源码阅读体验,然后给几个案例解读,选的例子都是比较简单.重在说明我琢磨的点线面源码阅读方法.我不是专业架构师,是从一个深度学习算法工程师的角度来谈的,不专业的地方请大家轻拍. 经常看别 ...

随机推荐

  1. maven编译的时候跳过test

    方式1:用命令带上参数 mvn install -Dmaven.test.skip=true 方式2:在pom.xml里面配置 <plugin> <groupId>org.ap ...

  2. Luogu3835 【模板】可持久化平衡树(fhq-treap)

    fhq-treap,也即非旋treap,可以在不进行旋转操作的前提下维护treap.由于不需要旋转,可以对其可持久化. fhq-treap的基本操作是merge和split,并且通过这两个操作实现对t ...

  3. Sublime Text3配置及控制台乱码[cmd杀死进程乱码/编译文件乱码]解决方法

    [NodeJs] 1.安装 http://nodejs.cn/download/ 2.安装过程省略(因为已经安装过了) 和平时安装软件没区别 3.配置环境 计算机--->属性-->高级系统 ...

  4. java构造函数总结

    构造函数总结 概念:    创建对象时由JVM自动调用的函数 作用:    在创建对象的时候给对象的成员变量赋值: 写法: 修饰符:可以用访问权限修饰符(public.private等)修饰:不能用s ...

  5. Minimum Cost POJ - 2516 (模板题 spfa最小费用最大流)

    题意: 人回家,一步一块钱,有x个人,y个房子,求能回家的最大人数且使之费用最小 解析: 就是....套模板,,,, 建图(⊙﹏⊙)...要仔细观察呐 对于人拆不拆都可以  都能过,,,,这里贴上拆开 ...

  6. 51nod1236 序列求和 V3 【数学】

    题目链接 51nod1236 题解 用特征方程求得斐波那契通项: \[f(n) = \frac{(\frac{1 + \sqrt{5}}{2})^{n} - (\frac{1 - \sqrt{5}}{ ...

  7. 洛谷P3622 动物园

    题意:给定一个n个元素的圈,m个条件.满足一个条件需要选某些元素或不选另一些元素. 问最多能满足多少条件.每个条件所关联的元素,最远的两个距离不会超过5. 解:想了半天...... 首先能想到断环成链 ...

  8. A1101. Quick Sort

    There is a classical process named partition in the famous quick sort algorithm. In this process we ...

  9. 【洛谷P3792】由乃与大母神原型和偶像崇拜

    题目大意:维护一个序列,支持单点修改和查询一段区间能不能组成连续的一段数. 题解:查询区间能不能组成一段连续的数这个操作较为复杂,很难在较小时间复杂度内直接维护.这里采用线段树维护区间哈希的策略,即: ...

  10. 【模板】Treap

    Treap,又称树堆,是一种通过堆性质来维持BST平衡的数据结构.具体体现在对于树上每一个点来说,既有BST维护的值,又有一个堆维护的随机生成的值.维护平衡性的办法是根据堆维护的值的相对大小关系进行左 ...