파이썬 이것저것/파이썬 딥러닝 관련

[Python] 딥러닝 자연어 처리를 위한 딥러닝

agingcurve 2022. 7. 15. 17:24
반응형

자연어 처리 Process

1. 자연어 전처리(Preprocessing)

2. 단어 표현 (WordEmbedding)

3. 모델 적용 (Modeling)

 

원 상태 그대로의 자연어는 전처리 과정이 필요함

 

자연어는 오류를 어떻게 없앨 것인가

그리고 의미랑 전혀 상관없는 단어를 어떻게 없앨지 오류를 없애는 것을 타이핑을 잘못 했거나, 오타가 있을 경우, 컴퓨터는 단어인가 라고 생각 할 수 있기 때문에 오류를 전처리 해서 없애줘야 함
문장을 나누는것을 토큰으로 나누게 됨

 

Noise Canceling

“안녕하 세요. 반갑 스니다.” => “안녕하세요. 반갑습니다.” 

 

 

Tokenizing

문장을 토큰(Token)으로 나눔, 토큰은 어절, 단어 등으로 목적에 따라 다르게 정의

 

“딥러닝 기초 과목을 수강하고 있습니다.” 

=> ['딥', '러닝', '기초', '과목', '을', '수강', '하고', '있습니다', '.']

 

StopWord removal 

불필요한 단어를 의미하는 불용어(StopWord) 제거

stopword라는 것은 큰 의미가 없는 단어를 뜻함 단어의미를 태스크에 따라서 요약을 한다고 햇을때, 그러나 라는 단어는 중요도가 다를 수 있음 그렇게 필요하지 않는 단어를 제거하는게 Stopword라고 함

 

한국어 stopword 예시)

아, 휴, 아이구, 아이쿠, 아이고, 쉿, 그렇지 않으면, 그러나, 그런데, 하지만, ..

 

 

워드 임베딩(Word Embedding)

 

단어를 문장이나 음성에서 추출을 한다면 그 단어들을 어떻게 표현을 할 것인지 문제를 해결하기 위해
워드 임베딩을 만들었음, 하나의 문서를 볼때, Doc1, Doc2 가 비슷한지 보고 싶을때, 이것에 대한 숫자를
워드 임베딩을 사용해서 만든다. 

비정형 데이터를 정형데이터로 바꾸는 작업

 

워드 임베딩(Word Embedding) 종류

Count-based Representations

- Bag of Words

- One-hot encoding

- Document term matrix

 

Distributed Representation

- Word2vec

 

Bag of Words

자연어 데이터에 속해있는 단어들의 가방

 

One-hot encoding

문서에 나오는 단어를 원핫 벡터로 만들어서 각각 벡터를 만든다. 

학습 데이터의 모든 토큰을 크기로 한 벡터에서 해당 문장에 토큰이 존재하는지 확인

Document term matrix

문서행렬은 은 각각의 단어에 대해서 문서에 대해 몇번 나왔는지 행렬을 만들 수 있다.

One hot encoding 결과에 빈도수 정보를 추가

 

 

카운트 기반 표현은 예를들어 기업, 소비자, 강아지, 컴퓨터들이 연관성을 표현하지 않는 방식임
단어의 관계까지 표현하는 방법까지 생각한 것임

 

Word2vec

tokenization을 하고 neural net을 사용해서 하는 것은 비슷한 단어는 비슷한 맥락에서 나온다는
기반에서 사용함

 

단어들을 의미상으로 유사한 단어가 벡터공간에 가까이 있도록 Mapping 시키는 작업을 의미
특정 함수를 통해 우리가 원하는 차원으로 단어의 벡터를 Embedding 함

 

Word2vec 예시

예를 드어 그대, 애인, 너는 비슷한 단어라고 보고 컴퓨터라는 단어가 들어가는 것은
멀리 떨어져 있어야 되는 단어이다. 라는 형식으로 어떤 단어가 주어졌을 때, center word가 있고
이를 예측할 수 있는 Word2vec을 만들면 비슷한 단어들이 벡터 공간에서 비슷한 자리에 나오게 됨
예를 들면 엄마, 아빠, 동생 이러한 비슷한 벡터에서 나오게 되는 것이 word2vec에 나오게 되고
고양이, 강아지 등 유사한 단어들이 나오게 되면 나머지 단어들이 비슷하면 유사한 doc 라고 알 수 있음

 

 

 

주변 단어(Context Words)로 중심단어(Center word)를 예측하도록 학습

 

중심단어(Center word)로 주변 단어(Context Words)를 예측하도록 학습

 

 

BoW(Bag of Words)

BoW(Bag of Words)는 토큰화된 단어들을 해당 글에서의 등장 횟수와 대응시켜 놓은 일종의 ‘단어-등장횟수’ 꾸러미(Bag)를 의미

import numpy as np
from konlpy.tag import Twitter

# 텍스트 파일을 읽어서 저장하는 함수

def read_txt(path):
    
    file = open(path, 'r')
    output = str(file.read())
    
    return output

'''
1. BoW를 딕셔너리 형태로 출력하는 함수

   Step01. 기존 word_dict 에 그 값이 있으면 1을 더해주고, 없으면 1을 부여
'''

