for textmining

선형대수학 중간고사 정리

|

최근 선형대수학 중간고사를 보게 됐는데 제 개인적 정리 용도로 업로드하는 글입니다.

Comment  Read more

Representation Learning

|

이번 글에서는 representation learning 개념에 대해 살펴보도록 하겠습니다. 딥뉴럴네트워크가 높은 성능을 내는 배경에는 복잡한 데이터 공간을 선형 분류가 가능할 정도로 단순화해 표현하기 때문이라는 이론인데요. 저도 공부하는 입장이니 많은 의견 부탁드립니다.

이번 글은 김현중, 고태훈 서울대 박사과정이 진행한 2017년 패스트캠퍼스 강의를 정리했음을 먼저 밝힙니다. 그럼 시작하겠습니다.

선형 모델의 한계

다중선형회귀(Multiple Linear Regression)는 설명변수(X)와 종속변수(Y) 사이의 관계를 선형으로 가정하고, 데이터와의 오차가 가장 작은 직선을 찾는 것을 목표로 합니다. 분류 문제도 마찬가지인데요. 선형판별분석(Linear Discriminant Analysis)이나 로지스틱 회귀분석(Logistic Regression)도 항상 선형 분류 경계면을 만들어 냅니다.

이를 시각적으로 이해해 보면, 아래 그림의 경우 모델의 학습 결과로 하나의 직선(hyperplane), 즉 $[-1,1,1]^T$가 도출된 것을 확인할 수 있습니다. 선형 모델은 바로 이런 직선을 찾는 것이 학습의 목표가 됩니다.

하지만 XOR 문제와 같이 데이터가 선형 관계가 아닐 경우 이들 모델은 높은 성능을 낼 수 없습니다. 아래 그림처럼 어떤 직선을 그어도 두 범주를 분류할 수가 없게 되거든요. 뉴럴네트워크의 할아버지격인 퍼셉트론(Perceptron)이 제시된 배경이기도 합니다.

뉴럴네트워크의 기본 구조

뉴럴네트워크를 이해해 보겠다면서 선형모델의 한계를 먼저 언급하고 있는 이유는 뉴럴네트워크의 본질이 사실상 선형 모델이기 때문입니다. 아래 그림은 뉴럴네트워크를 구성하고 있는 하나의 뉴런(neuron)을 나타낸 것입니다. 보시다시피 활성함수(activation function) 적용 직전의 값들은 가중치($w_i$)와 입력값($x_i$) 사이의 선형결합(linear combination)임을 확인할 수 있습니다. (아래 그림은 미국 스탠포드대학의 CS231n 강좌에서 퍼왔습니다)

다만 여기에서 활성함수에 주목해야 합니다. 퍼셉트론과 뉴럴네트워크의 큰 차이점 가운데 하나는 바로 활성함수 여부에 있거든요. 활성함수는 보통 시그모이드, 하이퍼볼릭탄젠트, ReLU 등과 같이 비선형 함수를 씁니다. 이를 통해 선형모델의 한계를 극복하고자 한 것이죠. 활성함수에 대한 자세한 내용은 이곳을 참고하시기 바랍니다.

XOR문제를 풀기 위한 단순 뉴럴네트워크

그럼 XOR 예시를 통해 뉴럴네트워크가 Representation Learining와 어떤 관련을 맺고 있는지 살펴보겠습니다. 아래 중앙 그림과 같은 XOR 문제를 풀기 위해 층이 두 개인 단순 뉴럴네트워크를 구축해 보겠습니다.

학습 결과 1층 첫번째 뉴런의 $h_1$이 아래 식처럼 도출될 경우 분류경계면은 하단 중앙의 연두색 선이 되고, 네트워크 전체 구조는 하단 좌측의 그림이 될 겁니다.

[{ h }{ 1 }={ x }{ 1 }+{ x }_{ 2 }-\frac { 3 }{ 2 }]

1층 첫번째 뉴런의 출력값인 $z_1$은 입력값과 가중치들의 선형결합으로 이뤄진 $h_1$이 활성함수($g$)에 의해 활성화된 것입니다. 뉴럴네트워크는 퍼셉트론과 흡사하나 활성함수가 추가됐다는 점이 다르다고 합니다. $g$는 아래와 같이 단순한 비선형 함수입니다.

[{ z }{ 1 }=g({ h }{ 1 })=\begin{Bmatrix} 1\quad if\quad { h }{ 1 }\ge 0 \ 0\quad if\quad { h }{ 1 }<0 \end{Bmatrix}]

이번엔 1층 두번째 뉴런의 출력값 $z_2$를 만들어 보겠습니다. $h_2$는 아래와 같고요, 활성함수는 $g$ 그대로 입니다.

\({ h }_{ 2 }={ x }_{ 1 }+{ x }_{ 2 }-\frac { 5 }{ 2 },\quad { z }_{ 2 }=g({ h }_{ 2 })\)

자, 이제 거의 다 왔습니다. 이번엔 전체 네트워크의 출력값 $z$를 만들어 보겠습니다. 학습 결과물은 다음과 같다고 칩시다.

\({ o }_{ 1 }={ z }_{ 1 }-{ z }_{ 2 }-1,\quad z=g({ o }_{ 1 })\)

최종 결과물 $z$를 보시면 동그라미와 네모 두 범주를 잘 분리하고 있는 점을 확인할 수 있습니다.

뉴럴네트워크와 Represention Learning

위에서 예시로 든 단순 뉴럴네트워크의 학습과정을 좌표 축 위에 그리면 아래 그림과 같습니다. 이 모델의 첫번째 층은 입력값 $(x_1, x_2)$를 받아서 $(z_1, z_2)$를 출력합니다. 이 덕분에 모델의 두번째 층은 직선 하나만으로도 데이터의 범주를 분리해낼 수 있게 됐습니다. 기존대로라면 선형으로 분리할 수 없는 데이터가 선형 분리가 가능하게끔 데이터가 변형됐다는 얘기입니다. 다시 말해 뉴럴네트워크의 학습 과정에서 데이터의 representaion이 $(x_1, x_2)$에서 $(z_1, z_2)$로 바뀐 겁니다.

이 글에서는 설명의 편의를 위해 단순 뉴럴네트워크를 예로 들었으나, 깊고 방대한 뉴럴네트워크는 학습데이터가 꽤 복잡한 represention이어도 이를 선형 분리가 가능할 정도로 단순화하는 데 좋은 성능을 낸다고 합니다. 이 때문에 뉴럴네트워크를 representation learner라고 부르는 사람들도 있습니다.

Comment  Read more

주성분분석(Principal Component Analysis)

|

이번 글에서는 차원축소(dimensionality reduction)변수추출(feature extraction) 기법으로 널리 쓰이고 있는 주성분분석(Principal Component Analysis)에 대해 살펴보도록 하겠습니다. 이번 글은 고려대 강필성 교수님과 역시 같은 대학의 김성범 교수님 강의를 정리했음을 먼저 밝힙니다. 그럼 시작하겠습니다.

기법 개요

PCA는 데이터의 분산(variance)을 최대한 보존하면서 서로 직교하는 새 기저(축)를 찾아, 고차원 공간의 표본들을 선형 연관성이 없는 저차원 공간으로 변환하는 기법입니다. 이를 그림(출처)으로 나타내면 아래와 같습니다. 2차원 공간에 있는 데이터들이 하나의 주성분(PC1)을 새로운 기저로 선형변환된 걸 확인할 수 있습니다. 여기에서 핑크색 표시가 돼 있는 사선축이 원 데이터의 분산을 최대한 보존하는(=데이터가 가장 많이 흩뿌려져 있는) 새 기저입니다. PCA의 목적은 바로 이런 축을 찾는 데 있습니다.

Feature Extraction

변수추출(Feature Extraction)은 기존 변수를 조합해 새로운 변수를 만드는 기법으로, 단순히 일부 중요 변수만을 빼내는 변수선택(Feature Selection)과는 대비됩니다. 변수추출에는 기존 변수 가운데 일부만 활용하는 방식이 있고, 모두 쓰는 방식이 있는데 PCA는 후자에 해당합니다. 아울러 PCA는 기존 변수를 선형결합(linear combination)해 새로운 변수를 만들어 냅니다.

