Mark Chang's Blog

Machine Learning, Deep Learning and Python

Torch NN Tutorial 5 : Backward Propagation ( Part 2 : nn.Criterion )

Backward Propagation in nn.Criterion

本文接續 Torch NN Tutorial 4: Backward Propagation (part 1) ,講解 nn.Criterion 中,與 backward propagation 相關的程式碼。

Criterion 的 forward 是負責計算 loss funciton 的值,而 backward 則是計算 的值。其中, 為模型預測出的結果。

nn.Criterion 程式碼:https://github.com/torch/nn/blob/master/Criterion.lua

backward 的部分,如下:

nn/Criterion.lua
1
2
3
4
5
6
function Criterion:backward(input, target)
   return self:updateGradInput(input, target)
end

function Criterion:updateGradInput(input, target)
end

nn.Criterionbackward 只做一件事,也就是 updateGradInput ,而 updateGradInput 的運算內容則由繼承它的類別來實作。

Backward Propagation in nn.MSECriterion

本文舉 nn.MSECriterion 為例。

nn.MSECriterion 程式碼:https://github.com/torch/nn/blob/master/MSECriterion.lua

updateGradInput 的部分,如下:

nn/MSECriterion.lua
1
2
3
4
5
6
7
8
9
function MSECriterion:updateGradInput(input, target)
   input.THNN.MSECriterion_updateGradInput(
      input:cdata(),
      target:cdata(),
      self.gradInput:cdata(),
      self.sizeAverage
   )
   return self.gradInput
end

此部分的運算由 C 來實作,運算完後,回傳結果 gradInput

C 程式碼: https://github.com/torch/nn/blob/master/lib/THNN/generic/MSECriterion.c

nn/lib/THNN/generic/MSECriterion.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void THNN_(MSECriterion_updateGradInput)(
          THNNState *state,
          THTensor *input,
          THTensor *target,
          THTensor *gradInput,
          bool sizeAverage)
{
  THNN_CHECK_NELEMENT(input, target);

  real norm = (sizeAverage ? 2./((real)THTensor_(nElement)(input)) : 2.);

  THTensor_(resizeAs)(gradInput, input);
  TH_TENSOR_APPLY3(real, gradInput, real, input, real, target,
    *gradInput_data = norm * (*input_data - *target_data);
  );
}

主要的運算是由第13行的 TH_TENSOR_APPLY3 來執行,這個 function 的意思是,執行某個 function 在三個 tensor 上。而要執行的 function 是 *gradInput_data = norm * (*input_data - *target_data) ,它需要 tensor ,分別是 input_datatarget_datagradInput_data

從數學公式上來看,公式如下:

其中, gradInput_datainput_data ,而 target_data 為常數 norm

如果 皆為向量,則 則是針對 中的每個元素來分別計算,如果 sizeAverage 為 true 的話,norm 還要除以向量的長度。舉以下例子, 則 :

其中, 代表 中的第一的元素,而前面乘上 是因為 sizeAveragetrue ,所以微分的結果要除以向量長度 3。

backward 執行以上運算,程式如下:

1
2
3
4
5
6
7
8
9
10
11
y_ = torch.Tensor{
    {1},{1},{1}
}

y = torch.Tensor{
    {1},{2},{3}
}

c1 = nn.MSECriterion()
c1:backward(y_,y)
print(c1.gradInput)

結果如下:

1
2
3
4
 0.0000
-0.6667
-1.3333
[torch.DoubleTensor of size 3x1]

如果 sizeAveragefalse 的話, 則不需再除以 input 的大小, 的結果如下:

sizeAverage 設為 false 的方法,即是在建立 nn.MSECriterion 時,輸入 false ,方法如下:

1
2
3
c2 = nn.MSECriterion(false)
c2:backward(y_,y)
print(c2.gradInput)

backward 執行運算,結果如下:

1
2
3
4
 0
-2
-4
[torch.DoubleTensor of size 3x1]

Materials

本次教學的完整程式碼於此:

https://github.com/ckmarkoh/torch_nn_tutorials/blob/master/5_backward_propagation_part_2.ipynb

Comments