문장은 여러개의 단어로 이루어져있고, 그 의미가 올바르게 전달되려면 각 단어가 정해진 순서대로 입력되어야 함
즉, 여러 데이터가 순서와 관계없이 입력되던 것과는 달리 데이터의 입력 순서를 고려해야하는 상황이 생김

여러 개의 데이터가 순서대로 입력됨
➡️ 앞서 입력받은 데이터를 잠시 기억해두고 기억된 데이터가 얼마나 중요한지 판단해서 별도의 가중치를 부여
➡️ 다음 데이터로 넘어감
예: 인공지능 비서에게 "오늘 주가가 몇이야?"라고 질문

앞서 나온 입력에 대한 결과가 뒤에 나오는 입력값에 영향을 주는 것을 알 수 있음
'주가' 앞에 나오는 단어가 '어제'이냐 '오늘'이냐에 따라 출력값이 완전히 달라짐!

한 층 안에서 반복을 여러번 해야 하는 RNN의 특정상 일반 신경망에 비해 기울기 소실 문제가 더 많이 발생하고 해결이 어려움
➡️ LSTM(Long Short Term Memory)의 보완: 반복되기 직전에 다음층으로 기억된 값을 넘길지 여부를 관리하는 단계를 추가함

입력값과 출력값을 어떻게 설정하냐에 따라 여러가지 상황에 적용 가능



입력된 문장 의미 파악 ➡️ 모든 단어를 종합해 하나의 카테고리로 분류

목표: 긴 텍스트 읽고 데이터가 어떤 의미를 지니는지 카테고리로 분류하기
로이터 뉴스 데이터: 1만 1228개의 뉴스 기사가 46개의 카테고리로 나누어진 대용량 텍스트 데이터
np.max(데이터셋) + 1 : 데이터셋의 카테고리 개수 구하기 (0부터 세므로 1을 더해줌)
# 데이터 불러오기
from tensorflow.keras.datasets import reuters
# 테스트셋, 학습셋으로 나누기
(X_train, y_train), (X_test, y_test) = reuters.load_data(num_words=1000, test_split = 0.2)
# y_train의 종류 구하기
category = np.max(y_train)+1
print(category, '카테고리')
print(len(X_train), '학습용 뉴스기사 개수')
print(len(X_test), '테스트용 뉴스기사 개수')
print(X_train[0])

print(X_train[0])의 값이 단어가 아닌 숫자임 ➡️ 이미 토큰화를 마친 데이터를 불러왔음을 알 수 있음
각 단어가 몇번째로 많이 나오는 단어인지에 따라 숫자를 붙임
예: 3 ➡️ 3번째로 빈번하게 등장하는 단어
num_words=1000: 기사 안의 단어들 중 빈도가 1~1000에 해당하는 단어만 불러오기 (효율성)
패딩: 각 기사의 단어 수가 각각 다르므로 동일하게 맞춰주는 작업. sequence() 함수 사용
from tensorflow.keras.preprocessing import sequence
X_train = sequence.pad_sequences(X_train, maxlen = 100)
X_test = sequence.pad_sequences(X_test, maxlen = 100) # 단어수 100개로 맞추기
원-핫 인코딩: y데이터를 0과 1만으로 이루어지도록 바꿈. categorical() 함수 사용
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
딥러닝 구조 만들기
Embedding(불러온 단어의 총 개수, 기사 당 단어 수)
LSTM(기사 당 단어 수, 활성화 함수)
model = Sequential()
model.add(Embedding(1000, 100))
model.add(LSTM(100, activation = 'tanh'))
model.add(Dense(46, activation = 'softmax'))
학습 실행: 모델의 실행 옵션 설정, 조기 중단 설정 EarlyStopping()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
early_stopping_callback = EarlyStopping(monitor='val_loss', patience=5)
history = model.fit(X_train, y_train, batch_size = 20, epochs=200, validation_data = (X_test, y_test), callbacks=[early_stopping_callback])

IMDB: 영화와 관련된 정보, 출연진 정보, 개봉 정보, 영화 후기, 평점 등을 남기는 사이트
load_data()를 이용해 테스트셋 지정: num_words=5000로 설정
sequence.pad_sequence()함수를 이용해 패딩: max_len = 500으로 설정
model.Sequential()
model.add(Embedding(5000, 100))
model.add(Dropout(0.5))
model.add(Conv1D(64, 5, padding='valid', activation='relu', strides=1)
model.add(MaxPooling1D(pool_size=4))
model.add(LTSM(55))
model.add(Dense(1))
model.add(Activation('sigmoid')
model.summary() # 현재 설정된 모델의 구조 출력

앞서 이미지에 적용할 때에는 이미지가 2차원 데이터이므로 Conv, MaxPooling을 2D로 적용한 반면, 여기에서는 텍스트 데이터이므로 1D로 적용하기
Conv1D

MaxPooling1D



5th epoch에서 테스트셋 정확도 87.96%로 학습 자동 중단
2020년 12월, 제 14대 세계 단백질 구조 예측 대회 도중 압도적인 정확성으로 단백칠 코드를 예측함
제작자: 구글의 딥마인드 (알파고 제작자)
주요 알고리즘: 어텐션


인코더와 디코더 사이에 층을 하나 만듦
➡️ 새로 삽입된 층에는 어텐션 스코어(각 셀로부터 계산된 스코어들)가 모임
➡️ 어텐션 스코어에 소프트맥스 함수를 적용해 어텐션 가중치 만들기
➡️ 어텐션 가중치를 이용해 입력값 중 어떤 셀을 중점적으로 볼 지를 판단
예: 첫번째 출력 단어인 '당신께'에 대응하는 단어는 'you'임을 학습
➡️ 매 출력마다 모든 입력값을 두루 활용하게 함
➡️ 마지막 셀에 모든 입력이 집중되던 RNN의 단점 극복
!pip install attention
# 앞서 작성한 모델 구조에 attention 추가
model.Sequential()
model.add(Embedding(5000, 500))
model.add(Dropout(0.5))
model.add(LTSM(64, return_sequences=True))
model.add(Attention())
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid')


정확도: (어텐션 X) 84.54% ➡️ (어텐션 O) 88.08%
seq2seq 구조의 한계점
• Decoder가 단어를 예측할 때, encoder의 마지막 시점 은닉층 정보(contect vector, C)만을 활용
➡️ 각 단어 예측 시 더 중요하게 집중해야 하는 encoder 부분 단어가 다른데, 이를 반영할 수 없음


