Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 제로베이스 데이터사이언스
- 아이펠
- AIFFEL
- Set
- 속성
- 추천시스템
- 데이터분석
- 제어문
- 클래스
- 머신러닝
- 딕셔너리
- NLP
- 후기
- 파이썬
- 파이썬코딩도장
- Python
- 스크랩
- 데이터사이언티스트
- 카카오
- 함수
- 자연어처리
- numpy
- 코딩도장
- 딥러닝
- 데이터사이언스 스쿨
- TensorFlow
- 기사
- AI
- 사이킷런
- 재귀함수
Archives
- Today
- Total
뮤트 개발일지
AIFFEL 아이펠 18일차 본문
영화리뷰 텍스트 감성분석하기
IMDB 영화리뷰 감성분석
# 인코딩 함수
def get_encoded_sentences(sentences, word_to_index):
return [get_encoded_sentence(sentence, word_to_index) for sentence in sentences]
encoded_sentences = get_encoded_sentences(sentences, word_to_index)
# decode 함수
def get_decoded_sentence(encoded_sentence, index_to_word):
return ' '.join(index_to_word[index] if index in index_to_word else '<UNK>' for index in encoded_sentence[1:]) #[1:]를 통해 <BOS>를 제외
print(get_decoded_sentence([1, 3, 4, 5], index_to_word))
데이터셋 분석
imdb = tf.keras.datasets.imdb
# IMDb 데이터셋 다운로드
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=10000)
print("훈련 샘플 개수: {}, 테스트 개수: {}".format(len(x_train), len(x_test)))
>>> 훈련 샘플 개수: 25000, 테스트 개수: 25000
# 이미 인코딩된 데이터를 받았음
# 데이터 확인
#실제 인코딩 인덱스는 제공된 word_to_index에서 index 기준으로 3씩 뒤로 밀려 있다
word_to_index = {k:(v+3) for k,v in word_to_index.items()}
# 처음 몇 개 인덱스는 사전에 정의되어 있음
word_to_index["<PAD>"] = 0
word_to_index["<BOS>"] = 1
word_to_index["<UNK>"] = 2 # unknown
word_to_index["<UNUSED>"] = 3
index_to_word = {index:word for word, index in word_to_index.items()}
print(index_to_word[1]) # '<BOS>' 출력
print(word_to_index['the']) # 4 출력
print(index_to_word[4]) # 'the' 출력
문장의 길이 통일해줘야 한다.
문장 최대 길이도 성능에 영향을 미치므로 적절한 길이를 찾아야 한다.
total_data_text = list(x_train) + list(x_test)
# 텍스트데이터 문장길이의 리스트를 생성한 후
num_tokens = [len(tokens) for tokens in total_data_text]
num_tokens = np.array(num_tokens)
# 문장길이의 평균값, 최대값, 표준편차를 계산해 본다.
print('문장길이 평균 : ', np.mean(num_tokens))
print('문장길이 최대 : ', np.max(num_tokens))
print('문장길이 표준편차 : ', np.std(num_tokens))
# 예를들어, 최대 길이를 (평균 + 2*표준편차)로 한다면,
max_tokens = np.mean(num_tokens) + 2 * np.std(num_tokens)
maxlen = int(max_tokens)
print('pad_sequences maxlen : ', maxlen)
print('전체 문장의 {}%가 maxlen 설정값 이내에 포함됩니다. '.format(np.sum(num_tokens < max_tokens) / len(num_tokens)))
문장 길이 pad 넣어서 통일 시켜주기
이 때, 패딩을 앞에 넣을 것인지 뒤에 넣을 것인지 정해야한다.
x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train,
value=word_to_index["<PAD>"],
padding='pre', # 혹은 'pre'
maxlen=maxlen)
x_test = tf.keras.preprocessing.sequence.pad_sequences(x_test,
value=word_to_index["<PAD>"],
padding='pre', # 혹은 'pre'
maxlen=maxlen)
* RNN은 입력데이터가 순차적으로 처리 되기 때문에 가장 마지막 입력이 최종 state값에 영향을 많이 미치게 된다. 그러므로 마지막 입력이 패딩으로 채워지는 것은 비효율적이다. 따라서 pre로 하는 것이 유리하다.
모델 설계
vocab_size = 10000 # 어휘 사전의 크기입니다(10,000개의 단어)
word_vector_dim = 16 # 워드 벡터의 차원 수 (변경 가능한 하이퍼파라미터)
# model 설계
model = tf.keras.Sequential()
model.add(tf.keras.layers.Embedding(vocab_size, word_vector_dim, input_shape=(None,)))
model.add(tf.keras.layers.LSTM(8)) # 가장 널리 쓰이는 RNN인 LSTM 레이어를 사용하였습니다. 이때 LSTM state 벡터의 차원수는 8로 하였습니다. (변경 가능)
model.add(tf.keras.layers.Dense(8, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid')) # 최종 출력은 긍정/부정을 나타내는 1dim 입니다.
model.summary()
# 학습데이터와 검증데이터 분리
# validation set 10000건 분리
x_val = x_train[:10000]
y_val = y_train[:10000]
# validation set을 제외한 나머지 15000건
partial_x_train = x_train[10000:]
partial_y_train = y_train[10000:]
# 데이터 학습
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
epochs=5
history = model.fit(partial_x_train,
partial_y_train,
epochs=epochs,
batch_size=512,
validation_data=(x_val, y_val),
verbose=1)
# 테스트 셋으로 평가
results = model.evaluate(x_test, y_test, verbose=2)
model.fit() 과정 중에 train/validation loss, accuracy 등이 매 epoch마다 history 변수에 저장되어 있다.
이를 통해 적절한 epoch를 찾을 수 있다. (다른 여러가지 아이디어도 얻을 수 있음)
history_dict = history.history
print(history_dict.keys()) # epoch에 따른 그래프를 그려볼 수 있는 항목들
>>> dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])
import matplotlib.pyplot as plt
acc = history_dict['accuracy']
val_acc = history_dict['val_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']
epochs = range(1, len(acc) + 1)
# "bo"는 "파란색 점"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b는 "파란 실선"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
plt.clf() # 그림 초기화
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
Word2Vec 사용
from gensim.models import KeyedVectors
word2vec_path = os.getenv('HOME')+'/aiffel/sentiment_classification/data/GoogleNews-vectors-negative300.bin.gz'
word2vec = KeyedVectors.load_word2vec_format(word2vec_path, binary=True, limit=1000000)
vector = word2vec['computer']
vector # 300dim의 워드 벡터
# 유사한 단어 추출
word2vec.similar_by_word("love")
word2vec 으로 교체하여 학습 진행
vocab_size = 10000 # 어휘 사전의 크기입니다(10,000개의 단어)
word_vector_dim = 300 # 워드 벡터의 차원수
embedding_matrix = np.random.rand(vocab_size, word_vector_dim)
# embedding_matrix에 Word2Vec 워드 벡터를 단어 하나씩마다 차례차례 카피한다.
for i in range(4,vocab_size):
if index_to_word[i] in word2vec:
embedding_matrix[i] = word2vec[index_to_word[i]]
from tensorflow.keras.initializers import Constant
vocab_size = 10000 # 어휘 사전의 크기입니다(10,000개의 단어)
word_vector_dim = 300 # 워드 벡터의 차원 수
# 모델 구성
model = tf.keras.Sequential()
model.add(tf.keras.layers.Embedding(vocab_size,
word_vector_dim,
embeddings_initializer=Constant(embedding_matrix), # 카피한 임베딩을 여기서 활용
input_length=maxlen,
trainable=True)) # trainable을 True로 주면 Fine-tuning
model.add(tf.keras.layers.Conv1D(16, 7, activation='relu'))
model.add(tf.keras.layers.MaxPooling1D(5))
model.add(tf.keras.layers.Conv1D(16, 7, activation='relu'))
model.add(tf.keras.layers.GlobalMaxPooling1D())
model.add(tf.keras.layers.Dense(8, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.summary()
# 학습의 진행
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
epochs=5 # 몇 epoch를 훈련하면 좋을지 결과를 보면서 바꾸어 봅시다.
history = model.fit(partial_x_train,
partial_y_train,
epochs=epochs,
batch_size=512,
validation_data=(x_val, y_val),
verbose=1)
# 테스트셋을 통한 모델 평가
results = model.evaluate(x_test, y_test, verbose=2)
print(results)
네이버 영화 리뷰로 감성분석하기
https://github.com/pjk7565/AIFFEL/blob/main/Exploration06/moviereview.ipynb
GitHub - pjk7565/AIFFEL
Contribute to pjk7565/AIFFEL development by creating an account on GitHub.
github.com
'AIFFEL' 카테고리의 다른 글
AIFFEL 아이펠 20일차 (0) | 2022.01.25 |
---|---|
AIFFEL 아이펠 19일차 (0) | 2022.01.25 |
AIFFEL 아이펠 17일차 (0) | 2022.01.25 |
AIFFEL 아이펠 16일차 (0) | 2022.01.25 |
AIFFEL 아이펠 15일차 (0) | 2022.01.24 |