데이터 한 그릇

딥러닝 자연어 처리 본문

딥러닝/모두의 딥러닝

딥러닝 자연어 처리

장사이언스 2022. 1. 6. 12:51

인간의 말을 컴퓨터가 알아듣게 만드는 처리

컴퓨터는 인간의 말을 그대로 이해할 수 없다.

컴퓨터가 알아들을 수 있게 언어를 가공해서 줘야만 한다.

즉, 전처리 작업이 필요하다.

 


텍스트의 토큰화

 

텍스트가 존재한다면 이를 단어별, 문장별, 형태소별로 나눌 수 있다.

입력된 텍스트를 잘게 나누는 과정을 토큰화(Tokenization) 라고 한다.

 

from tensorflow.keras.preprocessing.text import text_to_word_sequence

text = '해보지 않으면 해낼 수 없다. 오늘 저녁은 뭘 먹지'
result = text_to_word_sequence(text)
print(result)

 

결과 : ['해보지', '않으면', '해낼', '수', '없다', '오늘', '저녁은', '뭘', '먹지']

 

단어의 빈도수

텍스트를 단어를 기준으로 토큰화 했다면, 단어들의 빈도수를 셀 수 있다.

밑은 그 코드

 

from tensorflow.keras.preprocessing.text import Tokenizer

docs = ['먼저 텍스트의 각 단어를 나누어 토큰화합니다.',
       '텍스트의 단어로 토큰화해야 딥러닝으로 인식됩니다.',
       '토큰화한 결과는 딥러닝에서 사용할 수 있습니다.'
       ]

token = Tokenizer()
token.fit_on_texts(docs) #토큰화 함수에 문장 적용
print(token.word_counts) #단어 개수 세기

print(token.document_count) #총 몇 개의 문장이 들어가 있는지 파악
print(token.word_docs) #각 단어들이 몇 개의 문장에 등장하는지
print(token.word_index)#각 단어들의  index 표현

 

fit_on_texts 를 통해서 단어를 토큰화

단어의 개수를 셀 수 있고, 총 문장의 개수, 어떤 단어가 총 몇 개의 문장에 등장했는지,

단어의 인덱스 등등을 출력할 수 있다.

 


원-핫 인코딩

단어가 문장의 다른 요소와 어떠한 관계를 가지고 있는지를 알아보는 방법이 필요

가장 기본적인 방법은 원-핫 인코딩

 

from tensorflow.keras.preprocessing.text import Tokenizer

text = '오랫동안 꿈꾸는 이는 그 꿈을 닮아간다'

token = Tokenizer()
token.fit_on_texts([text])
print(token.word_index)

x = token.texts_to_sequences([text]) #인덱스로만 채워진 배열을 생성
print(x)

import tensorflow as tf

word_size = len(token.word_index) + 1 #파이썬 index 특징으로 맨 앞에 0이 추가

x = tf.keras.utils.to_categorical(x, num_classes = word_size)

print(x)

 

먼저 텍스트의 단어들에 인덱스를 붙이고 단어수를 셀 수 있는 함수 fit_on_texts 를 적용

단어 각각에 인덱스를 붙였다는건, 그 숫자가 그 단어를 대표함을 의미한다.

그 인덱스로만 이루어진 배열을 생성한다.

그리고 그 단어들을 원-핫 인코딩으로 표현한다.

이때 중요한 점은, 파이썬의 특징상 앞에 0이 더 붙는다는 점이다.

 


단어 임베딩

 

앞서 텍스트 단어들에 대해서 원-핫 인코딩을 하면 데이터의 속성이 굉장히 많아짐을 예측할 수 있다.

즉, 일만개의 단어가 있다고 했을 때, 9999개의 0이 존재하고 한 개의 1이 존재하는 행이 1만번 생성됨을 예측할 수 있다. 이는 공간 낭비이다.

따라서 차원을 축소하는 Embedding 과정을 거쳐야 한다.

예를 들어서 sad 는 happy 보다 bad에 가깝고 cat은 dolphine 보다 dog 에 가깝다.

이는 각 단어들의 유사도를 파악하여 하나의 속성으로 묶었기 때문에 가능하다.

즉 각각의 token 의 유사도를 분석해서 type을 파악하고 그 안에 token들을 배분했다고 하면 이해가 편하다.

그렇다면 유사도는 어떻게 파악하는가?

딥러닝의 오차 역전파(back propagation) 를 통해서 최적의 유사도를 계산하는 과정을 거친다.

 

from tensorflow.keras.layers import Embedding
from tensorflow.keras.models import Sequential

model = Sequential()
model.add(Embedding(16,4))

 


감성 분석

 

리뷰들을 딥러닝 작업하여 각 리뷰가 긍정적인 글인지 부정적인 글인지 파악하는 것.

긍정이면 1, 부정이면 0 이라는 클래스로 지정

 

import numpy as np

docs = ['너무 재밌네요','최고예요','참 잘 만든 영화예요',
       '추천하고 싶은 영화입니다.','한 번 더 보고싶네요','글쎄요',
       '별로예요','생각보다 지루하네요','연기가 어색해요','재미없어요']


#각 리뷰에 대한 긍정, 부정 레이블

classes = np.array([1,1,1,1,1,0,0,0,0,0])

#토큰화

token = Tokenizer()
token.fit_on_texts(docs)
print(token.word_index)

x = token.texts_to_sequences(docs)
print(x) #리뷰마다 데이터 길이가 다름.


#데이터 패딩

padded_x = pad_sequences(x,4)

#임베딩 사전 준비

word_size = len(token.word_index) + 1

#모델 생성

model = Sequential()
model.add(Embedding(word_size, 8, input_length = 4))
model.add(Flatten())
model.add(Dense(1, activation = 'sigmoid'))

model.compile(loss = 'binary_crossentropy', metrics = ['accuracy'],
             optimizer = 'adam')
model.fit(padded_x, classes, epochs = 20)

print(model.evaluate(padded_x,classes)[1])

 

각 리뷰를 일단 단어별로 토큰화

각 단어가 index 가 붙으면서 숫자로 labeling 됨.

각 리뷰마다 단어의 개수가 다르면서 데이터의 길이가 다름.

데이터 패딩을 통해서 데이터 길이를 맞춤.

데이터가 짧으면 0을 집어 넣고, 데이터가 길면 그 길이에 맞게 자름.

그리고 단어들을 원핫 인코딩 할시, 속성이 엄청 커질 수 있기 때문에, 속성을 축소해주는

따라서, 임베딩 작업이 필요하다. Embedding layer를 만든다.

`model.add(Embedding(word_size, 8, input_length = 4))`

에서 word_size 는 원핫 인코딩 할 시에 모든 단어의 개수가 속성으로 만들어지기 때문에 넣어주는 칸이고,

8은 내가 원하는 축소 개수이다.

input_length는 한번 단어를 넣을 때 몇 개를 넣을지 설정하는 구간.

나머지 과정은 똑같다.

Comments