본문 바로가기

(63)
03 파이토치 기초 (1) 텐서 텐서(Tensor)란? 넘파이 라이브러리의 ndarray 클래스와 유사한 구조로 배열이나 행렬과 유사한 자료 구조(자료형)이다. 파이토치에서는 텐서를 사용하여 모델의 입출력뿐만 아니라 모델의 매개변수를 부호화(Encode)하고 GPU를 활용해 연산을 가속화 할 수 있다. 공통점 수학 계산, 선형 대수 연산을 비롯해 전치, 인덱싱, 슬라이싱, random 샘플링 등 다양한 텐서 연산을 진핼할 수 있다. 차이점 CPU에서 사용하는 텐서와 GPU에서 사용하는 텐서의 선언 방식에 있다. 파이토치는 CPU 텐서와 GPU 텐서로 나눠지고, 각각의 텐서를 상호 변환하거나 GPU 사용 여부를 설정한다. 텐서 생성 텐서 생성 방법 torch.tensor() 입력된 데이터를 복사해 텐서로 변환하는 함수 데이터를 복사하기 ..
8장 어텐션 (2) 양방향 RNN 앞에서 배운 Encoder에 초점을 맞춰보자. 그 구조는 다음과 같았다. 여기서 주목할 것은 모델이 왼쪽에서 오른쪽으로 처리한다는 것이다. 즉 '고양이'에 대한 은닉 상태를 만들어낼때는 '나', '는', '고양이' 까지 세 단어의 정보가 인코딩되어 들어간다. 여기에서 전체적인 균형을 생각하면 '고양이' 단어의 주변 정보를 균형 있게 담는 것이 좋을 것이다. 그래서 LSTM을 양방향으로 처리하는 방법을 생각할 수 있다. 왼쪽에서 시작하는 TimeLSTM 계층과 오른쪽에서부터 시작하는 TimeLSTM 계층이 만들어내는 은닉 상태 벡터를 concat하여 정보를 균형있게 인코딩할 수 있다. 구현 할 때도 하나의 입력이 "abcd"이었다면 다른 것은 "dcba'로 순서를 바꿔 입력하면 된다. cla..
8장 어텐션 (1) seq2seq의 문제점은 Encoder의 출력이 '고정 길이의 벡터'라는 것이다. 기계번역을 예로 들면 입력 문장이 길어지게 되면 필요한 정보를 충분히 인코딩할 수 없을 것이다. 따라서 이를 해결하기위해 Encoder와 Decoder를 개선해보자. Encoder 개선 지금까지는 LSTM 계층의 마지막 은닉 상태만 Decoder에 전달했다. 그럼 모든 시각의 은닉 상태를 전달하게되면 Encoder는 고정 길이 벡터라는 제약으로부터 해방될 것이다. 그림으로는 다음과 같다. (케라스에서는 return_sequences=True로 설정하면 모든 시각의 은닉 상태 벡터를 반환한다.) $hs$의 각 단어에 대한 정보를 갖고 있는 벡터들의 집합이라고 볼 수 있다. Encoder의 개선은 이것이 전부다. Decoder..
7장 RNN을 사용한 문장 생성 (2) seq2seq 개선 입력 데이터 반전 이 트릭을 사용하면 많은 경우에 학습이 빨리져서 결과적으로 최종 정확도도 좋아진다고 한다. 참고로 입력 데이터 반전은 다음과 같이 할 수 있다. array = array[:, ::-1] 위와 같이 사용하면 배열의 행만 반전시킬 수 있다. 이 트릭을 사용해서 정확도가 향상됨을 보여준다. 왜 결과가 좋아지는지를 생각해보면 "나는 고양이이다"를 "I am a cat"으로 번역하는 문제에서 트릭을 사용하지 않으면 "나"로부터 "I"까지 가려면 여러 타임 스텝("는", "고양이" 등)을 거쳐야한다. 시간적으로 거리가 멀다. 입력을 반전시키면 이 거리가 짧아지게 되어 역전파시 기울기가 직접 전해진다. 입력 데이터 반전 덕분에 시간적으로 거리가 짧아지는 경우가 이전보다 더 많아지..
7장 RNN을 사용한 문장 생성 (1) "you say goodbye and I say hello."라는 말뭉치로 학습한 언어 모델을 예로 생각해보자. 이 모델에 "I"라는 단어를 입력으로 주면 모델은 다음과 같은 확률분포를 출력한다. 우리는 확률이 가장 높은 단어를 선택하는 결정적인 방법과 확률적으로 샘플링하는 방법을 사용할 수 있다. 여기서는 후자를 사용한다. 샘플링을 하였을 때 "say"가 선택되었다면 이것을 다시 모델에 입력하여 다음 단어의 확률분포를 얻는 식으로 문장을 생성해낼 수 있다. 주로 일정 길이나 "end of sentence"를 의미하는 eos 토큰이 나타날 때 까지 반복한다. 그럼 문장 생성을 구현해보자. class RnnlmGen(Rnnlm): def generate(self, start_id, skip_ids=None..
6장 게이트가 추가된 RNN (2) LSTM 구현 이전에 보았던 LSTM의 계산 그래프는 다음과 같다. 그리고 아래 수식들은 LSTM에서 수행하는 계산을 정리한 수식들이다. 행렬 라이브러리는 큰 행렬을 한꺼번에 계산할 때 효율이 좋기 때문에 $x{W_x}+h{W_h}+b$ 같은 아핀 변환을 다음과 같이 한 번에 처리한다. 이때의 계산 그래프는 slice 노드를 포함하여 다음과 같이 표현할 수 있다. 이제 LSTM 클래스를 구현해보자. 우선 초기화 부분이다. class LSTM: def __init__(self, Wx, Wh, b): ''' Parameters ---------- Wx: 입력 x에 대한 가중치 매개변수(4개분의 가중치가 담겨 있음) Wh: 은닉 상태 h에 대한 가장추 매개변수(4개분의 가중치가 담겨 있음) b: 편향(4개분의..
6장 게이트가 추가된 RNN (1) Simple RNN은 시간적으로 멀리 떨어진 long term 의존 관계를 잘 학습할 수 없다는 단점이 있다. 그래서 'gate'라는 구조가 추가된 LSTM이나 GRU가 주로 쓰인다. RNN의 문제점 장기 의존 관계를 학습하기 어려운 원인은 BPTT(시간 방향의 역전파)에서 기울기 소실 혹은 폭발이 일어난다. 기울기 소실과 폭발의 원인 hidden state의 역전파인 빨간색 선에만 주목해서 보면 tanh, +, MatMul 연산을 통과한다는 것을 알 수 있다. + 노드는 미분 값을 그대로 흘려보내기 때문에 문제가 되지 않는다. tanh의 미분 그래프는 다음과 같다. 보다시피 값이 1.0 이하이고 x가 0에서 멀어질수록 작아진다. 즉 역전파에서 기울기가 tanh 노드를 지날 때마다 값이 계속 작아진다는 ..
5장 RNN (2) 시계열 데이터 처리 계층 구현 RNN을 시계열 데이터 처리를 위해 TimeRNN 클래스를 구현한 것 처럼 Embedding, Affine, Softmax 계층도 Time 계층 구현이 필요하다. 그런 다음 이를 조합하면 RNNLM(RNN Language Model)을 구현할 수 있다. RNNLM의 처리는 다음과 같다. 현재 타임 스텝의 입력을 받고 그 다음 타임스텝의 단어를 예측한다. corpus로부터 데이터 입력과 정답을 만들어낼 때 다음과 같이 만들어야 한다. xs = corpus[:-1] # 입력 ts = corpus[1:] # 정답 Softmax with Loss 계층도 다음과 같이 Time 계층으로의 처리가 필요하다. 모든 타입 스텝의 손실함수를 더해서 평균한 것이 최종 손실이 된다. 수식으로는 ..