OneclickAI commited on
Commit
9a24bb1
ยท
verified ยท
1 Parent(s): 86fe4b3

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +332 -0
  2. config.json +24 -0
  3. test.py +77 -0
  4. train.py +73 -0
README.md ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ ---
4
+
5
+ ์•ˆ๋…•ํ•˜์„ธ์š” Oneclick AI ์ž…๋‹ˆ๋‹ค!!
6
+ ์˜ค๋Š˜์€, RNN(์ˆœํ™˜ ์‹ ๊ฒฝ๋ง, Recurrent Neural Network) ๋ชจ๋ธ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณผ๊นŒ ํ•ฉ๋‹ˆ๋‹ค.
7
+
8
+ ๋”ฅ๋Ÿฌ๋‹์ด ๋ฌธ์žฅ, ์Œ์„ฑ, ์ฃผ๊ฐ€ ์˜ˆ์ธก๊ณผ ๊ฐ™์€ ์ˆœ์„œ๊ฐ€ ์žˆ๋Š” ๋ฐ์ดํ„ฐ(Sequential Data)๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ๋œ ๊ฒƒ์€ ์ „์ ์œผ๋กœ RNN ๋•๋ถ„์ž…๋‹ˆ๋‹ค.
9
+ ๋‹จ์ˆœํ•œ ์‹ ๊ฒฝ๋ง์ด '์ˆœ์„œ'๋ผ๋Š” ๊ฐœ๋…์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฐ˜๋ฉด,
10
+ RNN์€ ๋งˆ์น˜ ์‚ฌ๋žŒ์ฒ˜๋Ÿผ ์‹œ๊ฐ„์˜ ํ๋ฆ„์— ๋”ฐ๋ผ ์ •๋ณด๋ฅผ ๊ธฐ์–ตํ•˜๊ณ , ๋‹ค์Œ์„ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ๊ฐ–์ถ”๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
11
+
12
+ ์˜ค๋Š˜์€ ์ด RNN์ด๋ผ๋Š” ์‹ ๊ฒฝ๋ง์ด ์–ด๋–ป๊ฒŒ ๊ณผ๊ฑฐ์˜ ์ •๋ณด๋ฅผ ๊ธฐ์–ตํ•˜๋ฉฐ ์ž‘๋™ํ•˜๋Š”์ง€,
13
+ ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ๋ฌธ์žฅ์˜ ์ˆจ๊ฒจ์ง„ ๋ฌธ๋งฅ๊ณผ ์˜๋ฏธ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.
14
+
15
+ ---
16
+
17
+ ## ๋ชฉ์ฐจ
18
+ 1. RNN ํ•ต์‹ฌ ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ
19
+ - ์™œ ์ˆœ์ฐจ ๋ฐ์ดํ„ฐ์— RNN์„ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ํ• ๊นŒ?
20
+ - RNN์˜ ์‹ฌ์žฅ : ์ˆœํ™˜ ๊ตฌ์กฐ์™€ ์€๋‹‰ ์ƒํƒœ์˜ ์—ญํ•™
21
+ - RNN์„ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ํŽผ์ณ๋ณด๊ธฐ
22
+ - RNN์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ ์ƒ์„ธ ๋ถ„์„
23
+ 2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ
24
+ - Keras๋กœ ๊ตฌํ˜„ํ•œ RNN ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜
25
+ - model.summary()๋กœ ๊ตฌ์กฐ ํ™•์ธํ•˜๊ธฐ
26
+ 3. ์ง์ ‘ RNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ
27
+ - 1๋‹จ๊ณ„ : ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ
28
+ - 2๋‹จ๊ณ„ : ๋ชจ๋ธ ์ปดํŒŒ์ผ
29
+ - 3๋‹จ๊ณ„ : ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€
30
+ - 4๋‹จ๊ณ„ : ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅ ๋ฐ ์žฌ์‚ฌ์šฉ
31
+ - 5๋‹จ๊ณ„ : ๋‚˜๋งŒ์˜ ๋ฌธ์žฅ์œผ๋กœ ๋ชจ๋ธ ํ…Œ์ŠคํŠธํ•˜๊ธฐ
32
+ 4. ๋‚˜๋งŒ์˜ RNN ๋ชจ๋ธ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ธฐ
33
+ - ๊ธฐ์ดˆ ์ฒด๋ ฅ ํ›ˆ๋ จ : ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹
34
+ - RNN์˜ ์น˜๋ช…์  ์•ฝ์  : ์žฅ๊ธฐ ์˜์กด์„ฑ ๋ฌธ์ œ
35
+ - ๊ธฐ์–ต๋ ฅ ๊ฐ•ํ™” : LSTM๊ณผ GRU์˜ ๋“ฑ์žฅ
36
+ - ๊ณผ๊ฑฐ์™€ ๋ฏธ๋ž˜๋ฅผ ๋™์‹œ์— : ์–‘๋ฐฉํ–ฅ RNN
37
+ 5. ๊ฒฐ๋ก 
38
+ ---
39
+
40
+ ## 1. RNN ํ•ต์‹ฌ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ
41
+ ๊ฐ€์žฅ ๋จผ์ €, RNN์ด ์™œ ์ˆœ์ฐจ์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ํ•„์ˆ˜์ ์ธ ๋„๊ตฌ์ธ์ง€ ๊ทธ ๊ทผ๋ณธ์ ์ธ ์ด์œ ๋ถ€ํ„ฐ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
42
+
43
+ **์™œ ์ˆœ์ฐจ ๋ฐ์ดํ„ฐ์— RNN์„ ์‚ฌ์šฉํ• ๊นŒ?? with MLP, CNN์˜ ํ•œ๊ณ„**
44
+ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์‹ ๊ฒฝ๋ง์ธ MLP(๋‹ค์ธต ํผ์…‰ํŠธ๋ก )์— "๋‚˜๋Š” ํ•™๊ต์— ๊ฐ„๋‹ค"๋ผ๋Š” ๋ฌธ์žฅ์„ ์ž…๋ ฅํ•œ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค.
45
+ MLP๋Š” ๊ฐ ๋‹จ์–ด๋ฅผ ๋…๋ฆฝ์ ์ธ ํŠน์ง•์œผ๋กœ ๋ณด๊ธฐ ๋•Œ๋ฌธ์—, "ํ•™๊ต์— ๋‚˜๋Š” ๊ฐ„๋‹ค"๋ผ๋Š” ๋ฌธ์žฅ๊ณผ ๊ฑฐ์˜ ๋™์ผํ•˜๊ฒŒ ๋ฐ›์•„๋“ค์ž…๋‹ˆ๋‹ค.
46
+ ๋‹จ์–ด์˜ '์ˆœ์„œ'๊ฐ€ ๊ฐ€์ง„ ์ค‘์š”ํ•œ ์˜๋ฏธ, ์ฆ‰ ๋ฌธ๋งฅ์„ ์™„์ „ํžˆ ์žƒ์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
47
+ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์— ํŠนํ™”๋œ CNN ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
48
+ CNN์€ ๊ณต๊ฐ„์ ์ธ ํŠน์ง•(ํ”ฝ์…€ ์ฃผ๋ณ€ ๊ด€๊ณ„)์„ ์ถ”์ถœํ•˜๋Š” ๋ฐ๋Š” ๋›ฐ์–ด๋‚˜์ง€๋งŒ, ์‹œ๊ฐ„์ ์ธ ์ˆœ์„œ๋‚˜ ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๋„๋ก ์„ค๊ณ„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
49
+ ๋ฐ˜๋ฉด, RNN์€ ์„ค๊ณ„ ์ž์ฒด๊ฐ€ '์ˆœ์„œ'๋ฅผ ๊ธฐ์–ตํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค.
50
+ ์ด์ „ ๋‹จ๊ณ„์˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์Œ ๋‹จ๊ณ„์˜ ์ž…๋ ฅ์œผ๋กœ ์žฌ์‚ฌ์šฉํ•˜๋Š” '์ˆœํ™˜' ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด, ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ๋ฌธ์žฅ์„ ์•ž์—์„œ๋ถ€ํ„ฐ ์ฐจ๋ก€๋กœ ์ฝ์œผ๋ฉฐ ๋‚ด์šฉ์„ ๋จธ๋ฆฟ์†์— ์ถ•์ ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
51
+
52
+ **RNN์˜ ์‹ฌ์žฅ : ์ˆœํ™˜ ๊ตฌ์กฐ์™€ ์€๋‹‰ ์ƒํƒœ์˜ ์—ญํ•™**
53
+ RNN์˜ ํ•ต์‹ฌ ์•„์ด๋””์–ด๋Š” ๋ฐ”๋กœ ์ˆœํ™˜ ๊ตฌ์กฐ(Recurrent Structure)์™€ ์€๋‹‰ ์ƒํƒœ(Hidden State) ์ž…๋‹ˆ๋‹ค.
54
+ - ์ˆœํ™˜ ๊ตฌ์กฐ(Recurrent Structure)
55
+ ์‹ ๊ฒฝ๋ง ๋‚ด๋ถ€์— '๋ฃจํ”„'๊ฐ€ ์กด์žฌํ•˜์—ฌ, ์ •๋ณด๊ฐ€ ๊ณ„์†ํ•ด์„œ ์ˆœํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค.
56
+ ๊ฐ ํƒ€์ž„์Šคํ… $t$์—์„œ ๋ชจ๋ธ์€ ์ž…๋ ฅ $x_t$์™€ ์ด์ „ ํƒ€์ž„์Šคํ…์˜ ์ •๋ณด ์š”์•ฝ๋ณธ์ธ $h_{t-1}$์„ ํ•จ๊ป˜ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
57
+
58
+ - ์€๋‹‰ ์ƒํƒœ(Hidden State, $h_t$)
59
+ ์€๋‹‰ ์ƒํƒœ๋Š” '๋ฉ”๋ชจ๋ฆฌ' ๋˜๋Š” '๋ฌธ๋งฅ ๋ฒกํ„ฐ'๋ผ๊ณ  ๋ถˆ๋ฆฌ๋ฉฐ, RNN์˜ ๋ชจ๋“  ๊ฒƒ์„ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
60
+ ํŠน์ • ํƒ€์ž„์Šคํ… t์—์„œ์˜ ์€๋‹‰ ์ƒํƒœ $h_t$๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆ˜์‹์œผ๋กœ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
61
+ $h_t=tanh(W_hhh_tโˆ’1+W_xhx_t+b_h)$์—ฌ๊ธฐ์„œ $W_hh$, $W_{xh}$๋Š” ํ•™์Šต์„ ํ†ตํ•ด ์ตœ์ ํ™”๋˜๋Š” ๊ฐ€์ค‘์น˜ ํ–‰๋ ฌ์ด๋ฉฐ, $b_h$๋Š” ํŽธํ–ฅ์ž…๋‹ˆ๋‹ค.
62
+ ์ค‘์š”ํ•œ ์ ์€ ๋ชจ๋“  ํƒ€์ž„์Šคํ…์—์„œ ๋™์ผํ•œ ๊ฐ€์ค‘์น˜($W$)์™€ ํŽธํ–ฅ($b$)์ด ๊ณต์œ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
63
+ ์ด๋Š” ๋ชจ๋ธ์ด ์‹œ๊ฐ„๊ณผ ๊ด€๊ณ„์—†์ด ์ผ๊ด€๋œ ํŒจํ„ด์„ ํ•™์Šตํ•˜๊ฒŒ ํ•˜๋ฉฐ, ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜๋ฅผ ํฌ๊ฒŒ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.
64
+ tanh์™€ ๊ฐ™์€ ํ™œ์„ฑํ™” ํ•จ์ˆ˜๋Š” ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ํŠน์ • ๋ฒ”์œ„(-1์—์„œ 1 ์‚ฌ์ด)๋กœ ์••์ถ•ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
65
+
66
+ **RNN์„ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ํŽผ์ณ๋ณด๊ธฐ**
67
+ ์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋„คํŠธ์›Œํฌ๋ฅผ ๊ธธ๊ฒŒ ํŽผ์ณ์„œ ํ‘œํ˜„ํ•˜๋ฉด, ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
68
+ ```markdown
69
+ ์‹œ๊ฐ„ ํ๋ฆ„ โ”€โ”€โ”€โ–ถ
70
+ ์ž…๋ ฅ ์‹œํ€€์Šค: xโ‚ xโ‚‚ xโ‚ƒ ... xโ‚œ
71
+ โ†“ โ†“ โ†“ โ†“
72
+ โ”Œโ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ” ... โ”Œโ”€โ”€โ”€โ”€โ”
73
+ hโ‚€ โ”€โ”€โ”€โ–ถ โ”‚RNN โ”‚โ–ถโ”‚RNN โ”‚โ–ถโ”‚RNN โ”‚ โ–ถ ... โ–ถโ”‚RNN โ”‚
74
+ โ””โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”˜
75
+ โ”‚ โ”‚ โ”‚ โ”‚
76
+ โ–ผ โ–ผ โ–ผ โ–ผ
77
+ hโ‚ hโ‚‚ hโ‚ƒ hโ‚œ
78
+ ```
79
+ RNN์€ ๋‚ด๋ถ€์ ์œผ๋กœ **๊ฐ™์€ ์…€** ์„ ๋งค ์‹œ์ ๋งˆ๋‹ค ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์กฐ ์ž…๋‹ˆ๋‹ค.
80
+ ํŽผ์ณ์„œ ๋ณด๋ฉด, ์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ํ•˜๋‚˜์˜ RNN์…€์ด ์‹œ๊ฐ„์ด ํ๋ฆ„์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ณต์ œ๋œ ๊ฒƒ ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.
81
+ ์ˆœ์„œ๋Œ€๋กœ ๋ณด์ž๋ฉด,
82
+ 1. ๊ฐ ์‹œ์ ์˜ $X_t$๊ฐ€ RNN ์…€์— ๋“ค์–ด๊ฐ€๊ณ ,
83
+ 2. ์ด์ „ ์‹œ์ ์˜ ์€์‹ ์ƒํƒœ์˜ $h_(t^-1)$๋„ ํ•จ๊ป˜ ๋“ค์–ด๊ฐ€์„œ,
84
+ 3. ์ƒˆ๋กœ์šด ์€๋‹‰์ƒํƒœ $h_t$๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
85
+ 4. ์ด $h_t$๋Š” ๋‹ค์Œ ์‹œ์ ์œผ๋กœ ์ „๋‹ฌ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
86
+
87
+ ์œ„ ๊ทธ๋ฆผ ์† ์—ฌ๋Ÿฌ ์…€์€ ๊ฐ™์€ RNN ์…€์„ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋ณต์ œํ•œ ๊ฒƒ์ด๊ณ , ๋ชจ๋“  ์…€์€ ๊ฐ€์ค‘์น˜๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹œ์ ์ด ๋‹ฌ๋ผ๋„ ๊ฐ™์€ ๊ทœ์น™์œผ๋กœ ๊ณ„์‚ฐ์ด ์ด๋ฃจ์–ด ์ง‘๋‹ˆ๋‹ค.
88
+
89
+ ๋ณด์ถฉ์„ค๋ช… ํ•˜์ž๋ฉด,
90
+ `๋‚˜๋Š” ํ•™๊ต์— ๊ฐ„๋‹ค`
91
+ ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด,
92
+ $X_1$์ด ๋‚˜๋Š”, $X_2$๊ฐ€ ํ•™๊ต์—, $X_3$ ๊ฐ€ ๊ฐ„๋‹ค๊ฐ€ ๋˜๋ฉด์„œ ์‹œ๊ฐ„์— ๋”ฐ๋ฅธ ์—ฐ์‚ฐ์ด ์ด๋ฃจ์–ด ์ง„๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
93
+
94
+ ## 2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ
95
+ ์ด์ œ ์ด๋ก ์„ ๋ฐ”ํƒ•์œผ๋กœ, TensorFlow Keras ๋ฅผ ํ†ตํ•ด ์ง์ ‘ RNN์„ ๊ตฌํ˜„ํ•ด ๋ด…์‹œ๋‹ค.
96
+ Keras๋กœ ๊ตฌํ˜„ํ•œ RNN ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜ ์‹ฌ์ธต ๋ถ„์„๋‹ค์Œ์€ IMDB ์˜ํ™” ๋ฆฌ๋ทฐ ๊ฐ์„ฑ ๋ถ„์„์„ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ RNN ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
97
+
98
+ ```python
99
+ import tensorflow as tf
100
+ from tensorflow import keras
101
+
102
+ # ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜ ์ •์˜
103
+ model = keras.Sequential([
104
+ # 1. ๋‹จ์–ด ์ž„๋ฒ ๋”ฉ ์ธต
105
+ # input_dim: ์ „์ฒด ๋‹จ์–ด ์ง‘ํ•ฉ์˜ ํฌ๊ธฐ (๊ฐ€์žฅ ๋นˆ๋ฒˆํ•œ 1๋งŒ๊ฐœ ๋‹จ์–ด)
106
+ # output_dim: ๊ฐ ๋‹จ์–ด๋ฅผ ํ‘œํ˜„ํ•  ๋ฒกํ„ฐ์˜ ์ฐจ์› (32์ฐจ์›)
107
+ keras.layers.Embedding(input_dim=10000, output_dim=32),
108
+
109
+ # 2. RNN ์ธต
110
+ # units: ์€๋‹‰ ์ƒํƒœ ๋ฒกํ„ฐ์˜ ์ฐจ์› (32์ฐจ์›)
111
+ keras.layers.SimpleRNN(32),
112
+
113
+ # 3. ์ตœ์ข… ๋ถ„๋ฅ˜๊ธฐ(Classifier)
114
+ # units: ์ถœ๋ ฅ ๋‰ด๋Ÿฐ์˜ ์ˆ˜ (๊ธ์ •/๋ถ€์ • 1๊ฐœ)
115
+ # activation: ์ถœ๋ ฅ ๊ฐ’์„ 0~1 ์‚ฌ์ด ํ™•๋ฅ ๋กœ ๋ณ€ํ™˜ (์ด์ง„ ๋ถ„๋ฅ˜)
116
+ keras.layers.Dense(1, activation="sigmoid"),
117
+ ])
118
+
119
+ # ๋ชจ๋ธ ๊ตฌ์กฐ ์š”์•ฝ ์ถœ๋ ฅ
120
+ model.summary()
121
+ ```
122
+ ๋ ˆ์ด์–ด๋ฅผ ์ž์„ธํžˆ ๋“ค์–ด๋‹ค ๋ด…์‹œ๋‹ค.
123
+
124
+ - **์ž„๋ฒ ๋”ฉ ์ธต(Embedding)**
125
+ ```python
126
+ keras.layers.Embedding(input_dim=10000, output_dim=32)
127
+ ```
128
+ ์ปดํ“จํ„ฐ๋Š” '์˜ํ™”', '์žฌ๋ฏธ' ๊ฐ™์€ ๋‹จ์–ด๋ฅผ ์ง์ ‘ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.
129
+ Embedding ์ธต์€ ๊ฐ ๋‹จ์–ด์— ๋ถ€์—ฌ๋œ ๊ณ ์œ ํ•œ ์ •์ˆ˜ ์ธ๋ฑ์Šค๋ฅผ output_dim ์ฐจ์›์˜ ์˜๋ฏธ๋ก ์  ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
130
+ ์ด ๊ณผ์ •์—์„œ '์Šฌํ””'๊ณผ '๋น„๊ทน' ๊ฐ™์€ ๋‹จ์–ด๋“ค์€ ๋ฒกํ„ฐ ๊ณต๊ฐ„์ƒ์—์„œ ๊ฐ€๊นŒ์šด ์œ„์น˜์—, 'ํ–‰๋ณต'๊ณผ๋Š” ๋จผ ์œ„์น˜์— ํ‘œํ˜„๋˜๋„๋ก ํ•™์Šต๋ฉ๋‹ˆ๋‹ค.
131
+
132
+ - **์ˆœํ™˜ ๊ณ„์ธต(SimpleRNN)**
133
+ ```python
134
+ keras.layers.SimpleRNN(32),
135
+ ```
136
+ ์ด ์ธต์ด ์ˆœํ™˜ ์‹ ๊ฒฝ๋ง์˜ ๋ณธ์ฒด์ž…๋‹ˆ๋‹ค.
137
+ ์ž…๋ ฅ๋œ ๋‹จ์–ด ์ž„๋ฒ ๋”ฉ ๋ฒกํ„ฐ ์‹œํ€€์Šค๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌํ•˜๋ฉฐ ์€๋‹‰ ์ƒํƒœ๋ฅผ ๊ณ„์†ํ•ด์„œ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
138
+ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋งˆ์ง€๋ง‰ ๋‹จ์–ด๊นŒ์ง€ ์ฒ˜๋ฆฌํ•œ ํ›„์˜ ์ตœ์ข… ์€๋‹‰ ์ƒํƒœ๋งŒ์„ ๋‹ค์Œ ์ธต์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
139
+ ์ด ์ตœ์ข… ์€๋‹‰ ์ƒํƒœ ๋ฒกํ„ฐ๋Š” ์ „์ฒด ๋ฌธ์žฅ์˜ ๋ฌธ๋งฅ์„ ์••์ถ•ํ•œ ๊ฒฐ๊ณผ๋ฌผ์ž…๋‹ˆ๋‹ค.
140
+
141
+ - **์™„์ „ ์—ฐ๊ฒฐ ๊ณ„์ธต(Dense)**
142
+ ```python
143
+ keras.layers.Dense(1, activation="sigmoid")
144
+ ```
145
+ ์ตœ์ข… ์€๋‹‰ ์ƒํƒœ ๋ฒกํ„ฐ๋ฅผ ๋ฐ›์•„, ๋ฆฌ๋ทฐ๊ฐ€ ๊ธ์ •(1์— ๊ฐ€๊นŒ์šด ๊ฐ’)์ธ์ง€ ๋ถ€์ •(0์— ๊ฐ€๊นŒ์šด ๊ฐ’)์ธ์ง€ ์ตœ์ข… ํŒ๋‹จ์„ ๋‚ด๋ฆฝ๋‹ˆ๋‹ค.
146
+ model.summary()๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜ ๊ณ„์‚ฐ ์›๋ฆฌ ์ดํ•ดํ•˜๊ธฐ์œ„ ์ฝ”๋“œ์—์„œ model.summary()๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ต๋‹ˆ๋‹ค.
147
+
148
+ ```bash
149
+ Model: "sequential"
150
+ _________________________________________________________________
151
+ Layer (type) Output Shape Param #
152
+ =================================================================
153
+ embedding (Embedding) (None, None, 32) 320000
154
+
155
+ simple_rnn (SimpleRNN) (None, 32) 2080
156
+
157
+ dense (Dense) (None, 1) 33
158
+
159
+ =================================================================
160
+ Total params: 322,113
161
+ Trainable params: 322,113
162
+ Non-trainable params: 0
163
+ _________________________________________________________________
164
+ ```
165
+
166
+ ๊ฐ ์ธต์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜๋Š” ์–ด๋–ป๊ฒŒ ๊ณ„์‚ฐ๋˜๋Š”์ง€ ์•Œ์•„๋ณด์ž๋ฉด,
167
+ 1. Embedding: input_dim * output_dim = 10,000 * 32 = 320,000 ๊ฐœ. (1๋งŒ ๊ฐœ ๋‹จ์–ด ๊ฐ๊ฐ์— ๋Œ€ํ•œ 32์ฐจ์› ๋ฒกํ„ฐ)
168
+ 2. SimpleRNN:
169
+ - ์ž…๋ ฅ ๊ฐ€์ค‘์น˜(W_xh): input_shape * units = 32 * 32 = 1024
170
+ - ์€๋‹‰ ์ƒํƒœ ๊ฐ€์ค‘์น˜(W_hh): units * units = 32 * 32 = 1024
171
+ - ํŽธํ–ฅ(b_h): units = 32
172
+ - ์ดํ•ฉ: 1024 + 1024 + 32 = 2,080 ๊ฐœ.
173
+ 3. Dense: input_shape * units + bias = 32 * 1 + 1 = 33 ๊ฐœ.
174
+
175
+ ์ด์ฒ˜๋Ÿผ summary๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์˜ ๊ตฌ์กฐ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๊ฐ ์ธต์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ•™์Šตํ•ด์•ผ ํ•˜๋Š”์ง€ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
176
+
177
+
178
+ ## 3. ์ง์ ‘ RNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ (์‹ค์ „ ์˜ˆ์ œ)
179
+ ์ด์ œ ์ „์ฒด ์ฝ”๋“œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ์‹คํ–‰ํ•˜๋ฉฐ ์ง์ ‘ ๋ชจ๋ธ์„ ํ•™์Šต์‹œ์ผœ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
180
+
181
+ **1๋‹จ๊ณ„ : ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ (ํŒจ๋”ฉ์˜ ์ค‘์š”์„ฑ)**
182
+ RNN์€ ๊ณ ์ •๋œ ๊ธธ์ด์˜ ์‹œํ€€์Šค๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.
183
+ ํ•˜์ง€๋งŒ ์˜ํ™” ๋ฆฌ๋ทฐ๋Š” ๊ธธ์ด๊ฐ€ ์ œ๊ฐ๊ฐ์ด๋ฏ€๋กœ, **ํŒจ๋”ฉ(Padding)**์„ ํ†ตํ•ด ๋ชจ๋“  ๋ฆฌ๋ทฐ์˜ ๊ธธ์ด๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถฐ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
184
+ ```python
185
+ import numpy as np
186
+ import tensorflow as tf
187
+ from tensorflow import keras
188
+ from keras import layers
189
+
190
+ # ๊ฐ€์žฅ ๋นˆ๋„๊ฐ€ ๋†’์€ 1๋งŒ๊ฐœ ๋‹จ์–ด๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์…‹ ๋กœ๋“œ
191
+ (x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=10000)
192
+
193
+ print(f"ํŒจ๋”ฉ ์ „ ์ฒซ ๋ฒˆ์งธ ๋ฆฌ๋ทฐ ๊ธธ์ด: {len(x_train[0])}")
194
+
195
+ # ๋ชจ๋“  ์‹œํ€€์Šค์˜ ๊ธธ์ด๋ฅผ 256์œผ๋กœ ํ†ต์ผ
196
+ # maxlen๋ณด๋‹ค ๊ธธ๋ฉด ์ž˜๋ผ๋‚ด๊ณ , ์งง์œผ๋ฉด ์•ž๋ถ€๋ถ„์„ 0์œผ๋กœ ์ฑ„์›€ (pre-padding)
197
+ x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen=256)
198
+ x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen=256)
199
+
200
+ print(f"ํŒจ๋”ฉ ํ›„ ์ฒซ ๋ฒˆ์งธ ๋ฆฌ๋ทฐ ๊ธธ์ด: {len(x_train[0])}")
201
+ ```
202
+
203
+ **2๋‹จ๊ณ„ : ๋ชจ๋ธ ์ปดํŒŒ์ผ**
204
+ ๋ชจ๋ธ์„ ์–ด๋–ป๊ฒŒ ํ•™์Šต์‹œํ‚ฌ์ง€ ํ•™์Šต ๋ฐฉ๋ฒ•์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
205
+ ```python
206
+ model.compile(
207
+ # ์†์‹ค ํ•จ์ˆ˜: ์˜ˆ์ธก์ด ์ •๋‹ต๊ณผ ์–ผ๋งˆ๋‚˜ ๋‹ค๋ฅธ์ง€ ์ธก์ •.
208
+ # ์ด์ง„ ๋ถ„๋ฅ˜(0 ๋˜๋Š” 1) ๋ฌธ์ œ์ด๋ฏ€๋กœ binary_crossentropy๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉ.
209
+ loss="binary_crossentropy",
210
+
211
+ # ์˜ตํ‹ฐ๋งˆ์ด์ €: ์†์‹ค์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜.
212
+ # Adam์€ ํ˜„์žฌ ๊ฐ€์žฅ ๋„๋ฆฌ ์“ฐ์ด๊ณ  ์„ฑ๋Šฅ์ด ์ข‹์€ ์˜ตํ‹ฐ๋งˆ์ด์ € ์ค‘ ํ•˜๋‚˜.
213
+ optimizer="adam",
214
+
215
+ # ํ‰๊ฐ€์ง€ํ‘œ: ํ›ˆ๋ จ ๊ณผ์ •์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ง€ํ‘œ. ์ •ํ™•๋„๋ฅผ ์‚ฌ์šฉ.
216
+ metrics=["accuracy"]
217
+ )
218
+ ```
219
+
220
+ **3๋‹จ๊ณ„ : ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€ (๋ฐฐ์น˜, ์—ํฌํฌ, ๊ทธ๋ฆฌ๊ณ  ๊ณผ์ ํ•ฉ)**
221
+ model.fit() ํ•จ์ˆ˜๋กœ ์‹ค์ œ ํ•™์Šต์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
222
+ batch_size: ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•  ๋ฐ์ดํ„ฐ ์ƒ˜ํ”Œ์˜ ์ˆ˜. ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ๊ณผ ํ•™์Šต ์†๋„์— ์˜ํ–ฅ์„ ์ค๋‹ˆ๋‹ค.
223
+ epochs: ์ „์ฒด ๋ฐ์ดํ„ฐ์…‹์„ ๋ช‡ ๋ฒˆ ๋ฐ˜๋ณตํ•˜์—ฌ ํ•™์Šตํ• ์ง€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
224
+
225
+ ```python
226
+ batch_size = 128
227
+ epochs = 10
228
+
229
+ # ๋ชจ๋ธ ํ•™์Šต ์‹คํ–‰
230
+ # validation_data๋ฅผ ์ง€์ •ํ•˜์—ฌ ๋งค ์—ํฌํฌ๋งˆ๋‹ค ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋กœ ์„ฑ๋Šฅ์„ ๊ฒ€์ฆ
231
+ history = model.fit(
232
+ x_train, y_train,
233
+ batch_size=batch_size,
234
+ epochs=epochs,
235
+ validation_data=(x_test, y_test)
236
+ )
237
+
238
+ # ํ•™์Šต ์™„๋ฃŒ ํ›„ ์ตœ์ข… ์„ฑ๋Šฅ ํ‰๊ฐ€
239
+ score = model.evaluate(x_test, y_test, verbose=0)
240
+ print(f"\nTest loss: {score[0]:.4f}")
241
+ print(f"Test accuracy: {score[1]:.4f}")
242
+ ```
243
+
244
+ ํ•™์Šต ๊ณผ์ •์„ ์ง€์ผœ๋ณผ ๋•Œ, ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์˜ ์ •ํ™•๋„(accuracy)๋Š” ๊ณ„์† ์˜ค๋ฅด๋Š”๋ฐ ๊ฒ€์ฆ ๋ฐ์ดํ„ฐ์˜ ์ •ํ™•๋„(val_accuracy)๊ฐ€ ์–ด๋А ์ˆœ๊ฐ„๋ถ€ํ„ฐ ์ •์ฒด๋˜๊ฑฐ๋‚˜ ๋–จ์–ด์ง„๋‹ค๋ฉด, ๋ชจ๋ธ์ด ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์—๋งŒ ๊ณผํ•˜๊ฒŒ ์ ์‘ํ•˜๋Š” **๊ณผ์ ํ•ฉ(Overfitting)**์ด ๋ฐœ์ƒํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.
245
+ ์ด๋Ÿด ๋•Œ๋Š”, ๋“œ๋กญ์•„์›ƒ์˜ ๋น„์œจ์„ ๋†’์ด๊ฑฐ๋‚˜ ํ•™์Šต์œจ์„ ์กฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
246
+
247
+ **4๋‹จ๊ณ„ : ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅ ๋ฐ ์žฌ์‚ฌ์šฉ**
248
+ ํ•™์Šต์— ์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ๋ชจ๋ธ์€ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•ด๋‘๊ณ  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋ถˆ๋Ÿฌ์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
249
+
250
+ ```python
251
+ # ๋ชจ๋ธ์˜ ๊ตฌ์กฐ, ๊ฐ€์ค‘์น˜, ํ•™์Šต ์„ค์ •์„ ๋ชจ๋‘ '.keras' ํŒŒ์ผ ํ•˜๋‚˜์— ์ €์žฅ
252
+ model.save("my_rnn_model_imdb.keras")
253
+
254
+ # ์ €์žฅ๋œ ๋ชจ๋ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
255
+ loaded_model = keras.models.load_model("my_rnn_model_imdb.keras")
256
+ ```
257
+
258
+ **5๋‹จ๊ณ„ : ๋‚˜๋งŒ์˜ ๋ฌธ์žฅ์œผ๋กœ ๋ชจ๋ธ ํ…Œ์ŠคํŠธํ•˜๊ธฐ (์‹ค์ „ ์˜ˆ์ธก)**
259
+ ์‹ค์ œ ๋ฌธ์žฅ์„ ์˜ˆ์ธกํ•˜๋ ค๋ฉด, ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์™€ ๋™์ผํ•œ ์ „์ฒ˜๋ฆฌ ๊ณผ์ •์„ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
260
+
261
+ ```python
262
+ # IMDB ๋ฐ์ดํ„ฐ์…‹์˜ ๋‹จ์–ด-์ธ๋ฑ์Šค ์‚ฌ์ „ ๋กœ๋“œ
263
+ word_index = keras.datasets.imdb.get_word_index()
264
+
265
+ # ์ƒˆ๋กœ์šด ๋ฆฌ๋ทฐ ๋ฌธ์žฅ
266
+ review = "This movie was fantastic and wonderful"
267
+
268
+ # 1. ์†Œ๋ฌธ์ž ๋ณ€ํ™˜ ๋ฐ ๋‹จ์–ด ๋ถ„๋ฆฌ -> 2. ๋‹จ์–ด ์ธ๋ฑ์Šค๋กœ ๋ณ€ํ™˜
269
+ tokens = [word_index.get(word, 2) for word in review.lower().split()]
270
+
271
+ # 3. ํŒจ๋”ฉ ์ฒ˜๋ฆฌ
272
+ padded_tokens = keras.preprocessing.sequence.pad_sequences([tokens], maxlen=256)
273
+
274
+ # 4. ์˜ˆ์ธก
275
+ prediction = loaded_model.predict(padded_tokens)
276
+ print(f"๋ฆฌ๋ทฐ: '{review}'")
277
+ print(f"๊ธ์ • ํ™•๋ฅ : {prediction[0][0] * 100:.2f}%")
278
+ ```
279
+
280
+ 4. ๋‚˜๋งŒ์˜ RNN ๋ชจ๋ธ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ธฐ
281
+ ๊ธฐ๋ณธ RNN๋„ ์ข‹์ง€๋งŒ, ๋” ๋ณต์žกํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ช‡ ๊ฐ€์ง€ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
282
+
283
+ **RNN์˜ ์น˜๋ช…์  ์•ฝ์  : ์žฅ๊ธฐ ์˜์กด์„ฑ ๋ฌธ์ œ (Vanishing Gradients)**
284
+ "๋‚˜๋Š” ํ”„๋ž‘์Šค์—์„œ ํƒœ์–ด๋‚˜ ์ž๋ž๋‹ค. ... (์ค‘๋žต) ... ๊ทธ๋ž˜์„œ ๋‚˜๋Š” ___๋ฅผ ์œ ์ฐฝํ•˜๊ฒŒ ๊ตฌ์‚ฌํ•œ๋‹ค."
285
+ ๋นˆ์นธ์— ๋“ค์–ด๊ฐˆ ๋ง์€ 'ํ”„๋ž‘์Šค์–ด'์ž…๋‹ˆ๋‹ค.
286
+ ์‚ฌ๋žŒ์€ ๋ฌธ์žฅ ๋งจ ์•ž์˜ 'ํ”„๋ž‘์Šค'๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๊ธฐ์–ตํ•˜์—ฌ ์‰ฝ๊ฒŒ ๋‹ต์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
287
+ ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ RNN์€ ์‹œํ€€์Šค๊ฐ€ ๊ธธ์–ด์งˆ์ˆ˜๋ก, ์—ญ๏ฟฝ๏ฟฝํŒŒ ๊ณผ์ •์—์„œ ๊ทธ๋ž˜๋””์–ธํŠธ(๊ธฐ์šธ๊ธฐ)๊ฐ€ ๊ณ„์† ๊ณฑํ•ด์ง€๋ฉด์„œ 0์— ๊ฐ€๊นŒ์›Œ์ ธ ์‚ฌ๋ผ์ง€๋Š” ๊ทธ๋ž˜๋””์–ธํŠธ ์†Œ์‹ค(Vanishing Gradient) ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
288
+ ์ด๋กœ ์ธํ•ด ๋ฌธ์žฅ ์•ž๋ถ€๋ถ„์˜ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ํ•™์Šตํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
289
+ ์ด๋ฅผ ์žฅ๊ธฐ ์˜์กด์„ฑ ๋ฌธ์ œ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
290
+
291
+ **๊ธฐ์–ต๋ ฅ ๊ฐ•ํ™” : LSTM๊ณผ GRU์˜ ๋“ฑ์žฅ**
292
+ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด **LSTM(Long Short-Term Memory)**๊ณผ **GRU(Gated Recurrent Unit)**๊ฐ€ ๋“ฑ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.
293
+ ์ด๋“ค์€ RNN ๋‚ด๋ถ€์— **๊ฒŒ์ดํŠธ(Gate)**๋ผ๋Š” ์ •๊ตํ•œ ์žฅ์น˜๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ •๋ณด์˜ ํ๋ฆ„์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
294
+ - LSTM: '์…€ ์ƒํƒœ(Cell State)'๋ผ๋Š” ๋ณ„๋„์˜ ๊ธฐ์–ต ์ปจ๋ฒ ์ด์–ด ๋ฒจํŠธ๋ฅผ ๋‘๊ณ , ๋ง๊ฐ ๊ฒŒ์ดํŠธ(Forget Gate), ์ž…๋ ฅ ๊ฒŒ์ดํŠธ(Input Gate), ์ถœ๋ ฅ ๊ฒŒ์ดํŠธ(Output Gate) 3๊ฐœ์˜ ๊ฒŒ์ดํŠธ๋ฅผ ํ†ตํ•ด ์–ด๋–ค ์ •๋ณด๋ฅผ ๋ฒ„๋ฆฌ๊ณ , ์–ด๋–ค ์ •๋ณด๋ฅผ ์ƒˆ๋กœ ๊ธฐ์–ตํ•˜๊ณ , ์–ด๋–ค ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ• ์ง€ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.
295
+ ์žฅ๊ธฐ ๊ธฐ์–ต์— ๋งค์šฐ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.
296
+ - GRU: LSTM์„ ๋” ๋‹จ์ˆœํ™”ํ•œ ๋ชจ๋ธ๋กœ, **๋ฆฌ์…‹ ๊ฒŒ์ดํŠธ(Reset Gate)**์™€ ์—…๋ฐ์ดํŠธ ๊ฒŒ์ดํŠธ(Update Gate) 2๊ฐœ์˜ ๊ฒŒ์ดํŠธ๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
297
+ ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜๊ฐ€ ์ ์–ด ๊ณ„์‚ฐ ํšจ์œจ์„ฑ์ด ๋†’๊ณ , ๋งŽ์€ ๊ฒฝ์šฐ LSTM๊ณผ ๋น„์Šทํ•œ ์„ฑ๋Šฅ์„ ๋ณด์ž…๋‹ˆ๋‹ค.
298
+
299
+ ```python
300
+ # LSTM์„ 2๊ฐœ ์ธต์œผ๋กœ ์Œ“์€ ๋ชจ๋ธ
301
+ model_lstm = keras.Sequential([
302
+ layers.Embedding(input_dim=10000, output_dim=64),
303
+ # return_sequences=True: ๋‹ค์Œ LSTM ์ธต์œผ๋กœ ์ „์ฒด ์‹œํ€€์Šค๋ฅผ ์ „๋‹ฌ
304
+ layers.LSTM(64, return_sequences=True),
305
+ layers.LSTM(32),
306
+ layers.Dense(1, activation='sigmoid')
307
+ ])
308
+ ```
309
+
310
+ **๊ณผ๊ฑฐ์™€ ๋ฏธ๋ž˜๋ฅผ ๋™์‹œ์— : ์–‘๋ฐฉํ–ฅ RNN (Bidirectional RNN)**
311
+ "์˜ค๋Š˜ ์ƒˆ๋กœ ์˜จ ___ ์„ ์ƒ๋‹˜์€ ์ •๋ง ๋ฉ‹์ง€๋‹ค."
312
+ ๋นˆ์นธ์— ๋“ค์–ด๊ฐˆ '์˜์–ด'๋ผ๋Š” ๋‹จ์–ด๋Š” ๋’ท๋ถ€๋ถ„์˜ '์„ ์ƒ๋‹˜'์ด๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๋ด์•ผ ๋” ์ •ํ™•ํžˆ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
313
+ ์ด์ฒ˜๋Ÿผ ๋ฌธ๋งฅ์€ ์ˆœ๋ฐฉํ–ฅ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์—ญ๋ฐฉํ–ฅ์˜ ์ •๋ณด๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
314
+ **์–‘๋ฐฉํ–ฅ RNN(Bidirectional RNN)**์€ ์‹œํ€€์Šค๋ฅผ ์ •๋ฐฉํ–ฅ์œผ๋กœ ํ•œ๋ฒˆ, ์—ญ๋ฐฉํ–ฅ์œผ๋กœ ํ•œ๋ฒˆ ๋…๋ฆฝ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ ํ›„, ๋‘ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์ณ์„œ ์ตœ์ข… ์ถœ๋ ฅ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
315
+ ์ด๋ฅผ ํ†ตํ•ด ๋ฌธ๋งฅ์„ ํ›จ์”ฌ ๋” ํ’๋ถ€ํ•˜๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
316
+
317
+ ```python
318
+ model_bidirectional = keras.Sequential([
319
+ layers.Embedding(input_dim=10000, output_dim=64),
320
+ # LSTM ๋ ˆ์ด์–ด๋ฅผ Bidirectional ๋ž˜ํผ๋กœ ๊ฐ์‹ธ๊ธฐ๋งŒ ํ•˜๋ฉด ๋จ
321
+ layers.Bidirectional(layers.LSTM(64)),
322
+ layers.Dropout(0.5), # ๊ณผ์ ํ•ฉ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ๋“œ๋กญ์•„์›ƒ ์ถ”๊ฐ€
323
+ layers.Dense(1, activation='sigmoid')
324
+ ])
325
+ ```
326
+
327
+ ## 5. ๊ฒฐ๋ก 
328
+ ์˜ค๋Š˜์€ ์ˆœ์ฐจ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ๊ทผ๊ฐ„์ด ๋˜๋Š” RNN์˜ ํ•ต์‹ฌ ์›๋ฆฌ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ, ์‹ค์ œ ์ฝ”๋“œ๋กœ ๋ชจ๋ธ์„ ๊ตฌํ˜„ํ•˜๊ณ , LSTM, GRU, ์–‘๋ฐฉํ–ฅ RNN๊ณผ ๊ฐ™์€ ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•์„ ํ†ตํ•ด ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•๊นŒ์ง€ ์ƒ์„ธํ•˜๊ฒŒ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.
329
+ RNN์€ ๊ทธ ์ž์ฒด๋กœ๋„ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ ๋ถ„์•ผ์˜ ๋ฐœ์ „์— ์—„์ฒญ๋‚œ ๊ธฐ์—ฌ๋ฅผ ํ•œ ๊ธฐ๋…๋น„์ ์ธ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
330
+ ํŠนํžˆ RNN์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๋ ค๋Š” ์‹œ๋„ ์†์—์„œ ํƒ„์ƒํ•œ ์–ดํ…์…˜(Attention) ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ์ดํ›„ **ํŠธ๋žœ์Šคํฌ๋จธ(Transformer)**๋ผ๋Š” ํ˜์‹ ์ ์ธ ๋ชจ๋ธ์˜ ๊ธฐ๋ฐ˜์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
331
+ ๋‹ค์Œ์—๋Š” ์–ดํ…์…˜ ๊ธฐ๋ฒ•๊ณผ ํŠธ๋žœ์Šคํฌ๋จธ ๋ชจ๋ธ, ์ธ์ฝ”๋”, ๋””์ฝ”๋”๋กœ ๋Œ์•„์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค!!
332
+ ์˜ค๋Š˜๋„ ์ข‹์€ํ•˜๋ฃจ ๋ณด๋‚ด์„ธ์š”!!
config.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "SimpleRNN_for_Sequence_Classification",
3
+ "embedding_layer": {
4
+ "input_dim": 10000,
5
+ "output_dim": 32
6
+ },
7
+ "rnn_layer": {
8
+ "type": "SimpleRNN",
9
+ "units": 32
10
+ },
11
+ "classifier_head": {
12
+ "units": 1,
13
+ "activation": "sigmoid"
14
+ },
15
+ "preprocessing": {
16
+ "max_sequence_length": 256,
17
+ "padding_type": "pre"
18
+ },
19
+ "training_details": {
20
+ "loss_function": "binary_crossentropy",
21
+ "optimizer": "adam",
22
+ "metrics": ["accuracy"]
23
+ }
24
+ }
test.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ from tensorflow import keras
3
+ import numpy as np
4
+
5
+ # --- 1. ๋ชจ๋ธ๊ณผ ๋‹จ์–ด ์‚ฌ์ „ ๋กœ๋“œ ---
6
+
7
+ # ์ €์žฅ๋œ Keras ๋ชจ๋ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
8
+ model_path = "my_rnn_model_imdb.keras"
9
+ try:
10
+ loaded_model = keras.models.load_model(model_path)
11
+ print(f"'{model_path}' ๋ชจ๋ธ์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.")
12
+ except Exception as e:
13
+ print(f"๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
14
+ exit()
15
+
16
+ # IMDB ๋ฐ์ดํ„ฐ์…‹์˜ ๋‹จ์–ด-์ธ๋ฑ์Šค ์‚ฌ์ „ ๋กœ๋“œ
17
+ word_index = keras.datasets.imdb.get_word_index()
18
+
19
+ # Keras์˜ ์˜ˆ์•ฝ๋œ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜์˜ํ•˜์—ฌ 3๋งŒํผ ์˜คํ”„์…‹ ์ถ”๊ฐ€
20
+ word_index = {k: (v + 3) for k, v in word_index.items()}
21
+ word_index["<pad>"] = 0
22
+ word_index["<start>"] = 1
23
+ word_index["<unk>"] = 2 # ์•Œ๋ ค์ง€์ง€ ์•Š์€ ๋‹จ์–ด(out-of-vocabulary)
24
+ word_index["<unused>"] = 3
25
+
26
+
27
+ # --- 2. ์˜ˆ์ธก์„ ์œ„ํ•œ ์ „์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ---
28
+
29
+ MAX_LEN = 256
30
+
31
+ def preprocess_text(text):
32
+ """
33
+ ์ƒˆ๋กœ์šด ํ…์ŠคํŠธ๋ฅผ ๋ชจ๋ธ ์ž…๋ ฅ ํ˜•์‹์— ๋งž๊ฒŒ ์ „์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
34
+ """
35
+ # ํ…์ŠคํŠธ๋ฅผ ํ† ํฐํ™”ํ•˜๊ณ  ์ •์ˆ˜๋กœ ์ธ์ฝ”๋”ฉ
36
+ tokens = [word_index.get(word, 2) for word in text.lower().split()]
37
+
38
+ # <start> ์ธ๋ฑ์Šค ์ถ”๊ฐ€
39
+ tokens = [word_index["<start>"]] + tokens
40
+
41
+ # ์‹œํ€€์Šค ํŒจ๋”ฉ
42
+ padded_sequence = keras.preprocessing.sequence.pad_sequences(
43
+ [tokens], maxlen=MAX_LEN, padding='pre'
44
+ )
45
+
46
+ return padded_sequence
47
+
48
+
49
+ # --- 3. ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ธฐ๋ฐ˜ ์˜ˆ์ธก ์‹คํ–‰ ---
50
+
51
+ print("\n์˜ํ™” ๋ฆฌ๋ทฐ ๊ฐ์„ฑ ๋ถ„์„๊ธฐ (์ข…๋ฃŒํ•˜๋ ค๋ฉด 'exit'๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”)")
52
+ print("-" * 50)
53
+
54
+ while True:
55
+ # ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฆฌ๋ทฐ ์ž…๋ ฅ๋ฐ›๊ธฐ
56
+ review_text = input("๋ฆฌ๋ทฐ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”: ")
57
+
58
+ if review_text.lower() == 'exit':
59
+ print("ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")
60
+ break
61
+
62
+ if not review_text.strip():
63
+ print("์ž…๋ ฅ๋œ ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.")
64
+ continue
65
+
66
+ # ํ…์ŠคํŠธ ์ „์ฒ˜๋ฆฌ
67
+ processed_input = preprocess_text(review_text)
68
+
69
+ # ๋ชจ๋ธ๋กœ ์˜ˆ์ธก ์ˆ˜ํ–‰
70
+ prediction = loaded_model.predict(processed_input)
71
+
72
+ # ๊ฒฐ๊ณผ ํ•ด์„ (sigmoid ์ถœ๋ ฅ > 0.5 ์ด๋ฉด ๊ธ์ •)
73
+ score = prediction[0][0]
74
+ sentiment = "๊ธ์ • (Positive)" if score > 0.5 else "๋ถ€์ • (Negative)"
75
+
76
+ print(f"๊ฒฐ๊ณผ: {sentiment} (์˜ˆ์ธก ์ ์ˆ˜: {score:.4f})")
77
+ print("-" * 50)
train.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ from tensorflow import keras
3
+ import numpy as np
4
+ from keras import layers
5
+
6
+ # ๊ฐ€์žฅ ๋นˆ๋„๊ฐ€ ๋†’์€ 1๋งŒ๊ฐœ ๋‹จ์–ด๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์…‹ ๋กœ๋“œ
7
+ (x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=10000)
8
+
9
+ print(f"ํŒจ๋”ฉ ์ „ ์ฒซ ๋ฒˆ์งธ ๋ฆฌ๋ทฐ ๊ธธ์ด: {len(x_train[0])}")
10
+
11
+ # ๋ชจ๋“  ์‹œํ€€์Šค์˜ ๊ธธ์ด๋ฅผ 256์œผ๋กœ ํ†ต์ผ
12
+ # maxlen๋ณด๋‹ค ๊ธธ๋ฉด ์ž˜๋ผ๋‚ด๊ณ , ์งง์œผ๋ฉด ์•ž๋ถ€๋ถ„์„ 0์œผ๋กœ ์ฑ„์›€ (pre-padding)
13
+ x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen=256)
14
+ x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen=256)
15
+
16
+ print(f"ํŒจ๋”ฉ ํ›„ ์ฒซ ๋ฒˆ์งธ ๋ฆฌ๋ทฐ ๊ธธ์ด: {len(x_train[0])}")
17
+
18
+ # ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜ ์ •์˜
19
+ model = keras.Sequential([
20
+ # 1. ๋‹จ์–ด ์ž„๋ฒ ๋”ฉ ์ธต
21
+ # input_dim: ์ „์ฒด ๋‹จ์–ด ์ง‘ํ•ฉ์˜ ํฌ๊ธฐ (๊ฐ€์žฅ ๋นˆ๋ฒˆํ•œ 1๋งŒ๊ฐœ ๋‹จ์–ด)
22
+ # output_dim: ๊ฐ ๋‹จ์–ด๋ฅผ ํ‘œํ˜„ํ•  ๋ฒกํ„ฐ์˜ ์ฐจ์› (32์ฐจ์›)
23
+ keras.layers.Embedding(input_dim=10000, output_dim=32),
24
+
25
+ # 2. RNN ์ธต
26
+ # units: ์€๋‹‰ ์ƒํƒœ ๋ฒกํ„ฐ์˜ ์ฐจ์› (32์ฐจ์›)
27
+ keras.layers.SimpleRNN(32),
28
+
29
+ # 3. ์ตœ์ข… ๋ถ„๋ฅ˜๊ธฐ(Classifier)
30
+ # units: ์ถœ๋ ฅ ๋‰ด๋Ÿฐ์˜ ์ˆ˜ (๊ธ์ •/๋ถ€์ • 1๊ฐœ)
31
+ # activation: ์ถœ๋ ฅ ๊ฐ’์„ 0~1 ์‚ฌ์ด ํ™•๋ฅ ๋กœ ๋ณ€ํ™˜ (์ด์ง„ ๋ถ„๋ฅ˜)
32
+ keras.layers.Dense(1, activation="sigmoid"),
33
+ ])
34
+
35
+
36
+ model.compile(
37
+ # ์†์‹ค ํ•จ์ˆ˜: ์˜ˆ์ธก์ด ์ •๋‹ต๊ณผ ์–ผ๋งˆ๋‚˜ ๋‹ค๋ฅธ์ง€ ์ธก์ •.
38
+ # ์ด์ง„ ๋ถ„๋ฅ˜(0 ๋˜๋Š” 1) ๋ฌธ์ œ์ด๋ฏ€๋กœ binary_crossentropy๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉ.
39
+ loss="binary_crossentropy",
40
+
41
+ # ์˜ตํ‹ฐ๋งˆ์ด์ €: ์†์‹ค์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜.
42
+ # Adam์€ ํ˜„์žฌ ๊ฐ€์žฅ ๋„๋ฆฌ ์“ฐ์ด๊ณ  ์„ฑ๋Šฅ์ด ์ข‹์€ ์˜ตํ‹ฐ๋งˆ์ด์ € ์ค‘ ํ•˜๋‚˜.
43
+ optimizer="adam",
44
+
45
+ # ํ‰๊ฐ€์ง€ํ‘œ: ํ›ˆ๋ จ ๊ณผ์ •์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ง€ํ‘œ. ์ •ํ™•๋„๋ฅผ ์‚ฌ์šฉ.
46
+ metrics=["accuracy"]
47
+ )
48
+
49
+ batch_size = 128
50
+ epochs = 10
51
+
52
+ # ๋ชจ๋ธ ํ•™์Šต ์‹คํ–‰
53
+ # validation_data๋ฅผ ์ง€์ •ํ•˜์—ฌ ๋งค ์—ํฌํฌ๋งˆ๋‹ค ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋กœ ์„ฑ๋Šฅ์„ ๊ฒ€์ฆ
54
+ history = model.fit(
55
+ x_train, y_train,
56
+ batch_size=batch_size,
57
+ epochs=epochs,
58
+ validation_data=(x_test, y_test)
59
+ )
60
+
61
+ # ํ•™์Šต ์™„๋ฃŒ ํ›„ ์ตœ์ข… ์„ฑ๋Šฅ ํ‰๊ฐ€
62
+ score = model.evaluate(x_test, y_test, verbose=0)
63
+ print(f"\nTest loss: {score[0]:.4f}")
64
+ print(f"Test accuracy: {score[1]:.4f}")
65
+
66
+ # ๋ชจ๋ธ์˜ ๊ตฌ์กฐ, ๊ฐ€์ค‘์น˜, ํ•™์Šต ์„ค์ •์„ ๋ชจ๋‘ '.keras' ํŒŒ์ผ ํ•˜๋‚˜์— ์ €์žฅ
67
+ model.save("my_rnn_model_imdb.keras")
68
+
69
+ # ๋ชจ๋ธ ๊ตฌ์กฐ ์š”์•ฝ ์ถœ๋ ฅ
70
+ model.summary()
71
+
72
+ # ์ €์žฅ๋œ ๋ชจ๋ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
73
+ loaded_model = keras.models.load_model("my_rnn_model_imdb.keras")