CastleJo의 개발일지

Ai Math - 벡터와 행렬, 그리고 경사하강법

|

Vector

\[\text{열벡터 } X = \begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix} \qquad \text{행벡터 }X^T = \begin{bmatrix} 1, 2, 3 \end{bmatrix}\]

개념적 관점

  • 공간상의 한 점
  • 원점으로부터 상대적 위치
  • 숫자를 곱해주면 길이만 변한다
    이를 스칼라곱이라 부르고, 음수를 곱한다면 반대 방향으로 바뀐다.

프로그래밍 관점

  • 벡터는 숫자를 원소로 가지는 배열 혹은 리스트

  • np.array([1,2,3])

  • 보통 프로그래밍의 영역에서는 행벡터를 기본 형태로 본다. 따라서, 수학적인 연산을 하기 위해서는 np.transpose()와 같은 메소드를 사용하여 변환한다.

벡터의 성질

  • 벡터는 같은 모양을 가지면 덧셈,뺄셈 연산을 할 수 있다.
    \(\begin{bmatrix} x_1 \\ x_2 \\ x_3 \end{bmatrix} \pm \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} = \begin{bmatrix} x_1 \pm y_1 \\ x_1 \pm y_2 \\ x_3 \pm y_3 \end{bmatrix}\)

  • 벡터는 같은 모양을 가지면 성분곱(Hadamard product)를 계산할 수 있다. \(\begin{bmatrix} x_1 \\ x_2 \\ x_3 \end{bmatrix} \odot \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} = \begin{bmatrix} x_1 * y_1 \\ x_1 * y_2 \\ x_3 * y_3 \end{bmatrix}\)

벡터의 노름(norm)

  • 원점에서부터의 거리
  • L1-Norm
    • 변화량의 절대값을 모두 더한다 \(\lVert x \rVert _1 = \sum_{i=1}^d \left\vert x_i \right\vert\)
    • Robust 학습, Rasso 회귀 등에서 사용
        def l2_norm(x : list):
            x_norm = np.abs(x)
            x_norm = np.sum(x_norm)
            return x_norm
      
  • L2-Norm
    • 피타고라스 정리를 이용한 유클리드 거리를 계산한다 \(\lVert x \rVert _2 = \sqrt{\sum_{i=1}^d x_i^2}\)
    • Laplace 근사, Ridge 회귀 등에서 사용
        def l1_norm(x : list):
            x_norm = x*x
            x_norm = np.sum(x_norm)
            x_norm = np.sqrt(x_norm)
            return x_norm
      
  • Norm의 종류에 따라 기하학적 성질이 달라져, 둘 다 사용한다.

  • 벡터의 뺄셈을 이용하여 두 벡터사이의 거리를 계산할 수 있다.

  • L2-Norm을 사용해 원점에서 두 벡터 사이의 각도를 구할 수 있다. \(\cos \theta = \frac {<x,y>} {\lVert x \rVert_2 \lVert y \rVert_2}\) \(<x,y> = \sum_{i=1}^d x_i y_i\)

벡터의 내적

  • 내적은 정사영된 벡터의 길이와 관련이 있다. > 정사영: Proj(x)라 부르며 벡터 y로 정사영된 벡터 x의 그림자 라고 부른다. \(Proj(x) = ||x||cos\theta\)

  • 내적은 정사영의 길이를 벡터 y의 길이   y   만큼 조정한 값이다.
\[\langle x, y\rangle=\|x\|_{2}|| y \|_{2} \cos \theta\]

행렬

  • 벡터를 원소로 가지는 2차원 배열
\[\begin{bmatrix} 1,2,3 \\ 4,5,6 \\ 7,8,9 \end{bmatrix}\]
  • 프로그래밍 관점에서는 행렬이 뒤바뀐다. \(X_{열행}\)

    따라서 수학적 연산을 할 땐 전치행렬을 적용시켜준다.

  • 행렬은 벡터와 마찬가지로 같은 형태일 때 덧셈, 뺄셈, 성분곱, 스칼라곱을 할 수 있다.

행렬곱셈

  • X의 i번째 행 벡터와 Y의 j번째 열 벡터 사이의 내적
\[XY = \sum_{k} X_{ik}Y_{kj}\]
  • numpy 에서는 X @ Y 연산을 사용한다.

  • numpy.inner()은 X의 i번째 행벡터와 Y의 j번쨰 행벡터의 내적을 나타낸다. 수학에서의 내적과 달라, 주의해야 한다.

행렬은 연산자이다.

  • 행렬곱을 통해 벡터를 다른 차원의 공간으로 보낼 수 있다.

  • 행렬곱을 통해 데이터를 추출, 압축할 수 있다.

역행렬

  • 어떤 행렬 A의 연산을 거꾸로 되돌리는 행렬을 역행렬이라 한다.

  • np.linalg.inv(x)를 통해 사용한다.

  • 역행렬은 행과 열 숫자가 같고 행렬식이 0이 아닌 경우에만 계산할 수 있다.

    • 만약 역행렬을 계산할 수 없는 행렬이면, 유사 역행렬(pseudo-inverse) 또는 무어펜로즈 역행렬(Moore-Penrose inverse)을 이용한다.
    • np.linalg.pinv()로 사용한다.