예컨대 PCA는 변수가 $p$개, 관측치가 $n$개 있는 데이터 $X$(p x n)로 새로운 변수 $z$를 아래와 같이 만드는 과정으로 이해하면 좋을 것 같습니다. 여기에서 벡터 $x_i$는 데이터 행렬 $X$의 $i$번째 변수에 해당하는 행벡터(1 x n)인데요, 이들을 적절히 조합해 새로운 벡터 $z_i$ (1 x n)들을 만들어내는 것입니다.

[\begin{align} \overrightarrow { { z }_{ 1 } } &={ \alpha }_{ 11 }\overrightarrow { { x }_{ 1 } } +{ \alpha }_{ 12 }\overrightarrow { { x }_{ 2 } } +…+{ \alpha }_{ 1p }\overrightarrow { { x }_{ p } } ={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }X\ \overrightarrow { { z }_{ 2 } } &={ \alpha }_{ 21 }\overrightarrow { { x }_{ 1 } } +{ \alpha }_{ 22 }\overrightarrow { { x }_{ 2 } } +…+{ \alpha }_{ 2p }\overrightarrow { { x }_{ p } } ={ \overrightarrow { { \alpha }_{ 2 } } }^{ T }X\ &…\ \overrightarrow { { z }_{ p } } &={ \alpha }_{ p1 }\overrightarrow { { x }_{ 1 } } +{ \alpha }_{ p2 }\overrightarrow { { x }_{ 2 } } +…+{ \alpha }_{ pp }\overrightarrow { { x }_{ p } } ={ \overrightarrow { { \alpha }_{ p } } }^{ T }X \end{align}]

사실 위와 같은 식의 선형결합은 선형변환으로도 이해할 수 있습니다. 바꿔 말하면 벡터 $z_i$는 $X$를 $α_i$( p x 1)라는 새로운 축에 사영(projection)시킨 결과물이라는 것이죠. 선형변환에 대해 살펴보시려면 이곳을, 사영에 대해 보시려면 이곳 방문을 권해 드립니다. 어쨌든 변수추출로 새롭게 만들어진 $z_i$로 구성된 행렬 $Z$는 아래와 같이 적을 수 있습니다.

[Z=\begin{bmatrix} \overrightarrow { { z }{ 1 } } \ \overrightarrow { { z }{ 2 } } \ … \ \overrightarrow { { z }{ p } } \end{bmatrix}=\begin{bmatrix} { \overrightarrow { { \alpha }{ 1 } } }^{ T }X \ { \overrightarrow { { \alpha }{ 2 } } }^{ T }X \ … \ { \overrightarrow { { \alpha }{ p } } }^{ T }X \end{bmatrix}=\begin{bmatrix} { \overrightarrow { { \alpha }{ 1 } } }^{ T } \ { \overrightarrow { { \alpha }{ 2 } } }^{ T } \ … \ { \overrightarrow { { \alpha }_{ p } } }^{ T } \end{bmatrix}X={ A }^{ T }X]

PCA의 목적과 solution

위 식에서 각 변수와 결합하는 계수들만 알면 PCA를 수행할 수 있게 됩니다. 앞서 설명드렸듯이 PCA의 목적은 원데이터 행렬 $X$의 분산을 최대한 보존하는 데 있기 때문에 $Z$의 분산 또한 최대화되어야 합니다. 그럼 우리가 알고 싶은 미지수인 $p$차원 계수벡터를 $α$, $X$의 공분산행렬(covariance matrix)을 $Σ$로 둡시다. 그럼 아래와 같이 식을 쓸 수 있습니다.

[\begin{align} \max _{ \alpha }{ { Var(Z)} } &=\max _{ \alpha }{ { Var({ \overrightarrow { \alpha } }^{ T }X)} } \ &=\max _{ \alpha }{ { { \overrightarrow { \alpha } }^{ T }Var(X)\overrightarrow { \alpha } } } \ &=\max _{ \alpha }{ { { \overrightarrow { \alpha } }^{ T }\Sigma \overrightarrow { \alpha } } } \end{align}]

위 식을 만족하는 $α$는 무수히 많을 수 있습니다. 사실 $α$의 크기를 무작정 키우기만 해도 $Z$의 분산을 높일 수가 있게 되거든요. 이 때문에 아래와 같은 제약식을 둡니다.

[\left| \alpha \right| ={ \overrightarrow { \alpha } }^{ T }\overrightarrow { \alpha } =1]

이를 종합해 라그랑지안 문제로 변형하겠습니다.

[L={ \overrightarrow { \alpha } }^{ T }\Sigma \overrightarrow { \alpha } -\lambda ({ \overrightarrow { \alpha } }^{ T }\overrightarrow { \alpha } -1)]

최대값을 구하기 위해 $L$을 미지수 $α$로 미분한 식을 0으로 두어 정리하면 아래와 같습니다.

[\begin{align} \frac { \partial L }{ \partial \overrightarrow { \alpha } } =\Sigma \overrightarrow { \alpha } -\lambda \overrightarrow { \alpha } &=0\ (\Sigma -\lambda )\overrightarrow { \alpha } &=0 \end{align}]

고유벡터(eigenvector)의 정의에 의해 $α$는 데이터의 공분산행렬 $Σ$의 고유벡터, $λ$는 $Σ$의 고유값이 됩니다. 따라서 원데이터 $X$의 분산을 최대화하는 $α$는 $Σ$의 고유벡터라는 사실을 알 수 있습니다. $Σ$의 고유벡터를 주성분(Principal Component)이라고 합니다.

한편 공분산행렬은 비특이행렬(non-singular matrix)로 고유값과 고유벡터의 개수가 차원수($p$)만큼 존재한다고 합니다.

공분산행렬 고유벡터의 성질

데이터가 각 변수별로 평균이 0으로 맞춰져 있을 때(centering 작업 이미 수행되어 있다고 가정) 데이터 $X$의 공분산 행렬 $Σ$는 아래와 같이 구합니다.

[\Sigma=cov(X)=\frac { 1 }{ n-1 } X{ X }^{ T }\propto X{ X }^{ T }]

$X​$의 차원수가 p x n이라면, 공분산행렬 $Σ​$은 p x p 크기의 정방행렬(square matrix)이 됩니다. 또한 $Σ^T=Σ​$인 대칭행렬(symetric matrix)입니다.

열벡터가 공분산행렬 $Σ$의 고유벡터인 행렬을 $A$, 대각성분이 $Σ$의 고유값이고 대각성분을 제외한 요소값이 0인 행렬을 $Λ$라고 할 때 다음과 같이 식을 쓸 수 있습니다.

[\Sigma A=\Lambda A\ \Sigma =A\Lambda { A }^{ -1 }]

$Σ$는 대칭행렬이므로 식을 다음과 같이 정리할 수 있습니다.

[\begin{align} { \Sigma }^{ T }=&{ \left( { A }^{ -1 } \right) }^{ T }\Lambda { A }^{ T }\ =&A\Lambda { A }^{ -1 }=\Sigma \ \ \therefore &{ A }^{ -1 }={ A }^{ T } \ &{ A }^{ T }A=I \end{align}]

따라서 공분산행렬 $Σ$의 서로 다른 고유벡터끼리는 서로 직교(orthogonal)함을 확인할 수 있습니다. 원데이터를 공분산 행렬의 고유벡터로 사영하기 전에는 변수 간 연관성이 있었더라도 PCA 변환에 의하여 좌표축이 바뀐 데이터들은 서로 무상관(uncorrelated)이게 됩니다.

고유값과 새 변수의 분산

$Σ$는 원데이터 $X$의 공분산행렬이고, $Σ$의 가장 큰 고유값과 고유벡터를 각각 $λ_1$, $α_1$이라고 두겠습니다. 이 둘로 만든 새로운 변수 $z_1$와 그 분산은 아래와 같이 쓸 수 있습니다.

[\begin{align} \overrightarrow { { z }_{ 1 } } &={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }X\ Var(\overrightarrow { { z }_{ 1 } } )&={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }\Sigma \overrightarrow { { \alpha }_{ 1 } } \end{align}]

