고양국제고/더브레인

[더브레인-3] 3. 전산형태론 예제 실습 안내

카루-R 2022. 7. 7. 14:59
반응형
 

환영합니다, Rolling Ress의 카루입니다.

** 3-3. 자연어 전처리 [언어]

이번에는 자연어 처리에서 중요하게 사용되는 전처리 방식에 대해 알아보도록 하겠습니다. 사실 이번 글은 제가 따로 설명할 내용이 없습니다. 여기서는 예제 코드를 통해 '아, 이런 식으로 자연어 처리가 가능하구나' 정도만 이해하고 넘어가는 걸 목표로 하겠습니다.

!pip install nltk

from nltk.corpus import stopwords
from nltk.stem import LancasterStemmer
from nltk.stem import PorterStemmer
from nltk.tag import pos_tag
from nltk.tokenize import RegexpTokenizer
from nltk.tokenize import TreebankWordTokenizer

import nltk
import re

우선 필요한 모듈을 불러줍니다. nltk는 대표적인 자연어 처리 모듈 중 하나입니다.

sentence = 'I was wondering if anyone out there could enlighten me on this car.'

# 문장을 처리하는 방법 1
# 2자 이내의 짧은 단어를 삭제합니다.
shortword = re.compile(r'\W*\b\w{1,2}\b')
data = shortword.sub('', sentence)

print('짧은 단어 삭제:', data)

# 문장을 처리하는 방법 2
# 단어를 기반으로 토큰화를 해봅시다.
tokenizer = RegexpTokenizer('[\w]+')
sentence = 'Time is an illusion. Lunchtime double so!'
tokens = tokenizer.tokenize(sentence)

print('\n단어 토큰화 1:', tokens)

sentence = "Starting a home-based restaurant may be an ideal. it doesn't have a food chain or restaurant of their own."
tokens = tokenizer.tokenize(sentence)
print('\n단어 토큰화 2:', tokens)

임의의 문장을 작성해두었습니다. 제가 영어 문장을 준비해달라고 부탁드렸을텐데, 원하신다면 sentence 부분을 준비하신 문장으로 바꿔주세요.

출력 결과가 크게 세 부분으로 나뉠텐데, 각각을 설명해드리겠습니다.

1. 영문 기준 2글자 이내의 단어는 큰 의미를 갖지 못하므로 지워줍시다. '마침표를 포함한' 비문이 출력됩니다.

2. 단어를 기준으로 토큰화합니다. 단어의 길이에 상관 없이, 주어진 문장을 기반으로 토큰화를 합니다. 결괏값은 리스트입니다.

3. 2번과 같습니다. 다만 문장이 다릅니다.

# 품사 분석을 위한 태그를 다운받습니다.
nltk.download('averaged_perceptron_tagger')

tokenizer = TreebankWordTokenizer()
tokens = tokenizer.tokenize(sentence)
postag = pos_tag(tokens)

print('트리뱅크 워드토크나이저 :', tokens)
print('품사 태깅 :', postag)

쪼갠 단어를 바탕으로 이렇게 품사를 매겨주게 됩니다. 원한다면 여기서 명사만 따온다든지, 동사만 따온다든지 할 수 있겠죠.

noun_list = [x for (x, y) in postag if y == 'NN']

이런 식으로 한다면 명사만 따온 리스트를 만들 수도 있습니다. 원하신다면 이렇게 해서 출력해보세요.

표제어(기본형)를 따오는 예제도 있는데, 이건 생략할게요. 사실 크게 중요한 부분은 아니라서. 그리고 여러분 머리가 터져요.

stemmer = PorterStemmer()
tokenizer = TreebankWordTokenizer()

sentence = "This was not the map we found in Billy Bones's chest, but an accurate copy, complete in all things with the single exception of the red crosses and the written notes."
tokens = tokenizer.tokenize(sentence)

# tokens를 순회하며 어간 추출 
data = [stemmer.stem(data) for data in tokens]

print('어간 추출 전 :', tokens)
print('\n어간 추출 후 :', data)
print('\n=====================\n')

# 다른 어간추출기와 비교
ps = PorterStemmer()
ls = LancasterStemmer()

wordlist = ['policy', 'doing', 'organization', 'have', 'going', 'love', 'lives', 'fly', 'dies', 'watched', 'has', 'starting']

porterdata = [ps.stem(data) for data in wordlist]
lancasterdata = [ls.stem(data) for data in wordlist]

print('어간 추출 전 :', wordlist)
print('\n포터 스테머의 어간 추출 후:',porterdata)
print('\n랭커스터 스테머의 어간 추출 후:',lancasterdata)

어간 추출기입니다. 여기는 크게 두 부분으로 나눌 수 있습니다.

첫 번째 파트는 문장을 아까 사용했던 토크나이저로 자른 뒤, 자른 단어에서 어간을 추출해내는 방식입니다.

두 번째는 단어 리스트를 만들고 거기에서 어간을 추출해내는 방식입니다. 여기서는 두 가지의 어간 추출기를 사용합니다. 여러분이 출력 결과를 비교해보고, 어느 것이 더 나은지 골라보세요. 실습을 완료했으면 문장을 바꿔서도 해보시기 바랍니다.

반응형