[D&A 운영진 딥러닝 스터디] 4주차 2차시

권유진·2022년 1월 27일

D&A 운영진 스터디

목록 보기
8/17

문자 데이터를 사용한 모델링에서 고려해야 할 요소

  1. 연속된 데이터의 정보 처리
  2. 단어가 나올 확률은 이전 단어나 주변 단어에 따라 결정(연속적 관계)
  3. 언어적 약속 ex) 먹고 싶습니다 요소 앞에는 먹을 것이 오며 단어에 받침이 있을 경우에는 이가 조사로 붙어야 함.

NLP 모델은 언어적 약속을 모델링해야 했고 이를 통계적으로 접근

  • Probability Language Model: 문장이 나타날 수 있는 확률을 각 단어가 동시에 나타나는 확률로 표현
  • n-gram Language Model: 문장의 부분에 대한 조건부 확률로 근사시켜 표현
    • Skip-gram도 이와 같은 지역성 조건부 확률을 활용
      P(나는,회가,먹고,싶습니다)=P(나는∣<SOS>)P(회가∣나는)P(먹고∣나는,회가)P(싶습니다∣나는,회가,먹고)P(<EOS>∣나는,회가,먹고,싶습니다)P(나는, 회가, 먹고, 싶습니다) \\= P(나는|<SOS>)P(회가|나는)P(먹고|나는, 회가)\\P(싶습니다|나는, 회가, 먹고)P(<EOS>|나는, 회가, 먹고, 싶습니다)

연속성의 정보를 담을 수 있는 딥러닝 모델

  • 일반적인 딥러닝 모델: One-To-One 문제(input과 output 모두 1개)
  • 문장, 문자 데이터는 여러 개의 연관성 깊은 Token(다수의 벡터)을 활용
    • Many-To-One: ex) 댓글의 악플 가능성 정도를 측정하는 sentence classification
    • One-To-Many: ex) 사진 속 내용을 설명하는 글을 만들어내는 Image Captioning
    • Many-To-Many(token-by-token): ex) 문장의 모든 token에 대한 품사를 예측하는 Pos Tagging
    • Many-To-Many(Encoder-Decoder): ex) 입력 문장에 대한 번역문을 만들어 주는 Translation

RNN(Recurrent Neural Network)

  • Sequential Data를 다루는 가장 대표적인 모델

  • 단어를 순서대로 하나의 Hidden Layer에 입력해 반복 업데이트

    • 데이터의 순서에 대한 정보 담을 수 있음
  • 파라미터: WihW_{ih}, WhhW_{hh}, WhoW_{ho}

    ht=tanh⁡(ht−1Whh+xtWih+bhh)h_t = \tanh (h_{t-1}W_{hh} + x_tW_{ih} + b_{hh})
  • Hidden Layer은 이전 Token들의 정보가 자동으로 축적

  • Loss는 Token별로 나오는 Loss를 더한 총합

  • Gradient Vanishing/Exploding 문제 발생(장기 기억력 떨어짐) ∵\because Activation Function

    • Truncated Back Propagation: Token의 과거 지정 개수의 Token까지만 부분적으로 업데이트
    • Gradient Clipping: 너무 큰 Gradient는 조정
    • 적절한 초기값 설정
    • 활성화함수 ReLU 사용
rnn = nn.RNN(input_size, hidden_size)
outputs, _status = rnn(input_data)
  
# input_shape = (batch_size, sequence_length, input_size)
# output_shape = (batch_size, sequence_length, hidden_size)
## input_size: 단어 벡터의 차원
## sequence_length: 문장의 길이
## hidden_size: output(hidden state)의 차원

LSTM(Long Short-Term Memory)

  • RNN의 단기기억만 가능하다는 단점 개선
    • Cell(ctc_t)를 이용해 Gradient가 곱해지는 값의 차이가 심각하지 않게 만듦
      • ∂ct∂ct−1\cfrac{\partial c_t}{\partial c_{t-1}}은 ftf_t를 포함
      • Forget Gate(ftf_t)의 값이 1에 가까울수록 Gradient 값이 작아지는 상황 줄여줌
  • Cell State(ctc_t)와 다수의 Gate(iti_t,ftf_t,c~t\tilde c_t,oto_t)를 통한 필터링 존재
  • 특정 시점에 대한 데이터 xtx_t와 그 이전 시점까지의 정보 ht−1h_{t-1}로 각각의 Gate와 현재 시점의 Cell 정보 ctc_t를 만들고 여기에 한 번의 처리를 거쳐 최종 형태의 정보 hth_t를 만들어 냄