고유벡터의 정의에 의해 아래와 같은 식이 성립합니다.

[\Sigma \overrightarrow { { \alpha }{ 1 } } ={ \lambda }{ 1 }\overrightarrow { { \alpha }_{ 1 } }]

이를 원식에 대입하고, $α$를 단위벡터로 정한 제약식을 원용해 정리하면 다음과 같습니다.

[\begin{align} Var({ z }_{ 1 })&={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }\Sigma \overrightarrow { { \alpha }_{ 1 } } \ &={ { \overrightarrow { { \alpha }_{ 1 } } }^{ T }\lambda }_{ 1 }\overrightarrow { { \alpha }_{ 1 } } \ &={ \lambda }_{ 1 }{ \overrightarrow { { \alpha }_{ 1 } } }^{ T }\overrightarrow { { \alpha }_{ 1 } } \ &={ \lambda }_{ 1 } \end{align}]

요컨대 $Σ$의 제1 고유벡터로 만든 새로운 변수 $z_1$의 분산은 그에 해당하는 고유값 $λ_1$이라는 뜻입니다.

이를 확장하여 $Σ$의 $i$번째로 큰 고유값과 고유벡터를 각각 $λ_i$, $α_i$이라고 둡시다. 이들로 만든 새로운 변수 $z_i$의 분산은 그에 해당하는 고유값 $λ_i$가 됩니다. 따라서 $Σ$의 고유값 전체 합과 원데이터 $X$의 분산은 서로 같습니다.

PCA 예제 1

다음과 같은 데이터 $X​$가 주어졌다고 합시다. 변수는 3개, 관측치는 5개로 구성된 데이터입니다.

구분 $n_1$ $n_2$ $n_3$ $n_4$ $n_5$
$p_1$ 0.2 0.45 0.33 0.54 0.77
$p_2$ 5.6 5.89 6.37 7.9 7.87
$p_3$ 3.56 2.4 1.95 1.32 0.98

우선 변수(행)별로 평균을 0으로 centering한 행렬 $X’​$를 만듭니다.

구분 $n_1$ $n_2$ $n_3$ $n_4$ $n_5$
$p_1$ -1.1930 -0.0370 -0.5919 0.3792 1.4427
$p_2$ -1.0300 -0.7647 -0.3257 1.0739 1.0464
$p_3$ 1.5012 0.3540 -0.0910 -0.7140 -1.0502

$X$의 공분산행렬은 다음과 같이 구할 수 있습니다.

[\begin{align} \Sigma =cov(X)&=\frac { 1 }{ 5-1 } X’{ X’ }^{ T }\\ &=\begin{bmatrix} 0.0468 & 0.1990 & -0.1993 \ 0.1990 & 1.1951 & -1.0096 \ -0.1993 & -1.0096 & 1.0225 \end{bmatrix} \end{align}]

$Σ$를 고유분해한 결과는 아래와 같습니다. 행렬 $A$는 각각의 열벡터가 $Σ$의 고유벡터로 구성돼 있습니다. 대각행렬 $Λ$는 각각의 대각원소가 $Σ$의 고유값입니다. $λ_1(2.7596)$에 대응하는 고유벡터는 $α_1$($[0.5699,0.5765,-0.5855]^T$)입니다.

[\begin{align} \Sigma A&=A\Lambda \\ A&=\begin{bmatrix} \overrightarrow { { \alpha }_{ 1 } } & \overrightarrow { { \alpha }_{ 2 } } & \overrightarrow { { \alpha }_{ 3 } } \end{bmatrix}\ &=\begin{bmatrix} 0.5699 & 0.7798 & 0.2590 \ 0.5765 & -0.6041 & 0.5502 \ -0.5855 & 0.1643 & 0.7938 \end{bmatrix}\\ \Lambda &=\begin{bmatrix} { \lambda }_{ 1 } & 0 & 0 \ 0 & { \lambda }_{ 2 } & 0 \ 0 & 0 & { \lambda }_{ 3 } \end{bmatrix}\ &=\begin{bmatrix} 2.7596 & 0 & 0 \ 0 & 0.1618 & 0 \ 0 & 0 & 0.0786 \end{bmatrix} \end{align}]

그렇다면 우리는 여기에서 가장 큰 고유값에 해당하는 고유벡터로 새로운 변수 $z_1$을 만들 수 있습니다. 아래 식에서 $x_1, x_2, x_3$은 각각 $X’$의 행벡터이고, 이 벡터들 앞에 붙는 계수는 해당하는 고유벡터의 요소값입니다.

[\begin{align} \overrightarrow { { z }_{ 1 } } &={ \overrightarrow { { \alpha }_{ 1 } } }^{ T }X\ \ &=\begin{bmatrix} 0.5699 & 0.5765 & -0.5855 \end{bmatrix}\begin{bmatrix} \overrightarrow { { x }_{ 1 } } \ \overrightarrow { { x }_{ 2 } } \ \overrightarrow { { x }_{ 3 } } \end{bmatrix}\ \ &=0.5699\overrightarrow { { x }_{ 1 } } +0.5765\overrightarrow { { x }_{ 2 } } -0.5855\overrightarrow { { x }_{ 3 } } \ &=0.5699\begin{bmatrix} -1.1930 & -0.0370 & -0.5919 & 0.3792 & 1.4427 \end{bmatrix}\ &\quad+0.5765\begin{bmatrix} -1.0300 & -0.7647 & -0.3257 & 1.0739 & 1.0464 \end{bmatrix}\ &\quad-0.5855\begin{bmatrix} 1.5012 & 0.3540 & -0.0910 & -0.7140 & -1.0502 \end{bmatrix}\ &=\begin{bmatrix} -2.1527 & -0.6692 & -0.4718 & 1.2533 & 2.0404 \end{bmatrix} \end{align}]

여기에서 $z_1$의 첫번째 요소(스칼라) -2.1527의 의미를 곱씹어봅시다. 원데이터의 첫번째 데이터($n_1$)는 [-1.930, -1.0300, 1.5012]였습니다. 이 $n_1$이 첫번째 고유벡터 $α_1$과 내적된 결과가 바로 -2.1527입니다. 축에 해당하는 벡터가 유닛벡터일 때 벡터의 내적과 사영은 동일한 의미를 지닙니다. 따라서 -2.1527은 $n_1$을 $α_1$라는 축에 사영해 $α_1$에서 어디쯤 위치하는지 나타내주는 스칼라값이라고 보면 좋을 것 같습니다. 이를 그림으로 나타내면 다음과 같습니다.

$z_1$의 두번째 요소 -0.6692는 원데이터의 두번째 데이터 $n_2$를 $α_1$라는 축에 사영한 결과로 볼 수 있습니다. 마찬가지 방식으로 $z_2, z_3$을 만들어 $Z$를 계산할 수 있습니다.

[Z={ A }^{ T }X\\ \begin{bmatrix} \overrightarrow { z_{ 1 } } \ \overrightarrow { z_{ 2 } } \ \overrightarrow { z_{ 3 } } \end{bmatrix}=\begin{bmatrix} { \overrightarrow { \alpha _{ 1 } } }^{ T } \ { \overrightarrow { \alpha _{ 2 } } }^{ T } \ { \overrightarrow { \alpha _{ 3 } } }^{ T } \end{bmatrix}X=\begin{bmatrix} -2.1527 & -0.6692 & -0.4718 & 1.2533 & 2.0404 \ -0.0615 & 0.4912 & -0.2798 & -0.4703 & 0.3204 \ 0.3160 & -0.1493 & -0.4047 & 0.1223 & 0.1157 \end{bmatrix}]

그러면 $Z$의 공분산행렬을 구해보겠습니다. 아래와 같습니다.

[cov(Z)=\begin{bmatrix} 2.7596 & 0 & 0 \ 0 & 0.1618 & 0 \ 0 & 0 & 0.0786 \end{bmatrix}]

보시다시피 새 변수 $z_1, z_2, z_3$ 사이에 공분산이 0이어서 무상관(uncorrelated) 관계가 된 것을 확인할 수 있습니다. 이는 $Σ$의 고유벡터는 서로 직교하는데, $X$가 이 고유벡터를 새로운 축, 즉 주성분으로 하여 선형변환되었기 때문입니다.

