working_helen
[text 감정 추출 모델] 텍스트 전처리 / Goolgetrans 번역 API 본문
text 감정 추출 모델 훈련 과정에서 진행한 텍스트 전처리와 구글 번역 API에 대해 공부해본다.
1. 텍스트 전처리
2. 토큰화
3. 정제
4. 정규화
5. Goolgetrans 번역 API
1. 텍스트 전처리 (Text preprocessing)
- 자연어 처리 문제에서 분석 목적에 맞게 텍스트 데이터를 사전에 전처리하는 작업
- 토큰화(tokenization) & 정제(cleaning) & 정규화(normalization) 3가지 과정으로 이루어진다.
- NLTK (Natural Language Toolkik) : 영어 텍스트 전처리를 위한 Python의 자연어 처리 패키지
2. 토큰화
1) 토큰화(tokenization)
- 주어진 코퍼스(corpus, 말뭉치)를 어떠한 작은 단위 토큰(token)으로 나누는 작업
- 토큰은 상황마다 다르게 지정할 수 있는데, 토큰의 기준을 단어(word)로 하는 경우를 단어 토큰화(word tokenization),
토큰의 기준을 문장(sentence)으로 하는 경우 문장 토큰화(Sentence Tokenization)가 된다.
2) 토큰화시 주의해야하는 부분
- 구두점이나 특수 문자가 의미있는 경우 : $45.55(가격), Ph.D(학위) 등
- 줄임말 표현인 경우 : we're, I'm, don't 등
- 하나의 단어이지만 띄어쓰기가 있는 경우 : New York, rock n roll 등
- 공백로 구분되지 않는 경우: 's (소유격)
3) nltk를 이용한 토큰화 : word_tokenize와 WordPunctTokenizer
## word_tokenize
from nltk.tokenize import word_tokenize
word_tokenize(text)
## WordPunctTokenizer
from nltk.tokenize import WordPunctTokenizer
punct_tokenizer = WordPunctTokenizer()
punct_tokenizer.tokenize(text)
3. 정제
1) 정제(cleaning)
- 노이즈 데이터를 제거하는 작업
- 분석 목적에 맞지 않는 불필요한 단어들을 제거
- 불필요한 특수문자 제거 : re.sub 함수와 정규표현식 이용
- 등장 빈도가 적은 단어를 삭제
- 불용어 제거
2) 불용어 Stopword
- 자주 등장하지만 분석을 하는 것에 있어서는 큰 도움이 되지 않는 단어
- 대명사, 조사, 관사, 접미사, 강조성 부사 등
- NLTK의 경우 179여 개 단어로 구성된 불용어 사전을 사용한다. 이때 NLTK 불용어 사전은 소문자 기준으로 등록되어 있으므로 모든 단어를 소문자로 바꾼 후 불용어를 제거를 진행한다.
4. 정규화
1) 정규화(normalization)
- 동일한 의미이지만 표현 방법이 다른 단어를 하나로 통합하는 작업
- 특히 표제어 추출과 어간 추출의 경우 서로 달라보이는 단어들을 하나로 일반화함을써 문서 내 단어 수를 줄이는 효과를 준다.
- 대소문자 통합 : 다만 미국 US와 대명사 us는 통합되지 말아야하는 등 주의가 필요
- 어간 추출 (Stemming)
- 표제어 추출 (Lemmatization)
2) 어간 추출 (Stemming)
- 단어의 어간을 추출하는 작업
- 문맥을 고려하지 않고, 사전에 정해진 규칙에 따라 단어의 어미를 자르기 때문에, 어간 추출 결과 전에 존재하지 않는 단어일 경우가 많다.
- nltk를 이용한 어간 추출
: nltk에는 Porter, Lancaster, Snowball Stemmer 여러가지 어간 추출 Stemmer가 존재
## Porter Stemmer 사용
from nltk.stem import PorterStemmer
stemmer = PorterStemmer()
words = [단어 list]
result = [stemmer.stem(word) for word in words]
3) 표제어 추출(Lemmatization)
- 단어의 표제어를 찾아가는 과정 ex) know, knows, known → know
- 문맥을 고려하면서 진행되기 때문에 Stemming에 비해 시간은 더 오래 걸리지만, 대신 단어의 원형이 더 잘 보존된다.
- nltk를 이용한 표제어 추출 : WordNetLemmatizer
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
words = [단어 list]
result = [lemmatizer.lemmatize(word) for word in words]
4) 품사 태깅 (Part-Of-Speech Tagging ; POS Tagging)
- 단어 토큰화시 각 단어가 주어진 문맥에서 어떤 품사로 쓰였는지 라벨링하는 방법
- Lemmatization은 Stemmin에 비해 문맥을 고려하지만, 여전히 적절하지 않게 분리되는 경우가 발생할 수 있다. 이 경우 표제어 추출기(lemmatizer)에게 단어의 품사 정보를 입력함으로써 성능을 개선할 수 있다.
- nltk를 이용한 토큰화 + POS 태깅 : nltk.pos_tag 함수
from nltk.tokenize import word_tokenize
text= "주어진 문장"
tokens=word_tokenize(text) #단어로 토큰화
pos_tokens=nltk.pos_tag(tokens) #품사 태깅
## 품사 지정해서 표제어 추출
lemmatizer = WordNetLemmatizer()
lemmatizer.lemmatize('dies', 'v')
- WordNetLemmatizer 객체에 POS Tagging까지 완료된 상태의 input를 입력해준다.
- 이때 nltk.pos_tag 함수의 품사 Tag 종류와 wordnet 객체의 품사 Tag 종류가 일치시켜주는 과정이 필요하다.
- 단어 토큰화 + POS 정보 태깅 → lemmatizer 입력 형식에 맞게 조정 → lemmatization
## Tag 대응시켜주는 함수
# return WORDNET POS compliance to WORDENT lemmatization (a,n,r,v)
def get_wordnet_pos(treebank_tag):
if treebank_tag.startswith('J'):
return wordnet.ADJ
elif treebank_tag.startswith('V'):
return wordnet.VERB
elif treebank_tag.startswith('N'):
return wordnet.NOUN
elif treebank_tag.startswith('R'):
return wordnet.ADV
else:
return wordnet.NOUN
5. 구글 번역 API
- 구글은 번역 API로 무료로 사용 가능한 googletrans와 유료인 Google Could Translation을 제공하고 있다.
- 본 프로젝트에서 사용한 googletrans의 경우 별도의 인증 key 없이 패키지 설치를 통해 사용할 수 있다.
- 언어 감지 및 번역 기능을 수행한다.
#적절한 파이썬 버전을 사용해야 error가 발생하지 않음
!pip install googletrans==4.0.0-rc1
from googletrans import Translator
translator = Translator()
text = "번역 전 문장"
#언어 감지
translator.detect(text)
#번역하기
translator.translate(번역할 문장, 번역할 언어, 번역 전 언어)
text_t = translator.translate(text) #default는 영어로 번역
text_t = translator.translate(text, dest='ko')
Jupyter Notebook
text1
"끔찍한 실수로 아내를 죽이고 벽 안에 묻어버리는 주인공, 그런데 한때 자신이 애지중지한 고양이를 함께 가둬버리는 바람에 사람들에게 발각된다는 유명한 스토리를 한 번쯤 들어보았을 것이다. 쇠락해 가는 가문의 마지막 후계자로 고택과 함께 스러져 내리는 남매, 그저 자신을 바라보는 텅 빈 눈동자를 참을 수 없어 이웃집 노인을 살해하는 한 남자의 이야기는 어떤가? 에드거 앨런 포의 작품 세계는 어둡고 음침하다. 그러나 놀랍도록 세밀하고 탁월하다. 「검은 고양이」 「어셔가의 붕괴」 「고자질하는 심장」 등 공포 문학의 독보적인 선구자 에드거 앨런 포는 인간의 병약한 신경과 무질서한 정신세계를 치밀한 구조와 정교한 짜임새로 그린다. 그래서 기묘하고 충격적이면서도 어쩐지 포의 이야기는 읽는 이의 이해와 몰입을 불러일으킨다. 한편 포의 천재성은 최초의 탐정 소설이자 셜록 홈즈를 탄생시킨 「모르그가의 살인 사건」과 「도둑맞은 편지」 등 미스터리·추리소설에서도 빛을 발한다. 시초격이라고 할 수 있는 장르 문학에서조차 200년이 지난 현대극에서도 상상할 수 없는 반전이 도사리고 있다. 그런가 하면 풍자 소설에서는 재치와 기지가 돋보여서 「일주일에 세 번의 일요일」 「정확한 과학 중 하나로 여겨지는 사기술」 「타르 박사와 페더 교수의 치료법」을 읽으면서는 포의 기발한 상상과 익살에 웃음을 터트리게 된다. 포의 천재성은 굳이 말로 설명하지 않아도 그의 작품에 여실히 드러난다. 인생의 희극과 비극을 치열하게 겪은 작가, 그만큼 인간의 양면성과 기이한 심리를 섬세하게 포착한 작가, 정밀한 구도와 섬세한 필체로 아낌없이 풀어낸 그의 세계를 이 열 편의 엄선한 작품선집으로 담았다. 독자들에게 아름답고도 비극적이며 소름끼치는 광기의 미학을 선사할 것이다."
text2
'《사서함 110호의 우편물》의 저자 이도우가 《잠옷을 입으렴》 이후 6년 만에 펴낸 장편소설 『날씨가 좋으면 찾아가겠어요』. 유년 시절 산에 살았던 어떤 소년, 인생 첫 단골 서점, 미로 같았던 반년간의 여름날, 새벽이 가까울 무렵 올라오는 야행성 사람들의 SNS 글 등 때로는 스쳐 간, 더 많이는 온전히 남은 삶의 여러 조각을 모아 만든 작품으로 서로에게 많이 미안한 이들이 오랫동안 하지 못했던 말들을 세월이 흐른 후 비로소 용기 내어 전하는 이야기를 담고 있다.\n\n\n\n미대입시학원에서 그림을 가르치던 해원은 학생과의 불화를 계기로 일을 그만두고 펜션을 운영하는 이모 곁에서 한동안 지내기로 한다. 열다섯 살 그 일 이후로 사람에게 기대한 적이 없었던 해원은 언젠가부터 사람을 그리는 것이 싫어 인물화를 그리지 않는다. 한편 노부부가 살던 낡은 기와집을 작은 서점 굿나잇책방으로 바꾸어 운영하고 있는 은섭은 자신의 서점을 기웃거리는 해원을 보고 놀란다. 삼 년 전 은섭에게 겨울 들판에 뒹구는 ‘마시멜로’의 진짜 이름이 뭐냐고 묻던 이웃집 그녀다.\n\n\n\n이모를 통해 그 낯선 서점의 책방지기가 옆집 사는 은섭이라는 것을 알게 된 해원은 굿나잇책방으로 향한다. 그리고 그녀가 머물 겨울 동안 책방 매니저 아르바이트를 하기로 한다. 어린 시절 타인에게 신경을 곤두세우며 살았다고 생각했지만 알고 보니 자기에만 매몰되어 있었던 해원은 은섭과 같은 중고등학교를 나왔지만 그를 잘 모른다. 해원이 알고 있던 것보다 은섭이 그녀의 인생 어떤 페이지에 더 많이 등장했었다는 사실도…….'
text1 = '''끔찍한 실수로 아내를 죽이고 벽 안에 묻어버리는 주인공, 그런데 한때 자신이 애지중지한 고양이를 함께 가둬버리는 바람에 사람들에게 발각된다는 유명한 스토리를 한 번쯤 들어보았을 것이다. 쇠락해 가는 가문의 마지막 후계자로 고택과 함께 스러져 내리는 남매, 그저 자신을 바라보는 텅 빈 눈동자를 참을 수 없어 이웃집 노인을 살해하는 한 남자의 이야기는 어떤가? 에드거 앨런 포의 작품 세계는 어둡고 음침하다. 그러나 놀랍도록 세밀하고 탁월하다. 「검은 고양이」 「어셔가의 붕괴」 「고자질하는 심장」 등 공포 문학의 독보적인 선구자 에드거 앨런 포는 인간의 병약한 신경과 무질서한 정신세계를 치밀한 구조와 정교한 짜임새로 그린다. 그래서 기묘하고 충격적이면서도 어쩐지 포의 이야기는 읽는 이의 이해와 몰입을 불러일으킨다. 한편 포의 천재성은 최초의 탐정 소설이자 셜록 홈즈를 탄생시킨 「모르그가의 살인 사건」과 「도둑맞은 편지」 등 미스터리·추리소설에서도 빛을 발한다. 시초격이라고 할 수 있는 장르 문학에서조차 200년이 지난 현대극에서도 상상할 수 없는 반전이 도사리고 있다. 그런가 하면 풍자 소설에서는 재치와 기지가 돋보여서 「일주일에 세 번의 일요일」 「정확한 과학 중 하나로 여겨지는 사기술」 「타르 박사와 페더 교수의 치료법」을 읽으면서는 포의 기발한 상상과 익살에 웃음을 터트리게 된다. 포의 천재성은 굳이 말로 설명하지 않아도 그의 작품에 여실히 드러난다. 인생의 희극과 비극을 치열하게 겪은 작가, 그만큼 인간의 양면성과 기이한 심리를 섬세하게 포착한 작가, 정밀한 구도와 섬세한 필체로 아낌없이 풀어낸 그의 세계를 이 열 편의 엄선한 작품선집으로 담았다. 독자들에게 아름답고도 비극적이며 소름끼치는 광기의 미학을 선사할 것이다.'''
text2 = '《사서함 110호의 우편물》의 저자 이도우가 《잠옷을 입으렴》 이후 6년 만에 펴낸 장편소설 『날씨가 좋으면 찾아가겠어요』. 유년 시절 산에 살았던 어떤 소년, 인생 첫 단골 서점, 미로 같았던 반년간의 여름날, 새벽이 가까울 무렵 올라오는 야행성 사람들의 SNS 글 등 때로는 스쳐 간, 더 많이는 온전히 남은 삶의 여러 조각을 모아 만든 작품으로 서로에게 많이 미안한 이들이 오랫동안 하지 못했던 말들을 세월이 흐른 후 비로소 용기 내어 전하는 이야기를 담고 있다.\n\n\n\n미대입시학원에서 그림을 가르치던 해원은 학생과의 불화를 계기로 일을 그만두고 펜션을 운영하는 이모 곁에서 한동안 지내기로 한다. 열다섯 살 그 일 이후로 사람에게 기대한 적이 없었던 해원은 언젠가부터 사람을 그리는 것이 싫어 인물화를 그리지 않는다. 한편 노부부가 살던 낡은 기와집을 작은 서점 굿나잇책방으로 바꾸어 운영하고 있는 은섭은 자신의 서점을 기웃거리는 해원을 보고 놀란다. 삼 년 전 은섭에게 겨울 들판에 뒹구는 ‘마시멜로’의 진짜 이름이 뭐냐고 묻던 이웃집 그녀다.\n\n\n\n이모를 통해 그 낯선 서점의 책방지기가 옆집 사는 은섭이라는 것을 알게 된 해원은 굿나잇책방으로 향한다. 그리고 그녀가 머물 겨울 동안 책방 매니저 아르바이트를 하기로 한다. 어린 시절 타인에게 신경을 곤두세우며 살았다고 생각했지만 알고 보니 자기에만 매몰되어 있었던 해원은 은섭과 같은 중고등학교를 나왔지만 그를 잘 모른다. 해원이 알고 있던 것보다 은섭이 그녀의 인생 어떤 페이지에 더 많이 등장했었다는 사실도…….'
text_df = pd.DataFrame({'text' : [text1, text2]}, index=range(2))
text_df
text | |
---|---|
0 | 끔찍한 실수로 아내를 죽이고 벽 안에 묻어버리는 주인공, 그런데 한때 자신이 애지중... |
1 | 《사서함 110호의 우편물》의 저자 이도우가 《잠옷을 입으렴》 이후 6년 만에 펴낸... |
영어로 번역
import googletrans
googletrans.__version__
'4.0.0-rc.1'
#!pip uninstall googletrans
#!pip install googletrans==4.0.0-rc1
from googletrans import Translator
text_e=list()
translator = Translator()
for t in text_df['text']:
t = translator.translate(t).text
text_e.append(t)
text_df['text_e'] = text_e
text_df
text | text_e | |
---|---|---|
0 | 끔찍한 실수로 아내를 죽이고 벽 안에 묻어버리는 주인공, 그런데 한때 자신이 애지중... | The main character who kills his wife and buri... |
1 | 《사서함 110호의 우편물》의 저자 이도우가 《잠옷을 입으렴》 이후 6년 만에 펴낸... | The author of the mailbox 110's mail, Lee Do -... |
import re
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.corpus import wordnet
from nltk.stem import PorterStemmer, WordNetLemmatizer
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
nltk.download('wordnet')
nltk.download('stopwords')
t = text_df['text_e'][0]
tokens=word_tokenize(t)
pos_tokens=nltk.pos_tag(tokens)
text_t=list()
for _ in pos_tokens:
text_t.append([_[0], get_wordnet_pos(_[1])])
text_t[:10]
[['The', 'n'],
['main', 'a'],
['character', 'n'],
['who', 'n'],
['kills', 'v'],
['his', 'n'],
['wife', 'n'],
['and', 'n'],
['buried', 'v'],
['it', 'n']]
lemmatizer = WordNetLemmatizer()
result = [lemmatizer.lemmatize(word[0], word[1]) for word in text_t]
result[:10]
['The', 'main', 'character', 'who', 'kill', 'his', 'wife', 'and', 'bury', 'it']
전처리 함수 정의
불용어 처리 > 토큰화 + POS > 표제어 추출 과정으로 전처리 진행
#영어 불용어 사전
stops = set(stopwords.words('english'))
#특수문자 제거
#영어 대소문자, 숫자, 공백문자(스페이스, 탭, 줄바꿈 등) 아닌 문자들 제거
def remove_special_characters(text, remove_digits=True):
text=re.sub(r'[^a-zA-Z0-9\s]', '', text)
return text
#불용어 제거
def delete_stops(text):
text = text.lower().split()
text = ' '.join([word for word in text if word not in stops])
return text
#품사 tag 매칭용 함수
def get_wordnet_pos(treebank_tag):
if treebank_tag.startswith('J'):
return wordnet.ADJ
elif treebank_tag.startswith('V'):
return wordnet.VERB
elif treebank_tag.startswith('N'):
return wordnet.NOUN
elif treebank_tag.startswith('R'):
return wordnet.ADV
else:
return wordnet.NOUN
#품사 태깅 + 표제어 추출
def tockenize(text):
tokens=word_tokenize(text)
pos_tokens=nltk.pos_tag(tokens)
text_t=list()
for _ in pos_tokens:
text_t.append([_[0], get_wordnet_pos(_[1])])
lemmatizer = WordNetLemmatizer()
text = ' '.join([lemmatizer.lemmatize(word[0], word[1]) for word in text_t])
return text
def clean(text):
text = remove_special_characters(text, remove_digits=True)
text = delete_stops(text)
text = tockenize(text)
return text
text_c=list()
translator = Translator()
for t in text_df['text_e']:
t = clean(t)
text_c.append(t)
text_df['text_c'] = text_c
text_df
text | text_e | text_c | |
---|---|---|---|
0 | 끔찍한 실수로 아내를 죽이고 벽 안에 묻어버리는 주인공, 그런데 한때 자신이 애지중... | The main character who kills his wife and buri... | main character kill wife bury wall terrible mi... |
1 | 《사서함 110호의 우편물》의 저자 이도우가 《잠옷을 입으렴》 이후 6년 만에 펴낸... | The author of the mailbox 110's mail, Lee Do -... | author mailbox 110s mail lee doo publish six y... |
text_c[0]
'main character kill wife bury wall terrible mistake heard people would heard famous story discover people lock pampered catwhat story man kill old man cant stand old man sister fall old house last successor decay familyedgar allan poes world dark dismalbut amazingly detail excellentthe unique pioneer edger allen poe black cat collapse usher heart heart heart draw dense structure sophisticated structure human vicious nerve disorder mental worldthus bizarre shock somehow story po understand immersion readeron hand poe genius also shin mystery mystery novel morgas murder case first detective novel sherlock holmeseven genre literature say initial unimaginable reversal modern dramason hand satire novel wit base outstanding read three sunday week private technology consider one exact science dr tar professor federdopos genius reveal work without explain wordsthe artist fiercely experienced comedy tragedy life artist capture two side bizarre psychology human being world precise composition delicate handwriting include carefully select workit give reader beautiful tragic creepy aesthetic madness'
from collections import Counter
word_count = Counter(text_df['text_c'][0].split())
#빈도수 상위 20
max = 20
pos_top_20 = {}
for word, counts in word_count.most_common(max):
pos_top_20[word] = counts
print(f'{word} : {counts}')
story : 3
man : 3
old : 3
heart : 3
novel : 3
kill : 2
heard : 2
people : 2
world : 2
poe : 2
structure : 2
human : 2
bizarre : 2
hand : 2
genius : 2
mystery : 2
artist : 2
main : 1
character : 1
wife : 1
#!pip install wordcloud
from wordcloud import WordCloud
font_path = "C:/Windows/Fonts/H2GTRM"
wc = WordCloud(font_path=font_path, background_color='ivory', width=1000, height=800)
cloud = wc.generate_from_frequencies(word_count)
plt.figure(figsize=(5,5))
plt.imshow(cloud)
plt.axis('off')
plt.show()
Reference
[토큰화]
https://wikidocs.net/21698
https://velog.io/@nkw011/nlp-tokenizer
[정제 & 정규화]
https://wikidocs.net/22530
https://wikidocs.net/21707
https://didu-story.tistory.com/71
https://cheris8.github.io/data%20analysis/TP-POS-Tagging/
https://velog.io/@limelimejiwon/Stemming%EC%96%B4%EA%B0%84-%EC%B6%94%EC%B6%9C-vs-Lemmatization%ED%91%9C%EC%A0%9C%EC%96%B4-%EC%B6%94%EC%B6%9C-in-%EC%9E%90%EC%97%B0%EC%96%B4-%EC%B2%98%EB%A6%AC
[텍스트 전처리]
https://wikidocs.net/21694
https://myjamong.tistory.com/77
https://yanoo.tistory.com/28
https://hitomis.tistory.com/68
https://americanoisice.tistory.com/49
[구글 번역 API]
https://www.dinolabs.ai/386
https://coding-kindergarten.tistory.com/98
'deep daiv. > 추천시스템 project' 카테고리의 다른 글
[text 감정 추출 모델] SVM 모델 학습 / text 감정 추출 결과 (0) | 2024.01.08 |
---|---|
[text 감정 추출 모델] Data Augmentation 데이터 증강 (0) | 2024.01.06 |
[Audio feature 군집화] Spotify Song Clustering with k-means (0) | 2023.09.16 |
[Audio feature 군집화] K-means 분류 모델 (0) | 2023.09.10 |
[데이터 수집] 도서 데이터, 카카오 API (0) | 2023.09.05 |