Preprocessing Text Data

2023. 12. 27. 14:24Portfolio/kakao X goorm 군 장병 AI·SW 교육

Contents 접기

코퍼스(Corpus)

"코퍼스"는 언어 모델(LM)이나 자연어 처리(NLP) 시스템을 훈련시키기 위한 텍스트 데이터의 집합이다.

이 데이터는 다양한 주제와 형식의 텍스트로 구성될 수 있으며,

언어 모델이 언어 패턴, 의미, 문법 등을 이해하고 학습하는 데 사용된다.

 

예를 들어, 트위터 코퍼스는 트위터에서 수집한 트윗들의 집합으로,

실시간 발생하는 트윗(텍스트 데이터)이 쌓이고 다음과 같은 특징들을 갖는다. 

1. 전 세계의 다양한 언어와 스타일 : 전 세계에서 사용되므로 다양한 언어로 작성된 트윗들이 포함
2. 해시태그 및 멘션 : 주제에 대한 해시태그(#)와 다른 사용자 멘션(@)

3. 이모티콘 및 감정 표현 : 사용자들이 감정을 나타내거나 특정 상호아에 대한 반응 전달을 위해 사용

4. 실시간 이벤트 및 트렌드 : 실시간 특정 주제에 대한 대화가 급속하게 변화

5. 사용자 생성 콘텐츠 : 개인 및 기업 사용자들이 생성한 다양한 콘텐츠 포함

 

트위터 코퍼스를 활용하면 언어 모델은 다양한 언어적 특성과 사용자 활동 패턴에 적응하여

현실 세계의 언어 환경을 더 잘 이해할 수 있게 된다.

 

이처럼 NLP에서 크롤링 등으로 얻어낸 코퍼스 데이터가 만약 필요에 맞게 전처리되지 않은 상태라면,

해당 데이터를 사용하고자 하는 용도에 맞게 토큰화(tokenization) & 정규화(normalization)를 진행한다.

 

 

토큰화 (Tokenization)

"토큰화"는 주어진 코퍼스에서 토큰이라 불리는 단위로 나누는 작업을 의미한다.

 

1. 단어 토큰화(Word Tokenization)

token의 기준을 단어(word)로 하는 경우, 단어 토큰화라고 한다.

다만, 이때 단어는 단어 단위 외에도 단어구, 의미를 갖는 문자열로도 간주되기도 한다.

 

다음 입력으로부터 구두점(punctuation)과 같은 문자(.,?;!)는 제외시키는 간단한 단어 토큰화 작업을 진행해보자

입력: Time is an illusion. Lunchtime double so!

 

이러한 입력으로부터 구두점을 제외시킨 토큰화 작업의 결과는 다음과 같다.

출력: "Time", "is", "an", "illustion", "Lunchtime", "double", "so"

 

이 예제에서는 구두점을 지운 뒤 whitespace를 기준으로 잘라냈지만,

보통 토큰화 작업은 구두점 or 특수문자를 전부 제거하는 정제(cleaning) 작업을 수행하는 것만으로 해결되지 않는다.

(토큰에 따라 정제 수행에 따라 의미를 잃어버릴 수 있고, 한국어는 띄어쓰기만으로 구분 어려움) 

 

 

2. 토큰화 중 생기는 선택의 순간

토큰화를 하다보면, 예상하지 못한 경우가 있어 토큰화의 기준을 생각해봐야 하는 경우가 발생한다.

해당 데이터를 어떤 용도로 사용할 것인지에 따라 그 용도에 영향이 없는 기준으로 정하면 된다.

 

사용자가 원하는 결과가 나오도록 토큰화 도구를 직접 설계할 수도 있지만, 기존에 공개된 도구들의 사용 결과가

목적과 일치하는 경우도 존재한다. 예로 NLTK는 영어 코퍼스를 토큰화하기 위한 도구를 제공한다.

 

nltk를 사용해보자

from nltk.tokenize import word_tokenize

# 전처리하고자 하는 문장을 String 변수로 저장
sentence = '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.word_tokenize(sentence)  # 문장을 토큰화해 출력

 

더보기
['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',
 '.']

 

 

3. 토큰화에서 고려해야 할 사항

✔️ 구두점이나 특수 문자를 단순 제외해서는 안됨
ex) 마침표(.)는 문장의 경계를 알려줌, 단어 자체에 구두점을 갖는 경우, $는 가격을 의미함

✔️ 줄임말과 단어 내에 띄어쓰기가 있는 경우
ex) 영어권 언어의 아포스트로피(')는 단어가 줄임말로 쓰일 때 생기는 형태
ex) "rock n roll" 이라는 단어는 하나의 단어이지만 중간에 띄어쓰기 존재

 

 

 

4. 문장 토큰화(Sentence Tokenization)

만약 토큰의 단위가 문장이라면?

직관적으로 생각해보면 ?,마침표(.), ! 를 기준으로 문장을 잘라내면 되지 않을까 생각이 들 수 있지만,

?나 !는 문장의 구분을 위한 구분자(boundary) 역할을 하지만 마침표는 그렇지 않기 때문에 용도에 맞게 토큰화 진행 필요

 

NLTK에서는 영어 문장 토큰화를 수행하는 sent_tokenize를 지원한다.

