Eggs Sunny Side Up
본문 바로가기
Computer Engineering/딥러닝

로이터뉴스_제목분류하기

by guswn100059 2023. 7. 10.
# 문자를 인코딩할 때 원핫인코딩 or 단순 수치화
# 수치화, 토큰화가 진행되어 있는 데이터셋
# 뉴스 기사마다 길이가 다름
# 빈도수를 기반으로 수치화 진행 > 숫자가 작을수록 자주 등장한 단어
X_train

# 단어사전 확인
# '단어' : 숫자
reuters.get_word_index()
print(len(reuters.get_word_index()))

# y_train
# 답의 정리 상태
# 분류 개수가 몇개인지?(클래스의 개수가 몇개인지?)
# np.unique()
print('클래스의 개수', np.unique(y_train).size)

np.unique(y_train, return_counts = True)

### 전처리
- 다중분류 답데이터 정리 : 원핫인코딩
- 문장의 길이 정리 : 모든 문장의 길이를 통일
- 문장 크기 변형

# 답데이터 정리
# 원핫인코딩
# pandas -> pd.get_dummies()
# tensorflow -> from tensorflow.keras.utils import to_categorical -> to_categorical()
y_train_oh = pd.get_dummies(y_train)
y_test_oh = pd.get_dummies(y_test)

y_train_oh.shape, y_test_oh.shape

# 문제 데이터 정리(문장 정리)
# 1. 모델은 데이터의 크기가 일관성이 있게 받음
# 2. 길이가 긴 뉴스기사는 단어를 잘라서 문장의 길이를 축소
# 3. 길이가 짧은 뉴스기사는 패딩작업(0 채움)을 통한 길이 확장

# 적절한 문장의 길이 찾기
# 모든 문장의 길이를 담은 리스트 변수 생성해보기
X_train[0]
len(X_train[0]) # 0번째 기사는 길이 : 87, 1번째 : 56
len(X_train[1]) # 1번째 기사는 길이 : 56

train_len = []
for i in range(X_train.size):
  train_len.append(len(X_train[i]))

print(train_len[1])

print('최대값 : ', max(train_len))
print('최소값 : ', min(train_len))
print('평균값 : ', np.mean(train_len))
print('중앙값 : ', np.median(train_len))

# 평균값, 중앙값 길이차이가 있으니 이 값들의 중간 정도로 길이를 설정해보자

# 길이에 해당하는 뉴스 기사 개수 파악 시각화
# 데이터 밀도 확인 -> 히스토그램
# x축 뉴스 길이 구간별 표시
# y축 뉴스기사 개수
plt.hist(train_len, bins=20)
plt.xlabel('news_len') # 뉴스 길이
plt.ylabel('news_cnt') # 해당 길이에 대한 뉴스 개수
plt.ylim(0, 300) # y축 범위 제한
plt.show()

# 모든 뉴스 기사의 문장 길이를 120으로 맞추기
from tensorflow.keras.preprocessing import sequence

# 길이가 길다면 축소, 길이가 짧다면 확장
X_train_seq = sequence.pad_sequences(X_train, maxlen=120)
X_test_seq = sequence.pad_sequences(X_test, maxlen=120)

# 크기 확인(뉴스개수, 열(단어)의 개수)
X_train_seq.shape, X_test_seq.shape

len(X_train_seq[0])

X_train_seq[0] # 부족한 데이터의 개수만큼 0으로 채우는 패딩작업 진행

# rnn에 사용하기 위해서 차원을 늘려줌
# 1차원 -> 2차원 (행 120, 열 1)
X_train_seq_reshape = X_train_seq.reshape(8982, 120, 1)

# test 변형
X_test_seq_reshape = X_test_seq.reshape(2246, 120, 1)

# 크기 확인
X_train_seq_reshape.shape, X_test_seq_reshape.shape

X_train_seq_reshape[0]

### 모델링

from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, SimpleRNN
# cnn -> 이미지 중요한 부분 추출
# rnn -> 시간 순서에 따라 들어오는 데이터에 대한 기억을 하는 기능(순환)

# 1. SimpleRNN 한층
srnn_model = Sequential()

# input_shape = (timesteps, features)
srnn_model.add(SimpleRNN(128, input_shape=(120, 1))) # 기본값 activation='tanh'

# 중간층(units=64)
srnn_model.add(Dense(64, activation='relu'))

# 출력층(다중분류, 유닛:클래스의 개수(답데이터-주제), 활성화함수)
srnn_model.add(Dense(46, activation='softmax'))

srnn_model.summary()