역행렬의 응용

  • 연립방정식 풀기

    \(2x + 3y = 8\) \(1x + 1y = 3\)
    아래와 같이 나타낼 수 있다.
    \((A)\begin{bmatrix} 2,3 \\ 1,1 \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} = (B)\begin{bmatrix} 8 \\ 3 \end{bmatrix}\) \(\begin{bmatrix} x \\ y \end{bmatrix} = A^+B=A^T(AA^T)\)

  • 선형회귀분석

    \[\left[\begin{array}{c} -\mathbf{x}_{1}- \\ \overline{\mathbf{x}}_{2} \overline{\mathbf{x}} \\ \vdots \\ -\mathbf{x}_{n} \end{array}\right]\left[\begin{array}{c} \beta_{1} \\ \beta_{2} \\ \vdots \\ \beta_{m} \end{array}\right] \neq\left[\begin{array}{c} y_{1} \\ y_{2} \\ \vdots \\ y_{m} \end{array}\right]\]
    • 선형회귀분석은 연립방정식과 달리 행이 더 크므로 방정식을 푸는건 불가능하다.

    • np.linalg.pinv()를 사용해 L2노름을 최소화하는 선형회귀식을 찾을 수 있다.

    \[\begin{aligned} \mathbf{X} \beta=& \hat{\mathbf{y}} \approx \mathbf{y} \Rightarrow \beta=\mathbf{X}^{+} \mathbf{y} \\ =&\left(\mathbf{X}^{\top} \mathbf{X}\right)^{-1} \mathbf{X}^{\top} \mathbf{y} \end{aligned}\]
    • Sklearn 라이브러리의 LinearRegression을 사용해도 같은 결과를 가져올 수 있다.

Gradient Descent

  • 변수의 움직임에 따른 함수값의 변화를 측정하는 미분을 이용하여 극값을 찾기 위한 방법으로 최적화에서 제일 많이 사용된다.

    \[f^{\prime}(x)=\lim _{h \rightarrow 0} \frac{f(x+h)-f(x)}{h}\]
  • 미분은 함수의 해당 지점에서 기울기를 구할 수 있는데, 이를 이용해 미분값이 0에 가까워지는 부분까지 업데이트하는 것을 경사하강법 이라고 한다.

      # var = 시작점
      # gradient = 기울기를 계산하는 함수
      # lr = 학습률
      # eps = 알고리즘 종료 조건
      var = init
      grad = gradient(var)
      while(norm(grad) > eps):
          var = var - lr*grad
          grad = gradient(var)
    
    
  • 변수가 벡터라면 *편미분을 이용하여 동시에 업데이트 한다

경사하강법으로 선형회귀 계수 구하기

  • 아래와 같은 방법으로 그레디언트 벡터를 구한다 \(\partial_{\beta_{k}\|\mathbf{y}-\mathbf{X} \beta\|_{2}}=\partial_{\beta_{k}}\left\{\frac{1}{n} \sum_{i=1}^{n}\left(y_{i}-\sum_{j=1}^{d} X_{i j} \beta_{j}\right)^{2}\right\}^{1 / 2}\) \(=-\frac{\mathbf{X}_{\cdot k}^{\top}(\mathbf{y}-\mathbf{X} \beta)}{n\|\mathbf{y}-\mathbf{X} \beta\|_{2}}\)

  • 이제 목적식을 최소화하는 B를 구하는 경사하강법 알고리즘이 도출되었다.

    \[\beta^{(t+1)} = \beta^{(t)}+\frac{\lambda}{n} \frac{\mathbf{X}^{\top}\left(\mathbf{y}-\mathbf{X} \beta^{(t)}\right)}{\left\|\mathbf{y}-\mathbf{X} \beta^{(t)}\right\|}\] \[\beta^{(t+1)} \quad \beta^{(t)}+\frac{2 \lambda}{n} \mathbf{X}^{\top}\left(\mathbf{y}-\mathbf{X} \beta^{(t)}\right)\]
    
      for t in range(T):
          error = Y - X @ beta
          grad = -transpose(X) @ error
          beta = beta - lr*grad
    
    

경사하강법은 만능인가?

  • 함수가 미분 가능하고 볼록한 함수에 대해선 적절한 하이퍼파라미터를 조정했을 때 수렴이 보장된다.
  • 하지만 비선형회귀 문제일 경우 항상 수렴이 보장하지 않는다.

Stochastic Gradient Descent

  • 모든 데이터가 아닌, 데이터의 일부를 활용하여 업데이트 하는 것

  • 볼록이 아닌 목적식도 최적화할 수 있다

  • 좀 더 효율적인 자원 활용이 가능하다.

  • 매번 다른 mini-batch를 활용하므로 곡선 모양이 계속 바뀌게 된다.

피어세션 정리

역전파, 경사하강법에 대한 토의, 추후 정리 예정

학습 회고

컴공 4학년을 수료해왔지만, 아예 다른 분야라는 것을 알게되었다.
아예 새로 시작한다는 마음으로 열심히 해봐야겠다.