import pandas as pd
import numpy as np
import os
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from tqdm.auto import tqdm
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings(action='ignore')
class BaseModel(nn.Module):
def __init__(self, embed_dim = 128,
seq_dim = 512,
lstm_bidirect = True):
super(BaseModel, self).__init__()
embed_1 = nn.Embedding(num_embedding = 128,
embedding_dim = embed_dim,
padding_idx = 0)
embed_2 = nn.Embedding(num_embedding = 128,
embedding_dim = embed_dim,
padding_idx = 0)
lstm_1 = nn.LSTM(input_size = embed_dim,
hidden_size = seq_dim,
batch_first = True,
bidirectional = lstm_bidirect)
lstm_2 = nn.LSTM(input_size = embed_dim,
hidden_size = seq_dim,
batch_first = True,
bidirectional = lstm_bidirect)
in_channels = 4 * seq_dim
self.regressor = nn.Sequential(nn.Linear(in_features=in_channels,
out_features=512),
nn.BatchNorm1d(512),
nn.ReLU(),
nn.Linear(in_features=512,
out_features=1))
def forward(self, frag1, frag2):
frag1 = self.embed_1(frag1)
frag2 = self.embed_2(frag2)
frag1_hidden, _ = self.frag1_lstm(frag1)
frag1_hidden = frag1_hidden[:,-1,:]
frag2_hidden, _ = self.frag2_lstm(frag2)
frag2_hidden = frag2_hidden[:,-1,:]
x = torch.cat([frag1_hidden, frag2_hidden], axis = -1)
x = self.regressor(x)
return x
가령 단어 'BOOK'이 있고 B가 21, O가 7, K가 11이라고 하면 BOOK은 21,7,7,11로 인코딩 되어 있을까요? 이 각 정수를 각각 임베딩 층을 거치도록 하여 문자 단위 임베딩을 얻게 됩니다. 임베딩 층은 모델을 설계할 때 추가하므로 정수 인코딩까지만 진행합니다.
'good book'의 정수 인코딩 결과
12, 7, 7, 17
21, 7, 7, 11
[[53 41 48 54 52 34 47 37 52 0 0 0 0 0 0]
[48 39 0 0 0 0 0 0 0 0 0 0 0 0 0]
[37 38 46 48 47 52 53 51 34 53 48 51 52 0 0]
[41 34 55 38 0 0 0 0 0 0 0 0 0 0 0]
[46 34 51 36 41 38 37 0 0 0 0 0 0 0 0]
[53 41 51 48 54 40 41 0 0 0 0 0 0 0 0]
[45 48 47 37 48 47 0 0 0 0 0 0 0 0 0]
[53 48 0 0 0 0 0 0 0 0 0 0 0 0 0]
[49 51 48 53 38 52 53 0 0 0 0 0 0 0 0]
[53 41 38 0 0 0 0 0 0 0 0 0 0 0 0]
[56 34 51 0 0 0 0 0 0 0 0 0 0 0 0]
[42 47 0 0 0 0 0 0 0 0 0 0 0 0 0]
[42 51 34 50 0 0 0 0 0 0 0 0 0 0 0]
[34 47 37 0 0 0 0 0 0 0 0 0 0 0 0]
[37 38 46 34 47 37 0 0 0 0 0 0 0 0 0]
[53 41 38 0 0 0 0 0 0 0 0 0 0 0 0]
[56 42 53 41 37 51 34 56 34 45 0 0 0 0 0]
[48 39 0 0 0 0 0 0 0 0 0 0 0 0 0]
[35 51 42 53 42 52 41 0 0 0 0 0 0 0 0]
[53 51 48 48 49 52 0 0 0 0 0 0 0 0 0]
[39 51 48 46 0 0 0 0 0 0 0 0 0 0 0]
[53 41 34 53 0 0 0 0 0 0 0 0 0 0 0]
[36 48 54 47 53 51 58 0 0 0 0 0 0 0 0]
[14 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
각 행은 각 단어를 의미한다. 단어의 최대 길이를 15로 제한하였으므로 길이가 15보다 짧은 단어는 뒤에 0으로 패딩된다. 53은 t, 41은 h, 48은 o, 54는 u에 각각 해당된다. X_data는 뒤에 0으로 패딩되어 길이가 70인 것에 비해 X_char_data는 0번 단어는 무시되어 길이가 70이 아니다. 즉, 위 출력 결과에서 행의 개수가 70이 아니다.
위에서 전처리한 문자 단위 정수 인코딩 입력을 1D CNN의 입력으로 사용하여 문자 임베딩을 얻고 워드 임베딩과 연결하여 양방향 LSTM의 입력으로 사용할 수 있다.
word_ids = Input(shape=(None,),dtype='int32',name='words_input')
word_embeddings = Embedding(input_dim = vocab_size, output_dim = 64)(word_ids)
# char 임베딩
char_ids = Input(shape=(None, max_len_char,),name='char_input')
embed_char_out = TimeDistributed(Embedding(len(char_to_index), 30, embeddings_initializer=RandomUniform(minval=-0.5, maxval=0.5)), name='char_embedding')(char_ids)
dropout = Dropout(0.5)(embed_char_out)
# char 임베딩에 대해서는 Conv1D 수행
conv1d_out= TimeDistributed(Conv1D(kernel_size=3, filters=30, padding='same',activation='tanh', strides=1))(dropout)
maxpool_out=TimeDistributed(MaxPooling1D(max_len_char))(conv1d_out)
char_embeddings = TimeDistributed(Flatten())(maxpool_out)
char_embeddings = Dropout(0.5)(char_embeddings)
# char 임베딩을 Conv1D 수행한 뒤에 워드 임베딩과 연결
output = concatenate([word_embeddings, char_embeddings])
# 연결한 벡터를 가지고 문장의 길이만큼 LSTM을 수행
output = Bidirectional(LSTM(50, return_sequences=True, dropout=0.50, recurrent_dropout=0.25))(output)
# 출력층
output = TimeDistributed(Dense(tag_size, activation='softmax'))(output)
model = Model(inputs=[word_ids, char_ids], outputs=[output])
model.compile(loss='categorical_crossentropy', optimizer='nadam', metrics=['acc'])
벡터의 특정 차원에 단어 혹은 의미를 직접 매핑하는 방식
희소 표현은 데이터를 벡터 또는 행렬을 기반으로 수치화하며 표현할 때 극히 일부의 인덱스만 특정 값으로 표현하고, 대부분의 나머지 인덱스는 의미 없는 값으로 표현하는 기법이다. 대표적으로 원 핫 인코딩 방식이 있다.