아울러 앞선 증명에서 살펴보았든 $z_1$의 분산은 $λ_1$이라는 사실 또한 확인할 수 있습니다. 만약 새 변수로 $z_1$만 남기고 나머지를 생략하게 된다면 아래 식과 같이 원데이터 $X$ 분산의 92%를 보존하면서도 원데이터를 3차원에서 1차원으로 줄일 수 있게 됩니다. 다시 말해 3개 주성분 가운데 첫번째 주성분(PC1)을 선택해도 원데이터의 설명력을 어느 정도 보존할 수 있다는 이야기입니다.

[\frac { { \lambda }{ 1 } }{ { \lambda }{ 1 }+{ \lambda }{ 2 }+{ \lambda }{ 3 } } =\frac { 2.7596 }{ 2.7596+0.1618+0.0786 } =0.920]

loading plot

PCA는 기존 변수를 선형결합하는 과정에서 새 변수를 만들게 되는데요, 선형결합의 계수들을 가지고 시각화를 하면 각 변수별로 중요도를 어림짐작할 수 있습니다.

위 그림의 가로축은 가장 큰 고유값에 해당하는 주성분(PC1)의 계수를 뜻합니다. 세로축은 두번째 주성분(PC2)의 계수입니다. 여기에서 기존 변수 $x_2$는 PC1을 만들 때 상대적으로 중요하지만, PC2에는 그렇지 않음을 알 수 있습니다. $x_3$는 반대로 PC1에는 덜 중요하고, PC2에는 중요함을 알 수 있습니다.

PCA 예제 2

이번엔 R로 분석하는 예제를 소개합니다. 내장 데이터인 iris를 대상으로 PCA를 적용해 보기로 했습니다. PCA를 수행한 뒤 summary 함수를 쓰면 아래와 같은 표를 얻을 수 있습니다. iris의 독립변수는 네 개이므로 PCA를 수행하면 네 개의 주성분을 얻을 수 있고, 각 축이 전체 데이터의 분산에서 차지하는 비율을 의미합니다.

구분 PC1 PC2 PC3 PC4
변수 비율 0.7296245 0.2285076 0.03668922 0.005178709

2D Score Plot을 그리면 아래 그림과 같습니다. PC1, PC2 두 개만으로도 전체 데이터 분산의 95.8%를 보존하고 있기 때문에 2차원으로 시각화해도 원 데이터의 모양을 파악하는 데 문제가 없습니다.

loading plot은 아래 그림과 같습니다. PC1 기준으로는 ‘Petal.Length’, ‘Petal.Width’, ‘Sepal.Length’가 비교적 중요한 변수임을 확인할 수 있습니다. PC2 입장에서는 ‘Sepal.Width’가 중요한 변수입니다.

위 분석에 사용한 R 코드는 아래와 같습니다.

library(rgl)
library(devtools)
install_github("vqv/ggbiplot")
library(ggbiplot)

# PCA
# cor = whether the calculation should use the correlation matrix or the covariance matrix
# score = whether the score on each principal component should be calculated
pcadata < princomp(iris[,1:4], cor=T, scores=T)
# summary
plot(pcadata, type='l')
summary(pcadata)

# 2d score plot
ggbiplot(pcadata,groups = iris$Species)

# loading plot
plot(pcadata$loadings[,1:2], col=c('black','blue','red','green'), pch=16)
legend('topleft',
	 c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width'),
     text.col=c('black','blue','red','green'))

PCA의 절차

지금까지 논의한 내용을 바탕으로 PCA 수행절차를 정리하면 다음과 같습니다.

  1. 기존 데이터 $X$의 공분산행렬 계산
  2. 공분산행렬의 고유값과 고유벡터 계산
  3. 고유값의 크기 순서대로 고유벡터를 나열
  4. 정렬된 고유벡터 가운데 일부 선택
  5. 해당 고유벡터와 $X$ 내적

PCA는 서로 직교하는 새 기저로 데이터를 변환하기 때문에 변수 간 상관관계가 높은 데이터에 효과가 좋다고 합니다. 데이터 차원축소, 압축에 널리 쓰이고 있습니다.

Comment  Read more

딥러닝 학습 기술들

|

이번 글은 딥러닝 관련 다양한 학습기술들을 살펴보고자 합니다. 이번 글은 미국 스탠포드 대학의 CS231n과 역시 같은 대학의 CS224d 강좌를 정리했음을 먼저 밝힙니다. 따로 정리할 예정인 배치정규화(batch-regularization)를 제외하고 전반적인 내용을 요약하였습니다. 그럼 시작하겠습니다.

딥러닝 학습의 일반적 절차

딥러닝의 일반적 절차는 다음과 같습니다.

  1. 적절한 네트워크 선택

    1) 구조(structure) : Single words vs Bag of Words, etc.

    2) 비선형성(nonlinearity) 획득 방법 : ReLu vs tanh, etc.

  2. 그래디언트 체크 : 네트워크를 구축했는데 그래디언트 계산이 혹시 잘못될 염려가 있으므로 잘됐는지 체크해봅니다

  3. 학습 파라메터 초기화 : 초기화 방법에도 여러가지가 있으므로 적절히 선택합니다

  4. 학습 파라메터 최적화 : Stochastic Gradient vs Adam, etc.

  5. 과적합 방지 : dropout vs regularize, etc.

비선형성 획득 : 활성함수

뉴럴네트워크의 개별 뉴런에 들어오는 입력신호의 총합을 출력신호로 변환하는 함수를 활성화함수(activation function)라고 합니다. 활성화함수 유무는 초창기 모델인 퍼셉트론(perceptron)과 뉴럴네트워크의 유일한 차이점이기도 하죠. 활성화함수는 대개 비선형함수(non-linear function)를 씁니다. 활성화함수로 왜 선형함수를 쓰면 안되는 걸까요? ‘밑바닥부터 시작하는 딥러닝’의 한 글귀를 인용해보겠습니다.

선형함수인 $h(x)=cx$를 활성화함수로 사용한 3층 네트워크를 떠올려 보세요. 이를 식으로 나타내면 $y(x)=h(h(h(x)))$가 됩니다. 이는 실은 $y(x)=ax$와 똑같은 식입니다. $a=c^3$이라고만 하면 끝이죠. 즉, 은닉층이 없는 네트워크로 표현할 수 있습니다. 뉴럴네트워크에서 층을 쌓는 혜택을 얻고 싶다면 활성화함수로는 반드시 비선형 함수를 사용해야 합니다.

그러면 뉴럴네트워크 활성화함수 몇 가지 살펴보겠습니다.

시그모이드

로지스틱 함수로도 불립니다. 원래 수식 및 미분식은 아래와 같습니다.

[\sigma (x)=\frac { 1 }{ 1+{ e }^{ -x } } \ \sigma ‘\left( x \right) =\sigma (x)(1-\sigma (x))]

시그모이드 함수의 범위는 $[0,1]$이고요, 그래프의 모양은 아래와 같습니다.

시그모이드 함수를 1차 미분한 그래프는 아래와 같습니다.

시그모이드 함수는 개별 뉴런이 내뱉어 주는 값을 S자 커브 형태로 자연스럽게 활성화를 해주기 때문에 예전부터 인기가 좀 있었습니다. 다만 입력값이 -5보다 작거나 5보다 클 경우에는 그래디언트 값이 지나치게 작아지고(=이렇게 되면 학습이 잘 안되죠), exp 연산이 다소 무겁다(=학습이 느려지죠)는 단점이 있습니다.

아울러 $σ(x)$의 범위는 $[0,1]$로서 모두 0 이상의 값을 지닌다는 문제가 있습니다. 이게 단점이 되는 이유는 바로 학습 속도와 관련이 있는데요. 예컨대 아래와 같은 뉴런이 있고 활성화함수 $f$가 시그모이드라고 가정해봅시다.

