[NLP] ppmi과 SVD 차원축소

2023. 2. 12. 21:44Natural Language Processing

단어발생행렬과 코사인 유사도를 통해 측정한 유사도는 한가지 문제점이 있다. 

 

영어의 경우 a나 the 같은 정관사들은 출현빈도가 매우 높은데, 

 

다른 단어들과의 동시발생확률이 높기때문에 코사인 유사도가 높게 측정될 수 있다. 

 

이러한 이유로 만들어진 것이 PMI(pointwise mutual information)이다. 

 

PMI는 전체 corpus에서 단어의 출현빈도가 고려된 유사도 측정 기법이다. 

 

동시발생확률(P(w1, w2))에서 각 w1, w2의 전체 출현빈도가 나누어지기 때문에 단순히 출현빈도가 높은 이유만으로

 

유사도가 높게 특정되는 일은 없게 된다. 

 

다만 PMI는 log값을 취하기 때문에 동시발생이 일어나지 않았으면(분자가 0) log가 - 무한대이기 때문에 

 

음수는 0으로 처리한 방식이 PPMI이다.

 

    W = ppmi(C)
    print(W)
    
    결과:
    [[0.       5.183222 0.       ... 0.       0.       0.      ]
 	[5.183222 0.       5.768184 ... 0.       0.       0.      ]
	 [0.       5.768184 0.       ... 0.       0.       0.      ]
 	...
 	[0.       0.       0.       ... 0.       0.       0.      ]
 	[0.       0.       0.       ... 0.       0.       0.      ]
 	[0.       0.       0.       ... 0.       0.       0.      ]]

기존 동시발생행렬이 PPMI를 거쳐 변환된 행렬이다.

 

PPMI 역시 문제가 있는데 이는 희소행렬이라는 점이다.

 

희소행렬은 특정 위치들을 제외하고는 대부분 0을 값으로 가진 행렬을 말한다.

 

희소행렬일 경우에 어휘 사전의 크기가 매우 클 경우 차원의 저주에 빠질 가능성이 있다. 

 

이를 위해서 차원 축소를 할 수 있다. 

 

특이값 분해(SVD)는 대표적인 차원 축소 방법인데 행렬에서 중요한 차원만 뽑아내어 행렬의 크기를 감소시킬 수 있다. 

 

    U, S, V = np.linalg.svd(W)
    print(U[:, :2])
    
    결과:
    [[ 1.72929704e-01  2.11431116e-01]
 [ 1.40233383e-01 -1.96865320e-01]
 [ 1.34319469e-01  1.85117483e-01]
 [ 1.89498574e-01 -2.34345853e-01]
 .
 .
 .
 [ 8.48612711e-02 -1.07393414e-01]
 [ 1.73474774e-01  3.80239896e-02]
 [ 1.20473333e-01 -4.91582155e-02]]

차원 축소된 U 행렬에서 가장 앞선 2 원소만 추출하였다.

    for word, word_id in word_to_id.items():
        plt.annotate(word, (U[word_id,0], U[word_id, 1]))
    plt.scatter(U[:,0], U[:,1], alpha=0.5)
    plt.show()

각 단어마다의 (차원축소된) 단어 행렬을 scatter 그래프로 나타내었다.

i, my, myself 와 같은 유사 단어들이 밀집된 것을 확인할 수 있다.

'Natural Language Processing' 카테고리의 다른 글

[NLP] RNN(순환 신경망)  (0) 2023.02.22
[NLP] word2vec 개선 - 임베딩, 네거티브 샘플링  (0) 2023.02.19
[NLP] word2vec  (0) 2023.02.13
[NLP] 동시발생행렬  (0) 2023.02.12
[NLP] 말뭉치 전처리  (0) 2023.02.12