토큰화에 대해서는 자연어 처리 공모전 참가를 위해 공부해 둔 것이 있으니 참조하자.
[자연어 스터디] 02. 텍스트 전처리
We will rock you
라는 문장이 있을 때, 이 문장의 단어는 We, will, rock, you
4개로 토큰화할 수 있다.We=1, will=2, rock=3, you=4
로 표기하자고 약속하면 위 문장은 [1, 2, 3, 4]
로 나타낼 수 있다. -> 즉 자연어를 정수 숫자로 나타낸 것이다.Bags of Words는 문서에 많이 등장하는 단어가 중요한 단어일 것이라 가정하고, 단어의 등장 빈도로 문서를 벡터화하는 방법이다.
모델에 넣을 하나의 문서에서 각 단어가 몇번 등장하는지 카운팅한다.
a, that, you, it
과 같은 단어들은 모든 문서에서 빈번하게 등장할 것이다. 그러나 이는 실제로는 별로 중요하지 않은 단어들이다. Bags of Words에서는 이를 구분할 방법이 없다.I want to change my job
과 Here's your change
는 다른 의미를 갖지만, 단순히 빈도수로 계산하면 같은 단어로 묶이게 된다.We will rock you
를 [0, 0, 0, 1, 2, 3, 4]
로 변환했다고 하자.
제공받은 한국어 데이터를 전처리 수행한 코드이다. 전처리의 방법은 무궁무진하므로 정답이 없다.
## 토큰화
from tensorflow.keras.preprocessing.text import Tokenizer
max_words = 40000
tokenizer = Tokenizer(num_words=max_words, lower=True)
# 학습 텍스트 데이터를 바탕으로 토크나이징 (띄어쓰기 기반으로 기본적인 처리)
tokenizer.fit_on_texts(x_train)
## 단어 -> 인덱스
# 텍스트 순서를 토큰화된 인덱스 순서로 변환
x_train = tokenizer.texts_to_sequences(x_train)
x_test = tokenizer.texts_to_sequences(x_test)
## Padding & Truncate
from tensorflow.keras.preprocessing.sequence import pad_sequences
# 문장의 길이를 40으로 설정
max_length = 40
# 두괄식을 가정하여 뒷부분을 삭제
x_train = pad_sequences(x_train, maxlen=max_length, padding='pre', truncating='post')
x_test = pad_sequences(x_test, maxlen=max_length, padding='pre', truncating='post')
# 모델이 처리할 수 있도록 numpy로 변환
x_train = np.array(x_train)
x_test = np.array(x_test)
# 모델링에 필요한 라이브러리 불러오기
import tensorflow as tf
from tensorflow import keras
from keras.backend import clear_session
from keras.models import Model
from keras.layers import Input, Embedding, Dense
from keras.layers import Conv1D, MaxPool1D, Flatten
from keras.layers import LSTM, GRU, SimpleRNN, Bidirectional
# 0. 필요 변수
max_words = 40000
max_length = 40
# 1. 세션 클리어
clear_session()
# 2. 레이어 연결
# 인풋레이어
il = Input(shape=(max_length,))
# 임베딩 레이어 : 임베딩차원은 128
embedding = Embedding(input_dim=max_words,
output_dim=128,
input_length=max_length)(il)
# 학습을 위한 히든레이어 (Conv1D + Bidirectional LSTM)
hl = Conv1D(filters=64,
kernel_size=5,
strides=1,
padding='valid',
activation='swish')(embedding)
forward_LSTM = LSTM(32, return_sequences=True)
backward_LSTM = LSTM(32, return_sequences=True, go_backwards=True)
hl = Bidirectional(layer=forward_LSTM, backward_layer=backward_LSTM)(hl)
forward_GRU = GRU(32, return_sequences=True)
backward_RNN = SimpleRNN(16, return_sequences=True, go_backwards=True)
hl = Bidirectional(layer=forward_GRU, backward_layer=backward_RNN)(hl)
hl = Conv1D(filters=32,
kernel_size=5,
strides=1,
padding='valid',
activation='swish')(hl)
hl = MaxPool1D(pool_size=2)(hl)
hl = Flatten()(hl)
hl = Dense(1024, activation='swish')(hl)
# Output
ol = Dense(1, activation='sigmoid')(hl)
# 3. 모델 선언
model = Model(il, ol)
# 4. 컴파일
model.compile(loss=keras.losses.binary_crossentropy,
metrics=['accuracy'],
optimizer='adam')
# 요약
model.summary()
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 40)] 0
embedding (Embedding) (None, 40, 128) 5120000
conv1d (Conv1D) (None, 36, 64) 41024
bidirectional (Bidirectiona (None, 36, 64) 24832
l)
bidirectional_1 (Bidirectio (None, 36, 48) 10704
nal)
conv1d_1 (Conv1D) (None, 32, 32) 7712
max_pooling1d (MaxPooling1D (None, 16, 32) 0
)
flatten (Flatten) (None, 512) 0
dense (Dense) (None, 1024) 525312
dense_1 (Dense) (None, 1) 1025
=================================================================
Total params: 5,730,609
Trainable params: 5,730,609
Non-trainable params: 0
_________________________________________________________________