$x_0$, $x_1$, $x_2$는 모두 0 이상의 값을 갖습니다. 이들은 직전 층에서 시그모이드 함수에 의해 그 값이 양수로 활성화됐기 때문입니다. 여기에서 역전파시 최종 Loss에서 출발해 시그모이드 적용 직전의 $w_ix_i+b$ 각각에 들어오는 그래디언트를 $δ$라고 두겠습니다. 그렇다면 $w_i$의 그래디언트는 아래와 같습니다.

[\frac { \partial L }{ \partial { w }{ i } } ={ x }{ i }\times \delta]

앞서 말씀드렸듯 $x_0​$, $x_1​$, $x_2​$는 모두 0 이상이기 때문에 $δ​$가 양수라면 Loss에 대한 $w_0, w_1, w_2​$ 각각의 그래디언트가 모두 양수, 반대라면 모두 음수 값이 될 것입니다. 따라서 데이터 $x​$와 파라메터 $w​$를 2차원 벡터로 가정해 본다면 $w​$의 그래디언트는 2사분면과 4사분면 쪽 방향이 될 수는 없습니다.

결과적으로 $w$ 학습시 아래 그림처럼 허용되는 방향에 제약이 가해져(요소값이 모두 양수인’ 1사분면과’ 모두 음수인 ‘3사분면’ 쪽 방향만 선택 가능) 학습속도가 늦거나 수렴이 어렵게 됩니다. 이 문제는 함수값이 0에 대해 대칭(zero-centered)인 하이퍼볼릭탄젠트 같은 함수를 쓰면 극복할 수 있다고 합니다.

하이퍼볼릭탄젠트

하이퍼볼릭탄젠트는 시그모이드 함수의 크기와 위치를 조절(rescale and shift)한 함수입니다. 시그모이드 함수와의 관계식과 미분식은 각각 아래와 같습니다.

[\begin{align} tanh(x)&=2\sigma (2x)-1\ &=\frac { { e }^{ x }-{ e }^{ -x } }{ { e }^{ x }+{ e }^{ -x } } \tanh’\left( x \right) &=1-tanh^{ 2 }\left( x \right) \end{align}]

하이퍼볼릭탄젠트의 범위는 $[-1,1]$입니다. 그래프의 모양은 시그모이드 함수와는 달리 0을 기준으로 대칭인 점을 확인할 수 있습니다. 이 때문에 하이퍼볼릭탄젠트는 시그모이드를 활성화함수로 썼을 때보다 학습 수렴 속도가 빠르다고 합니다.

하이퍼볼릭탄젠트를 1차 미분한 그래프는 아래와 같습니다. 시그모이드함수와 마찬가지로 $x$가 -5보다 작거나 5보다 크면 그래디언트가 0으로 작아지는 점을 볼 수 있습니다. 이것이 하이퍼볼릭탄젠트의 단점입니다.

Rectified Linear Unit (ReLU)

ReLU는 아래와 같이 정의됩니다.

[f(x)=max(0,x)]

그래프의 모양은 아래와 같습니다. $x$가 양수이기만 하면 그래디언트가 1로 일정하므로 그래디언트가 죽는 현상을 피할 수 있고, 미분하기도 편리해 계산복잡성이 낮습니다. 실제로 시그모이드나 하이퍼볼릭탄젠트 함수 대비 학습수렴 속도가 6배나 빠르다고 합니다.

다만 위 그림에서 확인할 수 있듯 0을 기준으로 대칭인 모양은 아닙니다. 아울러 $x$가 음수이면 그래디언트가 무조건 0이 된다는 단점이 있습니다. 이를 극복하기 위해 Leaky ReLU가 고안되었습니다.

Leaky ReLU

Leaky ReLU의 식은 아래와 같습니다.

[f(x)=max(0.01x,x)]

그래프의 모양은 다음과 같습니다. $x$가 음수일 때 그래디언트가 0.01이라는 점을 제외하고는 ReLU와 같은 특성을 지닙니다.

Exponential Linear Units (ELU)

ELU는 ReLU의 특성을 공유하고요, 그래디언트가 죽지 않는다는 장점이 있다고 합니다. 다음 수식과 같습니다.

[f(x)=x\quad if\quad x>0\ f(x)=\alpha ({ e }^{ x }-1)\quad if\quad x\le 0]

Maxout Neurons

MN은 다음과 같습니다. 연결된 두 개의 뉴런 값 중 큰 값을 취해 비선형성을 확보합니다. 다만 활성화함수를 적용하기 위해 필요한 연산량이 많다는 단점이 있습니다.

[f(x)=max({ w }{ 1 }^{ T }x+{ b }{ 1 },{ w }{ 2 }^{ T }x+{ b }{ 2 })]

학습 파라메터 초기화

각 층의 가중치(weights)와 편향(bias) 등 학습 파라메터는 초기값 설정이 매우 중요하다고 합니다. 뉴럴네트워크가 풀려는 문제 자체가 non-convex optimization이기 때문에 시작점에 따라 최적지점을 찾지 못하게 될 수도 있습니다.

또한 학습 파라메터의 초기값을 적절하게 설정할 경우 그래디언트 조절에도 유의미한 효과를 낸다고 합니다. 이와 관련해 시그모이드 함수의 1차 미분 그래프를 다시 보도록 하겠습니다.

입력값 $x$에 가중치 $w$를 곱하고 편향 $b$를 더한 식을 $t$라고 둡시다. 여기에서 $w$가 100, $b$가 50이라면 $x$가 0.01로 매우 작더라도 $t$는 51이 됩니다. 역전파시 시그모이드 함수를 통과시키면 $σ’(51)$가 반환이 될텐데요, 위 그래프를 보시다시피 $t$가 5만 넘어도 $σ’(t)$는 0에 수렴하기 때문에 그래디언트가 죽어버리는 결과를 초래하게 됩니다. 그래디언트가 지나치게 작아지기 때문에 이후 학습이 사실상 불가능해지는 것이지요.

이와 별개로 뉴럴네트워크 입력층의 가중치 $W$를 모두 0으로 초기화한다면 어떻게 될까요? 순전파 때는 $W$가 0이기 때문에 두번째 층의 뉴런에 모두 같은 값이 전달됩니다. 미분의 연쇄법칙(chain-rule)을 떠올려보면 두번째 층의 모든 뉴런에 같은 값이 입력된다는 것은 역전파 때 두번째 층의 가중치가 모두 똑같이 갱신된다는 말이 됩니다. 다시 말해 뉴런이 100개가 됐든 1000개가 됐든 거의 같은 값을 출력하게 돼 네트워크의 표현력을 제한하게 된다는 얘기입니다.

따라서 학습파라메터의 초기값을 잘 설정해주어야 합니다. 이와 관련해 다양한 파라메터 초기화 방법론이 제시되었습니다. 일부를 소개하면 다음과 같습니다. 여기에서 $n_{in}$은 직전 레이어의 차원수, $n_{out}$은 다음 레이어의 차원수입니다. 아래 초기화식은 각 층의 가중치 $W$에 관한 식이고요, 은닉층과 출력층의 편향 $b$는 대개 0으로 설정한다고 합니다.

LeCun Initialization (Xavier Initialization)

[W\sim Uniform({ n }{ in },{ n }{ out })\ Var(W)=\frac { 1}{ { n }_{ in } }]

Glorot Initialization

[W\sim Uniform({ n }{ in },{ n }{ out })\ Var(W)=\frac { 2 }{ { n }{ in }+{ n }{ out } }]

He Initialization

[W\sim Uniform({ n }{ in },{ n }{ out })\ Var(W)=\frac { 2 }{ { n }_{ in } }]

학습 파라메터 최적화 (1)

학습 파라메터 최적화 기법으로 널리 쓰이는 그래디언트 디센트(Gradient Descent)는 기본적으로 아래와 같은 구조를 지닙니다. 여기에서 $θ$는 갱신 대상 학습 파라메터, $dL/dθ$는 Loss에 대한 $θ$의 그래디언트, $η$는 학습률(leaning rate)을 의미합니다. 즉 아래 식은 Loss에 대한 $θ$의 그래디언트 반대 방향으로 $η$만큼 조금씩 $θ$를 업데이트하라는 뜻입니다.

[\theta \leftarrow \theta -\eta \frac { \partial L }{ \partial \theta }]

