텍스트 사전 분비 작업(텍스트 전처리) - 텍스트 정규화
- 텍스트 정규화는 텍스트를 머신러닝 알고리즘이나 NLP 애플리케이션에 입력 데이터로 사용하기 위해 클렌징, 정제, 토큰화, 어근화 등의 다양한 사전 작업을 수행하는 것이다.
- 텍스트 정규화의 주요 작업을 NLTK 패키지를 이용해 실습해보자
클렌징
- 텍스트에서 분석에 오히려 방해가 되는 불필요한 문자, 기호 등을 사전에 제거하는 작업.
- 예를 들어, HTML, XML 태그나 특정 기호 등을 제거
텍스트 토큰화
- 문서에서 문장을 분리하는 문장 토큰화
- 문장의 마침표(.), 개행문자(\n) 등 문장의 마지막을 뜻하는 기호에 따라 분리하는 것이 일반적이다.
- 또한, 정규 표현식에 따른 문장 토큰화도 가능하다.
- 문장 토큰화는 각 문장이 가지는 sementic적인 의미가 중요한 요소로 사용될 때 사용한다.
- NLTK에서 많이 쓰이는 sent_tokenize를 이용해 수행해보자
In [1]:
from nltk import sent_tokenize
import nltk
nltk.download('punkt') #마침표, 개행 문자 등의 데이터셋을 다운로드함
text_sample = 'The Matrix is everywhere its all around us, here even in this room. \
You can see it out your window or on your television. \
You feel it when you go to work, or go to church or pay your taxes.'
sentences = sent_tokenize(text=text_sample)
print(type(sentences), len(sentences))
print(sentences)
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Unzipping tokenizers/punkt.zip.
<class 'list'> 3
['The Matrix is everywhere its all around us, here even in this room.', 'You can see it out your window or on your television.', 'You feel it when you go to work, or go to church or pay your taxes.']
sent_tokenize가 반환하는 것은 각각의 문장으로 구성된 리스트 객체
- 문장에서 단어를 토큰으로 분리하는 단어 토큰화
- 기본적으로 공백, 콤마(,), 마침표(.), 개행문자 등으로 단어를 분리하고 정규 표현식을 이용해 다양한 유형으로 토큰화를 수행할 수 있다.
- Bag of Word 같이 단어의 순서가 중요하지 않은 경우 단어 토큰화만 사용해도 충분하다.
- NLTK에서 제공하는 word_tokenize를 이용해 수행해보자
In [2]:
from nltk import word_tokenize
sentence = 'The Matrix is everywhere its all around us, here even in this room.'
words = word_tokenize(sentence)
print(type(words), len(words))
print(words)
<class 'list'> 15
['The', 'Matrix', 'is', 'everywhere', 'its', 'all', 'around', 'us', ',', 'here', 'even', 'in', 'this', 'room', '.']
- 이번엔 sent_tokenize와 word_tokenize를 조합하여 문서에 대해 모든 단어를 토큰화해보자
- 3개의 문장으로 된 text_sample을 문장별로 단어 토큰화를 적용하기 위해 문서를 먼저 문장으로 나누고, 개별 문장을 다시 단어로 토큰화하는 tokenize_text() 함수를 생성하자
In [3]:
def tokenize_text(text):
sentences = sent_tokenize(text)
word_tokens = [word_tokenize(sentence) for sentence in sentences]
return word_tokens
word_tokens = tokenize_text(text_sample)
print(type(word_tokens), len(word_tokens))
print(word_tokens)
<class 'list'> 3
[['The', 'Matrix', 'is', 'everywhere', 'its', 'all', 'around', 'us', ',', 'here', 'even', 'in', 'this', 'room', '.'], ['You', 'can', 'see', 'it', 'out', 'your', 'window', 'or', 'on', 'your', 'television', '.'], ['You', 'feel', 'it', 'when', 'you', 'go', 'to', 'work', ',', 'or', 'go', 'to', 'church', 'or', 'pay', 'your', 'taxes', '.']]
문장을 단어별로 하나씩 토큰화할 경우 문맥적인 의미는 무시될 수 밖에 없다.
이러한 문제를 해결하기 위해 도입된 것이 n-gram이다.
- n-gram은 연속된 n개의 단어를 하나의 토큰화 단위로 분리해 내는 것이다.
- 예를 들어, "Agent Smith knocks the door"를 2-gram으로 만들면 (Agent, Smith), (Smith, knocks), (knocks, the), (the, door)와 같이 연속적으로 2개의 단어들을 순차적으로 이동하면서 단어들을 토큰화한다.
스톱 워드 제거
- 스톱 워드(stop word)는 분석에 큰 의미가 없는 단어를 지칭한다.
- 예를 들어, 영어에서 is, the, a, will 등 문장을 구성하는 필수 문법 요소이지만 문맥적으로는 큰 의미가 없는 단어가 이에 해당된다.
- 빈번하게 나오는 단어들이므로 사전에 제거하지 않으면 빈번함으로 인해 오히려 중요한 단어로 인지될 수 있다. 따라서 제거하는 것이 중요하다.
- 언어별로 이런 스톱 워드가 목록화되어 있다.
In [4]:
import nltk
nltk.download('stopwords')
[nltk_data] Downloading package stopwords to /root/nltk_data...
[nltk_data] Unzipping corpora/stopwords.zip.
Out[4]:
True
In [5]:
print('영어 stop words 개수:', len(nltk.corpus.stopwords.words('english')))
print(nltk.corpus.stopwords.words('english')[:20])
영어 stop words 개수: 179
['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his']
위 예제에서 3개의 문장별로 단어를 토큰화한 word_tokens 리스트에 대해서 stopwords로 필터링해보자
In [9]:
import nltk
stopwords = nltk.corpus.stopwords.words('english')
all_tokens = []
# 위 예제의 3개의 문장별로 얻은 word_tokens list 에 대해 stop word 제거 Loop
for sentence in word_tokens:
filtered_words=[]
# 개별 문장별로 tokenize된 sentence list에 대해 stop word 제거 Loop
for word in sentence:
#소문자로 모두 변환합니다.
word = word.lower()
# tokenize 된 개별 word가 stop words 들의 단어에 포함되지 않으면 word_tokens에 추가
if word not in stopwords:
filtered_words.append(word)
all_tokens.append(filtered_words)
print(all_tokens)
[['matrix', 'everywhere', 'around', 'us', ',', 'even', 'room', '.'], ['see', 'window', 'television', '.'], ['feel', 'go', 'work', ',', 'go', 'church', 'pay', 'taxes', '.']]
is, this 같은 스톱 워드가 제거됐음을 알 수 있다
Stemming과 Lemmatization
- 많은 언어에서 문법적인 요소에 따라 단어가 다양하게 변한다.
- Stemming과 Lemmatization는 문법적, 의미적으로 변화하는 단어의 원형을 찾는 것이다.
- Lemmatization이 Stemming보다 정교하며 의미론적인 기반에서 단어의 원형을 찾는다.
- Stemming은 원형 단어로 변환 시 일반적인 방법을 적용하거나 더 단순화된 방법을 적용해 원래 단어에서 일부 철자가 훼손된 어근 단어를 추출하는 경향이 있다.
- 이에 비해 Lemmatization은 품사와 같은 문법적인 요소와 더 의미적인 부분을 감안해 정확한 철자로 된 어근 단어를 찾아준다. → Stemming보다 변환이 더 오래 걸림
- NLTK는 다양한 Stemmer를 제공함 → Porter, Lancaster, Snowball Stemmer
- Lemmatization을 위한 WordNetLemmatizer 제공
진행형, 3인칭 단수, 과거형에 따른 동사, 비교/최상급에 따른 형용사 변화 등에 따라 Stemming은 더 단순하게 원형 단어를 찾아준다.
LancasterStemmer()와 같은 Stemmer 객체를 생성하고 stem('단어') 메서드를 호출하면 원하는 '단어'의 Stemming이 가능하다.
In [10]:
from nltk.stem import LancasterStemmer
stemmer = LancasterStemmer()
print(stemmer.stem('working'), stemmer.stem('works'), stemmer.stem('worked'))
print(stemmer.stem('amusing'), stemmer.stem('amuses'), stemmer.stem('amused'))
print(stemmer.stem('happier'), stemmer.stem('happiest'))
print(stemmer.stem('fancier'), stemmer.stem('fanciest'))
work work work
amus amus amus
happy happiest
fant fanciest
work의 경우는 모두 기본 단어에서 ing, s, ed가 붙는 단순한 변화이므로 원형 단어를 제대로 인식한다.
그러나, amuse의 경우는 amus에 ing, s, ed가 붙으므로 정확한 단어인 amuse로 인식하지는 못한다.
형용사인 happy, fancy의 경우도 비교급, 최상급으로 변형된 단어의 정확한 원형을 찾지 못한다.
따라서, 이번에는 WordNetLemmatizer로 수행해보자
In [11]:
from nltk.stem import WordNetLemmatizer
import nltk
nltk.download('wordnet')
lemma = WordNetLemmatizer()
#보다 정확한 원형 추출을 위해 단어의 '품사'를 입력해주고 lemmatize의 파라미터로 동사면 'v', 형용사면 'a'를 입력해야함
print(lemma.lemmatize('amusing', 'v'), lemma.lemmatize('amuses', 'v'), lemma.lemmatize('amused', 'v'))
print(lemma.lemmatize('happier', 'a'), lemma.lemmatize('happiest', 'a'))
print(lemma.lemmatize('fancier', 'a'), lemma.lemmatize('fanciest', 'a'))
[nltk_data] Downloading package wordnet to /root/nltk_data...
amuse amuse amuse
happy happy
fancy fancy
Stemmer보다 정확하게 원형 단어를 추출해줌을 알 수 있다.
'Data Science > 파이썬 머신러닝 완벽 가이드' 카테고리의 다른 글
[sklearn] (51) - 텍스트 분류 실습 - 20 뉴스그룹 분류 (0) | 2023.08.01 |
---|---|
[sklearn] (50) Bag of Words - BOW (0) | 2023.08.01 |
[sklearn] (48) 자연어처리(NLP, Natural Language Processing)와 텍스트 분석(Text Analytics) (0) | 2023.07.28 |
[sklearn] (47) 군집화 실습 - 고객 세그먼테이션(Customer Segmentation) (0) | 2023.07.28 |
[sklearn] (46) DBSCAN(밀도 기반 클러스터링), make_circles (0) | 2023.07.26 |