# 深度学习笔记（6）全连接层的实现

2017-02-08

## Caffe中全连接层的实现

```layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}```

Caffe中全连接层相关的GPU文件有1个，为\src\caffe\layersi\nner_product_layer.cu 。

### 前向计算

```template
void InnerProductLayer::Forward_gpu(const vector*>& bottom,
const vector*>& top) {
const Dtype* bottom_data = bottom[0]->gpu_data();
Dtype* top_data = top[0]->mutable_gpu_data();
const Dtype* weight = this->blobs_[0]->gpu_data();
//M_为batch_size
if (M_ == 1) {
//top_data(M*N) = bottom_data(M*K) * weight(K*N)
//这里的计算实际调用了cublas中的矩阵计算函数，我们之前也有讲解，有兴趣可以深入看一下
caffe_gpu_gemv(CblasNoTrans, N_, K_, (Dtype)1.,
weight, bottom_data, (Dtype)0., top_data);
//若有偏置，加上偏置
if (bias_term_)
caffe_gpu_axpy(N_, bias_multiplier_.cpu_data()[0],
this->blobs_[1]->gpu_data(), top_data);
} else {
//同上面
caffe_gpu_gemm(CblasNoTrans,
transpose_ ? CblasNoTrans : CblasTrans,
M_, N_, K_, (Dtype)1.,
bottom_data, weight, (Dtype)0., top_data);
if (bias_term_)
caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, 1, (Dtype)1.,
bias_multiplier_.gpu_data(),
this->blobs_[1]->gpu_data(), (Dtype)1., top_data);
}
}```

### 反向传播

```template
void InnerProductLayer::Backward_gpu(const vector*>& top,
const vector& propagate_down,
const vector*>& bottom) {
if (this->param_propagate_down_[0]) {
const Dtype* top_diff = top[0]->gpu_diff();
const Dtype* bottom_data = bottom[0]->gpu_data();
// Gradient with respect to weight
//对权重求导weight_diff = top_diff * bottom_data
if (transpose_) {
caffe_gpu_gemm(CblasTrans, CblasNoTrans,
K_, N_, M_,
(Dtype)1., bottom_data, top_diff,
(Dtype)1., this->blobs_[0]->mutable_gpu_diff());
} else {
caffe_gpu_gemm(CblasTrans, CblasNoTrans,
N_, K_, M_,
(Dtype)1., top_diff, bottom_data,
(Dtype)1., this->blobs_[0]->mutable_gpu_diff());
}
}
if (bias_term_ && this->param_propagate_down_[1]) {
const Dtype* top_diff = top[0]->gpu_diff();
// Gradient with respect to bias
//对偏置值b求导 bias_diff = bias * top_diff
//这个和我之前公式推导出来的不一样，不知道为什么，如果有谁知道请留言告诉我，谢谢
caffe_gpu_gemv(CblasTrans, M_, N_, (Dtype)1., top_diff,
bias_multiplier_.gpu_data(), (Dtype)1.,
this->blobs_[1]->mutable_gpu_diff());
}
if (propagate_down[0]) {
const Dtype* top_diff = top[0]->gpu_diff();
// Gradient with respect to bottom data
//对上一层的输出求导bottom_diff = top_diff * weight
if (transpose_) {
caffe_gpu_gemm(CblasNoTrans, CblasTrans,
M_, K_, N_,
(Dtype)1., top_diff, this->blobs_[0]->gpu_data(),
(Dtype)0., bottom[0]->mutable_gpu_diff());
} else {
caffe_gpu_gemm(CblasNoTrans, CblasNoTrans,
M_, K_, N_,
(Dtype)1., top_diff, this->blobs_[0]->gpu_data(),
(Dtype)0., bottom[0]->mutable_gpu_diff());
}
}
}```