- 문맥은 단어들의 순서를 통해서 형성 ▷ RNN은 단어가 쓰여진 순서의 패턴으로 문맥을 파악하기에 좋은 모형!
- RNN 신경망 모형의 입력은 내가 정한 수의 입력
- RNN의 출력인 o는 모형을 통해 예측하고 싶은 값 혹은 라벨로 구성
- 시계열의 앞 값들이 뒤에 미치는 영향은 은닉층의 노드들 간의 연결 통해 구현
- BUT RNN은 딥러닝의 대표적인 문제인 경사소실의 문제 심각!
- ex. 문서 분류) 원핫 벡터(one- hot vector) -> 밀집 벡터(dense vector) -> RNN 모형의 입력으로 사용(-> hidden layer -> Output layer) -> 마지막 출력 노드를 이용해 문서 분류
* 원핫 벡터 -> 밀집 벡터 : 딥러닝에서는 문서를 단어의 시퀀스로 표현하고, 각 단어들은 고정된 길이의 벡터가 되어야 하므로!->
: 단어에 대해 원핫 인코딩을 먼저 수행하고 이를 다시 연속형 값을 갖는 축소된 벡터(밀집 벡터)로 변환하는 과정
- 범주형 데이터 분석하려면 -> 수치로 변환
1) 더미 변수의 이용 : 0과 1만으로 표현
* 범주형 -> 벡터 형태의 연속된 수치로 변환(ex. A: [1,0,0,0]) = "원핫 인코딩(one-hot encoding)" -> 결과 = 원핫 벡터
* 말뭉치에 사용된 단어 수만큼 더미 변수 필요 -> 오직 하나의 변수만 1의 값을 가져 희소한 벡터 생성
* 모든 데이터 간의 거리가 동일하게 유지되어 잘못된 가정들이 사라짐
2) 임베딩(Embedding) : 범주형 데이터를 연속적인 값을 갖는, 상대적으로 작은 크기의 벡터로 변환하는 작업
* 즉 원핫 인코딩에 의한 희소 벡터를 축소된 밀집 벡터로 변환하는 과정(학습 통해 계산된 가중치 이용)
* 결과 = 밀집 벡터(대부분의 변수가 0이 아닌 연속적인 값을 가짐)
* 1. 차원이 큰 원핫 벡터는 연산이 비효율적
2. 대상 간의 의미적 유사도 계산 가능(ex. 사과 - 책상보다는 귤에 가까움)
3. 단어가 의미적인 정보를 함축함으로써 연산 가능(ex. king+woman-man = queen)
4. 전이학습(transfer learning) 가능(기존에 학습된 모형을 새로운 환경에서 재사용 -> 학습의 속도, 효과 up)
- BOW / 카운트 기반의 문서 표현에서 문서는 단어들의 빈도를 벡터 형태로 표현
- 카운트 기반의 문서 표현은 코사인 유사도와 같은 방법으로 희소 벡터 자체로 유사도 계산 가능(즉 임베딩이라고 봐도 무방)
- BOW는 문서 단위로 임베딩 --> 단어의 순서 정보를 잃으므로 문맥에 대한 파악은 이뤄지지 x
- 대부분의 딥러닝 기반의 자연어 처리 기법에서는 문서를 단어의 시퀀스로 표현
--> 문서 직접 임베딩x 단어 임베딩, 임베딩된 단어의 시퀀스로 문서 표현
BOW | 단어 임베딩 |
단어의 순서 고려x ▶ 문맥 파악x | 단어의 순서 고려 O ▶ 문맥 파악 O |
문서가 1차원 벡터로 표현 | 문서가 2차원 행렬 또는 1차원 벡터의 리스트로 표현 |
[RNN을 이용한 문서 분류 - NLTK 영화 리뷰 감성분석]
- 이진 분류 ▶ sigmoid , 신경망의 최종 출력단 크기 = 1, 손실함수 = binary_crossentropy
- 다중 분류 ▶ softmax
- 은닉층으로 사용 ▶ relu
- Keras에서 제공하는 토크나이저(tokenizer)를 사용해 RNN 모형에 적합한 형태로 입력 데이터 변환 ex. tokenizer. ~~~
- 기본적인 토큰화, 단어에 인덱스를 부여해 사전 작성, 인덱스를 이용해 주어진 문장 변환 기능
- ex. "I am so happy" --토큰화--> ['I','am','so','happy'] --인덱스 부여--> [7,2,9,13]
- 사전에서 인덱스 0은 사용x(길이가 짧은 문서에 채워 넣을 값으로 0을 사용하기에)
- num_words : 모형에 사용할 단어 수 --> 지정된 값보다 큰 경우, 사전에 포함되지 않은 단어 빼고 시퀀스 생성
- 생략x싶으면 oov_token 매개변수를 이용해 단어들을 변환할 문자열 할당 -> 사전에 없는 단어들이 공통값으로 변환
- fit_on_texts() : 말뭉치에 대해 단어 인덱스 사전 구축
- texts_to_sequences() : 사전을 이용해 문서들을 인덱스의 시퀀스로 변환
- word_index() : 토크나이저가 생성한 사전에서 단어의 인덱스 확인
- 신경망 모형의 입력은 길이가 일정해야 ! --> pad_sequences()를 이용, 모든 입력 시퀀스의 길이를 매개변수 maxlen만큼 변환 - ex. pad_sequences(X, maxlen = maxlen, truncating = 'pre')
- truncating이 'pre'면 시퀀스의 앞을 잘라내고, 'post'면 뒤를 잘라냄(크기가 maxlen보다 작으면 남는 부분 0으로)
[RNN이 아닌 일반적인 신경망 모형을 이용한 분류]
- Sequential 모형 --> 순차적으로 층을 쌓아서 신경망 모형을 구성하는데 활용
- Embedding layer, Flatten() layer, Dense() layer
- Embedding layer: RNN위해 원핫 인코딩& 워드 임베딩 수행하는 layer ->결과: (단어 수, 단어 표현 밀집 벡터 크기)
- Flatten() layer: 2차원 행렬 -> 1차원 벡터로 변환. 위의 결과를 단어수*밀집 벡터 크기 개의 독립적 입력변수로 변환
- Dense() layer: 일반적인 신경망의 은닉층으로 알고 있는, 모든 노드들이 연결되는 밀집 층 생성
- 감성분석-이진분류) 출력의 크기=1, 활성화함수='sigmoid'
- 학습은 손실함수, optimizer이용 --> compile() 메서드 이용
- 이진분류) 손실함수 = 'binary_crossentropy', optimizer = 'rmsprop'
ex. model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
- fitting은 fit() 메서드
- 입력과 라벨 반드시 지정
- epochs = 학습의 반복 횟수, verbose = 학습현황의 출력 여부, validation_split = 검정 데이터셋의 비율
- 검증 데이터셋은 과대적합의 여부 판단
- 매 epoch별로 학습 데이터셋에 대한 정확도, 검증 데이터셋의 정확도 비교해 적절한 에포크 수 결정
[RNN 모형 적용해 문서의 순서정보 활용한 문서 분류]
- Dense() 레이어를 추가하여 모형의 성능 높일 수 o
- 학습 데이터셋의 정확도는 쭉 상승해도 검증 데이터셋의 정확도는 잘안오르면 과대적합, 실제 학습 거의x 판단
-> RNN의 목적인 앞에서부터 순서에 따라 다음 단어에 미치는 영향을 축적하는 것이 경사소실 문제로 학습x
-> "장기간에 걸친 시간의존성" (RNN의 가장 큰 문제점)
-> "LSTM(Long Short-Term Memory)"
1. LSTM : 앞부분의 정보가 뒤로 갈수록 소실되는 것을 방지하기 위해 장기&단기 의존성을 모두 표현, 학습
즉 장기 기억정보를 추가함으로써 장기의존성 학습
2. GRU(Gated Recurrent Unit) : LSTM을 간소화한 모형으로 LSTM에 비해 계산량↓ 속도↑ 좋은 성능
3. 양방향 LSTM
- 뒤 단어가 앞 단어에 영향을 미치기도 하기에
- 두개의 LSTM을 구현하고 각 층의 은닉 노드를 연결
- SimpleRNN 대신 LSTM 임포트
- Bidirectional로 LSTM 레이어를 감싸기
- ex. Bidirectional(LSTM(64))
[성능이 그렇게 좋게 나오지 않는 이유의 후보들]
1. 딥러닝의 많은 데이터 요구
But 나이브 베이즈, 로지스틱 회귀분석에 비해 딥러닝은 더 많은 데이터를 요구해서 성능이 낮을 수도
--> 개선하기 위해 워드 임베딩 벡터에 대해 학습된 가중치를 Word2Vec과 같은 기존의 학습된 모형으로부터 가져올 수도
--> But 기존의 학습된 모형은 일반적인 문서들 대상이지만 이번에 논한건 영화 리뷰에 대한 감석 분석이라는 목표
--> 좋은 성능 보장은 어려움 (시도해볼만은 함)
2. 단어의 수 n개 이상의 문서가 내용 잘리는 것
3. 검증 데이터 셋으로인해 머신러닝에 비해 더 적은 수의 학습데이터로 학습
4. 과대적합
결론적으로 딥러닝 학습이 목표라면 충분한 양의 데이터 확보가 중요!
+) 학습된 모형을 통해 결과 예측 --> model의 predict() method이용!
[패널 질문]
1. RNN 모델은 어떻게 경사소실 문제가 발생하며, LSTM과 GRU는 어떻게 이 문제를 해결했는가?
A) RNN 모델은 학습하려는 문장이 길어질 수록 미분값이 중첩되어 경사소실 문제가 발생한다. 이러한 문제를 해결하기 위해 LSTM에서는 ‘Cell’이라는 새로운 개념을 도입하여 미분값이 오래 유지되게 하였고 이를 더욱 간단화 한 모델이 GRU이다. 또한 활성함수를 통해서도 경사소실 문제를 어느정도 해결 할 수 있는데, tanh가 sigmoid함수보다 최대 기울기가 커서 더욱 이 문제를 잘 해결한다.
2. Dense() layer는 몇 개를 추가하는 것이 모형의 성능을 높이기에 충분하다고 할 수 있을까?
A) 정해진건 없지만 unit의 증가 = 데이터의 차원 증가, layer 증가 = 더 복잡한 모델을 만드는 것이므로 두 요소들을 무작정 증가시키면 성능을 향상시킬 수도 있겠지만 오버피팅이 발생할 수 있으므로 cv 점수를 확인하면서 조절해야한다.
또한 크기가 큰 행렬이 input으로 들어오는 경우 Dense layer를 하나만 사용하면 크기를 대폭 줄여서 정보손실이 너무 많아지고, task에 적합한 모델 생성이 어렵게 되고 구체적으로 미세조정을 하기 힘들어진다.추가적으로, Dense layer는 input이 들어오면 가중치와 곱해주고 bias를 더해서 activation 함수를 통해 결과를 도출, 즉 입력과 출력을 연결하는 역할을 한다. activation 함수의 경우는 relu는 은닉층으로 역전파를 통해 좋은 성능이 나오기 때문에 마지막 층이 아니면 주로 relu를 이용한다. 또한 이진 분류 문제의 경우 sigmoid를, 클래스 분류 문제의 경우는 softmax를 사용한다. 주로 Dense layer는 출력층에 사용되는데 이 경우 분류하려는 클래스와 동일한 개수의 뉴런, 즉 unit을 사용해야 한다.또한 신경망은 분류해야하는 클래스의 개수에 대한 확률을 예측해야하기 때문에 이전 은닉층의 뉴런 개수가 출력층보다 적게 되면 부족한 정보가 전달될 수 있어 은닉층의 뉴런은 적어도 출력층의 뉴런보다는 많아야 한다.
[NLP]CNN & 트랜스포머 (0) | 2022.11.15 |
---|---|
[NLP] 11장_Word2Vec, ELMo, Doc2Vec (0) | 2022.11.09 |
[NLP 스터디] 10장_RNN - 딥러닝을 이용한 문서 분류 (0) | 2022.10.16 |
[NLP 스터디] 9장_인공신경망과 딥러닝의 이해 (0) | 2022.10.16 |
[NLP 스터디] 7회차. 토픽 모델링 (0) | 2022.10.16 |