인공지능 응용 공학

PMI (pointwise mutual information) 척도를 사용한 통계적 기법 개선

coding art 2023. 2. 3. 17:53
728x90

동시발생 행렬에서의 동시발생은 하나의 단어를 두고 인접한 위치에서 특정 단어가 출현한 횟수를 나타낸다. 하지만 빈도수가 높다고 해서 그 단어의 중요성이 높아지는 것은 아니다.

 

예를 들어 보자. ‘the’와 ‘car’ 는 자주 동시 발생 한다. 한편 ‘car’와 ‘drive’는 관련성이 확실히 높다. 그렇지만 단순히 출현횟수만 따진다면 ‘car’와 ‘drive’ 보다는 ‘the’와 ‘car’가 더 높을 것이다.

 

이 문제 해결을 위해서 PMI(pointwise mutual information) 척도를 새로이 도입하자.

P(x)는 x가 일어날 확률, P(y)는 y가 일어날 확률, P(x, y)는 x와 y가 동시에 일어날 확률을 의미한다. 이 PMI 값이 높을수록 관련성이 높다는 의미이다. 동시발생 행렬을 사용하여 위 식을 다시 써보자. C(x, y)는 단어 x와 y가 동시 발생하는 횟수, C(x)와 C(y)는 단어 x와 y의 등장 횟수를 나타낸다. 단어장에 포함되어 있는 총 단어 수를 N이라고 하면 윗 식은 다음과 같이 쓸 수 있다.

수치 예를 들자. N=10,000이고, ‘the’와 ‘car’와 ‘drive’가 각각 1000회, 20회, 10회가 출현한다고 가정하자. 아울러 ‘the’와 ‘car’ 의 동시발생 횟수는 10회, ‘car’와 ‘drive’의 동시 발생 횟수는 5회라고 가정하자. 이러한 조건은 동시 발생 횟수 관점에서는 ‘car’는 ‘drive’ 보다 ‘the’와 관련이 깊다고 볼 수 있다. 반면에 PMI 값 관점에서 살펴보자.

이 계산 결과에서 보듯이 ‘car’는 ‘the’보다 ‘drive’와의 관련성이 커졌음을 알 수 있다. 이러한 결과는 단독으로 출현하는 횟수가 고려되었기에 즉 ‘the’가 자주 출현했으므로 PMI 점수가 낮게 평가되었는 점이다. 단 두 단어의 동시 발생 횟수가 0이면 -∞ 값이 나오므로 이를 피할 수 있도록 PPMI를 다음과 같이 정의한다.

PPMI(x, y) = max(0, PMI(x, y))

동시 발생행렬을 ppmi()로 변환하는 함수를 코딩해보자.

 

동시 발생행렬 C와 같은 크기의 행렬 M을 0 으로 초기화 한다.

C를 sum() 명령으로 합산하여 전체 동시발생 횟수 N을 계산하다.

axis=0을 기준으로 즉 C의 컬럼별로 합산한다.

C는 shape이 2차원임을 알 수 있으며, shape[0]과 shape[1] 출력이 가능하다.

1 def ppmi(C, verbose=False, eps = 1e-8):
''’
:param C: 동시 발생행렬
:param verbose: 진행 상황을 출력할지 여부
'''
M = np.zeros_like(C, dtype=np.float32)
N = np.sum(C)
S = np.sum(C, axis=0)
total = C.shape[0] * C.shape[1]
cnt = 0


for i in range(C.shape[0]):
for j in range(C.shape[1]):
pmi = np.log2(C[i, j] * N / (S[j]*S[i]) + eps)
M[i, j] = max(0, pmi)


if verbose:
cnt += 1
if cnt % (total//100) == 0:
print('%.1f%% 완료' % (100*cnt/total))
return M

shape[0]과 shape[1]을 for loop에 의해 ppmi를 계산하여 반환한다.

함수 ppmi()는 preprocess()와 create_co_matrix() 연산 결과를 사용함에 유의하자.

 

2 W = ppmi(C)
np.set_printoptions(precision=3) # 유효 자릿수를 세 자리로 표시
print('동시발생 행렬')
print(C)
print('-'*50)
print('PPMI')
print(W)

동시 발생 행렬을 PPMI 행렬로 변경해 보자.

 

3 (7, 7)
C.shape[0]= 7
C.shape[1]= 7
동시발생 행렬
[[0 1 0 0 0 0 0]
[1 0 1 0 1 1 0]
[0 1 0 1 0 0 0]
[0 0 1 0 1 0 0]
[0 1 0 1 0 0 0]
[0 1 0 0 0 0 1]
[0 0 0 0 0 1 0]]
PPMI
[[0. 1.807 0. 0. 0. 0. 0. ]
[1.807 0. 0.807 0. 0.807 0.807 0. ]
[0. 0.807 0. 1.807 0. 0. 0. ]
[0. 0. 1.807 0. 1.807 0. 0. ]
[0. 0.807 0. 1.807 0. 0. 0. ]
[0. 0.807 0. 0. 0. 0. 2.807]
[0. 0. 0. 0. 0. 2.807 0. ]]

하지만 동시 발생 매트릭스나 ppmi매트릭스나 다 단어장의 크기가 커진다면 특징 벡터의 차원 수도 증가하게 되어 그다지 실용적이지 못하다는 점에 유의하자. 만약 단어장의 규모가 10,000개에 달한다고 가정해 보자. 그렇다면 동시 발생 매트릭스의 크기도 10,000x10,000 즉 10의 8승개 즉 거의 다 0으로 채워지는 1억개의 메모리가 필요하게 된다는 사실이다. 이문제를 해결하기 위해서 SVD(Singular Value Decomposition)기법을 사용하여 차원(dimension)을 최대한 줄여야(reduction) 할 것이지만 매트릭스의 크기가 지나치게 크다면 그다지 의미가 없어질 것이다.

 

참조: ”Deep Learning from Scratch ⓶: 밑바닥부터 시작하는 딥러닝2“, pp.77 ~ 111., 사이토 고키 지음, 한빛미디어.

 

ppmi.ipynb
0.01MB