ft=σ(Wfxt+Ufht−1+bf)it=σ(Wixt+Uiht−1+bi)ot=σ(Woxt+Uoht−1+bo)c~t=tanh⁡(Wcxt+Ucht−1+bc)ct=ft⊙ct−1+it⊙c~ht=ot⊙tanh⁡(ct)f_t = \sigma(W_fx_t + U_fh_{t-1}+ b_f)\\ i_t = \sigma(W_ix_t + U_ih_{t-1}+ b_i)\\ o_t = \sigma(W_ox_t + U_oh_{t-1}+ b_o)\\ \tilde c_t = \tanh(W_cx_t + U_ch_{t-1}+ b_c)\\ c_t = f_t \odot c_{t-1} + i_t \odot \tilde c\\ h_t = o_t \odot \tanh(c_t)
  • Forget Gate(ftf_t): 이전 정보까지의 정보를 담고있는 Cell(ct−1c_{t-1})를 얼마나 잊을 것인지 결정
  • Input Gate(iti_t): 현재 Token에 대한 정보(c~\tilde c)를 얼마나 가져올 것인지 결정
  • Cell(ctc_t): 과거의 정보 중 불필요한 부분 지우고 현재 정보를 적당히 합산
  • Output Gate(oto_t): Output Gate를 통해 Cell 정보를 수정을 거쳐 최종적인 h_t 구함

참고
https://medium.datadriveninvestor.com/how-do-lstm-networks-solve-the-problem-of-vanishing-gradients-a6784971a577

Bi-RNN(Bidirectional Recurrent Neural Network)

  • 양방향 정보 모두 이용(왼쪽→\rightarrow오른쪽, 왼쪽←\leftarrow오른쪽)
  • 양방향의 Hidden Layer를 Concatenate해 사용

GRU(Gated Recurrent Units)

  • LSTM의 Output부분을 제거한 간소화 버전으로 알려진 모델
  • 최종 Hidden Layer를 과거의 누적 정보(ht−1h_{t-1})와 현재 정보(h^t\hat h_t)의 Weight Average를 이용해 표현
    zt=σ(Wzxt+Uzht−1+bz)rt=σ(Wrxt+Urht−1+br)h^t=tanh⁡(Whxt+Ut(rt⊙ht−1)+bh)ht=(1−zt)⊙ht−1+zt⊙h^tz_t = \sigma(W_zx_t+U_zh_{t-1}+b_z)\\ r_t = \sigma(W_rx_t+U_rh_{t-1}+b_r)\\ \hat h_t = \tanh(W_hx_t + U_t(r_t \odot h_{t-1})+b_h)\\ h_t = (1-z_t) \odot h_{t-1} + z_t \odot \hat h_t

Attention Mechanism

  • RNN Encoder-Decoder 구조의 모델 사용
    • 번역하고자 하는 문장 Source Sentence의 정보를 저장하는 RNN Encoder
    • 위에서 저장된 정보를 바탕으로 번역된 문장을 생성하는 RNN Decoder
  • Decoder에서 원 문장의 어떤 단어에 집중해 단어를 만들어 낼 것인지에 대한 정보(Attention Score) 활용
  • 다른 언어이지만 같은 뜻을 나타내는 Pair에 대한 정보 얻을 수 있음(Attention Score 참조)

Convolution Neural Network for Text Classification

  • 이미지 데이터에 많이 사용되는 CNN을 NLP에 적용
  • RNN의 구조적 한계로 할 수 없었던 병렬 처리를 CNN을 통해 해결
  • Convolution Filter의 사용은 n-gram Feature와 비슷함
  • 구조 특성상 문장 생성이 필요한 task에는 적용이 어려움
  • 텍스트를 이미지처럼 만들어 분류하는 모델 제안

