컴언

'확률'에 해당되는 글 1건

  1. [언어 모델링] n-gram

[언어 모델링] n-gram

Natural Language Processing

자연어 처리에서 확률의 중요성


우리가 자연어로 만들어내는 문장들은 정규화되지 않고 무한하며 복잡한 문법을 따르기 때문에 컴퓨터가 처리하기 어렵습니다. 하지만 효과적인 언어 모델링을 이용하면 분석이 한결 더 쉬워질 수 있습니다. 예를 들어 음성 인식의 경우를 생각해 봅시다.


"It's hard to recognize a speech."


와 


"It's hard to wreck a nice beach."


라는 두 문장이 있습니다. 발음해보시면 알겠지만, 둘은 서로 거의 비슷한 음성적 특성을 가지는 문장입니다. 하지만 두 번째 문장처럼 일어나기 힘든(단어들이 조합되기 힘든) 말이 주어질 확률은 낮습니다. 따라서 확률적으로 훨씬 빈도/가능성이 제일 높은 첫 번째 문장으로 인식하죠. 한국어에서도 사이시옷 같은 괴랄한 맞춤법 규칙, 띄어쓰기, 발음 변동 현상과 같은 문제를 해결하는 데 언어 모델링이 엄청 중요하다고 생각합니다.



비슷하게, "피아노를" 이라는 어절을 주면 다음에 "치다" 같은 단어가 올 것이라고 예상할 수 있습니다. 이런 생각에서 다양한 확률론적 모델이 고안되었고 오늘 다룰 n-gram 이 그런 확률적 분석 방법의 하나입니다. 


n-gram

 


n-gram 은 n개 어절/음절을 연쇄적으로 분류해 그 빈도를 따집니다. n=1 일 때는 unigram, 2일 때는 bigram, 3 - trigram 식으로 불리는데 분석 예제를 보면 무슨 뜻인지 감이 오실겁니다.


"쓸쓸하던 그 골목" 음절 단에서 bigram 으로 분석한 결과


['쓸', '쓸'], ['쓸', '하'], ['하', '던'], ['던', ' '], [' ', '그'], ['그', ' '], [' ', '골'], ['골', '목']

"쓸쓸하던 그 골목을 당신은 기억하십니까" 을 단에서 trigram 으로 분석한 결과

[['쓸쓸하던', '그', '골목을'], ['그', '골목을', '당신은'], ['골목을', '당신은', '기억하십니까'], ['당신은', '기억하십니까', ' '], ['기억하십니까', ' ', ' ']]



그리고 긴 텍스트를 분석하게 된다면 같은 n-gram 이 여러개 나오게 될 겁니다. 그 n-gram 들의 수를 세서 리스트로 만든 것을 빈도 리스트 (frequency list) 라고 합니다. 저는 이상의 소설에서 가장 많이 나온 n-gram 이 뭘까 궁금해서 이상의 날개를 이용해 Python으로 n-gram 분석을 해봤습니다. 아래를 보시죠.

Python 구현



#!/usr/bin/env python3
# -*- coding:utf-8 -*-]

with open('nalgae.txt', 'r', encoding='utf-8', newline='\n') as f:
	file = f.read()
sample_file = ''.join(file) 

#어절 n-gram 분석
#sentence: 분석할 문장, num_gram: n-gram 단위
def word_ngram(sentence, num_gram):
	# in the case a file is given, remove escape characters
	sentence = sentence.replace('\n', ' ').replace('\r', ' ')
	text = tuple(sentence.split(' '))
	ngrams = [text[x:x+num_gram] for x in range(0, len(text))]
	return tuple(ngrams)

#음절 n-gram 분석
#sentence: 분석할 문장, num_gram: n-gram 단위
def phoneme_ngram(sentence, num_gram):
	text = tuple(sentence) # split the sentence into an array of characters
	ngrams = [text[x:x+num_gram] for x in range(0, len(text))]
	return ngrams

#n-gram 빈도 리스트 생성
def make_freqlist(ngrams):
	freqlist = {}

	for ngram in ngrams:
		if (ngram in freqlist):
			freqlist[ngram] += 1
		else:
			freqlist[ngram] = 1
	
	return freqlist

ngrams = word_ngram(sample_file, 3)
freqlist = make_freqlist(ngrams)
sorted_freqlist = sorted(freqlist.items(), key=operator.itemgetter(1))
print(sorted_freqlist)


 


빈도 리스트는 길어서 상위 4개 trigram 만 적습니다.

날개의 본문은 저작권이 만료되었으므로 한국저작권위원회 공유마당에서 내려받으실 수 있습니다.

(('것', '같았다.', '나는'), 3), (('돈을', '놓고', '가는'), 3), (('그', '돈', '오'), 4), (('알', '수', '없다.'), 4)]

날개의 n-gram 분석 결과도 흥미롭네요 ㅎㅎ


추가>> bigram 분석 결과 시 다음과 같이 나왔습니다. 

(('다.', '나는'), 6), (('돈을', '놓고'), 6), (('내', '방'), 6), (('놓고', '가는'), 6), (('아내', '방으로'), 6), (('견딜', '수가'), 6), (('이불', '속에서'), 6), (('수', '있는'), 6), (('않았다.', '나는'), 6), (('', '나는'), 6), (('한', '번'), 6), (('나는', '그'), 7), (('내', '방으로'), 7), (('나는', '이'), 8), (('나는', '또'), 12), (('것이다.', '나는'), 12), (('나는', '내'), 12)]




여담: Google Books Ngram Viewer



Google Ngram Viewer (링크: https://books.google.com/ngrams) 은 구글이 구축한 말뭉치에서 연도별로 검색된 n-gram 을 검색해서 보여줍니다. 빅데이터 텍스트 마이닝 분야뿐 만 아니라 요새는 인문학 연구, 마케팅에도 자주 쓰인다고 하네요. 상당히 흥미로운 통계도 찾을 수 있으니 직접 해보시기 바랍니다.



참고자료


  1. Zhu, Xiaojin. "Language Modeling." CS769: Advanced Natural Language Processing (2010): n. pag. Web.
  2. 심광섭. "품사 태깅 말뭉치에서 추출한 n-gram을 이용한 음절 단위의 한국어 형태소 분석." 정보과학회논문지 : 소프트웨어 및 응용, 40.12 (2013): 869-876. Print.