그래디언트 디센트 방법론에도 여러 변형이 존재합니다. 세 가지 살펴보겠습니다. 아래 제시된 코드는 파이썬 기준입니다.

Batch Gradient Descent

이 방법은 전체 학습데이터 Loss에 대한 각 파라메터의 그래디언트를 한꺼번에 구한 뒤 1 epoch동안 모든 파라메터 업데이트를 단 한번 수행하는 방식입니다. 매우 느리고 메모리 요구량이 많다는 단점이 있지만 최적해를 찾을 수 있다는 장점이 있다고 합니다. (It’s guaranteed to converge to the global minimum for convex error surfaces and to a local minimum for non-convex surfaces)

for i in range(nb_epochs):
    params_grad = evaluate_gradient(loss_function, data, params)
    params = params - learning_rate * params_grad

Stochastic Gradient Descent

학습데이터의 순서를 랜덤으로 섞은 뒤 개별 레코드(위 코드에서 example) 단위로 Loss와 그래디언트를 구한 뒤 학습 파라메터를 조금씩 업데이트하는 방식입니다. 1 epoch동안 학습데이터 개수만큼의 업데이트가 수행됩니다. BGD보다 훨씬 빠르면서도 수렴 결과가 BGD와 일치(학습률을 줄였을 때)한다고 합니다.

for i in range(nb_epochs):
    np.random.shuffle(data)
    for example in data:
    	params_grad = evaluate_gradient(loss_function, example, params)
    	params = params - learning_rate * params_grad

Mini-batch Gradient Descent

이 방식은 개별 레코드가 아니라 batch_size(아래 코드에서 50) 단위로 학습한다는 점을 제외하고는 SGD와 같습니다. SGD에 비해 안정적으로 학습하는 경향이 있다고 합니다. 게다가 데이터가 배치 단위로 들어가게 되면 사실상 행렬 연산이 되기 때문에 시중에 공개돼 있는 강력한 라이브러리를 사용할 수 있다는 장점 또한 있습니다.

for i in range(nb_epochs):
    np.random.shuffle(data)
    for batch in get_batches(data, batch_size=50):
    	params_grad = evaluate_gradient(loss_function, batch, params)
    	params = params - learning_rate * params_grad

학습 파라메터 최적화 (2)

그래디언트 디센트 계열 외에 다양한 최적화 기법을 소개합니다. 최근 각광받고 있는 기법들입니다.

Momentum

모멘텀은 운동량을 뜻하는 단어로 물리 현상과 관계가 있습니다. 예컨대 아래 그림처럼 공이 한번 움직이기 시작하면 기울기 방향으로 힘을 받아 가속하게 되죠. 모멘텀 기법은 바로 이 점에 착안했습니다.

모멘텀 기법은 수식으로는 다음과 같이 쓸 수 있습니다. 여기에서 $μv$는 물체가 아무런 힘을 받지 않을 때 서서히 하강시키는 역할을 합니다($μ$는 0.9 등의 값으로 설정합니다). 물리에서는 지면 마찰이나 공기 저항에 해당합니다. 나머지는 그래디언트 디센트 기법과 동일합니다.

[v\leftarrow \mu v-\eta \frac { \partial L }{ \partial \theta } \ \theta \leftarrow \theta +v]

모멘텀 기법의 최적화 효과를 직관적으로 나타낸 그림은 아래와 같습니다. 하단 좌측 그림을 보시면 현재의 그래디언트가 모멘텀과 같은 방향이라면 업데이트가 더 크게 이뤄지게 됩니다. 하단 우측 그림에서 최적화 지점이 원 내부 중앙이라고 했을 때 모멘텀 기법이 조금 더 효율적인 업데이트 경로를 거치고 있는 점을 확인할 수 있습니다.

코드로는 아래와 같습니다. 여기에서 $μ$는 사용자가 지정하는 하이퍼파라메터입니다.

param_grad = evaluate_gradient(loss_function, data, params)
v = mu * v - learning_rate * param_grad
param = v + param

Nesterov Accelerated Gradient

이 기법은 모멘텀 기법을 업그레이드한 버전입니다. 현재 학습 파라메터(붉은색 원 : 아래 코드에서 $params$)를 직전까지 축적된 그래디언트 방향(녹색선)으로 이동시킵니다. 이 벡터($params_{ahead}$)를 기준으로 그래디언트(붉은색 선 : $params_grad_{ahead}$)를 계산합니다. 실제 업데이트는 둘을 모두 반영해 이뤄집니다.

모멘텀과의 차이 : 모멘텀은 현재 점(붉은색 원)에서 그래디언트를 구합니다. NAG는 녹색선과 빨간선이 이루는 꼭지점에서 그래디언트를 구합니다.

이 기법을 코드로 나타내면 아래와 같습니다. 여기에서도 $μ$는 역시 사용자가 지정하는 하이퍼파라메터입니다.

params_ahead = params + mu * v
params_grad_ahead = evaluate_gradient(loss_function, data, params_ahead)
v = mu * v - learning_rate * params_grad_ahead
params = v + params

AdaGrad

학습률 감소와 연관된 기법입니다. AdaGrad는 각각의 학습 파라메터에 맞춤형으로 학습률을 조정하면서 학습을 진행합니다. 수식은 아래와 같습니다. 여기에서 $⊙$는 행렬의 원소별 곱셈을 의미합니다. 식을 보시면 학습 파라메터의 원소 가운데 많이 움직인(크게 갱신된) 원소는 학습률이 낮아지게 돼 있습니다. 다시 말해 학습률이 학습 파라메터의 원소마다 다르게 적용된다는 뜻입니다.

[h\leftarrow h+\frac { \partial L }{ \partial \theta } \odot \frac { \partial L }{ \partial \theta } \ \theta \leftarrow \theta -\frac { \eta }{ \sqrt { h } } \frac { \partial L }{ \partial \theta }]

이를 코드로 나타면 아래와 같습니다. 아래 코드에서 eps는 분모가 너무 0에 가깝지 않도록 안정화하는 역할을 합니다. 보통 $10^{-4}$에서 $10^{-8}$의 값을 쓴다고 합니다.

params_grad = evaluate_gradient(loss_function, data, params)
h = h + params_grad**2
params = params - learning_rate / (np.sqrt(h) + eps) * params_grad

RMSProp

AdaGrad는 학습률 $η$를, 과거의 기울기를 제곱한 값을 계속 더해나간 $h$로 나눠줍니다. 학습을 진행할 수록 $η$가 지속적으로 작아진다는 뜻입니다. 계속 학습하면 $η$가 0이 돼서 학습이 불가능해지는 시점이 옵니다. RMSProp은 이를 개선하기 위한 기법입니다. 즉 과거의 모든 기울기를 다 더해 균일하게 반영하는 것이 아니라, 먼 과거의 기울기는 서서히 잊고 새로운 기울기 정보를 크게 반영하기 위해 $h$를 계산할 때 지수이동평균(Exponential Moving Average)을 적용합니다.

코드는 아래와 같습니다. 여기에서 decay_rate는 사용자 지정 하이퍼파라메터이고 보통 $[0.9, 0.99, 0.999]$ 가운데 하나를 쓴다고 합니다.

params_grad = evaluate_gradient(loss_function, data, params)
h = decay_rate * h + (1 - decay_rate) * params_grad**2
params = params - learning_rate / (np.sqrt(h) + eps) * params_grad

Adam

모멘텀은 공이 구르듯 하는 물리 법칙에 착안해 만들어진 기법입니다. AdaGrad과 RMSProp은 학습 파라메터의 개별 원소마다 학습률을 달리 적용합니다. 두 기법을 합친 것이 바로 Adam입니다. 퍼포먼스가 좋아서 최근 많은 관심을 받고 있는 기법인데요. 코드는 다음과 같습니다.

params_grad = evaluate_gradient(loss_function, data, params)
m = beta1 * m + (1 - beta1) * params_grad
v = beta2 * v + (1 - beta2) * params_grad**2
params = params - learining_rate * m / (np.sqrt(v) + eps)

여기에서 $beta_1$, $beta_2$, $eps$는 사용자가 지정하는 하이퍼파라메터입니다. 논문에 따르면 각각 0.9, 0.999, $10^{-8}$이 좋다고 합니다.

