하루 하루

NLTK - Learning to Classify Text ( 4 ) 본문

IT/Artificial intelligence

NLTK - Learning to Classify Text ( 4 )

san_deul 2020. 5. 26. 18:20

Sentence Segmentation

코퍼스의 문장 경계선이 어디인지 확인하는 문제이다.

예를 들어서, "Its length is 16.7 cm."라는 한 문장이 있다면

'.'을 기준으로 문장을 나누면 'Its length is 16.'와 '7 cm.' 두 개가 된다.

따라서 코퍼스의 특징에 따라서 나뉠 수 있도록 학습이 필요하다. 

 

 

treebank_raw로 sentence segementation을 학습하는 예제

import nltk
sents = nltk.corpus.treebank_raw.sents( )

sents를 sents[:3]dmf 통해서 살펴보면 

[['.', 'START'],
 ['Pierre','Vinken',',', '61', 'years', 'old',',','will','join',
   'the','board','as','a','nonexecutive','director','Nov','.','29','.'],
 ['Mr','.', 'Vinken', 'is','chairman', 'of', 'Elsevier', 'N', '.', 'V', 
   '.,', 'the', 'Dutch', 'publishing', 'group','.']]

다음과 같이 문장 단위로 나뉜 것을 확인할 수 있다. 

tokens = []
boundaries = set()
offset = 0
for sent in sents:
        tokens.extend(sent)
        offset += len(sent)
        boundaries.add(offset-1)

sents에는 각 문장마다 리스트를 가지고서 token으로 분류되어 있다.

for 문을 통해서 각 문장의 리스트를 sent로 가져와서 

tokens에  sent의 모든 항목을 추가하고, 

offset 에는 sent의 길이를 더해서 

boundaries에 offset-1을 넣는다. 

len(sent) 랑 offset를 보면 각 문장이 끝나는 인덱스가 offset-1 이 되는 것을 알 수 있다. 

따라서 boundaries 에는 다음과 같이 각 문장들이 token으로 분리되었을 때, 문장들이 끝나는 

위치를 저장한다. 

def punct_features(tokens, i):
        return {'next-word-capitalized': tokens[i+1][0].isupper(),
                'prev-word': tokens[i-1].lower(),
                'punct': tokens[i],
                'prev-word-is-one-char': len(tokens[i-1]) == 1}

위 함수는 특징을 추출하는 함수로 각각 특징들을 보면, 다음 단어가 대문자인지, 앞의 단어가 무엇인지, 어떤 단어 인지

, 앞의 단어가 한 글자인지를 알려준다. 

featuresets = [(punct_features(tokens, i), (i in boundaries))
        for i in range(1, len(tokens)-1)
                if tokens[i] in '.?!']

featursets에 '.?!' 중 하나의 값을 가지는 token 들의 ( 특징 ,  boundaries에 있는지 ) 값을 넣는다. 

 

size = int(len(featuresets) * 0.1)
train_set, test_set = featuresets[size:], featuresets[:size]

featursets의 90%를 train_set으로 설정하고, 10%는 test_set으로 설정한다.

classifier = nltk.NaiveBayesClassifier.train(train_set)
nltk.classify.accuracy(classifier, test_set)
print("Sentence Segmentation:", nltk.classify.accuracy(classifier, test_set))

결과를 출력해보면

 

이 나오게 된다. 

classifier.show_most_informative_features(5)

흘 통해서 가장 나뉜 특징들을 확인할 수 있다. 

앞의 단어가 mr 이면 나뉘는 경계가 아닐 가능성이 높고, 

앞의 단어가 숫자여도 나뉘는 경계가 아닐 가능성이 높다. 

Comments