from nltk.tokenize import sent_tokenize

# Case 1
text = "His barber kept his word. But keeping such a huge secret to himself was driving him crazy. Finally, the barber went up a mountain and almost to the edge of a cliff. He dug a hole in the midst of some reeds. He looked about, to make sure no one was near."
print('문장 토큰화1 :',sent_tokenize(text))

# Case 2
text = "I am actively looking for Ph.D. students. and you are a Ph.D student."
print('문장 토큰화2 :',sent_tokenize(text))

 

# Case 1
문장 토큰화1: ['His barber kept his word.', 'But keeping such a huge secret to himself was driving him crazy.', 'Finally, the barber went up a mountain and almost to the edge of a cliff.', 'He dug a hole in the midst of some reeds.', 'He looked about, to make sure no one was near.']

# Case 2
문장 토큰화2 : ['I am actively looking for Ph.D. students.', 'and you are a Ph.D student.']

 

 

 

5. 품사 태깅(Part-of-speech tagging)

영어 단어 'fly'는 동사로는 '날다'라는 의미를 갖지만, 명사로는 '파리'라는 의미를 갖고있다.

한국어도 '못' 이라는 단어는 "망치를 사용해서 목재를 고정하는 물건"과 "할 수 없다" 라는 두 개의 뜻을 가진다.

 

결국 단어의 의미를 제대로 파악하기 위해서는 해당 단어가 어떤 품사로 쓰였는 지 봐야하고,

이 작업을 품사 태깅(POS tagging)이라고 한다. 

NLTK POS Tags

 

NLTK POS Tags

 

NLTK를 통해 품사 태깅 실습을 해보자

# 각 문장을 토큰화한 후 품사를 태깅하여 결과를 출력

tokens = nltk.word_tokenize(sentence)  # 문장을 토큰화
nltk.pos_tag(tokens)  # 토큰화한 문장을 품사 태깅해 출력
더보기
[('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'),
 ('.', '.')]

각 토큰들이 품사에 따라 분류되었다.

한국어 NLP를 위해서는 KoNLPy라는 파이썬 패키지를 사용해야 한다.

 

 

 

불용어(Stopword)

갖고 있는 데이터에서 유의미한 단어 토큰을 선별하기 위해서는 의미가 없는 단어 토큰을 제거해야 한다.

여기서 의미가 없는 토큰은 I, my, me, over, 조사, 접미사와 같은 자주 등장하지만 실제 의미 분석을 하는데는

거의 기여하는 바가 없는 경우이다. 

 

NLTK에서는 위와 같은 100여개 이상의 영단어를 불용어로 패키지 내에서 미리 정의하고 있다.

# nltk 모듈에서 Stopwords를 직접 불러온다
from nltk.corpus import stopwords

stop_words_list = stopwords.words('english')
print('불용어 개수 :', len(stop_words_list))
print('불용어 10개 출력 :',stop_words_list[:10])

 

불용어 개수 : 179
불용어 10개 출력 : ['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're"]

 

stopwords.words("englisth")는 NLTK가 정의한 영어 불용어 리스트를 리턴한다.

 

위에서 토큰화를 진행한 문장에서 stopwords를 제거해보자

# 문장에서 stopwords 제거

result = []  # stopwords가 제거된 결과를 담기 위한 리스트를 생성한다

for token in tokens:  # for문을 통해 각각의 token이 stopwords인지 아닌지를 판별해 결과에 저장한다
    if token.lower() not in stopWords:  # 만약 소문자로 변환한 token이 stopWords 내에 없으면:
        result.append(token)  # token을 리스트에 첨부한다

print(result)  # 결과를 출력한다

 

['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에 추가하여 다시 적용해보자

# stopwords에 쉼표(,)와 마침표(.) 추가하여 다시 적용하기

stop_words = stopwords.words("english")
stop_words.append(',')
stop_words.append('.')

result = []  # stopwords가 제거된 결과를 담기 위한 리스트를 생성한다

for token in tokens:  # for문을 통해 각각의 token이 stopwords인지 아닌지를 판별해 결과에 저장한다
    if token.lower() not in stop_words:  # 만약 소문자로 변환한 token이 stopWords 내에 없으면:
        result.append(token)  # token을 리스트에 첨부한다

print(result)  # 결과를 출력한다
['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']

 

완료!

아직 한국어 처리는 해보지 않았지만, 형태소 단위와 띄어쓰기가 영어보다 잘 지켜지지 않는 점 때문에 쉽지 않을 것 같다..

 

 

 

 

참고

https://wikidocs.net/21698

https://velog.io/@ssook1222/NLP-%EC%BD%94%ED%8D%BC%EC%8A%A4%EC%99%80-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%84%B8%ED%8A%B8%EC%9D%98-%EC%8B%A4%EC%A0%9C-%EC%9D%B4%ED%95%B4

 

02-01 토큰화(Tokenization)

자연어 처리에서 크롤링 등으로 얻어낸 코퍼스 데이터가 필요에 맞게 전처리되지 않은 상태라면, 해당 데이터를 사용하고자하는 용도에 맞게 토큰화(tokenization) & 정제(c…

wikidocs.net

썸네일 출처

http://aispiration.com/text/nlp-intro-python.html