def bag_of_words(tokenized_sentences):
    
    word_dict = dict()
    
    for sentence in tokenized_sentences:
        for word in sentence:
            try:
                word_dict[word] += 1
            except:
                word_dict[word] = 1


    return word_dict

'''
2. 읽어온 텍스트 파일을 형태소 단위로 분석해서 저장하는 
   함수를 완성
'''

def get_splited_doc(path):
    
    output = []
    
    text = read_txt(path)
    analyzer = Twitter()
    output = analyzer.morphs(text)
    
    return text, output

def main():
    
    PATH = "./data/text.txt"
    
    origin, splitted = get_splited_doc(PATH)
    
    print('형법 제2장 원본: ', origin)
    
    bow_criminal_law = bag_of_words([splitted])
    
    print('\n형법 제2장의 BoW: ', bow_criminal_law)
    
    return bow_criminal_law

if __name__ == "__main__":
    main()

 

 

단어 임베딩(Word Embedding)과 원-핫 인코딩(One-hot Encoding)

단어 임베딩(Word Embedding)은 문장 안의 단어들을 우리가 수행할 일에 적합한 언어 공간, 즉 문장 안의 단어들을 벡터 공간으로 사상(mapping)하는 것을 의미

원-핫 인코딩(One-hot Encoding)은 각 단어를 한 차원으로 설정하여 모든 단어의 개수와 같은 차원의 벡터를 생성한 뒤, 특정 단어에 대하여 그 위치의 차원 값을 1로 하고 나머지 차원은 0으로 만들어 주는 것을 의미

import tensorflow as tf
from tensorflow.python.keras.preprocessing.text import Tokenizer

import logging, os
logging.disable(logging.WARNING)
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"

'''
1. embedding 함수를 완성

'''

def embedding(sentence1, sentence2):
    
    tokenizer = Tokenizer()
    tokenizer.fit_on_texts(sentence1+sentence2)
    word_dict = tokenizer.word_index
    
    # word_dict의 value가 0부터 시작하게 바꿔줌
    for k, v in word_dict.items():
        word_dict[k] = v - 1
    
    sen1 = tokenizer.texts_to_sequences(sentence1)
    sen2 = tokenizer.texts_to_sequences(sentence2)
    
    sen1 = [token[0] for token in sen1]
    sen2 = [token[0] for token in sen2]
    
    return word_dict, sen1, sen2

'''
2. 텐서플로우를 사용하여 원-핫 인코딩을 실행
'''   

def one_hot(sen1, sen2, word_dict):
    
    oh_sen1 = sum(tf.one_hot(sen1, len(word_dict)))
    oh_sen2 = sum(tf.one_hot(sen2, len(word_dict)))
    
    return oh_sen1, oh_sen2

def main():
    
    sentence1 = ['나','는','오늘','저녁','에','치킨','을','먹','을','예정','입니다']
    sentence2 = ['나','는','어제', '맥주','와', '함께', '치킨','을', '먹었', '습니다']
    
    word_dict, seq_1, seq_2 = embedding(sentence1, sentence2)
    onehot_sen1, onehot_sen2 = one_hot(seq_1, seq_2, word_dict)
        
    print('리스트 요소-인덱스 딕셔너리: ', word_dict)
    
    print('\n정수값으로 변환된 sentence1:', seq_1)
    print('\n정수값으로 변환된 sentence2:', seq_2)
    
    print('\n원-핫 인코딩된 문장1:', onehot_sen1.numpy())
    print('\n원-핫 인코딩된 문장2:', onehot_sen2.numpy())
    
    return onehot_sen1, onehot_sen2

if __name__ == '__main__':
    main()

 

 

Word2Vec

Word2Vec 단어(Word)를 벡터(Vector)로 변환하는 것을 의미하는 것으로써, 일반적으로 CBOW(Continuous Bag of Words), Skip-Gram 모델을 지칭

CBOW 모델은 주변 단어(Context Word)를 바탕으로 특정 단어(Target Word)를 예측하는 모델

Skip-Gram 모델은 특정 단어를 바탕으로 주변 단어들을 예측하는 모델

from gensim.models import word2vec
import list_file

'''
1. CBOW 방식의 Word2Vec 모델을
   반환하는 CBOW 함수를 완성
'''

def CBOW(sentences):
    
    model_cbow = word2vec.Word2Vec(sentences, size=300, min_count =1, window= 10, sg=0)
    
    return model_cbow

'''
2. Skip-Gram 방식의 Word2Vec 모델을
   반환하는 Skip_Gram 함수를 완성
'''

def Skip_Gram(sentences):
    
    model_skipgram = word2vec.Word2Vec(sentences, size=300,
    min_count=1, window=10, sg=1)
    
    return model_skipgram

'''
3. 각 모델의 결괏값을 정의
'''

def main():
    
    sen1, sen2 = list_file.sen1(), list_file.sen2()
    
    sentences = [sen1, sen2]
    
    cbow = CBOW(sentences)
    skipgram = Skip_Gram(sentences)
    
    idx2word_set_cbow = cbow.wv.index2word
    idx2word_set_skipgram = skipgram.wv.index2word
    
    print('CBOW: ', idx2word_set_cbow)
    print('\nSkip-Gram: ', idx2word_set_skipgram)
    
    return idx2word_set_cbow, idx2word_set_skipgram

if __name__ == '__main__':
    main()