블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Statistics Graph

Recent Comment

2018.11.25 18:05 AI Deep Learning

자연어 처리 강좌를 정리한다. 





개념


- 문장을 분해하여 관계를 만들어 주어야 한다. 

- 데이터를 서로 연결하다보면 2차원 이상으로 발전한다. 

- 자연어는 모델링은 쉽지만, 전처리와 결과의 해석이 중요한다. 결과에 따른 해석이 따라 의미가 틀려진다. 이는 이미지/음성과 틀린 부분이다.

- 음운론, 형태론, 통사론, 의미론, 추리론

- Document -> Tokenizing -> Streaming/Tagging (컴퓨터가 이해하는 방식으로 배치하기) -> 최종 Word2Vec 에서 사용함




Tokenizing


- 구글 Colab을 사용한다.

- Token: document에서 쓸만한 것들로 의미를 같는 문자열 -> Tokenizing

- Colab에서 필요한 모듈 설치하기 in ubuntu

! apt-get update

! apt-get install g++ openjdk-8-jdk 

! pip3  install  nltk konlpy wordcloud matplotlib gensim 


! apt-get install fonts-nanum*

! apt-get install fontconfig

! fc-cache -fv

! cp /usr/share/fonts/truetype/nanum/Nanum* /usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf/

! rm -rf /content/.cache/matplotlib/*


- import nltk # Natural Language ToolKit 사용

  + sent_tokenize, word_tokenize

- import re  #정규표현식 사용

// 패키지 사용

text = """갤럭시(GalaxyNote9)노트9. 2018년 08월 폭발적인 인기를 이끌고 있습니다. 

담당자 010-222-9999. 홍보팀 010-8888-9999"""

from nltk import sent_tokenize, word_tokenize, FreqDist

sent_tokenize(text)

tokens = word_tokenize(text)


// 정규표현식

import re

tokenizer = re.compile(r'[가-힣]+')

tokenizer.findall(text)




Stemming & Tagging


순서 Tokenizing -> Stemming -> Tagging을 한다. 일반/평문이 결과값이 잘나오고, 강조문/도치문/압축문은 일반/평문으로 만들어하는게 좋다. 


Stemming: 정규화

- 토큰의 어근/어간 추출

- 가능한 비슷한 의미 형태로 묶어주기 => 원형화한다

   예) 가다, 가니, 가고 => 가- 

         산뜻하다, 산뜻하니, 산뜻하고 => 산뜻하-


Tagging: 문법/Filter

- Token별 높은 확률의 태그(속성값/문법)을 추가 

- 단어의 품사별로 묶음: 동사, 명사, 부사


// 토큰

text = "Don't hesitate to ask question"

from nltk.tokenize import TreebankWordTokenizer

tokenizer = TreebankWordTokenizer()

token = tokenizer.tokenize(text)


// 태그

from nltk import pos_tag

pos_tag(token)


// 한글처리

// 테크

from konlpy.tag import Okt

twitter = Okt()

twitter.pos('서울R&D캠퍼스 수업자료')


//토큰, 스테밍을 같이 처리 stem === stemming

text = "워런 버핏은 삼성전자가 아닌 애플주식을 왜 샀을까"

print(twitter.pos(text, stem="true"))




Word Cloud로 시각화하기


- Visualization (시각화)

- 연설문을 워드클라우드로 표현하기 

// 필요 모듈 설치

! apt-get update

! apt-get install g++ openjdk-8-jdk 

! pip3  install  nltk konlpy wordcloud matplotlib gensim 


! apt-get install fonts-nanum*

! apt-get install fontconfig

! fc-cache -fv

! cp /usr/share/fonts/truetype/nanum/Nanum* /usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf/

! rm -rf /content/.cache/matplotlib/*

speech_text = "https://raw.githubusercontent.com/YongBeomKim/nltk_tutorial/master/data/pyongyang_fin.txt"

script_text = "https://raw.githubusercontent.com/YongBeomKim/nltk_tutorial/master/data/movie_memories_of_murder_2003.txt"

font_file = "/usr/local/lib/python3.6/dist-packages/matplotlib/mpl-data/fonts/ttf/NanumGothicCoding.ttf"


// 워드클라우드 사용

import requests

import pandas as pd

import matplotlib.pyplot as plt

from wordcloud import WordCloud

from nltk import FreqDist

from nltk.tokenize import word_tokenize

import nltk

nltk.download('punkt')


texts = requests.get(speech_text).text

texts[:100]


// 그리기 

%matplotlib inline

wcloud = WordCloud(font_file).generate(texts)

plt.figure(figsize=(12,12))

plt.imshow(wcloud)

plt.axis('off')


명사만을 사용하여 word cloud 표현

from konlpy.tag import Okt

twitter = Okt()

tokens = twitter.pos(texts, stem=True)

tokens_noun = [token[0] for token in tokens if token[1] == 'Noun']

texts_noun = " ".join(tokens_noun)

texts_noun[:300]




Deep Learning 수행


Natural Language Processing + Deep Learning을 결합하여 챗봇을 만들어가기

  - RNN, LSTM, GRU가 챗봇만드는 기본 알고리즘

  - Data 입력/전처리 (Train Data) -> Cell 선택 및 모델 구성 -> Training / Modeling / Validation -> Model 평가 

  - Input -> Hidden Layer -> Output

  - Input Data 를 구성하는 Word2Vec


Word2Vec는 문장에 따라 데이터를 구조화한다. 

  - 하나의 중심데이터와 주변데이터로 구분함. 

  - 단어간 유사도 검사

  - 구조자체가 작아서, 딥러닝이라 할 수 없다. 

  - 로지스틱 회귀식(2 Cell)을 통해 분류한다. 

  - Corpus (말뭉치) -> Vocabulary Builder -> Context Builder -> Input -> Output 

  


새로운 방식

  - Input 하나에 Output 여러개를 통해 학습 => Skip-gram (sg)

  - try -> error를 통해 맞는 길로 찾아는 방식

과거 방식

  - Input 여러개에 대한 Output 으로 중심 단어 하나 => CBOW (Content Back of Word)


     



실습


  - 20차원의 구조를 만든다. 

  - Dimension(차원)안에 토큰을 넣는다. 비슷한 토큰은 같은 차원에 넣는다. 

  - 빈도수가 적은 것은 하나의 차원에 묶는다. 이안에 빈도수가 높은 것은 중심축에 놓는다. 

    



- size: 차원 30개 (중요)  <== 실습 단어가 151개여서 유의미화를 위해 30차원으로 줄여서 설정했음.

- window: 주변 데이터

- min_count: 10번이상 등장한 단어만 (중요)

- hs: ?

- workers: cpu parallel 동작

- sg: skip-gram

// 전처리후 

...

// 명사 저장

sentences = txtnoun(sentences, skip=skips, tags=["Noun"])

script_file = 'scripts.txt'

with open(script_file, 'w', encoding="utf-8") as file:

   file.write(sentences)


// gensim 이용 모델 만들기

%%time

from gensim.models import word2vec

data = word2vec.LineSentence(script_file)

model = word2vec.Word2Vec(data, size=30, window=2, min_count=10, hs=1, workers=4, iter=100, sg=1)

model_file = "script.model"

model.save(model_file)


결과

CPU times: user 1.59 s, sys: 113 ms, total: 1.71 s, Wall time: 1.7 s


// 모델의 단어수 

model = word2vec.Word2Vec.load(model_file)

len(model.wv.vocab.keys())

list(model.wv.index2word)


결과

151 


// 근접 백터값 확인하기, 참깨밭을 제거하고 추출해 봄

model.wv.most_similar(['현장','백광호'], negative=['참깨밭'], topn=20)


30차원을 시각화하기 위해 skitlearn의 TSNE를 이용해서 2차원으로 변경해서 표현한다. 




<참조>

- 강좌 슬라이드, 전체 실습 파일

- 정규 표현식 정리, 실습하는 서비스

KoNLP

- Word2Vec 관련 이론

posted by peter yun 윤영식