728x90
반응형
네이버 영화 리뷰 데이터
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import tensorflow as tf
train_file = tf.keras.utils.get_file('ratings_train.txt', \
origin='https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt',\
extract=True)
Downloading data from https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt
14630912/14628807 [==============================] - 0s 0us/step
train = pd.read_csv(train_file, sep='\t')
train.head()
print("train shape:", train.shape)
# train shape: (150000, 3)
레이블별 갯수 출력하기
train['label'].value_counts()
sns.countplot(x='label', data=train)
결측값
train.isnull().sum()
train[train['document'].isnull()]
# 결측값 제거
train = train.dropna()
print("train shape:",train.shape)
# train shape: (149995, 3)
레이블 별 글자수의 분포를 히스토그램으로 출력
# 레이블 별 글자수의 분포를 히스토그램으로 출력
# 긍정의 글자수
postive_len = train[train['label']==1]['document'].str.len()
# 부정의 글자수
negative_len = train[train['label']==0]['document'].str.len()
postive_len.iloc[:10]
1 33 4 61 8 22 9 45 10 16 11 43 13 51 15 16 16 64 18 45 Name: document, dtype: int64
fig, (ax1, ax2) = plt.subplots(1,2,figsize=(10,5))
ax1.hist(postive_len)
ax1.set_title("positive")
ax2.hist(negative_len)
ax2.set_title("negative")
fig.suptitle("Number of characters")
plt.show()
형태소 분석하기
text = '한글 자연어 처리는 재밌다. 이제부터 열심히 해야지ㅎㅎㅎㅎ'
okt.morphs(text)
# 형태소 분리
okt.morphs(text, stem=True)
# 행태소로 분리, 어간 추출
okt.nouns(text)
# 명사만 추출
okt.phrases(text)
# 어절까지추출
okt.pos(text)
# 품살르 붙여서 형태소 분석
[('한글', 'Noun'), ('자연어', 'Noun'), ('처리', 'Noun'), ('는', 'Josa'), ('재밌다', 'Adjective'), ('.', 'Punctuation'), ('이제', 'Noun'), ('부터', 'Josa'), ('열심히', 'Adverb'), ('해야지', 'Verb'), ('ㅎㅎㅎㅎ', 'KoreanParticle')]
# 데이터 전처리
# 텍스트의 내용 중 한글, 영문, 공백을 제외한 다른 문자들은 제거
train['document'] = \ train['document'].str.replace("[^A-Za-z가-힣ㄱ-ㅎㅏ-ㅣ]","")
train['document'].head()
0 아더빙진짜짜증나네요목소리
1 흠포스터보고초딩영화줄오버연기조차가볍지않구나
2 너무재밓었다그래서보는것을추천한다
3 교도소이야기구먼솔직히재미는없다평점조정
4 사이몬페그의익살스런연기가돋보였던영화스파이더맨에서늙어보이기만했던커스틴던스트가너무나도이...
Name: document, dtype: object
형태소 분석. stopword 제거 후 형태소 분석하기
def word_tokenization(text) :
# 한글 불용어
stop_words = ['는','을','를','이','가','의','던','고','하','다','은','에','들','지','게','도']
return [word for word in okt.morphs(text) if word not in stop_words]
start = time.time()
data = train['document'].apply((lambda x : word_tokenization(x)))
print("실행시간 :", time.time()-start)
data.head()
실행시간 : 1631.960827589035
0 [아더, 빙, 진짜, 짜증나네요, 목소리]
1 [흠, 포스터, 보고, 초딩, 영화, 줄, 오버, 연기, 조차, 가볍지, 않구나]
2 [너, 무재, 밓었, 다그, 래서, 보는것을, 추천, 한]
3 [교도소, 이야기, 구먼, 솔직히, 재미, 없다, 평점, 조정]
4 [사이, 몬페, 그, 익살스런, 연기, 돋보였던, 영화, 스파이더맨, 에서, 늙어,...
Name: document, dtype: object
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence
import pad_sequences
tokenizer = Tokenizer() tokenizer.fit_on_texts(data)
print("총 단어 갯수:", len(tokenizer.word_index))
# 총 단어 갯수: 122402
5회 이상만 vocab_size 에 포함
def get_vocab_size(threshold) :
cnt = 0
for x in tokenizer.word_counts.values() :
if x >=threshold :
cnt += 1
return cnt
vocab_size = get_vocab_size(5)
# 5회 이상 출현단어
print("vocab_size:",vocab_size)
# vocab_size: 23384
훈련 데이터 검증데이터 분리
training_size = 120000
#train 분할
train_sentences = data[:training_size]
valid_sentences = data[training_size:]
# label 분할
train_labels = train['label'][:training_size]
valid_labels = train['label'][training_size:]
print(train_sentences.shape)
print(valid_sentences.shape)
(120000,)
(29995,)
토큰화하기
oov_tok = "<OOV>"
vovab_size = 15000
tokenizer = Tokenizer(oov_token = oov_tok, num_words=vocab_size)
tokenizer.fit_on_texts(data) print("단어사전개수:",len(tokenizer.word_counts))
# 단어사전개수: 122402
문자를 숫자로 표현
print(train_sentences[:2])
train_sequences = tokenizer.texts_to_sequences(train_sentences)
valid_sequences = tokenizer.texts_to_sequences(valid_sentences)
print(train_sequences[:2]) print(valid_sequences[:2])
0 [아더, 빙, 진짜, 짜증나네요, 목소리]
1 [흠, 포스터, 보고, 초딩, 영화, 줄, 오버, 연기, 조차, 가볍지, 않구나]
Name: document, dtype: object
[[13657, 16287, 8, 6835, 615], [1005, 423, 33, 554, 2, 354, 1539, 20, 1044, 6416, 1]] [[277, 9, 299, 208, 3401, 23332, 860, 9, 908, 178, 11017, 877, 3, 156, 48], [381, 158, 2, 487, 193, 2437, 38, 57, 259, 10630, 1, 33, 13153, 2, 72]]
문자의 최대길이
max_length = max(len(x) for x in train_sequences)
print("문자 최대 길이:", max_length)
# 문자 최대 길이: 69
train_padded = pad_sequences(train_sequences, padding = 'post', maxlen=max_length)
valid_padded = pad_sequences(valid_sequences, padding = 'post', maxlen=max_length)
train_padded[:1]
array([[13657, 16287, 8, 6835, 615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
모델 구성하기
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, LSTM, Embedding, Bidirectional
def create_model() :
# bi 양방향 rnn
# return_sequences=True 상대값 전달
model = Sequential([ Embedding(vocab_size, 32),
Bidirectional(LSTM(32, return_sequences=True)),
Dense(32, activation='relu'),
Dense(1, activation='sigmoid') ])
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
model = create_model()
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, None, 32) 748288
_________________________________________________________________
bidirectional_1 (Bidirection (None, None, 64) 16640
_________________________________________________________________
dense_2 (Dense) (None, None, 32) 2080
_________________________________________________________________
dense_3 (Dense) (None, None, 1) 33
=================================================================
Total params: 767,041
Trainable params: 767,041
Non-trainable params: 0
_________________________________________________________________
딥러닝 모델의 구조가 복잡하고, 데이터 크기가 클수록 학습시간이 오래걸림.
=> 오랜시간 학습한 모델을 저장할 필요가 있음. modelcheckpoint 함수 이용
save_weights_only=True : weight 만저장
save_weights_only=False : 모델 레이터와 weight 모두 저장
save_best_only = True : 좋은 가중치만 저장
save_best_only = False : 모든 가중치 저장
checkpoint_path = 'best_performed_model.ckpt'
checkpoint = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
save_weights_only=True,
save_best_only = True,
monitor = 'val_loss', verbose=1)
earlystopping 함수 : 모델의 성능이 개선되지 않을 경우 학습을 중단
monitor = 'val_loss' : 성능평가 기준
patience=2 : 2 epochs 까지 개선되지 않으면 중지
call back : 함수에서 호출되는 함수
early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss',patience=2)
학습하기
history = model.fit(train_padded, train_labels, validation_data=(valid_padded, valid_labels),
callbacks=[early_stop, checkpoint],
batch_size=64, epochs=10, verbose=2)
Epoch 1/10
1875/1875 - 31s - loss: 0.4138 - accuracy: 0.8022 - val_loss: 0.3530 - val_accuracy: 0.8437
Epoch 00001: val_loss improved from inf to 0.35297, saving model to best_performed_model.ckpt
Epoch 2/10
1875/1875 - 24s - loss: 0.3111 - accuracy: 0.8652 - val_loss: 0.3561 - val_accuracy: 0.8424
Epoch 00002: val_loss did not improve from 0.35297
Epoch 3/10
1875/1875 - 24s - loss: 0.2710 - accuracy: 0.8824 - val_loss: 0.3645 - val_accuracy: 0.8445
Epoch 00003: val_loss did not improve from 0.35297
def plot_graphs(history, metric) :
plt.plot(history.history[metric])
plt.plot(history.history['val_'+metric], '')
plt.xlabel('Epochs')
plt.ylabel(metric)
plt.legend([metric, 'val_'+metric])
plt.show()
plot_graphs(history, 'accuracy')
plot_graphs(history, 'loss')
반응형
'Data_Science > Data_Analysis_Py' 카테고리의 다른 글
62. Tokenizer (0) | 2021.12.07 |
---|---|
60. LSTM 기본 (0) | 2021.12.07 |
58. IMDB || SimpleRNN (0) | 2021.12.07 |
57. seed || simpleRNN (0) | 2021.12.07 |
56. 영화리뷰 분석 (0) | 2021.12.07 |