앞서 설명한 web scraping으로 얻어낸 text data를 전처리 하는 작업을 시작하겠습니다.
우선 얻어낸 text data를 하나의 str 문자열 변수로 묶어 줍니다.
str_munja = '안녕하세요. 저는 str 문자열 변수로 묶인 text data입니다.'
이 문자열을 각각의 단어로 쪼개고, 각 단어의 품사를 구분하고, text data를 분석하는데 필요 없는 형태소를 제거하는 작업을 해주면 됩니다.
3가지의 작업 단계가 있는데, 사실 text data를 분석하는 과정에는 각 단어의 품사를 구분하는 과정은 중요하지 않습니다.
첫번째, Tokenize 작업(형태소 분석)
text data 전체를 하나의 단어 수준으로 쪼개는 작업을 의미합니다. 리스트 형식으로 쪼개줍니다.
['안녕하세요', '.', '저는', 'str', '문자열', '변수로', '묶인', 'text', 'data입니다' '.']
두번째, Pos tagging 작업(각각의 형태소의 품사를 표시)
pos는 part of speech(발화에서 맡은 역할) 이라는 뜻입니다. 튜플 형식으로 표현해줍니다.
[('안녕하세요', 'NNP'), ('.', '.'), ('저는', 'NNP'), ('str', 'NNP'), ~]
세번째, Stopwords 제거(불용어 제거)
불용어란, text data 문장을 분석하는데 도움이 안되는 단어. 즉, 특수기호 or 조사(을, 를, 이, 가) 등등 입니다.
위의 3가지 작업을 진행해주면 정말 필요한 형태소만 남게 됩니다. 이 형태소로 해당 문장의 의미 파악, 유사도 분석 등 여러 작업을 해줄 수 있습니다.
이런 작업을 해주기 위해서는 어떤 단어의 출현 빈도가 높은지 단어 사전을 만들어 줘야 합니다. 단어사전은 dict 형식으로 만들게 되는데 key에는 단어, value에는 출현 빈도가 들어갑니다.
이런 작업을 진행할 때, 우리는 nltk library를 사용해야 합니다.
nltk는 Natural Language Toolkit의 약자로 우리가 text data 즉, 사람이 사용하는 언어를 분석하므로 Natural Language(사람 언어)에 대한 Toolkit(작업 도구)라는 뜻입니다.
import nltk
nltk를 import 해주었으면, 우리가 분석하고자 하는 문장을 str 변수로 저장해줘야 합니다.
munjang = 'NLTK is a leading platform for building Python programs to work with human language data. It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet, along with a suite of text processing libraries for classification, tokenization, stemming, tagging, parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries, and an active discussion forum.'
그다음 nltk library에게 str로 저장된 munjang을 word(단어) 수준으로 tokenize 해달라고 명령을 해줘야 합니다.
nltk.word_tokenize(munjang)
['NLTK',
'is',
'a',
'leading',
'platform',
'for',
'building',
'Python',
'programs',
'to',
'work',
'with',
'human',
'language',
'data',
'.',
'It',
'provides',
'easy-to-use',
'interfaces',
'to',
'over',
'50',
'corpora',
'and',
'lexical',
'resources',
'such',
'as',
'WordNet',
',',
'along',
'with',
'a',
'suite',
'of',
'text',
'processing',
'libraries',
'for',
'classification',
',',
'tokenization',
',',
'stemming',
',',
'tagging',
',',
'parsing',
',',
'and',
'semantic',
'reasoning',
',',
'wrappers',
'for',
'industrial-strength',
'NLP',
'libraries',
',',
'and',
'an',
'active',
'discussion',
'forum',
'.']
이제 각 단어의 품사가 뭔지 알려주는 작업을 실시하면 됩니다.
nltk에게 토큰화(각각의 형태소로 분리)된 변수 token을 pos(품사 표시)를 한 뒤, tag 해달라는 명령을 해줍니다.
token = nltk.word_tokenize(munjang)
nltk.pos_tag(token)
[('NLTK', 'NNP'),
('is', 'VBZ'),
('a', 'DT'),
('leading', 'VBG'),
('platform', 'NN'),
('for', 'IN'),
('building', 'VBG'),
('Python', 'NNP'),
('programs', 'NNS'),
('to', 'TO'),
('work', 'VB'),
('with', 'IN'),
('human', 'JJ'),
('language', 'NN'),
('data', 'NNS'),
('.', '.'),
('It', 'PRP'),
('provides', 'VBZ'),
('easy-to-use', 'JJ'),
('interfaces', 'NNS'),
('to', 'TO'),
('over', 'IN'),
('50', 'CD'),
('corpora', 'NNS'),
('and', 'CC'),
('lexical', 'JJ'),
('resources', 'NNS'),
('such', 'JJ'),
('as', 'IN'),
('WordNet', 'NNP'),
(',', ','),
('along', 'IN'),
('with', 'IN'),
('a', 'DT'),
('suite', 'NN'),
('of', 'IN'),
('text', 'NN'),
('processing', 'NN'),
('libraries', 'NNS'),
('for', 'IN'),
('classification', 'NN'),
(',', ','),
('tokenization', 'NN'),
(',', ','),
('stemming', 'VBG'),
(',', ','),
('tagging', 'VBG'),
(',', ','),
('parsing', 'NN'),
(',', ','),
('and', 'CC'),
('semantic', 'JJ'),
('reasoning', 'NN'),
(',', ','),
('wrappers', 'NNS'),
('for', 'IN'),
('industrial-strength', 'JJ'),
('NLP', 'NNP'),
('libraries', 'NNS'),
(',', ','),
('and', 'CC'),
('an', 'DT'),
('active', 'JJ'),
('discussion', 'NN'),
('forum', 'NN'),
('.', '.')]
품사 표현 | 뜻 |
명사 | N |
형용사 | A / J |
동사 | V |
이제 마지막 불용어를 제거해주면 됩니다.
그런데, 문장이 만약 영어라면 nltk library에 stopwords(불용어 제거) 함수가 있습니다.
179개의 stopwords가 있는데, 여기서 우리가 더 추가하거나 뺄 수도 있습니다.
from nltk.corpus import stopwords
nltk library에 stopwords를 지원하는 언어가 많은데, 그중 영어를 선택해야 합니다.
stopWords = stopwords.words('english')
우선, 불용어 제거를 위해 품사 표시가 안되어 있는 list를 가져오겠습니다.
token
['NLTK', 'is', 'a', 'leading', 'platform', 'for', 'building', 'Python', 'programs', 'to', 'work', 'with', 'human', 'language', 'data', '.', 'It', 'provides', 'easy-to-use', 'interfaces', 'to', 'over', '50', 'corpora', 'and', 'lexical', 'resources', 'such', 'as', 'WordNet', ',', 'along', 'with', 'a', 'suite', 'of', 'text', 'processing', 'libraries', 'for', 'classification', ',', 'tokenization', ',', 'stemming', ',', 'tagging', ',', 'parsing', ',', 'and', 'semantic', 'reasoning', ',', 'wrappers', 'for', 'industrial-strength', 'NLP', 'libraries', ',', 'and', 'an', 'active', 'discussion', 'forum', '.']
여기서 for 문과 if문을 돌려주면서 stopwords를 제거해주면 됩니다.
succes = []
for i in token:
if i.lower() not in stopWords:
succes.append(i)
succes
이때, token의 단어들에 lower() 함수를 쓰는 이유는 nlkt에서 제공하는 stopwords에는 전부 소문자로 된 stopword만 들어있기 때문입니다. 결과물은 다음과 같습니다.
['NLTK', 'leading', 'platform', 'building', 'Python', 'programs', 'work', 'human', 'language', 'data', '.', 'provides', 'easy-to-use', 'interfaces', '50', 'corpora', 'lexical', 'resources', 'WordNet', ',', 'along', 'suite', 'text', 'processing', 'libraries', 'classification', ',', 'tokenization', ',', 'stemming', ',', 'tagging', ',', 'parsing', ',', 'semantic', 'reasoning', ',', 'wrappers', 'industrial-strength', 'NLP', 'libraries', ',', 'active', 'discussion', 'forum', '.']
이때, ','이나 '.' 같은 특수기호는 제거가 안돼서 stopwords에 추가를 하겠습니다.
stopWords = stopword.words('english)
stopWords.append(',')
stopWords.append('.')
succes = []
for i in token:
if i.lower() not in stopWords:
succes.append(i)
succes
이렇게 특수기호를 제거하는 방법도 있지만 더 쉬운 re.match('^[a-zA-Z]+', '변수 명')을 사용하면 더 쉽습니다.
['NLTK', 'leading', 'platform', 'building', 'Python', 'programs', 'work', 'human', 'language', 'data', 'provides', 'easy-to-use', 'interfaces', '50', 'corpora', 'lexical', 'resources', 'WordNet', 'along', 'suite', 'text', 'processing', 'libraries', 'classification', 'tokenization', 'stemming', 'tagging', 'parsing', 'semantic', 'reasoning', 'wrappers', 'industrial-strength', 'NLP', 'libraries', 'active', 'discussion', 'forum']
이제 각 단어의 파생적 의미를 제거하고, 기본 사전형 단어로 바꿔주는 작업을 실시하겠습니다.
Lemmatization 작업이라고 합니다. Lemma는 단어의 사전형 이라는 뜻입니다.
이 기능 역시 nltk에 들어 있습니다. 불러오도록 하겠습니다.
lemmatizer = nltk.wordnet.WordNetLemmatizer()
예를 들어 설명하겠습니다.
print(lemmatizer.lemmatize("ran"))
print(lemmatizer.lemmatize("ran", 'v'))
lemmatizer 안에 있는 lemmatize라는 기능을 실행하면 ( )안에 있는 단어를 사전형으로 바꿔주거나, 뒤에서 지정하는 품사 형태로 바꿔주게 됩니다.
이제 lemmatizer 함수를 이용해 munjang을 토큰 단위로 쪼개고, 단어의 품사가 동사인 것만 출력하겠습니다.
import nltk
from nltk.corpus import stopwords
munjang = 'NLTK is a leading platform for building Python programs to work with human language data. It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet, along with a suite of text processing libraries for classification, tokenization, stemming, tagging, parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries, and an active discussion forum.'
token = nltk.word_tokenize(munjang)
token_pos = nltk.pos_tag(token)
result = []
for a, b in token_pos:
if b.startswith('V'):
result.append(a)
result
['is', 'leading', 'building', 'work', 'provides', 'stemming', 'tagging']
이때, 출력값의 단어를 모두 사전형 단어로 바꿔주고 불용어 제거도 하도록 하겠습니다.
import nltk
from nltk.corpus import stopwords
lemmatizer = nltk.wordnet.WordNetLemmatizer()
munjang = 'NLTK is a leading platform for building Python programs to work with human language data. It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet, along with a suite of text processing libraries for classification, tokenization, stemming, tagging, parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries, and an active discussion forum.'
token = nltk.word_tokenize(munjang)
token_pos = nltk.pos_tag(token)
result = []
for a, b in token_pos:
if b.startswith('V'):
if a.lower() not in stopWords:
result.append(lemmatizer.lemmatize(a))
result
이번에는 moviereview.txt 파일을 불러 읽어서 동사 단어만 출력하는 필터를 만들어 보겠습니다.
import nltk
from nltk.corpus import stopwords
lemmatizer = nltk.wordnet.WordNetLemmatizer()
stopWords = stopwords.words('english')
stopWords.append(',')
stopWords.append('.')
with open('moviereview.txt', 'r', encoding = 'utf-8') as f:
f_str = f.readlines()
token = nltk.word_tokenize(f_str[1])
token_pos = nltk.pos_tag(token)
result = []
for a, b in token_pos:
if b.startswith('V'):
if a.lower() not in stopWords:
result.append(lemmatizer.lemmatize(a))
result