1. Simple RNN
1.1 순환 신경망
- 순서가 있는 데이터를 입력으로 받고 변화하는 입력에 대한 출력을 얻음
1.2 RNN의 한 셀 모양
2. RNN 실습
2.1 간단한 Time Stamp 데이터로 RNN 실습
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import tensorflow as tf
import numpy as np
X = []
Y = []
for i in range(6):
lst = list(range(i, i+4))
X.append(list(map(lambda c : [c/10], lst)))
Y.append((i +4)/10)
X = np.array(X)
Y = np.array(Y)
for i in range(len(X)):
print(X[i], Y[i])
print()
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
[[0. ]
[0.1]
[0.2]
[0.3]] 0.4
[[0.1]
[0.2]
[0.3]
[0.4]] 0.5
[[0.2]
[0.3]
[0.4]
[0.5]] 0.6
[[0.3]
[0.4]
[0.5]
[0.6]] 0.7
[[0.4]
[0.5]
[0.6]
[0.7]] 0.8
[[0.5]
[0.6]
[0.7]
[0.8]] 0.9
- 0.0 ~ 0.3 -> 0.4
- 0.1 ~ 0.4 -> 0.5
- 이런식의 데이터
2.2 Simple RNN 구성
1
2
3
4
5
6
7
8
model = tf.keras.Sequential([
tf.keras.layers.SimpleRNN(
units=10, return_sequences=False, input_shape=[4, 1]),
tf.keras.layers.Dense(1)
])
model.compile(optimizer = 'adam', loss = 'mse')
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
simple_rnn (SimpleRNN) (None, 10) 120
_________________________________________________________________
dense (Dense) (None, 1) 11
=================================================================
Total params: 131
Trainable params: 131
Non-trainable params: 0
_________________________________________________________________
- input_shape이 4.1 이라는것은 timesteps가 4, input_dim이 1
- units : SimpleRNN 레이어에 존재하는 뉴런의 수
- return_sequences : 출력으로 시퀀스 전체를 출력할지 여부
2.3 모델의 구성도
2.4 학습
1
model.fit(X, Y, epochs=100, verbose=0)
1
<tensorflow.python.keras.callbacks.History at 0x7fd850d79d90>
2.5 예측
1
model.predict(np.array([[[-0.1],[0.0],[0.1],[0.2]]]))
1
array([[0.29263034]], dtype=float32)
- -0.1 ~ 0.2 다음은 0.3이 나와야하는데 0.2926이 나오는것 보니, 비슷은 해보인다
2.6 Simple RNN의 단점
- Long-Term Dependency : 입력 데이터가 길어지면 학습 능력이떨어짐
- 현재의 답을 얻기 위해 과거의 정보에 의존해야하는 RNN, 하지만 과거 시점이 현재와 너무 멀어지면 문제를 풀기 어려움
3. LSTM
3.1 LSTM
- Simple RNN의 장기 의존성 문제를 해결하기 위한 알고리즘
- Time Step을 가르지르며 셀 상태가 보존
4. LSTM 실습
4.1 예제
1
2
3
4
5
6
7
8
9
10
11
12
X = []
Y = []
for i in range(1000):
lst = np.random.rand(100)
idx = np.random.choice(100, 2, replace = False)
zeros = np.zeros(100)
zeros[idx] = 1
X.append(np.array(list(zip(zeros, lst))))
Y.append(np.prod(lst[idx]))
print(X[0], Y[0])
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
[[0. 0.80008966]
[0. 0.30359938]
[0. 0.87163122]
[0. 0.7413119 ]
[0. 0.11942425]
[0. 0.27352657]
[0. 0.76802368]
[0. 0.14609984]
[0. 0.18106652]
[0. 0.01171455]
[0. 0.92461019]
[0. 0.27576429]
[0. 0.8144809 ]
[0. 0.15831039]
[0. 0.03956734]
[0. 0.74086254]
[0. 0.71514832]
[0. 0.05864715]
[0. 0.2165122 ]
[0. 0.67536621]
[0. 0.83084592]
[0. 0.02361978]
[0. 0.96610312]
[0. 0.65990591]
[0. 0.97501121]
[0. 0.56664119]
[0. 0.98403786]
[0. 0.61782982]
[0. 0.98569084]
[0. 0.93561593]
[0. 0.06791456]
[0. 0.54954407]
[0. 0.49462747]
[0. 0.74715515]
[0. 0.31521783]
[0. 0.72605368]
[0. 0.62690249]
[0. 0.31447398]
[0. 0.15953186]
[0. 0.12764518]
[0. 0.07478073]
[0. 0.00354316]
[0. 0.28523369]
[0. 0.06752979]
[0. 0.83515363]
[0. 0.85055375]
[1. 0.88817727]
[0. 0.00453563]
[0. 0.30259626]
[0. 0.93822272]
[0. 0.10927959]
[0. 0.92989588]
[0. 0.47279259]
[0. 0.40970746]
[0. 0.32246528]
[0. 0.73999216]
[0. 0.62096274]
[0. 0.48123822]
[0. 0.78971826]
[0. 0.89842873]
[0. 0.87298911]
[0. 0.55976035]
[0. 0.82265406]
[0. 0.11174719]
[0. 0.00784555]
[0. 0.6851193 ]
[0. 0.75893765]
[0. 0.50567489]
[0. 0.01901901]
[0. 0.7303575 ]
[0. 0.68753022]
[0. 0.45555408]
[0. 0.47891555]
[0. 0.73691181]
[0. 0.05961961]
[0. 0.94850333]
[0. 0.79596296]
[0. 0.86432501]
[0. 0.49509131]
[0. 0.1899921 ]
[0. 0.25937904]
[0. 0.52905918]
[0. 0.21323525]
[0. 0.41142003]
[0. 0.15834983]
[0. 0.52050195]
[0. 0.13767634]
[0. 0.67453866]
[0. 0.54832447]
[0. 0.4106969 ]
[0. 0.57071902]
[0. 0.54413813]
[0. 0.16043092]
[1. 0.37390211]
[0. 0.6987448 ]
[0. 0.31205635]
[0. 0.0487809 ]
[0. 0.14050364]
[0. 0.69102483]
[0. 0.49156883]] 0.3320913581177933
- LSTM을 처음 제안한 논문에서 LSTM의 성능을 확인하기 위해서 제시한 문제
4.2 RNN으로
1
2
3
4
5
6
7
8
9
model = tf.keras.Sequential([
tf.keras.layers.SimpleRNN(
units=30, return_sequences=True, input_shape=[100, 2]),
tf.keras.layers.SimpleRNN(units=30),
tf.keras.layers.Dense(1)
])
model.compile(optimizer='adam', loss='mse')
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
simple_rnn_1 (SimpleRNN) (None, 100, 30) 990
_________________________________________________________________
simple_rnn_2 (SimpleRNN) (None, 30) 1830
_________________________________________________________________
dense_1 (Dense) (None, 1) 31
=================================================================
Total params: 2,851
Trainable params: 2,851
Non-trainable params: 0
_________________________________________________________________
- 일단 SimpleRNN으로 확인
4.3 SimpleRNN 훈련 후 그래프
1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib.pyplot as plt
X = np.array(X)
Y = np.array(Y)
history = model.fit(X[:2560], Y[:2560], epochs=100, validation_split=0.2)
plt.plot(history.history['loss'], 'b-', label = 'loss')
plt.plot(history.history['val_loss'], 'r--', label = 'val_loss')
plt.xlabel('Epoch')
plt.legend()
plt.show()
1
2
3
4
5
6
7
8
9
10
11
Epoch 1/100
25/25 [==============================] - 1s 27ms/step - loss: 0.0806 - val_loss: 0.0600
Epoch 2/100
25/25 [==============================] - 0s 20ms/step - loss: 0.0517 - val_loss: 0.0586
Epoch 3/100
25/25 [==============================] - 0s 19ms/step - loss: 0.0512 - val_loss: 0.0581
...
Epoch 99/100
25/25 [==============================] - 0s 20ms/step - loss: 0.0100 - val_loss: 0.0821
Epoch 100/100
25/25 [==============================] - 0s 19ms/step - loss: 0.0099 - val_loss: 0.0804
- Loss가 계속 벌어진다. 이것은 아까 이야기했던 Long-Term Dependency 때문임
4.4 LSTM
1
2
3
4
5
6
7
8
9
model = tf.keras.Sequential([
tf.keras.layers.LSTM(units=30, return_sequences=True,
input_shape=[100, 2]),
tf.keras.layers.LSTM(units=30),
tf.keras.layers.Dense(1)
])
model.compile(optimizer = 'adam', loss = 'mse')
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm (LSTM) (None, 100, 30) 3960
_________________________________________________________________
lstm_1 (LSTM) (None, 30) 7320
_________________________________________________________________
dense_2 (Dense) (None, 1) 31
=================================================================
Total params: 11,311
Trainable params: 11,311
Non-trainable params: 0
_________________________________________________________________
4.5 LSTM 훈련 후 그래프
1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
history = model.fit(X[:2560], Y[:2560], epochs=100, validation_split=0.2)
plt.plot(history.history['loss'], 'b-', label = 'loss')
plt.plot(history.history['val_loss'], 'r--', label = 'val_loss')
plt.xlabel('Epoch')
plt.legend()
plt.show()
1
2
3
4
5
6
7
8
9
Epoch 1/100
25/25 [==============================] - 1s 46ms/step - loss: 0.0620 - val_loss: 0.0558
Epoch 2/100
25/25 [==============================] - 1s 29ms/step - loss: 0.0507 - val_loss: 0.0539
Epoch 3/100
25/25 [==============================] - 1s 29ms/step - loss: 0.0508 - val_loss: 0.0543
...
Epoch 100/100
25/25 [==============================] - 1s 29ms/step - loss: 0.0510 - val_loss: 0.0543
- SimpleRNN과는 다르게 Loss와 Val Loss가 같이 떨어진다.
5. GRU 레이어 (Gated Recurrent Unit)
5.1 GRU의 셀 구조
- LSTM에 비해 연산량이 작고, 성능이 어떤 경우는 괜찮은것으로 나타난다.
5.2 GRU 생성
1
2
3
4
5
6
7
8
mdoel = tf.keras.Sequential([
tf.keras.layers.GRU(units=30, return_sequences=True, input_shape=[100, 2]),
tf.keras.layers.GRU(units=30),
tf.keras.layers.Dense(1)
])
model.compile(optimizer = 'adam', loss = 'mse')
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm (LSTM) (None, 100, 30) 3960
_________________________________________________________________
lstm_1 (LSTM) (None, 30) 7320
_________________________________________________________________
dense_2 (Dense) (None, 1) 31
=================================================================
Total params: 11,311
Trainable params: 11,311
Non-trainable params: 0
_________________________________________________________________
5.3 GRU 훈련 후 그래프 그리기
1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
history = model.fit(X[:2560], Y[:2560], epochs=100, validation_split=0.2)
plt.plot(history.history['loss'], 'b-', label = 'loss')
plt.plot(history.history['val_loss'], 'r--', label = 'val_loss')
plt.xlabel('Epoch')
plt.legend()
plt.show()
1
2
3
4
5
6
7
8
Epoch 1/100
25/25 [==============================] - 1s 52ms/step - loss: 0.0506 - val_loss: 0.0550
Epoch 2/100
25/25 [==============================] - 1s 29ms/step - loss: 0.0497 - val_loss: 0.0555
Epoch 3/100
...
Epoch 100/100
25/25 [==============================] - 1s 30ms/step - loss: 6.9079e-04 - val_loss: 9.3052e-04
- 이것도 마찬가지로 Loss와 Val Loss가 엄청 잘 떨어진다.
6. 감성 분석 실습
6.1 감성분석
- 입력된 자연어 안의 주관적 의견, 감정등을 찾아내는 문제
- 문장의 긍정/부정 등을 구분하는 경우가 많음
6.2 Data Load
1
2
3
4
import tensorflow as tf
path_to_train_file = tf.keras.utils.get_file('train_txt', 'https://raw.githubusercontent.com/hmkim312/datas/main/navermoviereview/ratings_train.txt')
path_to_test_file = tf.keras.utils.get_file('test_txt', 'https://raw.githubusercontent.com/hmkim312/datas/main/navermoviereview/ratings_test.txt')
1
2
3
4
Downloading data from https://raw.githubusercontent.com/hmkim312/datas/main/navermoviereview/ratings_train.txt
14630912/14628807 [==============================] - 4s 0us/step
Downloading data from https://raw.githubusercontent.com/hmkim312/datas/main/navermoviereview/ratings_test.txt
4898816/4893335 [==============================] - 2s 0us/step
1
2
3
4
5
6
7
train_text = open(path_to_train_file, 'rb').read().decode(encoding='utf-8')
test_text = open(path_to_test_file, 'rb').read().decode(encoding='utf-8')
print(f'Length of text : {len(train_text)} characters')
print(f'Length of text : {len(test_text)} characters')
print()
print(train_text[:100])
1
2
3
4
5
6
7
Length of text : 6937271 characters
Length of text : 2318260 characters
id document label
9976970 아 더빙.. 진짜 짜증나네요 목소리 0
3819312 흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나 1
10265843
- 일전에 사용했던 영화 리뷰 감성분석 https://hmkim312.github.io/posts/네이버영화평점을_이용한_감정분석/
- id: 리뷰한 관객의 id 고유값
- document: 실제 리뷰
- label: 감정 (0: 부정, 1: 긍정)
- 총 200K의 감정분석(20만)
- ratings_test.txt: 5만개의 테스트용 리뷰
- ratings_train.txt: 15만개의 훈련용 리뷰
- 모든 리뷰는 140자 미만
- 100k(10만) 부정 리뷰 (평점이 0점 ~ 4점)
- 100K(10만) 긍정 리뷰 (평점이 9점 ~ 10점)
- 평점이 5점 ~ 8점은 중립리뷰점수로 로 제외시킴
6.3 데이터가 깨끗하지 않음
1
train_text[:300]
1
'id\tdocument\tlabel\n9976970\t아 더빙.. 진짜 짜증나네요 목소리\t0\n3819312\t흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나\t1\n10265843\t너무재밓었다그래서보는것을추천한다\t0\n9045019\t교도소 이야기구먼 ..솔직히 재미는 없다..평점 조정\t0\n6483659\t사이몬페그의 익살스런 연기가 돋보였던 영화!스파이더맨에서 늙어보이기만 했던 커스틴 던스트가 너무나도 이뻐보였다\t1\n5403919\t막 걸음마 뗀 3세부터 초등학교 1학년생인 8살용영화.ㅋㅋㅋ...별반개도 아까움.\t0\n7797314\t원작의'
6.4 데이터 전처리
1
train_text.split('\n')
1
2
3
4
5
6
7
['id\tdocument\tlabel',
'9976970\t아 더빙.. 진짜 짜증나네요 목소리\t0',
'3819312\t흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나\t1',
'10265843\t너무재밓었다그래서보는것을추천한다\t0',
'9045019\t교도소 이야기구먼 ..솔직히 재미는 없다..평점 조정\t0',
'6483659\t사이몬페그의 익살스런 연기가 돋보였던 영화!스파이더맨에서 늙어보이기만 했던 커스틴 던스트가 너무나도 이뻐보였다\t1',
...]
- split을 하여 리뷰별로 가져옴
1
train_text.split('\n')[3].split('\t')
1
['10265843', '너무재밓었다그래서보는것을추천한다', '0']
- 리뷰 한줄을 탭으로 split하면 id, review, target이 나옴
6.5 Target 데이터 정리
1
2
3
4
5
6
7
import numpy as np
train_Y = np.array([[int(row.split('\t')[2])] for row in train_text.split('\n')[1:] if row.count('\t') >0])
test_Y = np.array([[int(row.split('\t')[2])] for row in test_text.split('\n')[1:] if row.count('\t') >0])
print(train_Y.shape, test_Y.shape)
print(train_Y[:5])
1
2
3
4
5
6
(150000, 1) (50000, 1)
[[0]
[1]
[0]
[0]
[1]]
- 일단 타겟이 되는 0(부정), 1(긍정) 데이터를 따로 모아놨음
6.6 Tokenization, Cleaning
- Tokenization : 자연어 처리 가능한 최소의 단위로 나누는 것, 이번에는 띄어쓰기
- Cleaning : 불필요한 기호를 제거
6.7 Cleaning 함수 생성 및 데이터 전처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import re
def clean_str(string):
string = re.sub(r"[^가-힣A-Za-z0-9(),!?\'\`]", " ", string)
string = re.sub(r"\'s", " \'s", string)
string = re.sub(r"\'ve", " \'ve", string)
string = re.sub(r"n\'t", " n\'t", string)
string = re.sub(r"\'re", " \'re", string)
string = re.sub(r"\'d", " \'d", string)
string = re.sub(r"\'ll", " \'ll", string)
string = re.sub(r",", " , ", string)
string = re.sub(r"!", " ! ", string)
string = re.sub(r"\(", " \( ", string)
string = re.sub(r"\)", " \) ", string)
string = re.sub(r"\?", " \? ", string)
string = re.sub(r"\s{2,}", " ", string)
string = re.sub(r"\'{2,}", "\'", string)
string = re.sub(r"\'", "", string)
return string.lower()
- 불필요한 특수문자를 제거하는 함수 생성
1
2
3
4
5
train_text_X = [row.split('\t')[1] for row in train_text.split('\n')[1:] if row.count('\t') > 0]
train_text_X = [clean_str(sentence) for sentence in train_text_X]
sentences = [sentence.split(' ') for sentence in train_text_X]
for i in range(5):
print(sentences[i])
1
2
3
4
5
['아', '더빙', '진짜', '짜증나네요', '목소리']
['흠', '포스터보고', '초딩영화줄', '오버연기조차', '가볍지', '않구나']
['너무재밓었다그래서보는것을추천한다']
['교도소', '이야기구먼', '솔직히', '재미는', '없다', '평점', '조정']
['사이몬페그의', '익살스런', '연기가', '돋보였던', '영화', '!', '스파이더맨에서', '늙어보이기만', '했던', '커스틴', '던스트가', '너무나도', '이뻐보였다']
- train_text 리뷰에 ‘\t’가 있다면 split하는 코드
- 위에서 만든 clean_str을 적용하는 코드
- 공백(띄어쓰기)로 split하는 코드
6.8 리뷰의 길이
1
2
3
4
5
6
7
8
import matplotlib.pyplot as plt
sentence_len = [len(sentence) for sentence in sentences]
sentence_len.sort()
plt.plot(sentence_len)
plt.show()
print('리뷰의 길이가 25자 미만인것 : ', sum([int(l <= 25)for l in sentence_len]))
1
리뷰의 길이가 25자 미만인것 : 142587
- 학습을 위해 네트워크에 입력을 넣을땐 입력 데이터는 그 크기가 같아야함
- 입력 벡터의 크기를 맞추기위해 긴 문장을 줄이고, 짧은 문장은 공백으로 채우는 방법을 사용
- 15만개의 문장중에 대부분이 25단어 이하로 되어있음, 142587개
6.9 데이터 전처리 25개 단어까지 넣기
1
2
3
4
5
6
7
sentences_new = []
for sentence in sentences:
sentences_new.append([word[:5] for word in sentence][:25])
sentences = sentences_new
for i in range(5):
print(sentences_new[i])
1
2
3
4
5
['아', '더빙', '진짜', '짜증나네요', '목소리']
['흠', '포스터보고', '초딩영화줄', '오버연기조', '가볍지', '않구나']
['너무재밓었']
['교도소', '이야기구먼', '솔직히', '재미는', '없다', '평점', '조정']
['사이몬페그', '익살스런', '연기가', '돋보였던', '영화', '!', '스파이더맨', '늙어보이기', '했던', '커스틴', '던스트가', '너무나도', '이뻐보였다']
6.10 토크나이징과 패딩
1
2
3
4
5
6
7
8
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
tokenizer = Tokenizer(num_words=20000)
tokenizer.fit_on_texts(sentences)
train_X = tokenizer.texts_to_sequences(sentences)
train_X = pad_sequences(train_X, padding= 'post')
print(train_X[:3])
1
2
3
4
5
6
[[ 25 884 8 5795 1111 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0]
[ 588 5796 6697 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]]
6.11 모델 구성
1
2
3
4
5
6
7
8
model = tf.keras.Sequential([
tf.keras.layers.Embedding(20000, 300, input_length = 25),
tf.keras.layers.LSTM(units = 50),
tf.keras.layers.Dense(2, activation = 'softmax')
])
model.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy', metrics = ['accuracy'])
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Model: "sequential_4"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, 25, 300) 6000000
_________________________________________________________________
lstm_2 (LSTM) (None, 50) 70200
_________________________________________________________________
dense_4 (Dense) (None, 2) 102
=================================================================
Total params: 6,070,302
Trainable params: 6,070,302
Non-trainable params: 0
_________________________________________________________________
6.12 임베딩 레이어(Embedding Layer)
- 임베딩 레이어 : 자연어를 수치화된 정보로 바꾸기 위한 레이어
- 자연어는 시간의 흐름에 따라 정보가 연속적으로 이어지는 스퀀스 데이터
- 영어는 문자 단위, 한글은 문자를 넘어 자소 단위로도 쪼개기도 함, 혹은 형태소, 띄어쓰기로도 하기도함
- 여러 단어로 묶어서 사용하는 n-gram 방식도 있음
- 원핫인코딩까지 포함
6.13 학습
1
history = model.fit(train_X, train_Y, epochs=5, batch_size = 120, validation_split= 0.2)
1
2
3
4
5
6
7
8
9
10
Epoch 1/5
1000/1000 [==============================] - 50s 50ms/step - loss: 0.4301 - accuracy: 0.7884 - val_loss: 0.3805 - val_accuracy: 0.8224
Epoch 2/5
1000/1000 [==============================] - 51s 51ms/step - loss: 0.3263 - accuracy: 0.8467 - val_loss: 0.3903 - val_accuracy: 0.8211
Epoch 3/5
1000/1000 [==============================] - 47s 47ms/step - loss: 0.2766 - accuracy: 0.8662 - val_loss: 0.4175 - val_accuracy: 0.8196
Epoch 4/5
1000/1000 [==============================] - 47s 47ms/step - loss: 0.2357 - accuracy: 0.8836 - val_loss: 0.4570 - val_accuracy: 0.8113
Epoch 5/5
1000/1000 [==============================] - 47s 47ms/step - loss: 0.2016 - accuracy: 0.8990 - val_loss: 0.5628 - val_accuracy: 0.8102
6.14 테스트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
test_sentence = '재미있을 줄 알았는데 완전 실망했다. 너무 졸리고 돈이 아까웠다'
test_sentence = test_sentence.split(' ')
test_sentences =[]
now_sentence = []
for word in test_sentence:
now_sentence.append(word)
test_sentences.append(now_sentence[:])
test_X_1 = tokenizer.texts_to_sequences(test_sentences)
test_X_1 = pad_sequences(test_X_1, padding = 'post', maxlen=25)
prediction = model.predict(test_X_1)
for idx, sentence in enumerate(test_sentences):
print(sentence)
print(prediction[idx])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
['재미있을']
[0.33282876 0.66717124]
['재미있을', '줄']
[0.3296478 0.67035216]
['재미있을', '줄', '알았는데']
[0.41936734 0.5806327 ]
['재미있을', '줄', '알았는데', '완전']
[0.36908486 0.6309151 ]
['재미있을', '줄', '알았는데', '완전', '실망했다.']
[0.36908486 0.6309151 ]
['재미있을', '줄', '알았는데', '완전', '실망했다.', '너무']
[0.375071 0.624929]
['재미있을', '줄', '알았는데', '완전', '실망했다.', '너무', '졸리고']
[0.989423 0.01057698]
['재미있을', '줄', '알았는데', '완전', '실망했다.', '너무', '졸리고', '돈이']
[0.9979898 0.00201018]
['재미있을', '줄', '알았는데', '완전', '실망했다.', '너무', '졸리고', '돈이', '아까웠다']
[0.9983991 0.00160098]
- 처음에는
재미있을
이라는 단어 떄문에 긍정으로 판단되다가,졸리고
가 나오자 바로 부정으로 바뀌었다. - 앞에가 0(부정), 뒤에가 1(긍정)일 확률임
7. 요약
7.1 요약
- RNN의 종류와 이를 활용하여 감성분석을 진행했다.
- 솔직히 아직 공부가 부족해서 무슨 이야기인지 이해가 안가는 부분이 있음
- 딥러닝은 따로 인강을 들으며 더 공부를 해야겠다.