각 기법 비교

너무나도 유명한 그림이라 설명은 생략하겠습니다. 저 역시 정리 용도로 올려 둡니다.

과적합 방지

과적합(overfitting)이란 모델이 학습데이터에만 지나치게 적응해서 일반화 성능이 떨어지는 경우를 말합니다. 기계학습은 범용 성능을 지향하기 때문에 학습데이터 외에 처음 보는 데이터가 주어지더라도 올바르게 판단할 수 있는 능력을 가져야 합니다. 뉴럴네트워크 학습시 과적합을 방지하는 몇 가지 기법에 대해 살펴보도록 하겠습니다.

모델 크기 줄이기

가장 간단한 방법입니다. 레이어나 뉴런 등 학습해야할 파라메터의 개수를 줄여서 과적합을 방지합니다.

early stopping

학습을 일찍 중단하는 방식으로 과적합을 방지합니다.

가중치 감소

과적합은 학습 파라메터의 값이 커서 발생하는 경우가 많다고 합니다. 가중치 감소(weight decay)는 이를 방지하기 위해 학습 파라메터의 값이 크면 그에 상응하는 큰 패널티를 부여하는 기법입니다.

1) L2 Regularization : 가장 일반적인 regulization 기법입니다. 기존 손실함수($L_{old}$)에 모든 학습파라메터의 제곱을 더한 식을 새로운 손실함수로 씁니다. 아래 식과 같습니다. 여기에서 $1/2$이 붙은 것은 미분 편의성을 고려한 것이고, $λ$는 패널티의 세기를 결정하는 사용자 지정 하이퍼파라메터입니다. 이 기법은 큰 값이 많이 존재하는 가중치에 제약을 주고, 가중치 값을 가능한 널리 퍼지도록 하는 효과를 냅니다.

[W=\begin{bmatrix} { w }{ 1 } & { w }{ 2 } & … & { w }{ n } \end{bmatrix}\ { L }{ new }={ L }{ old }+\frac { \lambda }{ 2 } { (w }{ 1 }^{ 2 }+{ w }{ 2 }^{ 2 }+…+{ w }{ n }^{ 2 })]

2) L1 Regulazation : 기존 손실함수에 학습파라메터의 절대값을 더해 적용합니다. 이 기법은 학습파라메터를 sparse하게(거의 0에 가깝게) 만드는 특성이 있습니다.

[{ L }{ new }={ L }{ old }+\lambda (\left { w }_{ 1 } \right +\left { w }_{ 2 } \right +…+\left { w }_{ n } \right )]

**3) L1 + L2 **: 물론 두 기법을 동시에 사용할 수도 있습니다.

[{ L }{ new }={ L }{ old }+\frac { { \lambda }{ 1 } }{ 2 } { W }^{ T }W+{ \lambda }{ 2 }(\left { w }_{ 1 } \right +\left { w }_{ 2 } \right +…+\left { w }_{ n } \right )]

Dropout

드롭아웃은 일부 뉴런을 꺼서 학습하는 방법입니다. 일종의 앙상블(ensemble) 효과를 낸다고 합니다. 학습시에는 삭제할 뉴런을 무작위로 끄고, 테스트할 때 모든 뉴런을 씁니다.

기타 학습 기법들

기타 기법들을 소개합니다.

학습률 감소

학습률(learining rate)은 아래 그림처럼 학습 과정에 중요한 역할을 차지합니다. 지나치게 크면 발산하여 올바른 학습을 할 수 없고, 작으면 학습시간이 너무 길어집니다.

학습 시작부터 종료시까지 학습률을 고정한 채로 학습을 시킬 수도 있지만 학습이 거듭될 수록 해당 모델이 최적 지점에 수렴하게 될 것이므로 막바지에는 학습률을 작게 해 파라메터를 미세 조정하는 것이 좋을 것입니다. 학습률 감소 기법은 이 때문에 제안됐는데요, 각각 아래와 같습니다. 여기에서 $η$는 학습률, $t$는 스텝 수이며 $k$는 사용자가 지정하는 하이퍼파라메터입니다.

step decay : 스텝마다 일정한 양만큼 학습률을 줄이는 기법입니다. 5epoch마다 반으로 줄이거나 20epoch마다 1/10씩 줄이는 방법이 많이 쓰이지만, 데이터나 네트워크 구조에 따라 일률적으로 적용하기는 어렵습니다.

exponential decay : $η=η_0e^{-kt}$

$1/t$ decay : $η=η_0/(1+kt)$

하이퍼파라메터 최적화

하이퍼파라메터는 사용자가 지정해줘야 하는 값으로 어떤 값이 최적인지는 미리 알기 어렵습니다. 데이터나 모델 구조마다 달라지기도 하고요. 최적의 하이퍼파라메터를 찾기 위한 일반적인 절차는 아래와 같습니다.

  • 1단계 : 하이퍼파라메터 값의 범위를 설정한다
  • 2단계 : 설정된 범위에서 하이퍼파라메터의 값을 무작위로 추출한다
  • 3단계 : 샘플링한 하이퍼파라메터 값을 사용해 학습하고, 검증 데이터로 정확도를 평가한다 (단, 에폭은 작게 설정)
  • 2단계와 3단계를 반복하고, 그 결과를 보고 하이퍼파라메터 탐색 범위를 좁힌다

Multi-Task Learning

Multi-Task Learing이란 여러 학습 과제를 동시에 해결하는 기계학습의 한 종류입니다. 예컨대 같은 학습말뭉치로 개체명인식(Named Entity Recognition)품사분류(Part-Of-Speech Tagging)를 동시에 수행하는 뉴럴네트워크를 만들 수 있습니다. 아래 그림을 먼저 볼까요?

위 그림의 두 네트워크는 마지막에 붙어있는 소프트맥스 계층(Softmax layer)만 제외하면 완전히 동일합니다. 다만 $S_1$의 소프트맥스 확률값은 NER, $S_2$는 포스태깅 과제를 수행하면서 나오는 스코어라는 점에 유의할 필요가 있습니다. 위와 같은 Multi-Task Learining 네트워크에서는 아래 수식처럼 역전파시 $S_1$의 그래디언트와 $S_2$의 그래디언트가 동일한 네트워크에 함께 전달되면서 학습이 이뤄지게 됩니다.

[{ \delta }^{ total }={ \delta }^{ NER }+{ \delta }^{ POS }]

Comment  Read more

한국어 품사 분류와 분포(distribution)

|

이번 글에서는 한국어 품사 분류의 기준에 대해 간략히 살펴보고 단어의 분포(distribution)가 품사의 의미와 어떤 관계를 맺고 있는지 알아보도록 하겠습니다. 이번 글은 경희대 이선웅 교수님의 강의와 표준국어문법론을 정리했음을 먼저 밝힙니다. 그럼 시작하겠습니다.

품사와 품사론

학교문법에 따르면 품사란 단어를 문법적 성질의 공통성에 따라 몇 갈래로 묶어 놓은 것입니다. 품사론은 품사의 종류와 성격 등에 관해 연구하는 분야를 뜻하는데요. 예컨대 7차 교육과정의 문법 교과서에 있는 아래와 같은 진술이 품사론의 영역이라고 볼 수 있겠습니다.

가. ‘(허리가) 굽다’는 ‘굽어, 굽어서’로 활용하고 ‘(불에)굽다’는 ‘구워, 구워서’로 활용한다.

나. 명사 중에는 반드시 그 앞에 꾸며 주는 말, 즉 관형어가 있어야만 문장에 쓰일 수 있는 것들이 있다.

다. 국어의 재귀칭에는 ‘저2, 저희2, 자기, 당신2’가 있다.

‘가’는 사실 형태론의 설명 대상입니다. 단어의 변화 양상에 주목한 문장이기 때문입니다. ‘나’는 통사론이라 말할 수 있습니다. 문장 내 다른 성분과의 문법적 관계를 서술한 문장이거든요. ‘다’는 단어 수준의 의미에 방점을 둔 어휘론의 설명 대상입니다.

