smooth_L1_loss_layer.cu解读 caffe源码初认识
.cpp是cpu上運(yùn)行的代碼,.cu是gpu上運(yùn)行的代碼。
這是smooth_L1_loss_layer.cu的前向傳播部分
#include "caffe/fast_rcnn_layers.hpp"namespace caffe {template <typename Dtype> __global__ void SmoothL1Forward(const int n, const Dtype* in, Dtype* out) {// f(x) = 0.5 * x^2 if |x| < 1// |x| - 0.5 otherwise CUDA_KERNEL_LOOP(index, n) {Dtype val = in[index];Dtype abs_val = abs(val);if (abs_val < 1) {out[index] = 0.5 * val * val;} else {out[index] = abs_val - 0.5;}} }template <typename Dtype> void SmoothL1LossLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) {int count = bottom[0]->count();caffe_gpu_sub(count,bottom[0]->gpu_data(),bottom[1]->gpu_data(),diff_.mutable_gpu_data()); // d := b0 - b1if (has_weights_) {caffe_gpu_mul(count,bottom[2]->gpu_data(),diff_.gpu_data(),diff_.mutable_gpu_data()); // d := w * (b0 - b1) }SmoothL1Forward<Dtype><<<CAFFE_GET_BLOCKS(count), CAFFE_CUDA_NUM_THREADS>>>(count, diff_.gpu_data(), errors_.mutable_gpu_data());CUDA_POST_KERNEL_CHECK;Dtype loss;caffe_gpu_asum(count, errors_.gpu_data(), &loss);top[0]->mutable_cpu_data()[0] = loss / bottom[0]->num(); 注意:這里是bottom[0]->num(),不是bottom[0]->count() }blob的主要變量:
shared_ptr<SyncedMemory> data_; shared_ptr<SyncedMemory> diff_; vector<int> shape_; int count_; int capacity_;?
blob只是一個(gè)基本的數(shù)據(jù)結(jié)構(gòu),因此內(nèi)部的變量相對(duì)較少,首先是data_指針,指針類型是shared_ptr,屬于boost庫(kù)的一個(gè)智能指針,這一部分主要用來(lái)申請(qǐng)內(nèi)存存儲(chǔ)data,data主要是正向傳播的時(shí)候用的。同理,diff_主要用來(lái)存儲(chǔ)偏差,shape_都是存儲(chǔ)Blob的形狀,count表示Blob中的元素個(gè)數(shù),也就是個(gè)數(shù)*通道數(shù)*高度*寬度,capacity表示當(dāng)前的元素個(gè)數(shù),因?yàn)锽lob可能會(huì)reshape。count是一個(gè)迭代期參與的圖片個(gè)數(shù)。帶data的里面存儲(chǔ)的是激活值和W、b,diff中存儲(chǔ)的是殘差和dW、db。
?
blob中除了數(shù)據(jù)成員之外,也有很多用于操作數(shù)據(jù)的函數(shù)成員,下面就說(shuō)幾個(gè)比較重要的:
??? void Blob<Dtype>::Reshape():這個(gè)函數(shù)是在原來(lái)分配的內(nèi)存不夠的情況下重新分配內(nèi)存。
??? const Dtype* Blob<Dtype>::cpu_data():這個(gè)是獲取Blob結(jié)構(gòu)體中的data_數(shù)據(jù)的指針,同時(shí)限制不能對(duì)返回的指針指向的內(nèi)容進(jìn)行更改。
??? const Dtype* Blob<Dtype>::cpu_diff():這個(gè)是獲取Blob結(jié)構(gòu)體中的diff_數(shù)據(jù)的指針,同時(shí)限制不能對(duì)返回的指針指向的內(nèi)容進(jìn)行更改。
??? Dtype* Blob<Dtype>::mutable_cpu_data():獲取Blob結(jié)構(gòu)體中的data_數(shù)據(jù)的指針,同時(shí)可以對(duì)指針指向的內(nèi)容更改。
??? Dtype* Blob<Dtype>::mutable_cpu_diff():獲取Blob結(jié)構(gòu)體中的diff_數(shù)據(jù)的指針,同時(shí)可以對(duì)指針指向的內(nèi)容更改。
??? void Blob<Dtype>::ShareData(const Blob& other):讓其他Blob的data_數(shù)據(jù)和當(dāng)前Blob共享。
? ??void Blob<Dtype>::ShareDiff(const Blob& other):讓其他Blob的diff_和當(dāng)前的Blob共享。 ??
?
blob類里面有重載很多個(gè)count()函數(shù),主要還是為了統(tǒng)計(jì)blob的容量(volume),或者是某一片(slice),從某個(gè)axis到具體某個(gè)axis的shape乘積。
inline int count(int start_axis, int end_axis)int count = bottom[0]->count();????? count()沒帶參數(shù),計(jì)算的是bottom[0]這個(gè)輸入blob所有的元素個(gè)數(shù)。這里就是計(jì)算一個(gè)迭代期的所有圖片的所有通道的所有坐標(biāo)點(diǎn)形成的blob數(shù)據(jù)結(jié)構(gòu)元素的個(gè)數(shù)。
top[0]->mutable_cpu_data()[0] = loss / bottom[0]->num(); num()是計(jì)算一個(gè)迭代期參與的所有圖片的個(gè)數(shù)。這里就是求一個(gè)迭代期所有幾張圖片的平均loss。 ???????????
?
caffe_gpu_asum(count, errors_.gpu_data(), &loss); caffe_gpu_asum是對(duì)向量進(jìn)行L1范數(shù)計(jì)算,實(shí)際上就是對(duì)向量求其每個(gè)元素絕對(duì)值的和。第一個(gè)參數(shù)是要計(jì)算的元素的個(gè)數(shù)。
?
caffe_gpu_sub(count,bottom[0]->gpu_data(),bottom[1]->gpu_data(),diff_.mutable_gpu_data()); // d := b0 - b1if (has_weights_) {caffe_gpu_mul(count,bottom[2]->gpu_data(),diff_.gpu_data(),diff_.mutable_gpu_data()); // d := w * (b0 - b1) }caffe_gpu_sub,caffe_gpu_mul:這兩個(gè)函數(shù)分別實(shí)現(xiàn)element-wise(即點(diǎn)乘,每個(gè)矩陣對(duì)應(yīng)元素相乘)的乘減(y[i] = a[i] *?- b[i])。第一個(gè)參數(shù)是要計(jì)算的元素個(gè)數(shù)。
?
總結(jié); ??smooth_L1_loss_layer的loss計(jì)算是將所有對(duì)應(yīng)元素(某張圖片,某個(gè)通道的對(duì)應(yīng)坐標(biāo))相減,判斷絕對(duì)值是否小于1然后各個(gè)元素分別進(jìn)行smooth_L1(x)這個(gè)函數(shù)的處理,各個(gè)元素都有一個(gè)loss,然后把所有的loss相加除以圖片數(shù),就得到每張圖片box_loss的值。 ?????
?
loss的兩個(gè)輸入是1x84維的向量(fast中是這樣,faster中的rpn是36*w*h),這個(gè)向量表示21類的dx,dy,dh,dw。count數(shù)出所有的個(gè)數(shù),然后兩個(gè)輸入相對(duì)應(yīng)的每一個(gè)進(jìn)行這個(gè)計(jì)算,計(jì)算出84個(gè)loss,再對(duì)84個(gè)loss求和。當(dāng)然這是單個(gè)圖片,如果batch有多個(gè)圖片,對(duì)多個(gè)圖片loss求平均。
fast中使用的smoothL1和faster中使用的smoothL1有一點(diǎn)差別,但不大。faster中除了在rpn使用smoothl1,還要在fast那部分使用,所以faster中的smoothl1應(yīng)該是兼容的。
?
轉(zhuǎn)載于:https://www.cnblogs.com/ymjyqsx/p/7086698.html
總結(jié)
以上是生活随笔為你收集整理的smooth_L1_loss_layer.cu解读 caffe源码初认识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: HDU 2037 今年暑假不AC
- 下一篇: 发布Web端