# 다중분류 컴파일 설정
srnn_model.compile(loss='categorical_crossentropy',
                optimizer = 'Adam',
                metrics=['accuracy'])

# 학습(문제, 답, 반복횟수 20)
srnn1_h = srnn_model.fit(X_train_seq_reshape, y_train_oh, epochs=20)

# 2. SimpleRNN 층 추가
srnn_model2 = Sequential()

# input_shape = (timesteps, features)
srnn_model2.add(SimpleRNN(128, input_shape=(120, 1), return_sequences=True)) # 기본값 activation='tanh'
srnn_model2.add(SimpleRNN(64, return_sequences=True))
srnn_model2.add(SimpleRNN(64))

# 중간층(units=64)
srnn_model2.add(Dense(64, activation='relu'))

# 출력층(다중분류, 유닛:클래스의 개수(답데이터-주제), 활성화함수)
srnn_model2.add(Dense(46, activation='softmax'))

srnn_model2.summary()

# 다중분류 컴파일 설정
srnn_model2.compile(loss='categorical_crossentropy',
                optimizer = 'Adam',
                metrics=['accuracy'])

# 학습(문제, 답, 반복횟수 20)
srnn2_h = srnn_model2.fit(X_train_seq_reshape, y_train_oh, epochs=20)

### 3. LSTM 모델 사용하기(장단기 기억 메모리 모델)
- 시퀀스 길이가 길어질수록 기억값이 감소되는 RNN과는 달리 기억을 메모리에 관리함으로써 중요한 기억은 강조하고, 불필요한 기억은 삭제하는 모델
- forget gate, input_gate, output_gate

### 워드 임베딩(Word Embedding)
- 밀집표현 : 사용자가 설정한 값으로 모든 단어의 벡터 표현의 차원을 맞춤
  - 사용자가 밀집 표현의 차원을 128로 설정한다면, 모든 단어의 벡터 표현의 차원은 128로 바뀌면서 모든 값이 실수로 변환
- 한 단어의 의미를 풍부하게 하는 효과
- 자연어를 컴퓨터가 이해하고, 효율적으로 처리할 수 있게 하는 방법
- 원핫 인코딩(원핫 벡터)를 사용하는 것보다 밀집벡터가 저차원에 속함 -> 메모리 소모 적음

from tensorflow.keras.layers import LSTM, Embedding

lstm_model = Sequential()
# 데이터 처리, 워드 임베딩 - 입력층 부분에 연결
# input_dim : 데이터 내에서 사용할 단어의 최대 개수 (사용할 단어의 수)
# output_dim : 임베딩 층을 통과한 후 생성된 실수의 개수(임베딩층의 차원의 수)
# 뉴스 기사를 적을 때 사용되는 일반적인 단어의 수 : 1000
lstm_model.add(Embedding(input_dim=1000 , output_dim=50))
lstm_model.add(LSTM(128)) # 순환신경망 LSTM 1층

# 중간층
lstm_model.add(Dense(64, activation='relu'))

# 출력층
lstm_model.add(Dense(46, activation='softmax'))

lstm_model.summary()

# 학습/평가 방법 설정
lstm_model.compile(loss='categorical_crossentropy',
                   optimizer='adam',
                   metrics=['accuracy'])

# 학습
lstm_h = lstm_model.fit(X_train_seq_reshape, y_train_oh, epochs=20)

import tensorflow as tf
tf.__version__

# 시각화
# srnn1_h, srnn2_h, lstm_h - acc 시각화해서 비교
plt.figure(figsize=(10,3))
plt.plot(srnn1_h.history['accuracy'], label='srnn1')
plt.plot(srnn2_h.history['accuracy'], label='srnn2')
plt.plot(lstm_h.history['accuracy'], label='lstm')
plt.legend() # 범례표시
plt.show()

# 자연어 처리 분야 모델 학습은 아직도 많은 연구와 노력이 필요
# 현재 우리 모델도 일반화를 찾아가려면 데이터 처리, 모델에 설정값을 더 잘 표현해줘야함
# 워드임베딩 방식 - 자연어 처리 방식
# SimpleRNN, RNN 여러 층, LSTM(장단기 기억 메모리 모델) 연결

'Computer Engineering > 딥러닝' 카테고리의 다른 글

RNN_HELLO학습  (0) 2023.07.10
yolov8_chinchilla_detect  (0) 2023.07.07
yolov6_chinchilla_detect  (0) 2023.07.07
mlp, cnn_개, 고양이_이미지데이터 _분류  (0) 2023.07.06
OpenCV04_픽셀 및 채널  (0) 2023.07.06

댓글