실습코드(charseq문제)

# 다음 character을 예측하는 모델 구축
# charseq 문제
sample = ' if you want you'

# make dictionary
char_set = list(set(sample))
char_dic = {c:i for i,c in enumerate(char_set)}

# hyperparameters
input_size = len(char_set)
dic_size = len(char_dic)
hidden_size = len(char_dic)
learning_rate = 0.1

# data setting
sample_idx = [char_dic[c] for c in sample] # index 가져옴
x_data = [sample_idx[:-1]] # 마지막 character 제외 후 가져옴
x_one_hot = [np.eye(dic_size)[x] for x in x_data] # np.eye는 Identity matrix임-여기서 원하는 vector 가져옴
y_data = [sample_idx[1:]]

# transform as torch tensor variable
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)

# declare RNN
rnn = torch.nn.RNN(input_size, hidden_size, batch_first=True)

# loss&optimizer setting
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(rnn.parameters(), learning_rate)

# start training
for i in range(100):
    optimizer.zero_grad()
    outputs, _status = rnn(X)
    loss = criterion(outputs.view(-1, input_size), Y.view(-1))
    loss.backward()
    optimizer.step()
  
    result = outputs.data.numpy().argmax(axis=2)
    result_str = ''.join([char_set[c] for c in np.squeeze(result)])
    print(F'{i}, loss: {loss.item()}, prediction: {result}, true Y: {y_data}, prediction str: {result_str}')

실습코드(longseq문제)

  • fixed size로 긴 문장을 자름
  • 'if you want to build a ship, don't drum up people together to '
    • 'if you wan' →\rightarrow 'f you want'
    • 'f you want' →\rightarrow ' you want '
    • ' you want ' →\rightarrow 'you wnat t'
# 문장 자르기
sentence = "if you wnat to build a ship, don't drum up people together to collect wood and don't assign them tasks and work, but rather teach them to long for the endless immensity of the area"
char_set = list(set(sentence))
char_dic = {c:i for i,c in enumerate(char_set)}

sequence_length = 10
input_size = len(char_set)
dic_size = len(char_dic)
hidden_size = len(char_dic)
learning_rate = 0.1

x_data = []
y_data = []
for i in range(0, len(sentence)-sequence_length):
    x_str = sentence[i:i+sequence_length]
    y_str = sentence[i+1:i+sequence_length+1]
    print(i, x_str, '->',y_str)
    x_data.append([char_dic[c] for c in x_str]) # x str to index
    y_data.append([char_dic[c] for c in y_str]) # y str to index
    
x_one_hot = [np.eye(dic_size)[x] for x in x_data] # one_hot vector로 만듦
  
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)
  
# declare model
class Net(nn.Module): # nn.Module을 상속한 다음 Net이라는 Class로 정의
    def __init__(self, input_dim, hidden_dim, layers): # 모듈의 내부적 하위 모듈 정의
        super(Net, self).__init__()
        self.rnn = nn.RNN(input_dim, hidden_dim, num_layers=layers, batch_first=True)
        self.fc = torch.nn.Linear(hidden_dim, hidden_dim, bias=True)
    def forward(self, x):
        x, _stats = self.rnn(x)
        x = self.fc(x)
        return x
        
net = Net(dic_size, hidden_size, 2)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), learning_rate)

# train
for i in range(100):
    optimizer.zero_grad()
    outputs = net(X)
    loss = criterion(outputs.view(-1, dic_size), Y.view(-1))
    loss.backward()
    optimizer.step()
    
    results = outputs.argmax(dim=2)
    predict_str = ''
    for j, result in enumerate(results):
        print(i, j, ''.join([char_set[t] for t in result]), loss.item())
        if j==0:
            predict_str += ''.join([char_set[t] for t in result])
        else:
            predict_str += char_set[result[-1]]

참고
파이썬 딥러닝 파이토치 (이경택, 방성수, 안상준)
모두를 위한 딥러닝 시즌 2 Lab 11-0, 11-1, 11-3, 11-4

profile
데이터사이언스를 공부하는 권유진입니다.

0개의 댓글