caffe源碼學習:softmaxWithLoss前向計算

來源:互聯網
上載者:User

轉自:http://blog.csdn.net/liyaohhh/article/details/52115638

caffe源碼學習:softmaxWithLoss

 

   在caffe中softmaxwithLoss是由兩部分組成,softmax+Loss組成,其實主要就是為了caffe架構的可擴充性。


  運算式(1)是softmax計算運算式,(2)是sfotmaxLoss的計算損失表達。在caffe中是單獨的計算每層的輸入和輸出,然後再進行向後傳遞data結果和向前傳遞diff的結果。

    caffe中softmax的計算:


      如上所示;在reshape階段主要是進行相關參數維度設定。softmax_axis主要是制定從哪個維度開始切,預設是1.後面主要是初始化了兩個變數,sum_multiplier_和scale_局部變數的初始化。sum_multiplier_的形狀是channel的大小,一般主要是通過矩陣乘法來實現每個feature map相對應的座標資料進行相加或者相減或者其他的操作。scale通常情況下被用來當作臨時的緩衝變數。這兩個變數的使用在caffe中到處可見。接下來就是forward_cpu部分的代碼。


      首先還是擷取top和bottom的data,把bottom的data中的資料拷貝給top,以後就直接在top中進行計算。另外在caffe中,dim變數表示的C*W*H,spatial_dim 標識的是W*H。

      在上面首先是outer_num_樣本資料中輸入softmax的資料進行一個‘歸一化’操作,大紅色方框是為了找出當前instance中輸入softmax的特徵中的那個最大的數值,然後再減去那個最大數值防止產生數值計算方面的問題(例如在mnist資料集中,outer_num_是128代表的是batch的大小,inner_num_是1,這裡的softmax前面連結的是inner product層,所以spatial_dim和inner_num的大小均為1,dim的大小是10,scale_data中其實也只有一個數,雖然caffe_copy之後有兩行迴圈,其實由於inner_num是1,也就一行迴圈). 計算出最大的數值,然後把那個最大是數值乘以sum_multiplier_,就從1個數變成了C個數。繼而做exp,把結果存放到topdata,然後把全部channel的資料求和(求和caffe使用矩陣和向量的乘法進行計算)存放到scale_data,形狀是inner_num_,也就是W*H(其實就是1*1),最後就是除以求和結果啦。這麼多的語句也就描述了運算式(1). 最主要的是考慮到了數值計算中存在的問題。

     下面就應該是softmaxWithLoss計算損失;


   上面是softmaxWithLoss的set函數,可以和很清楚地看到在初始化完成softmax_param這個參數之後,直接把type設定成了softmax,然後又通過工廠函數建立softmaxlayer,繼而進行Set_up函數。可以看出softmaxWithLoss是內部建立了一個softmaxlayer。

    繼續後面主要就是檢查當前layer是否設定不對某個label進行計算Loss,也就是說,在mnist中有10個class,但是我只想對12345678進行分類,那就設定ignore_label為9.這個時候遇到標籤是9的就不計算Loss。注意protobuf中沒有設定預設的數值,has_xxx就返回false,只有設定了數值,才會true。後面的norm是為ignore服務的。

  接下來的reshape函數也沒啥用處,就是設定了三個變數。softmax_axis_=1,outer_num_=128,inner_num_=1.需要注意的是outer_num_ * inner_num_必須和bottom[1]->count()給定的lable數相同。也就是說當softmax前面接inner product的時候,每個lable對應的是instance對應的類別(一個數),但是當softmax前面是卷積層的時候,每個label就不是一個數,而是一個矩陣,對應著每個 feature map中每個像素值的分類。下面就是計算Loss:


   這裡壽麵是計算softmax_layer_的forward函數,softmax_top_vec_其實是prob_的一個引用。prob_data的大小是N*C*1*1.static_cast<int>(label[i * inner_num_ + j])是從對應的instance中取出相對應的標籤。如果當前的label和ignore label相同,那麼就不計算Loss損失,這樣就存在問題,假如128個instance中有10個不計算Loss,那麼最終在計算Loss的平均的時候,是除以多少呢。這就用到了norm。count在這裡統計我們計算了多少個instance的Loss數值。prob_data[i * dim + label_value * inner_num_ + j] dim是10,label_value是instance的標籤來當作index來從prob中取資料(該instance的分類結果),j是0,因為W=H=1。


   get_normalizer在VAILD模式下會返回我們計算了多少個Loss的個數,也就是count。這個時候當前batch的Loss就已經放回到top[0]中去了。下一步要計算的就是Loss的反向傳播。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.