이렇듯 품사론은 형태론, 통사론, 어휘론에 흩어져 있는 사실들을 묶어주는 종합적인 학문영역이어서 그 독자성은 적다고 할 수 있겠습니다. 품사론이 독자적으로 보이는 이유는 관습에 따른 착시현상일 뿐 그 내용 하나하나는 형태론적 지식, 통사론적 지식, 어휘론적 지식의 일부라는 이야기입니다.

학교문법에서는 한국어 품사를 9가지로 정의하고 있습니다. 이선웅 교수님에 따르면 그 체계는 아래 표와 같이 정리할 수 있는데요. 품사 분류 기준에 대해 자세히 살펴보시려면 이곳을 참고하시면 좋을 것 같습니다.

한국어 품사 분류 기준

학교문법에서 제시하는 품사 분류 기준은 세 가지입니다. 기능(function), 의미(meaning), 형태(form;형식)가 바로 그것입니다.

우선 기능은 한 단어가 문장 가운데서 다른 단어와 맺는 관계를 가리킵니다.

(1) 이 샘의 깊이가 얼마냐?

(2) 저 산의 높이가 얼마냐?

(3) 이 샘이 깊다.

(4) 저 산이 높다.

위 예시에서 ‘깊이’, ‘높이’는 문장의 주어로 쓰이고 있고, ‘깊다’, ‘높다’는 서술어로 사용되고 있습니다. 이처럼 기능이 같은 단어 부류를 일단 같은 품사로 묶을 수 있습니다.

의미란 형식적인 의미를 나타냅니다.

(가) 깊이, 깊다

(나) 높이, 높다

위 예시에서 ‘깊이’, ‘깊다’를 하나로 묶고, ‘높이’, ‘높다’를 같은 군집으로 넣을 수도 있습니다. 이 때 적용된 기준은 어휘적 의미인데요, 품사 분류에는 어휘적 의미보다는 형식적 의미가 중요한 기준이 됩니다. 다시 말해 어떤 단어가 사물의 이름을 나타내느냐, 그렇지 않으면 움직임이나 성질, 상태를 나타내느냐 하는 것입니다. 이렇게 본다면 ‘깊이’와 ‘높이’를 한 덩어리로, ‘깊다’와 ‘높다’를 다른 덩어리가 될 수 있습니다.

형식이라고 함은 단어의 형태적 특징을 의미합니다.

철수가 동화를 빨리 읽었다.

위 예시에서 철수, 동화 같은 단어는 변화하지 않습니다. 하지만 ‘읽었다’는 아래처럼 어미가 붙어 여러 가지 모습으로 변화를 일으킵니다.

읽었다, 읽는다, 읽는구나, 읽어라…

한국어 품사 분류의 실제

하지만 실제 품사를 분류할 때에는 여러가지 어려움이 따릅니다. 예컨대 의미는 품사 분류시 고려 대상이 될 수 있으나 결정적인 분류 기준은 될 수 없다는 겁니다. 예를 들어보겠습니다.

(a) 공부하다

(b) 공부

주지하다시피 (a)는 동사, (b)는 명사로 분류됩니다. 그렇다면 둘 사이에 의미상 큰 차이가 있다고 말할 수 있을까요? (a)의 경우 ‘하다’가 붙어 행위적인 속성이 더 강조된 느낌이 있기는 하지만 그 의미 차이가 결정적이지는 않은 것 같습니다.

사실 의미를 정확하게 알아내기란 어렵습니다. 예컨대 한국어의 ‘있다’는 아래처럼 형용사(exist)로도 동사(stay)로도 쓰입니다. 그럼 ‘있다’의 의미는 어디까지가 형용사 영역이고 어디까지가 동사 영역일까요? 구분하기 쉽지 않은 영역입니다.

형용사적 용법 : 사과가 세 개 있다.

동사적 용법 : 꼼짝 말고 여기 있어라.

한국어 품사 분류시 결정적 기준이 될 수 없는 건 형태도 마찬가지입니다. 이번엔 감탄사로 예를 들어보겠습니다.

(ㄱ) 영수가 학교에 간다.

(ㄴ) 영수! 조용히 해.

(ㄱ)의 영수는 명사, (ㄴ)의 영수는 감탄사로 쓰인 점을 확인할 수 있습니다. 형태는 같지만 의미가 달라졌다는 것이죠.

기능과 분포

한국어 품사를 분류할 때 가장 결정적인 기준은 바로 기능이라고 합니다. 앞선 예에서 (a)와 (b)를 분류할 때는 해당 단어가 문장 내에서 점하는 역할에 초점을 맞춰 본다는 것이죠. (a)의 경우 동작/작용의 기능이 있기 때문에 ‘동사’, (b)는 사물의 이름을 나타내는 기능이 있기 때문에 ‘명사’로 구분할 수 있게 됩니다. 마찬가지로 (ㄱ)은 사물의 이름으로 쓰였고, (ㄴ)은 문장의 다른 단어들과 문법적 관계가 없기 때문에 각각 명사, 감탄사(독립어)로 분류하게 됩니다.

그런데 한국어에서는 단어의 기능이 분포와 매우 밀접한 관련을 맺고 있다고 합니다. 분포란 단어의 등장 순서나 위치를 말합니다. 이와 관련해 국어학 창시자 격인 최현배 선생(1894~1970)이 쓰신 글을 인용해 보겠습니다. 최현배 선생 또한 기능이 가장 중요한 품사 분류 기준이면서, 기능은 분포와 상당한 관계가 있다고 지적했습니다.

씨(품사)의 가름(분류)은 그 말법에서의 구실 곧 씨 서로의 관계와 월(文)을 만드는 작용의 관계를 주장(主)으로 삼고, 그에 따르는 형식과 의미를 붙힘(從)으로 삼아, 이 네 가지가 서로 관계하는 양태를 표준으로 삼아 결정하여야 한다. (중략) 씨와 씨의 관계라는 것은 한 씨가 다른 씨와 합하는 일이 잇나 없나, 또 합하는 경우에는 어떠한 자리에서 하는가 하는 것이 그 씨의 뜻과 꼴(형식)에 들어나는 모양을 이름이요.

기능은 단어가 문장 내에서 어떤 역할을 하는지, 분포는 그 단어가 어느 자리에 있는지를 나타냅니다. 비유하자면 최순실 씨가 박근혜정부의 실세(기능)였던 건 박 전 대통령과 자주 만나고 가까이에 있었기(분포) 때문입니다. 이처럼 기능과 분포는 개념적으로 엄밀히 다르지만, 둘 사이에는 밀접한 관련을 지닙니다.

한국어 품사 분류의 일반적 기준

최형용(2013)은 한국어 품사 분류의 일반적인 기준을 아래와 같이 정의했습니다.

체언(명사) : 관형사가 그 앞에 올 수 있고 조사가 그 뒤에 올 수 있음

용언(동사/형용사) : 부사가 그 앞에 올 수 있고 선어말어미가 그 뒤에 올 수 있고 어말어미가 그 뒤에 와야 함

관형사 : 명사가 그 뒤에 와야 함

부사 : 용언, 부사, 절이 그 뒤에 와야 함

조사 : 체언 뒤에 와야 함

어미 : 용언 뒤에 와야 함

감탄사(간투사) : 특별한 결합 제약 없이 즉 문장 내의 다른 단어와 문법적 관계를 맺지 않고 따로 존재함

Distributed Representations와의 접점

Neural Network Language Model, Word2Vec, GloVe 등 단어를 벡터로 바꾸는 방법론이 제안되었습니다. 이 방법론들의 특징은 학습말뭉치의 단어 분포 정보를 보존하는 방식으로 벡터를 바꾸게 되는데요, 자세한 내용은 이곳을 참고하시면 좋을 것 같습니다.

어쨌든 이러한 모델들이 개별 단어의 형식적 의미나 형태를 전혀 고려하지 않음에도 높은 성능을 낼 수 있었던 건 지금까지 설명해드렸던 것처럼 임베딩된 단어벡터들이 분포 정보를 내포하고 있기 때문인 것 같습니다. 이 분포 정보가 단어의 기능이나 형식적 의미와 깊은 연관을 맺고 있기 때문에 임베딩 결과가 사람이 보기에도 그럴싸하게 나온다는 것이죠.

Comment  Read more