import torch
벡터미분, 역전파와 기울기 소멸
기울기 소멸: loss 를 W로 미분했더니 그 값이 거의 0ㅇ이 나오는 현상 \(\to\) update가 거의 이루어지지 않음
이유 - W -> loss인 함수는 W에 어떤한 선형변환 \(\to\) 비선형변환 \(\to\) 선형변환 \(\to\) 비선형변환 \(\to \dots\) \(\to\) loss 의 과정으로 해석 가능 - 즉 loss는 W의 합성의 합섭ㅇ의… 합성함수로 해석가능 - loss 를 W로 미분한 값은 각 변환단ㅇ계에서 정의되는 함수의 도함수를 모두 곱한 것과 같음(체인룰) - 체인 중에서도 하나라도 0이 나오면 곱한 값은 0 이다. - 체인이 길수록 하나라도 0이 나오는 경우가 많음
왜 깊은 신경망일수록 기울기 소멸이 빈번한가? - 체인이 길기 때문에.
왜 순환신경망일수록 기울기 소멸이 빈번할까>? - 체인이 길기 때문에.
import
벡터미분
-
벡터미분에 대한 강의노트:
-
요약: 회귀분석에서 손실함수에 대한 미분은 아래와 같은 과정으로 계산할 수 있다.
\(loss = ({\bf y}-{\bf X}{\bf W})^\top ({\bf y}-{\bf X}{\bf W})={\bf y}^\top {\bf y} - {\bf y}^\top {\bf X}{\bf W} - {\bf W}^\top {\bf X}^\top {\bf y} + {\bf W}^\top {\bf X}^\top {\bf X} {\bf W}\)
\(\frac{\partial }{\partial {\bf W}}loss = -2{\bf X}^\top {\bf y} +2 {\bf X}^\top {\bf X} {\bf W}\)
-
모형의 매트릭스화
우리의 모형은 아래와 같다.
\(y_i = \beta_0 + \beta_1 x_i + \epsilon_i, \quad i=1,2,\dots,10\)
풀어서 쓰면
\(\begin{cases} y_1 = \beta_0 +\beta_1 x_1 + \epsilon_1 \\ y_2 = \beta_0 +\beta_1 x_2 + \epsilon_2 \\ \dots \\ y_{10} = \beta_0 +\beta_1 x_{10} + \epsilon_{10} \end{cases}\)
아래와 같이 쓸 수 있다.
\(\begin{bmatrix} y_1 \\ y_2 \\ \dots \\ y_{10} \end{bmatrix} = \begin{bmatrix} 1 & x_1 \\ 1 & x_2 \\ \dots & \dots \\ 1 & x_{10} \end{bmatrix}\begin{bmatrix}\beta_0 \\ \beta_1 \end{bmatrix} + \begin{bmatrix} \epsilon_1 \\ \epsilon_2 \\ \dots \\ \epsilon_{10} \end{bmatrix}\)
벡터와 매트릭스 형태로 정리하면
\({\bf y} = {\bf X} {\boldsymbol \beta} + \boldsymbol{\epsilon}\)
-
손실함수의 매트릭스화: 우리가 최소화 하려던 손실함수는 아래와 같다.
\(loss=\sum_{i=1}^{n}(y_i-\beta_0-\beta_1x_i)^2\)
이것을 벡터표현으로 하면 아래와 같다.
\(loss=\sum_{i=1}^{n}(y_i-\beta_0-\beta_1x_i)^2=({\bf y}-{\bf X}{\boldsymbol \beta})^\top({\bf y}-{\bf X}{\boldsymbol \beta})\)
풀어보면
\(loss=({\bf y}-{\bf X}{\boldsymbol \beta})^\top({\bf y}-{\bf X}{\boldsymbol \beta})={\bf y}^\top {\bf y} - {\bf y}^\top {\bf X}{\boldsymbol\beta} - {\boldsymbol\beta}^\top {\bf X}^\top {\bf y} + {\boldsymbol\beta}^\top {\bf X}^\top {\bf X} {\boldsymbol\beta}\)
-
미분하는 과정의 매트릭스화
loss를 최소화하는 \({\boldsymbol \beta}\)를 구해야하므로 loss를 \({\boldsymbol \beta}\)로 미분한 식을 0이라고 놓고 풀면 된다.
\(\frac{\partial}{\partial \boldsymbol{\beta}} loss = \frac{\partial}{\partial \boldsymbol{\beta}} {\bf y}^\top {\bf y} - \frac{\partial}{\partial \boldsymbol{\beta}} {\bf y}^\top {\bf X}{\boldsymbol\beta} - \frac{\partial}{\partial \boldsymbol{\beta}} {\boldsymbol\beta}^\top {\bf X}^\top {\bf y} + \frac{\partial}{\partial \boldsymbol{\beta}} {\boldsymbol\beta}^\top {\bf X}^\top {\bf X} {\boldsymbol\beta}\)
\(= 0 - {\bf X}^\top {\bf y}- {\bf X}^\top {\bf y} + 2{\bf X}^\top {\bf X}{\boldsymbol\beta}\)
따라서 \(\frac{\partial}{\partial \boldsymbol{\beta}}loss=0\)을 풀면 아래와 같다.
\(\boldsymbol{\hat\beta}= ({\bf X}^\top {\bf X})^{-1}{\bf X}^\top {\bf y}\)
-
공식도 매트릭스로 표현하면: \(\boldsymbol{\hat\beta}= ({\bf X}^\top {\bf X})^{-1}{\bf X}^\top {\bf y}\) <– 외우세요
벡터미분 / 매트릭스 미분
- 정의 1: 벡터로 미분
\(\frac{\partial}{\partial y} = \begin{bmatrix} \frac{\partial}{\partial y_1} \\ \vdots \\ \frac{\partial}{\partial y_n} \end{bmatrix}\) , \(y = \begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix}\)
- 정의 2: 매트릭스로 미분
\(\frac{\partial}{\partial \bf{X} } := \begin{bmatrix} \frac{\partial}{\partial x_{11} } & \dots & \frac{\partial}{\partial x_{1p} } \\ \vdots & & \vdots \\ \frac{\partial}{\partial x_{n1} } & \dots & \frac{\partial}{\partial x_{np} } \end{bmatrix}, \bf{X} = \begin{bmatrix} x_{11} & \dots & x_{1p} \\ \vdots & & \vdots \\ x_{n1} & \dots & x_{np} \end{bmatrix}\)
1
\(\frac{\partial}{\partial x}(x^\top y) = y\), 단 \(x = \begin{bmatrix} x_1 \\ \vdots \\ x_n \end{bmatrix}, y = \begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix}\)
pf. \(\bf{x}^\top \bf{y} = \begin{bmatrix} x_1 & \dots x_n \end{bmatrix} \begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix} = x_1 y_1 + x_2 y_2 + \dots + x_n y_n\)
\(\frac{\partial}{\partial x} = \begin{bmatrix} \frac{\partial}{\partial x_1} \\ \vdots \\ \frac{\partial}{\partial x_n} \end{bmatrix}\) 이므로
\(\big( \frac{\partial}{\partial x} \big) x^\top y = \begin{bmatrix} \frac{\partial}{\partial x_1} \\ \vdots \\ \frac{\partial}{\partial x_n} \end{bmatrix} (x_1 y_1 + x_2 y_2 + \dots + x_n y_n)\)
\(= \begin{bmatrix} \frac{\partial}{\partial x_1}(x_1y_1 + \dots + x_n y_n) \\ \vdots \\ \frac{\partial}{\partial x_n}(x_1y_1 + \dots + x_n y_n) \end{bmatrix} = \begin{bmatrix} \frac{\partial}{\partial x_1} x_1 y_1 + \frac{\partial}{\partial x_1}x_2 y_2 + \dots + \frac{\partial}{\partial x_1}x_n y_n \\ \vdots \\ \frac{\partial}{\partial x_n} x_1 y_1 + \frac{\partial}{\partial x_n}x_2 y_2 + \dots + \frac{\partial}{\partial x_n}x_n y_n \end{bmatrix}\)
\(= \begin{bmatrix} y_1 + 0 + \dots + 0 \\ \vdots \\ 0+0+ \dots + y_n \end{bmatrix} = \begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix} = \bf{y}\)
2
\(\frac{\partial}{\partial x}(\bf{x}^\top \bf{y}) = \bf{y}\) 임을 보이는 다른 풀이
pf. \(\frac{\partial}{\partial x} \big(\bf{x}^\top \bf{y} \big) = \big( \frac{\partial}{\partial x} x^\top \big) y = \bf{I} \bf{y} = \bf{y}\)
\(\frac{\partial}{\partial x} x^\top = \begin{bmatrix} \frac{\partial}{\partial x_1} \\ \vdots \\ \frac{\partial}{\partial x_n}\end{bmatrix} \begin{bmatrix} x_1 & \dots & x_n \end{bmatrix} = \begin{bmatrix} \frac{\partial}{\partial x_1} x_1 & \dots & \frac{\partial}{\partial x_n} x_n \\ \vdots & & \\ \frac{\partial}{\partial x_n} x_1 & \dots &\frac{\partial}{\partial x_n} x_n \end{bmatrix} = \bf{I}\)
2
\(\frac{\partial}{\partial x}(\bf{y}^\top \bf{x} ) = \bf{y}\)
pf. \(\frac{\partial}{\partial x}(\bf{y}^\top\bf{x}) = \frac{\partial}{\partial x}(\bf{x}^\top \bf{y}) = \bf{y}\)
3
\(\frac{\partial}{\partial B}(\bf{y}^\top \bf{X} \bf{B}) = \bf{x}^\top \bf{y}\)
단, \(\bf{B} := p \times 1\) vector, \(\bf{X} := n \times p\) matrix, \(\bf{y} := n \times 1\) vector
pf. \(\bf{y}^\top \bf{X} \bf{B}\)는 스칼라(\(1 \times 1\))이므로 \(\bf{y}^\top\bf{X}\bf{B} = (\bf{y}^\top \bf{X} \bf{B})^\top = \bf{B}^\top \bf{X}^\top \bf{y}\)
\(\frac{\partial}{\partial \bf{B}}(\bf{y}^\top \bf{X} \bf{B}) = \frac{\partial}{\partial \bf{B}}(\bf{B}^\top \bf{X}^\top \bf{y}) = \big( \frac{\partial}{\partial \bf{B}} \bf{B}^\top \big) \bf{X}^\top \bf{y} = \bf{X}^\top \bf{y}\)
(다른 풀이)
\(\frac{\partial}{\partial \bf{B}}(\bf{y}^\top \bf{X} \bf{B}) = \bf{X}^\top \bf{y}\)임을 보이는 다른 풀이
\(\bf{XB} = \begin{bmatrix} x_{11} & \dots & x_{1p} \\ \vdots & & \vdots \\ x_{n1} & \dots & x_{np} \end{bmatrix} \begin{bmatrix} \beta_1 \\ \vdots \\ \beta_p \end{bmatrix} = \begin{bmatrix} x_{11}B_1 + \dots + x_{1p} B_p \\ x_{21}B_1 + \dots + x_{2p}B_p \\ \vdots \\ x_{n1} B_1 + \dots + x_{np} B_p \end{bmatrix}\)
\(\bf{y}^\top \bf{XB} = \begin{bmatrix} y_1 & \dots y_n \end{bmatrix}\begin{bmatrix} x_{11}B_1 + \dots + x_{1p} B_p \\ x_{21}B_1 + \dots + x_{2p}B_p \\ \vdots \\ x_{n1} B_1 + \dots + x_{np} B_p \end{bmatrix}\)
\(= y_1(x_{11}B_1 + \dots + x_{1p}B_p) + y_2(x_{21}B_1 + \dots + x_{2p}B_p ) + \dots + y_n(x_{n1}B_1 + \dots + x_{np} B_p) = A_1 + A_2 + \dots A_n\)
- note: \(A_1, A_2, \dots\)은 모두 스칼라(\(1 \times 1\))
\(\big( \frac{\partial}{\partial B} \big)(\bf{y}^\top \bf{XB}) = \begin{bmatrix} \frac{\partial}{\partial B_1} \\ \vdots \\\frac{\partial}{\partial B_p} \end{bmatrix}(A_1 + A_2 + \dots A_n)\)
\(= \begin{bmatrix}\frac{\partial}{\partial B_1} A_1 \\ \vdots \\ \frac{\partial}{\partial B_p} A_1 \end{bmatrix} + \begin{bmatrix} \frac{\partial}{\partial B_1} A_2 \\ \vdots \\ \frac{\partial}{\partial B_p} A_2 \end{bmatrix}+ \dots +\begin{bmatrix} \frac{\partial}{\partial B_1} A_n \\ \vdots \\ \frac{\partial}{\partial B_p} A_n \end{bmatrix}\)
\(\frac{\partial}{\partial B_1}A_1 = \frac{\partial}{\partial B_1}y_1(x_{11}B_1 + \dots + x_{1p}B_p) = y_1 x_{11} + 0 + \dots + 0\)
\(\frac{\partial}{\partial B_2}A_2 = \frac{\partial}{\partial B_2}y_1(x_{11}B_1 + \dots + x_{1p}B_p) = 0 + y_1 x_{12} + 0 + \dots + 0\)
\(= \begin{bmatrix} y_1 x_{11} \\ y_1 x_{12} \\ \vdots \\ y_1 x_{1p}\end{bmatrix} + \begin{bmatrix} y_2 x_{21} \\ y_2 x_{22} \\ \vdots \\ y_2 x_{2p} \end{bmatrix} + \dots + \begin{bmatrix} y_n x_{n1} \\ y_n x_{n2} \\ \vdots \\ y_n x_{np} \end{bmatrix}\)
\(= \begin{bmatrix} y_1 x_{11} + y_2 x_{21} + \dots + y_n x_{n1} \\ y_1 x_{12} + y_2 x_{22} + \dots + y_n x_{n2} \\ \vdots \\ y_1 x_{1p} + y_2 x_{2p} + \dots + y_n x_{np} \end{bmatrix} = \begin{bmatrix} x_{11} & x_{21} & \dots & x_{n1} \\ x_{12} & x_{22} & \dots & x_{n2} \\ \vdots & \vdots & & \vdots \\ x_{1p} & x_{2p} & \dots & x_{np} \end{bmatrix} \begin{bmatrix} y_1 \\ y_2 \\ \vdots \\ y_n \end{bmatrix} = \bf{X}^\top \bf{y}\)
4
\(\frac{\partial}{\partial y} \bf{y}^\top \bf{y} = 2\bf{y}\)
pf. \(\bf{y}^\top \bf{y} = \begin{bmatrix} y_1 & \dots & y_n \end{bmatrix} \begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix} = y_{1}^{2} + \dots + y_{n}^{2}\)
\(\therefore \frac{\partial}{\partial y}(\bf{y}^\top y) = \frac{\partial}{\partial y}(y_{1}^{2} + \dots + y_{n}^{2}) = \begin{bmatrix} \frac{\partial}{\partial y_1} \\ \vdots \\ \frac{\partial}{\partial y_n} \end{bmatrix} (y_{1}^{2} + \dots + y_{n}^{2})\)
\(= \begin{bmatrix} \frac{\partial}{\partial y_1}(y_{1}^{2} + \dots + y_{n}^{2}) \\ \vdots \\ \frac{\partial}{\partial y_n}(y_{1}^{2} + \dots + y_{n}^{2}) \end{bmatrix} = \begin{bmatrix}2y_1 + 0 + \dots + 0 \\ 0 + 2y_2 + \dots + 0 \\ \vdots \\ 0 + 0 + \dots + 2y_n \end{bmatrix} = 2\begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix} = 2\bf{y}\)
(틀린 풀이) \(\frac{\partial}{\partial y}(\bf{y}^\top \bf{y}) {\color{orange}=} \big( \frac{\partial}{\partial y} \bf{y}^\top \big) \bf{y}\) 미분하는 값에 대해 상수일때만 가능
그런데 \(\big(\frac{\partial}{\partial y}\bf{y}^\top \big) = \bf{I}\)이므로, \(\frac{\partial}{\partial y} (\bf{y}^\top \bf{y}) = \bf{I} \bf{y} = \bf{y}\)
(틀린 풀이의 스칼라 버전) \(\frac{d}{dy} y^2 = \big( \frac{d}{dy} y \big) y = 1 \times y = \bf{y}\)
(올바른 풀이) : \(\frac{d}{dy} y^2 = \big( \frac{d}{dy} \big) {\color{red}y} {\color{blue}y} = \big( \frac{d}{dy} {\color{red}y} \big) {\color{blue}y} + {\color{red}y} \big( \frac{d}{dy} {\color{blue}y} \big)\)
Note: 곱의 미분 : 함수 \(f(x), g(x)\) 가 \(x\)에 대하여 미분 가능하면 \(\{ {\color{red}f(x)} \times {\color{blue}g(x)} \}' = {\color{red}f(x)}'g{\color{blue}(x)} + {\color{red}f(x)}{\color{blue}g(x)}'\)
- 여기서는 \({\color{red}y}\)가 \(f(x)\), \({\color{blue}y}\)가 \(g(x)\)
다시 벡터로 돌아오자
(올바른 풀이) \(\frac{\partial}{\partial y}({\color{red}y}^\top {\color{blue}y}) = A + B = \bf{I}{\color{red}y} + \bf{I}{\color{blue}y} = 2\bf{y}\)
- \(A :=\) 빨간 \(y\)만 변수로 보고 미분
- \(B :=\) 파란 \(y\)만 변수로 보고 미분
\(A = \big( \frac{\partial}{\partial y} {\color{red}y}^\top \big) {\color{blue}y} = \bf{I} {\color{blue}y}\)
\(B = \big( \frac{\partial}{\partial y} \big) ( {\color{red}y}^\top {\color{blue}y} )\) 스칼라라 순서 변경 가능\(:= \big( \frac{\partial}{\partial y} \big) ({\color{blue}y}^\top {\color{red}y} \big) = ( \frac{\partial}{\partial y} {\color{blue}y}^\top \big) {\color{red}y} = \bf{I} {\color{red}y}\)
5
\(\frac{\partial}{\partial B} \bf{B}^\top \bf{X}^\top \bf{X} \bf{B} = 2\bf{X}^\top \bf{XB}\)
pf. \(\frac{\partial}{\partial B}({\color{red}B}^\top{\color{red}X}^\top {\color{blue}X} {\color{blue}B}) = A + B = \bf{I}\bf{X}^\top \bf{XB} + \bf{I}\bf{X}^\top\bf{XB} = 2\bf{X}^\top \bf{XB}\)
\(A = \big( \frac{\partial}{\partial B} {\color{red}B}^\top\big) \bf{X}^\top \bf{X} {\color{blue}B} = \bf{I} \bf{X}^\top \bf{X} {\color{red}B}\)
\(B = \big( \frac{\partial}{\partial B} \big) ( {\color{red}B}^\top \bf{X}^\top \bf{X} {\color{blue}B}) = \big(\frac{\partial}{\partial B} \big) ({\color{blue}B}^\top \bf{X}^\top \bf{X}{\color{red}B}) = \bf{I} \bf{X}^\top \bf{X} {\color{red}B}\)
\(loss = (\bf{y} - \bf{XB})^\top(\bf{y} - \bf{XB}) = \bf{y}\bf{y}^\top - \bf{y}^\top\bf{XB} - \bf{B}^\top\bf{X}^\top \bf{y} + \bf{B}^\top \bf{X}^\top \bf{XB}\)
\(\frac{\partial}{\partial B} loss = 0 - \frac{\partial}{\partial B} \bf{y}^\top \bf{XB} - \frac{\partial}{\partial B} \bf{B}^\top \bf{X}^\top \bf{y} + \frac{\partial}{\partial B} \bf{B}^\top \bf{X}^\top \bf{XB} = 0 - \bf{X}^\top \bf{y} - \bf{X}^\top \bf{y} + 2\bf{X}^\top \bf{XB} = - 2\bf{X}^\top \bf{y} + 2\bf{X}^\top \bf{XB}\)
\(\therefore \frac{\partial}{\partial B} loss = 0 \leftrightarrow 2\bf{X}^\top \bf{y} = 2\bf{X}^\top \bf{XB}\)
\(\therefore \hat{\bf{B}} = (\bf{X}^\top \bf{X})^{-1}\bf{X}^\top \bf{y}\)
체인룰
-
체인룰: 어려운 하나의 미분을 손쉬운 여러개의 미분으로 나누는 기법
-
손실함수가 사실 아래와 같은 변환을 거쳐서 계산되었다고 볼 수 있다.
- \({\bf X} \to {\bf X}{\bf W} \to {\bf y} -{\bf X}{\bf W} \to ({\bf y}-{\bf X}{\bf W})^\top ({\bf y}-{\bf X}{\bf W})\)
-
위의 과정을 수식으로 정리해보면 아래와 같다.
\({\bf u}={\bf X}{\bf W}\), \(\quad {\bf u}: n \times 1\)
\({\bf v} = {\bf y}- {\bf u},\) \(\quad {\bf v}: n \times 1\)
\(loss={\bf v}^\top {\bf v},\) \(\quad loss: 1 \times 1\)
-
손실함수에 대한 미분은 아래와 같다.
\[\frac{\partial }{\partial {\bf W}} loss = \frac{\partial }{\partial {\bf W}} {\bf v}^\top {\bf v}\]
(그런데 이걸 어떻게 계산함?)
-
계산할 수 있는것들의 모음..
\(\frac{\partial}{\partial {\bf v}} loss = 2{\bf v}\) \(\quad \to\) (n,1) 벡터
\(\frac{\partial }{\partial {\bf u}} {\bf v}^\top = -{\bf I}\) \(\quad \to\) (n,n) 매트릭스
\(\frac{\partial }{\partial \bf W}{\bf u}^\top = {\bf X}^\top\) \(\quad \to\) (p,n) 매트릭스
-
혹시.. 아래와 같이 쓸 수 있을까?
\[\left(\frac{\partial }{\partial \bf W}{\bf u}^\top \right) \left(\frac{\partial }{\partial \bf u}{\bf v}^\top \right) \left(\frac{\partial }{\partial \bf v}loss \right) = \frac{\partial {\bf u}^\top}{\partial \bf W} \frac{\partial {\bf v}^\top}{\partial \bf u} \frac{\partial loss}{\partial \bf v}\]
- 가능할것 같다. 뭐 기호야 정의하기 나름이니까!
-
그렇다면 혹시 아래와 같이 쓸 수 있을까?
\[\frac{\partial {\bf u}^\top}{\partial \bf W} \frac{\partial {\bf v}^\top}{\partial \bf u} \frac{\partial loss}{\partial \bf v} = \frac{\partial loss }{\partial\bf W}=\frac{\partial }{\partial \bf W} loss\]
- 이건 선을 넘는 것임.
- 그런데 어떠한 공식에 의해서 가능함. 그 공식 이름이 체인룰이다.
-
결국 정리하면 아래의 꼴이 되었다.
\[\left(\frac{\partial }{\partial \bf W}{\bf u}^\top \right) \left(\frac{\partial }{\partial \bf u}{\bf v}^\top \right) \left(\frac{\partial }{\partial \bf v}loss \right) = \frac{\partial }{\partial \bf W}loss\]
-
그렇다면?
\[\left({\bf X}^\top \right) \left(-{\bf I} \right) \left(2{\bf v}\right) = \frac{\partial }{\partial \bf W}loss\]
그런데, \({\bf v}={\bf y}-{\bf u}={\bf y} -{\bf X}{\bf W}\) 이므로
\[-2{\bf X}^\top\left({\bf y}-{\bf X}{\bf W}\right) = \frac{\partial }{\partial \bf W}loss\]
정리하면
\[\frac{\partial }{\partial \bf W}loss = -2{\bf X}^\top{\bf y}+2{\bf X}^\top {\bf X}{\bf W}\]
예시: 2021 빅데이터분석 중간고사 문제 2-(b)
-
미분계수를 계산하는 문제였음..
-
체인룰을 이용하여 미분계수를 계산하여 보자.
= torch.ones(5)
ones= torch.tensor([11.0,12.0,13.0,14.0,15.0])
x = torch.vstack([ones,x]).T
X = torch.tensor([17.7,18.5,21.2,23.6,24.2]) y
= torch.tensor([3.0,3.0]) W
= X@W
u = y-u
v = v.T @ v loss
/home/csy/anaconda3/envs/py37/lib/python3.7/site-packages/ipykernel_launcher.py:3: UserWarning: The use of `x.T` on tensors of dimension other than 2 to reverse their shape is deprecated and it will throw an error in a future release. Consider `x.mT` to transpose batches of matrices or `x.permute(*torch.arange(x.ndim - 1, -1, -1))` to reverse the dimensions of a tensor. (Triggered internally at /opt/conda/conda-bld/pytorch_1666642814471/work/aten/src/ATen/native/TensorShape.cpp:3277.)
This is separate from the ipykernel package so we can avoid doing imports until
loss
tensor(2212.1799)
-
\(\frac{\partial}{\partial\bf W}loss\) 의 계산
\(\frac{\partial }{\partial \bf W}loss = \left({\bf X}^\top \right) \left(-{\bf I} \right) \left(2{\bf v}\right)\)
@ -torch.eye(5) @ (2*v) X.T
tensor([ 209.6000, 2748.6001])
-
참고로 중간고사 답은
@ -torch.eye(5)@ (2*v) / 5 X.T
tensor([ 41.9200, 549.7200])
입니다.
-
확인
= torch.tensor([3.0,3.0],requires_grad=True) _W
= (y-X@_W).T @ (y-X@_W) _loss
_loss.backward()
_W.grad.data
tensor([ 209.6000, 2748.6001])
-
\(\frac{\partial}{\partial \bf v} loss= 2{\bf v}\) 임을 확인하라.
v
tensor([-18.3000, -20.5000, -20.8000, -21.4000, -23.8000])
= torch.tensor([-18.3000, -20.5000, -20.8000, -21.4000, -23.8000],requires_grad=True) _v
= _v.T @ _v _loss
_loss.backward()
_v.grad.data, v
(tensor([-36.6000, -41.0000, -41.6000, -42.8000, -47.6000]),
tensor([-18.3000, -20.5000, -20.8000, -21.4000, -23.8000]))
-
\(\frac{\partial }{\partial {\bf u}}{\bf v}^\top\) 의 계산
= torch.tensor([36., 39., 42., 45., 48.],requires_grad=True)
_u _u
tensor([36., 39., 42., 45., 48.], requires_grad=True)
= y - _u ### 이전의 _v와 또다른 임시 _v _v
(_v.T).backward()
RuntimeError: grad can be implicitly created only for scalar outputs
- 사실 토치에서는 스칼라아웃풋에 대해서만 미분을 계산할 수 있음
그런데 \(\frac{\partial}{\partial {\bf u}}{\bf v}^\top=\frac{\partial}{\partial {\bf u}}(v_1,v_2,v_3,v_4,v_5)=\big(\frac{\partial}{\partial {\bf u}}v_1,\frac{\partial}{\partial {\bf u}}v_2,\frac{\partial}{\partial {\bf u}}v_3,\frac{\partial}{\partial {\bf u}}v_4,\frac{\partial}{\partial {\bf u}}v_5\big)\) 이므로
조금 귀찮은 과정을 거친다면 아래와 같은 알고리즘으로 계산할 수 있다.
\(\frac{\partial }{\partial {\bf u}} {\bf v}^\top\)의 결과를 저장할 매트릭스를 만든다. 적당히
A
라고 만들자._u
하나를 임시로 만든다. 그리고 \(v_1\)을_u
로 미분하고 그 결과를A
의 첫번째 칼럼에 기록한다._u
를 또하나 임시로 만들고 \(v_2\)를_u
로 미분한뒤 그 결과를A
의 두번째 칼럼에 기록한다.(1)-(2)와 같은 작업을 \(v_5\)까지 반복한다.
(0)을 수행
= torch.zeros((5,5))
A A
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
(1)을 수행
u,v
(tensor([36., 39., 42., 45., 48.]),
tensor([-18.3000, -20.5000, -20.8000, -21.4000, -23.8000]))
= torch.tensor([36., 39., 42., 45., 48.],requires_grad=True)
_u = (y-_u)[0] v1
- 이때 \(v_1=g(f({\bf u}))\)와 같이 표현할 수 있다. 여기에서 \(f((u_1,\dots,u_5)^\top)=(y_1-u_1,\dots,y_5-u_5)^\top\), 그리고 \(g((v_1,\dots,v_n)^\top)=v_1\) 라고 생각한다. 즉 \(f\)는 벡터 뺄셈을 수행하는 함수이고, \(g\)는 프로젝션 함수이다. 즉 \(f:\mathbb{R}^5 \to \mathbb{R}^5\)인 함수이고, \(g:\mathbb{R}^5 \to \mathbb{R}\)인 함수이다.
여기서 \(v_1\)은 꼬리표로서 selection 작성되어 있음
v1.backward()
_u.grad.data
tensor([-1., -0., -0., -0., -0.])
0]= _u.grad.data A[:,
A의 첫번째 칼럼에 이것을 넣어주세요
A
tensor([[-1., 0., 0., 0., 0.],
[-0., 0., 0., 0., 0.],
[-0., 0., 0., 0., 0.],
[-0., 0., 0., 0., 0.],
[-0., 0., 0., 0., 0.]])
(2)를 수행
= torch.tensor([36., 39., 42., 45., 48.],requires_grad=True)
_u = (y-_u)[1] v2
v2.backward()
_u.grad.data
tensor([-0., -1., -0., -0., -0.])
1]= _u.grad.data
A[:, A
tensor([[-1., -0., 0., 0., 0.],
[-0., -1., 0., 0., 0.],
[-0., -0., 0., 0., 0.],
[-0., -0., 0., 0., 0.],
[-0., -0., 0., 0., 0.]])
(3)을 수행 // 그냥 (1)~(2)도 새로 수행하자.
for i in range(5):
= torch.tensor([36., 39., 42., 45., 48.],requires_grad=True)
_u = (y-_u)[i]
_v
_v.backward()= _u.grad.data A[:,i]
A
tensor([[-1., -0., -0., -0., -0.],
[-0., -1., -0., -0., -0.],
[-0., -0., -1., -0., -0.],
[-0., -0., -0., -1., -0.],
[-0., -0., -0., -0., -1.]])
- 이론적인 결과인 \(-{\bf I}\)와 일치한다.
-
\(\frac{\partial }{\partial {\bf W}}{\bf u}^\top\)의 계산
\(\frac{\partial }{\partial {\bf W}}{\bf u}^\top = \frac{\partial }{\partial {\bf W}}(u_1,\dots,u_5)=\big(\frac{\partial }{\partial {\bf W}}u_1,\dots,\frac{\partial }{\partial {\bf W}}u_5 \big)\)
= torch.zeros((2,5))
B B
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
W
tensor([3., 3.])
= torch.tensor([3., 3.],requires_grad=True)
_W _W
tensor([3., 3.], requires_grad=True)
for i in range(5):
= torch.tensor([3., 3.],requires_grad=True)
_W = (X@_W)[i]
_u
_u.backward()= _W.grad.data B[:,i]
# X의 트랜스포즈 B
tensor([[ 1., 1., 1., 1., 1.],
[11., 12., 13., 14., 15.]])
X
tensor([[ 1., 11.],
[ 1., 12.],
[ 1., 13.],
[ 1., 14.],
[ 1., 15.]])
- 이론적인 결과와 일치
잠깐 생각해보자..
-
결국 위의 예제에 한정하여 임의의 \({\bf \hat{W}}\)에 대한 \(\frac{\partial}{\partial {\bf \hat W}}loss\)는 아래와 같이 계산할 수 있다.
- (단계1) \(2{\bf v}\)를 계산하고
- (단계2) (단계1)의 결과 앞에 \(-{\bf I}\)를 곱하고
- (단계3) (단계2)의 결과 앞에 \({\bf X}^\top\)를 곱한다.
-
step1에서 \({\bf v}\)는 어떻게 알지?
X \(\to\) u=X@W \(\to\) v = y-u
그런데 이것은 우리가 loss를 구하기 위해서 이미 계산해야 하는것 아니었나?
step1: yhat, step2: loss, step3: derivate, step4: update
-
(중요) step2에서 loss만 구해서 저장할 생각 하지말고 중간과정을 다 저장해라. (그중에 v와 같이 필요한것이 있을테니까) 그리고 그걸 적당한 방법을 통하여 이용하여 보자.
backprogation 알고리즘 모티브
-
아래와 같이 함수의 변환을 아키텍처로 이해하자. (함수의입력=레이어의입력, 함수의출력=레이어의출력)
- \({\bf X} \overset{l1}{\to} {\bf X}{\bf W} \overset{l2}{\to} {\bf y} -{\bf X}{\bf W} \overset{l3}{\to} ({\bf y}-{\bf X}{\bf W})^\top ({\bf y}-{\bf X}{\bf W})\)
-
그런데 위의 계산과정을 아래와 같이 요약할 수도 있다. (\({\bf X} \to {\bf \hat y} \to loss\)가 아니라 \({\bf W} \to loss({\bf W})\)로 생각해보세요)
- \({\bf W} \overset{l1}{\to} {\bf u} \overset{l2}{\to} {\bf v} \overset{l3}{\to} loss\)
-
그렇다면 아래와 같은 사실을 관찰할 수 있다.
- (단계1) \(2{\bf v}\)는 function of \({\bf v}\)이고, \({\bf v}\)는 l3의 입력 (혹은 l2의 출력)
- (단계2) \(-{\bf I}\)는 function of \({\bf u}\)이고, \({\bf u}\)는 l2의 입력 (혹은 l1의 출력)
- (단계3) 마찬가지의 논리로 \({\bf X}^\top\)는 function of \({\bf W}\)로 해석할 수 있다.
-
요약: \(2{\bf v},-{\bf I}, {\bf X}^\top\)와 같은 핵심적인 값들이 사실 각 층의 입/출력 값들의 함수꼴로 표현가능하다. \(\to\) 각 층의 입/출력 값들을 모두 기록하면 미분계산을 유리하게 할 수 있다.
- 문득의문: 각 층의 입출력값 \({\bf v}, {\bf u}, {\bf W}\)로 부터 \(2{\bf v}, -{\bf I}, {\bf X}^\top\) 를 만들어내는 방법을 모른다면 헛수고 아닌가?
- 의문해결: 어차피 우리가 쓰는 층은 선형+(렐루, 시그모이드, …) 정도가 전부임. 따라서 변환규칙은 미리 계산할 수 있음.
-
결국
(1)
순전파를 하면서 입출력값을 모두 저장하고
(2)
그에 대응하는 층별 미분계수값 \(2{\bf v}, -{\bf I}, {\bf X}^\top\) 를 구하고
(3)
층별미분계수값을 다시 곱하면 (그러니까 \({\bf X}^\top (-{\bf I}) 2{\bf v}\) 를 계산) 된다.
backpropagation
(1)
순전파를 계산하고 각 층별 입출력 값을 기록
- yhat = net(X)
- loss = loss_fn(yhat,y)
(2)
역전파를 수행하여 손실함수의 미분값을 계산
- loss.backward()
-
참고로 (1)에서 층별 입출력값은 GPU의 메모리에 기록된다.. 무려 GPU 메모리..
-
작동원리를 GPU의 관점에서 요약 (슬기로운 GPU 활용)
gpu특징: 큰 차원의 매트릭스 곱셈 전문가 (원리? 어마어마한 코어숫자)
- 아키텍처 설정: 모형의 파라메터값을 GPU 메모리에 올림 //
net.to("cuda:0")
- 순전파 계산: 중간 계산결과를 모두 GPU메모리에 저장 (순전파 계산을 위해서라면 굳이 GPU에 있을 필요는 없으나 후에 역전파를 계산하기 위한 대비) //
net(X)
- 오차 및 손실함수 계산:
loss = loss_fn(yhat,y)
- 역전파 계산: 순전파단계에서 저장된 계산결과를 활용하여 손실함수의 미분값을 계산 //
loss.backward()
- 다음 순전파 계산: 이전값은 삭제하고 새로운 중간계산결과를 GPU메모리에 올림
- 반복.
some comments
-
역전파기법은 체인룰 + \(\alpha\) 이다. - 미분 계산을 하기 위함인데 여기서 파라메터 업데이트 필요하지
-
오차역전파기법이라는 용어를 쓰는 사람도 있다.
-
이미 훈련한 네트워크에 입력 \(X\)를 넣어 결과값만 확인하고 싶을 경우 순전파만 사용하면 되고, 이 상황에서는 좋은 GPU가 필요 없다. - 예) 개/고양이 확인 등
기울기소멸
고요속의 외침
-
https://www.youtube.com/watch?v=ouitOnaDtFY
-
중간에 한명이라도 잘못 말한다면..
정의
-
In machine learning, the vanishing gradient problem is encountered when training artificial neural networks with gradient-based learning methods and backpropagation.
이해
-
당연한것 아닌가?
- 그레디언트 기반의 학습 (그레디언트 기반의 옵티마이저): 손실함수의 기울기를 통하여 업데이트 하는 방식
- 역전파: 손실함수의 기울기를 구하는 테크닉 (체인룰 + \(\alpha\)). 구체적으로는 (1) 손실함수를 여러단계로 쪼개고 (2) 각 단계의 미분값을 각각 구하고 (3) 그것들을 모두 곱하여 기울기를 계산한다.
- 0 근처의 숫자를 계속 곱하면 터지거나 0으로 간다. (사실 안정적인 기울기가 나올 것이라고 생각하는것 자체가 이상함)
0 전달되면 업데이트 안 되잖아
import numpy as np
= np.random.uniform(low=-2,high=2,size=100)
grads grads
array([ 1.27649548, -1.3435985 , -1.98858349, 1.98266931, 0.74704939,
-0.4831162 , 1.41216797, -1.20423568, 0.66637324, 1.18085266,
0.23356958, -0.39851281, 0.2357107 , -0.28592461, -0.96001359,
-1.6276445 , -0.75687257, 0.48770524, 0.02553662, 0.18478814,
1.28850714, 1.41398052, -0.33970936, 0.36829707, 1.85991256,
0.02243541, -0.68804507, 0.63659842, -1.13905311, 0.94093391,
1.58809026, -0.25106013, -0.14446307, 1.31747003, 1.52190566,
-0.44264824, -1.95722305, -0.77865942, -0.3350363 , -0.53638126,
-0.77254936, -1.22118632, 0.6137345 , 0.89975951, -1.70293244,
1.42661365, -0.43175558, -1.30904545, -0.53912915, 1.51725173,
-1.83965849, 1.00143736, -0.67129779, 0.36061957, -1.68850939,
-0.4272909 , -0.34715325, 1.72387253, -0.98340508, -1.60825385,
1.64523373, -0.79036932, 1.82578785, -0.53592773, -0.61384056,
0.9689625 , 1.27971335, 0.51555469, -0.53425795, 0.38883373,
-0.28595978, -1.93730647, -1.94581503, -0.48984819, -1.21831701,
-1.25965989, 1.79542393, 1.2637913 , -0.93178556, -0.61210568,
1.23775906, -1.80601708, 1.40265496, -0.59602715, 1.44638486,
-1.71721283, 1.58345756, -1.03992841, 1.10167726, 1.13332066,
-0.76344022, -0.7246539 , 0.27256115, -1.95501872, -0.65922909,
0.78715854, -0.29077574, -0.45110518, -1.64836114, 1.91692815])
grads.prod()
-4.089052412862103e-11
- 기울기가 소멸함
= np.random.uniform(low=-5,high=5,size=100)
grads grads.prod()
-1.6059047739389678e+16
- 기울기가 폭발함.
= np.random.uniform(low=-1,high=3.5,size=100)
grads grads.prod()
13058.879478242436
-
도깨비: 기울기가 소멸하기도 하고 터지기도 한다.
해결책 (기울기 소멸에 대한 해결책)
-
Multi-level hierarchy
- 여러층을 쪼개서 학습하자 \(\to\) 어떻게? 사전학습, 층벼학습
- 기울기소실문제를 해결하여 딥러닝을 유행시킨 태초의(?) 방법임.
- 결국 입력자료를 바꾼뒤에 학습하는 형태
-
Gradient clipping
- 너무 큰 값의 기울기는 사용하지 말자. (기울기 폭발에 대한 대비책)
-
Faster hardware
- GPU를 중심으로 한 테크닉
- 근본적인 문제해결책은 아니라는 힌튼의 비판
- CPU를 쓸때보다 GPU를 쓰면 약간 더 깊은 모형을 학습할 수 있다 정도?
-
Residual Networks, LSTM
- 아키텍처를 변경하는 방법
-
Other activation functions
렐루의 개발
렐루가 음수는 아예 0, 양수는 기울기 확실하니까
-
배치정규화
- 어쩌다보니 되는것.
- 배치정규화는 원래 공변량 쉬프트를 잡기 위한 방법임. 그런데 기울기 소멸에도 효과가 있음. 현재는 기울기소멸문제에 대한 해결책으로 빠짐없이 언급되고 있음. 2015년의 원래 논문에는 기울기소멸에 대한 언급은 없었음. (https://arxiv.org/pdf/1502.03167.pdf)
- 심지어 배치정규화는 오버피팅을 잡는효과도 있음 (이것은 논문에 언급했음)
-
기울기를 안구하면 안되나?
- 베이지안 최적화기법: (https://arxiv.org/pdf/1807.02811.pdf) \(\to\) GPU를 어떻게 쓰지? \(\to\) 느리다