OneclickAI commited on
Commit
f735c49
ยท
verified ยท
1 Parent(s): 795f477
Files changed (3) hide show
  1. README.md +293 -0
  2. test.py +106 -0
  3. train.py +60 -0
README.md ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ ---
4
+
5
+ ์•ˆ๋…•ํ•˜์„ธ์š” Oneclick AI ์ž…๋‹ˆ๋‹ค!!
6
+ ์˜ค๋Š˜์€, CNN ๋ชจ๋ธ์— ๋Œ€ํ•ด์„œ ๊นŠ๊ฒŒ ์•Œ์•„๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณผ๊นŒ ํ•ฉ๋‹ˆ๋‹ค.
7
+
8
+ ๋”ฅ๋Ÿฌ๋‹์— ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ ์ด์œ ๊ฐ€ ๋ฐ”๋กœ CNN์˜ ํ•ฉ์„ฑ๊ณฑ ์‹ ๊ฒฝ๋ง (Convolutional Neural Network, CNN) ๋•๋ถ„์ธ๋ฐ์š”, ์˜ค๋Š˜์€ ์ด ์‹ ๊ฒฝ๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€, CNN์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์ง„ ์†์˜ ์ˆซ์ž๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.
9
+
10
+ ---
11
+
12
+ ## ๋ชฉ์ฐจ
13
+ 1. CNN ํ•ต์‹ฌ ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ
14
+ - ์™œ ์ด๋ฏธ์ง€์— CNN์„ ์‚ฌ์šฉํ• ๊นŒ?
15
+ - CNN์˜ ํ•ต์‹ฌ : ์ง€์—ญ ์ˆ˜์šฉ ์˜์—ญ๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ 
16
+ - CNN์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ
17
+ 2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ
18
+ - keras๋กœ ๊ตฌํ˜„ํ•œ CNN ๋ชจ๋ธ ์•„ํ‚คํ…์ณ
19
+ - model.summary()๋กœ ๊ตฌ์กฐ ํ™•์ธํ•˜๊ธฐ
20
+ 3. ์ง์ ‘ CNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ
21
+ - 1๋‹จ๊ณ„ : ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ
22
+ - 2๋‹จ๊ณ„ : ๋ชจ๋ธ ์ปดํŒŒ์ผ
23
+ - 3๋‹จ๊ณ„ : ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€
24
+ - 4๋‹จ๊ณ„ : ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅํ•˜๊ธฐ
25
+ - 5๋‹จ๊ณ„ : ๋ชจ๋ธ ์‚ฌ์šฉํ•˜๊ธฐ
26
+ 4. ๋‚˜๋งŒ์˜ CNN ๋ชจ๋ธ ๋งŒ๋“ค์–ด๋ณด๊ธฐ
27
+ - ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹
28
+ - ๋ชจ๋ธ ๊ตฌ์กฐ ๋ณ€๊ฒฝํ•˜๊ธฐ
29
+ - ์ „์ดํ•™์Šต์œผ๋กœ ์„ฑ๋Šฅ ๊ทน๋Œ€ํ™” ํ•˜๊ธฐ
30
+ 5. ๊ฒฐ๋ก 
31
+ ---
32
+
33
+ ## 1. CNN ํ•ต์‹ฌ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ
34
+ ๋“ค์–ด๊ฐ€๊ธฐ ์•ž์„œ, CNN ์ด ์–ด๋–ค ์›๋ฆฌ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€ ๋จผ์ € ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
35
+
36
+ **์™œ ์ด๋ฏธ์ง€์— CNN์„ ์‚ฌ์šฉํ• ๊นŒ??**
37
+ ๋‹จ์ˆœํ•œ ์‹ ๊ฒฝ๋ง(Fully Connected Layer)์— ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅํ•˜๋ ค๋ฉด, 2์ฐจ์›์ธ ์ด๋ฏธ์ง€๋ฅผ 1์ฐจ์›์˜ ๊ธด ๋ฐ์ดํ„ฐ๋กœ ํŽผ์น˜๋Š” ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ ๊ณผ์ •์ด ๊ผญ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
38
+ ์ด ๊ณผ์ •์—์„œ ํ”ฝ์…€ ๊ฐ„์˜ ๊ณต๊ฐ„์ ์ธ ์ •๋ณด๊ฐ€ ์ „๋ถ€ ํŒŒ๊ดด๋ฉ๋‹ˆ๋‹ค.
39
+ ์ด๋Š” ์–ด๋–ค ํ”ฝ์…€์ด ์„œ๋กœ ์ด์›ƒํ•ด ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์–ด์ ธ์„œ ๋ˆˆ์ด ์ฝ” ์˜†์— ์žˆ๋‹ค๋Š” ์œ„์น˜์ •๋ณด ๊ฐ™์€ ๋‚ด์šฉ์ด ๊ฐ€๋ผ์ € ๋ฒ„๋ฆฐ๋‹ค๋Š” ์˜๋ฏธ ์ž…๋‹ˆ๋‹ค.
40
+ CNN์€ ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ธ๊ฐ„์˜ ์‹œ์‹ ๊ฒฝ ๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฐฉํ•˜์—ฌ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
41
+
42
+ **CNN์˜ ํ•ต์‹ฌ ์•„์ด๋””์–ด**
43
+ ์ด๊ฒƒ์ด ๋ฐ”๋กœ ์ง€์—ญ์  ์ˆ˜์šฉ์˜์—ญ๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ  ์ž…๋‹ˆ๋‹ค.
44
+ - ์ง€์—ญ์  ์ˆ˜์šฉ ์˜์—ญ(Local Receptive Fields)
45
+ ์‹ ๊ฒฝ๋ง์˜ ๊ฐ ๋‰ด๋Ÿฐ์ด ์ด๋ฏธ์ง€ ์ „์ฒด๊ฐ€ ์•„๋‹Œ, ์ž‘์€ ์ผ๋ถ€์—๋งŒ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
46
+ ์ด๋Š” ์ „์ฒด ํ”ฝ์…€์— ๋Œ€ํ•ด์„œ๊ฐ€ ์•„๋‹Œ ์˜ˆ์‹œ๋ฅผ ๋“ค๋ฉด 3 * 3 ํ”ฝ์…€์—๋งŒ ์ ์šฉ๋˜๋Š” ๋ฐฉ์‹์ธ๋ฐ์š”, ์ด๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์€ ์ด๋ฏธ์ง€์˜ ์ „์ฒด ๋งฅ๋ฝ๋ณด๋‹ค ์„ , ๋ชจ์„œ๋ฆฌ, ์งˆ๊ฐ๊ณผ ๊ฐ™์€ ์ง€์—ญ์ ์ธ ํŒจํ„ด์„ ๋จผ์ € ํ•™์Šตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
47
+
48
+ - ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ (Parameter Sharing)
49
+ CNN์€ ์ด๋ฏธ์ง€ ์ „์ฒด๋ฅผ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด์„œ ์Šค์บ”ํ•˜๋Š” ๋А๋‚Œ์œผ๋กœ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.
50
+ ๋”ฐ๋ผ์„œ, ํ•œ๋ฒˆ ์ด๋ฏธ์ง€์˜ ํŠน์ง•์„ ํ•™์Šตํ•˜๋ฉด, ์ด๋ฏธ์ง€์˜ ๋ชจ๋“  ์œ„์น˜์—์„œ ํ•ด๋‹น ํŠน์ง•์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
51
+ ์ด๋ฅผ ํ†ตํ•ด์„œ ํ•™์Šตํ•  ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜๋ฅผ ๋งŽ์ด ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
52
+
53
+ **CNN์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ**
54
+ ์•ž์„  ์•„์ด๋””์–ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, CNN์€ ๋‹ค์Œ 3๊ฐ€์ง€์˜ ๊ณ„์ธต์„ ์กฐํ•ฉํ•ด์„œ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
55
+ - ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต (Convolutional Layer)
56
+ ํ•™์Šต ๊ฐ€๋Šฅํ•œ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฏธ์ง€์˜ ํŠน์ง•์„ ์ถ”์ถœํ•ด ๋ƒ…๋‹ˆ๋‹ค.
57
+ edge, corner ๋“ฑ์„ ์ถ”์ถœํ•˜์—ฌ ์–ป๋Š” ๊ฒฐ๊ณผ๋ฌผ์„ ํŠน์ง• ๋งต(Feature Map) ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
58
+
59
+ - ํ’€๋ง ๊ณ„์ธต (Pooling Layer)
60
+ ์•ž์„œ ๋งŒ๋“  ๋งต์˜ ํฌ๊ธฐ๋ฅผ ์ค„์ด๋Š” ์š”์•ฝ๋‹จ๊ณ„ ์ž…๋‹ˆ๋‹ค.
61
+ ์ตœ๋Œ€ ํ’€๋ง(Max Pooling)์€ ํŠน์ • ์˜์—ญํ—ค์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŠน์ง•(๊ฐ€์žฅ ํฐ ๊ฐ’)๋งŒ ๋‚จ๊ฒจ ๊ณ„์‚ฐ๋Ÿ‰์„ ์ค„์ด๊ณ , ๋ชจ๋ธ์ด ํŠน์ง•์˜ ๋ฏธ์„ธํ•œ ์œ„์น˜ ๋ณ€ํ™”์— ๋œ ๋ฏผ๊ฐํ•ด ํ•˜๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.
62
+
63
+ - ์™„์ „ ์—ฐ๊ฒฐ ๊ณ„์ธต (Dense Layer)
64
+ ์ถ”์ถœ๋œ ํŠน์ง•๋“ค์„ ์ข…ํ•ฉํ•˜์—ฌ ์ตœ์ข…์ ์œผ๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์–ด๋–ค ํด๋ž˜์Šค์— ์†ํ•˜๋Š”์ง€ ๋ถ„๋ฅ˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
65
+
66
+ ---
67
+
68
+ ## 2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ
69
+ ์ด์ œ, ์•ž์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ, ์‹ค์ œ TensorFlow Keras ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์‹ค๊ฐํ•ด ๋ด…์‹œ๋‹ค.
70
+ ๋‹ค์Œ์€, Keras๋กœ ๊ตฌํ˜„ํ•œ CNN ๋ชจ๋ธ ์•„ํ‚คํ…์ณ ์ž…๋‹ˆ๋‹ค.
71
+ ```python
72
+ import tensorflow as tf
73
+ from tensorflow import keras
74
+
75
+ # ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜ ์ •์˜
76
+ model = keras.Sequential([
77
+ # Input: (28, 28, 1) ์ด๋ฏธ์ง€
78
+ # ์ฒซ ๋ฒˆ์งธ Conv-Pool ๋ธ”๋ก
79
+ keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1)),
80
+ keras.layers.MaxPooling2D(pool_size=(2, 2)),
81
+
82
+ # ๋‘ ๋ฒˆ์งธ Conv-Pool ๋ธ”๋ก
83
+ keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
84
+ keras.layers.MaxPooling2D(pool_size=(2, 2)),
85
+
86
+ # ๋ถ„๋ฅ˜๊ธฐ(Classifier)
87
+ keras.layers.Flatten(),
88
+ keras.layers.Dropout(0.5),
89
+ keras.layers.Dense(10, activation="softmax"),
90
+ ])
91
+ ```
92
+ ์ด์ œ, ์•ž์„œ ์„ค๋ช…ํ–ˆ๋˜ ์ด๋ก ์ด ์ด ์ฝ”๋“œ์— ์–ด๋–ป๊ฒŒ ๋…น์•„์žˆ๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.
93
+
94
+ - **ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต(Conv2D)**
95
+ ```python
96
+ keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1))
97
+ ```
98
+ ์ด ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ, ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต์„ ํ˜•์„ฑ, ๋‹ค์Œ ์•„์ด๋””๏ฟฝ๏ฟฝ๏ฟฝ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
99
+ 1. ์ง€์—ญ ์ˆ˜์šฉ์˜์—ญ
100
+ ```kernel_size(3, 3)```์„ ํ†ตํ•ด์„œ ์ด๋ฏธ์ง€ ์ „์ฒด๊ฐ€ ์•„๋‹Œ 3 * 3 ํฌ๊ธฐ์˜ ์ž‘์€ ์˜์—ญ๋งŒ ๋ณด๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.
101
+ ์ด๋ ‡๊ฒŒ, ์ง€์—ญ์  ์ˆ˜์šฉ์˜์—ญ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค
102
+
103
+ 2. ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ 
104
+ ```Conv2D``` ๊ณ„์ธต์€ 32๊ฐœ์˜ ํ•„ํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
105
+ 3 * 3ํ•„ํ„ฐ๋Š” ๊ณ ์œ ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ(๊ฐ€์ค‘์น˜)์„ธํŠธ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์ด ํ•„ํ„ฐ ํ•˜๋‚˜๊ฐ€ ์ด๋ฏธ์ง€ ์ „์ฒด๋ฅผ ์Šค์บ”ํ•ฉ๋‹ˆ๋‹ค.
106
+ ๋งŒ์•ฝ, ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ ๊ฐ€ ์—†๋‹ค๋ฉด, ๊ฐ 3 * 3 ์œ„์น˜๋งˆ๋‹ค ๋ณ„๋„์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฏ€๋กœ ํฌ๊ธฐ๊ฐ€ ์—„์ฒญ ์ปค์ง‘๋‹ˆ๋‹ค.
107
+ ํ•˜์ง€๋งŒ, ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ  ๋•๋ถ„์—, ์ด ๊ฒฝ์šฐ์—์„œ ```(3 * 3 * 1 +1) * 32 = 320``` ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋งŒ์œผ๋กœ ์ด๋ฏธ์ง€ ์ „์ฒด์˜ ํŠน์ง•์„ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
108
+
109
+ - **ํ’€๋ง ๊ณ„์ธต(MaxPooling2D)**
110
+ ```python
111
+ keras.layers.MaxPooling2D(pool_size=(2, 2))
112
+ ```
113
+ ์•ž์„  ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต์ด ์ƒ์„ฑํ•œ ํŠน์ง•๋งต์„ 2* 2 ํฌ๊ธฐ์˜ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ์˜์—ญ์—์„œ ๊ฐ€์žฅ ํฐ ๊ฐ’๋งŒ ๋‚จ๊ธฐ๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.
114
+ ์ด๋ฅผ ํ†ตํ•ด ๋งต ํฌ๊ธฐ๊ฐ€ ์ ˆ๋ฐ˜์œผ๋กœ ์ค„์–ด๋“œ๋Š” **๋‹ค์šด ์ƒ˜ํ”Œ๋ง**์ด ์ผ์–ด๋‚˜๊ณ , ๊ณ„์‚ฐ ํšจ์œจ์„ฑ์ด ๋†’์•„์ ธ ๋ชจ๋ธ ํ•™์Šต์ด ๋” ๊ฐ€๋ฒผ์›Œ ์ง‘๋‹ˆ๋‹ค.
115
+
116
+ - **์™„์ „ ์—ฐ๊ฒฐ ๊ณ„์ธต(Dense Layer)**
117
+ ```python
118
+ keras.layers.Flatten()
119
+ keras.layers.Dense(10, activation="softmax")
120
+ ```
121
+ ์ตœ์ข… ๋ถ„๋ฅ˜๊ธฐ ์ด๋ฉฐ, ์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต ์ž…๋‹ˆ๋‹ค.
122
+ 1. ```keras.layers.Flatten()```
123
+ ์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต์€ 1์ฐจ์› ๋ฐฑํ„ฐ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—, Flastten ๊ณ„์ธต์ด ๋จผ์ € ๋“ค์–ด์™€ 2์ฐจ์› ํ˜•ํƒœ์˜ ํŠน์ง• ๋งต์„ ํ•œ ์ค„๋กœ ํŽผ์ณ์ค๋‹ˆ๋‹ค.
124
+
125
+ 2. ```keras.layers.Dense(10, activation="softmax")```
126
+ ์ด ์ฝ”๋“œ๊ฐ€ ์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต์ด๋ฉฐ, ๋ณดํ†ต Dense Layer ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
127
+ ํŠน์ง•๋ฐฑํ„ฐ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ 10๊ฐœ์˜ ํด๋ž˜์Šค ์ค‘ ์–ด๋А ํด๋ž˜์Šค์— ํ• ๋‹นํ• ์ง€ ์ตœ์ข…์ ์œผ๋กœ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
128
+ ```activation="softmax"```๋Š” ๊ฐ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์˜ˆ์ธก๊ฐ’์„ 0 ๊ณผ 1 ์‚ฌ์ด์˜ ํ™•๋ฅ ๊ฐ’์œผ๋กœ ํ•˜๊ฒŒ ํ•˜์—ฌ ๋ชจ๋“  ํ™•๋ฅ ์˜ ํ•ฉ์ด `์ด ๋˜๋„๋ก ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.
129
+
130
+ ---
131
+
132
+ ## 3. ์ง์ ‘ CNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ
133
+ ์ด์ œ, ์ง์ ‘ CNN ํ•™์Šต ์ฝ”๋“œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ๊ตฌํ˜„ํ•ด ๋ด…์‹œ๋‹ค.
134
+
135
+ **1๋‹จ๊ณ„. ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ**
136
+ ๋ชจ๋ธ์ด ํ•™์Šตํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ค๋‹ˆ๋‹ค.
137
+ ์ด๋ฒˆ์—”, ์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š” MNIST ์†๊ธ€์”จ ์ˆซ์ž ๋ฐ์ดํ„ฐ์…‹์„ ๊ฐ€์ ธ์™€ ์ ์ ˆํ•œ ํ˜•ํƒœ๋กœ ์ „์ฒ˜๋ฆฌ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
138
+
139
+ ```python
140
+ import numpy as np
141
+ import tensorflow as tf
142
+ from tensorflow import keras
143
+ from keras import layers
144
+
145
+ # Keras ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด MNIST ๋ฐ์ดํ„ฐ์…‹์„ ์†์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
146
+ (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
147
+
148
+ # ์ •๊ทœํ™”: ํ”ฝ์…€ ๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ 0~255์—์„œ 0~1 ์‚ฌ์ด๋กœ ์กฐ์ •ํ•˜์—ฌ ํ•™์Šต ์•ˆ์ •์„ฑ ๋ฐ ์†๋„๋ฅผ ๋†’์ž…๋‹ˆ๋‹ค.
149
+ x_train = x_train.astype("float32") / 255.0
150
+ x_test = x_test.astype("float32") / 255.0
151
+
152
+ # ์ฑ„๋„ ์ฐจ์› ์ถ”๊ฐ€: ํ‘๋ฐฑ ์ด๋ฏธ์ง€(์ฑ„๋„ 1)์˜ ์ฐจ์›์„ ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
153
+ x_train = np.expand_dims(x_train, -1)
154
+ x_test = np.expand_dims(x_test, -1)
155
+
156
+ # ๋ ˆ์ด๋ธ” ์›-ํ•ซ ์ธ์ฝ”๋”ฉ: ์ˆซ์ž '5'๋ฅผ [0,0,0,0,0,1,0,0,0,0] ํ˜•ํƒœ์˜ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
157
+ num_classes = 10
158
+ y_train = keras.utils.to_categorical(y_train, num_classes)
159
+ y_test = keras.utils.to_categorical(y_test, num_classes)
160
+ ```
161
+
162
+ **2๋‹จ๊ณ„. ๋ชจ๋ธ ์ปดํŒŒ์ผ**
163
+ ๋ชจ๋ธ ์•„ํ‚คํ…์ณ๋ฅผ ์ •์˜ํ•˜๊ณ  ๋ชจ๋ธ์„ ์–ด๋–ป๊ฒŒ ํ•™์Šต์‹œํ‚ฌ์ง€์— ๋Œ€ํ•ด ์ •ํ•ฉ๋‹ˆ๋‹ค.
164
+ ```python
165
+ model = keras.Sequential([
166
+ keras.Input(shape=(28, 28, 1)), # ์ž…๋ ฅ ๋ ˆ์ด์–ด
167
+ layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
168
+ layers.MaxPooling2D(pool_size=(2, 2)),
169
+ layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
170
+ layers.MaxPooling2D(pool_size=(2, 2)),
171
+ layers.Flatten(),
172
+ layers.Dropout(0.5),
173
+ layers.Dense(num_classes, activation="softmax")
174
+ ])
175
+
176
+ model.compile(
177
+ # ์†์‹ค ํ•จ์ˆ˜(Loss Function): ๋ชจ๋ธ์˜ ์˜ˆ์ธก์ด ์ •๋‹ต๊ณผ ์–ผ๋งˆ๋‚˜ ๋‹ค๋ฅธ์ง€ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.
178
+ loss="categorical_crossentropy",
179
+ # ์˜ตํ‹ฐ๋งˆ์ด์ €(Optimizer): ์†์‹ค์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
180
+ optimizer="adam",
181
+ # ํ‰๊ฐ€์ง€ํ‘œ(Metrics): ํ›ˆ๋ จ ๊ณผ์ •์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ง€ํ‘œ๋กœ, ์ •ํ™•๋„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
182
+ metrics=["accuracy"]
183
+ )
184
+ ```
185
+
186
+ **3๋‹จ๊ณ„. ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€**
187
+ ```model.fit()```ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ํ•™์Šต์„ ์‹œ์ž‘ํ•˜๊ณ , ํ•™์Šต์ด ๋๋‚œ ํ›„ ```model.evaluate()```๋กœ ์ตœ์ข… ์„ฑ๋Šฅ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
188
+ ```python
189
+ batch_size = 128
190
+ epochs = 15
191
+
192
+ # ๋ชจ๋ธ ํ•™์Šต ์‹คํ–‰
193
+ history = model.fit(
194
+ x_train, y_train,
195
+ batch_size=batch_size,
196
+ epochs=epochs,
197
+ validation_data=(x_test, y_test)
198
+ )
199
+
200
+ # ํ•™์Šต ์™„๋ฃŒ ํ›„ ์ตœ์ข… ์„ฑ๋Šฅ ํ‰๊ฐ€
201
+ score = model.evaluate(x_test, y_test, verbose=0)
202
+ print(f"\nTest loss: {score[0]:.4f}")
203
+ print(f"Test accuracy: {score[1]:.4f}")
204
+ ```
205
+
206
+ **4๋‹จ๊ณ„. ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅํ•˜๊ธฐ**
207
+ ๋ชจ๋ธ์„ ์ €์žฅํ•˜๊ณ , ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
208
+ ```python
209
+ # ๋ชจ๋ธ์˜ ๊ตฌ์กฐ, ๊ฐ€์ค‘์น˜, ํ•™์Šต ์„ค์ •์„ ๋ชจ๋‘ '.keras' ํŒŒ์ผ ํ•˜๋‚˜์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
210
+ model.save("my_keras_model.keras")
211
+ print("\nModel saved to my_keras_model.keras")
212
+ ```
213
+
214
+ ์œ„ ๋‹จ๊ณ„๋ฅผ ์ „๋ถ€ ์ˆ˜ํ–‰ํ•œ ๋ชจ๋ธ์ด ์ง€๊ธˆ ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋“ค์–ด์žˆ๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ์ด์–ด์„œ, ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด ๋ณผ ๋–„, ์œ„ ์ฝ”๋“œ๋ฅผ์€ ์ง์ ‘ ์‹คํ–‰ํ•˜์ง€ ๋ง๊ณ , ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ฃผ์„ธ์š”!
215
+ ๋งŒ์ผ, ์œ„ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ง์ ‘ ๋”ฅ๋Ÿฌ๋‹์„ ์‹œ์ผญ๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด, Files์˜
216
+ train.py๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ฃผ์„ธ์š”!
217
+
218
+ **5๋‹จ๊ณ„. ๋ชจ๋ธ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ**
219
+ ์•ž์„  ๋‹จ๊ณ„๋“ค์„ ๊ฑฐ์ณ ์™„์„ฑํ•œ ๋ชจ๋ธ์ด ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ํŽ˜์ด์ง€์— ์˜ฌ๋ผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
220
+ ์ด์ œ, ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ํŽ˜์ด์ง€์˜ ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์™€์„œ, ์ง์ ‘ ์‚ฌ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
221
+ Files์˜ test.py๋ฅผ ์‹คํ–‰์‹œ์ผœ ๋ณด์„ธ์š”!!
222
+ ์ง์ ‘ ์ค€๋น„ํ•œ ์ˆซ์ž ์†๊ธ€์”จ๋ฅผ ๋ชจ๋ธ์— ์ž…๋ ฅ์œผ๋กœ ๋„ฃ์œผ๋ฉด, ๊ทธ ์ˆซ์ž๊ฐ€ ์–ด๋–ค ์ˆซ์ž์ธ์ง€ ๋งž์ถฐ์ค„ ๊ฒ๋‹ˆ๋‹ค!!
223
+ ์ฝ”๋“œ ์‹คํ–‰์„ ์œ„ํ•ด์„œ, ์ด ์ข…์†์„ฑ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
224
+ cmd ์ฐฝ์„ ์—ด๊ณ , ์ด ์ฝ”๋“œ๋ฅผ ๋„ฃ๊ณ  ์‹คํ–‰ํ•˜์—ฌ ๋จผ์ € ์ข…์†์„ฑ์„ ๋ฐ›์•„์ฃผ์„ธ์š”
225
+ ```bash
226
+ pip install tensorflow huggingface_hub Pillow numpy
227
+ ```
228
+ ## 4. ๋‚˜๋งŒ์˜ CNN ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ
229
+ ์ด์ œ, ์„ฑ๋Šฅ์„ ๋” ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•ด, ๋˜ ์›ํ•˜๋Š” ๋ชฉ์ ์— ๋งž๊ฒŒ ๋ชจ๋ธ์„ ์ˆ˜์ •ํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค.
230
+
231
+ - **ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹**
232
+ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” batch_size, epochs, ์˜ตํ‹ฐ๋‚˜์ด์ €์˜ leaarning_rate๋“ฑ์„ ์กฐํ•ฉํ•˜์—ฌ ์ตœ์ ํ™” ํ•ฉ๋‹ˆ๋‹ค.
233
+ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๊ฑด๋“œ๋ ค์„œ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
234
+ ```python
235
+ # ์˜ˆ: Adam ์˜ตํ‹ฐ๋งˆ์ด์ €์˜ ํ•™์Šต๋ฅ (learning_rate)์„ ์ง์ ‘ ์„ค์ •
236
+ optimizer = keras.optimizers.Adam(learning_rate=0.001)
237
+ model.compile(loss="categorical_crossentropy", optimizer=optimizer, metrics=["accuracy"])
238
+ ```
239
+
240
+ - **๋ชจ๋ธ ๊ตฌ์กฐ ๋ณ€๊ฒฝ**
241
+ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์„ ์œ„ํ•ด์„œ, ```Conv2D-MaxPooling2D``` ๋ธ”๋ก์„ ๋” ๊นŠ๊ฒŒ, ```Conv2D``` ๊ณ„์ธต์˜ ํ•„ํ„ฐ ์ˆ˜๋ฅผ ๋Š˜๋ ค ๋” ํ’๋ถ€ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
242
+ ```python
243
+ model = keras.Sequential([
244
+ keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1)),
245
+ keras.layers.MaxPooling2D(pool_size=(2, 2)),
246
+ # ๋ธ”๋ก ์ถ”๊ฐ€!
247
+ keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
248
+ keras.layers.MaxPooling2D(pool_size=(2, 2)),
249
+ # ํ•„ํ„ฐ ์ˆ˜๋ฅผ ๋Š˜๋ฆฐ ๋ธ”๋ก ์ถ”๊ฐ€!
250
+ keras.layers.Conv2D(128, kernel_size=(3, 3), activation="relu"),
251
+ keras.layers.MaxPooling2D(pool_size=(2, 2)),
252
+
253
+ keras.layers.Flatten(),
254
+ keras.layers.Dense(128, activation='relu'), # Dense ์ธต ์ถ”๊ฐ€
255
+ keras.layers.Dropout(0.5),
256
+ keras.layers.Dense(10, activation="softmax"),
257
+ ])
258
+ ```
259
+
260
+ - **์ „์ดํ•™์Šต**
261
+ ์•„์ฃผ ํฐ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ํ•™์Šต๋œ ์ด๋ฏธ ๊ฐ•๋ ฅํ•œ ๋ชจ๋ธ์„ ๊ฐ€์ ธ์™€, ๊ทธ ๋ชจ๋ธ์ด ํ•™์Šตํ•œ ์ด๋ฏธ์ง€ ํŠน์ง•์ถ”์ถœ๋Šฅ๋ ฅ๋งŒ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์ž…๋‹ˆ๋‹ค.
262
+ ์ ์€ ๋ฐ์ดํ„ฐ๋กœ๋„ ๋†’์€ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
263
+ ```python
264
+ # Keras์—์„œ ์ œ๊ณตํ•˜๋Š” ์‚ฌ์ „ ํ•™์Šต๋œ VGG16 ๋ชจ๋ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ (๋ถ„๋ฅ˜๊ธฐ๋Š” ์ œ์™ธ)
265
+ base_model = keras.applications.VGG16(
266
+ weights='imagenet', # ImageNet์œผ๋กœ ์‚ฌ์ „ ํ•™์Šต๋œ ๊ฐ€์ค‘์น˜ ์‚ฌ์šฉ
267
+ include_top=False, # ๋ถ„๋ฅ˜๊ธฐ(Dense ์ธต)๋Š” ์ œ์™ธ
268
+ input_shape=(32, 32, 3) # VGG16์€ ์ตœ์†Œ 32x32 ์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Œ
269
+ )
270
+
271
+ # ๋ถˆ๋Ÿฌ์˜จ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋Š” ๊ณ ์ •(freeze)
272
+ base_model.trainable = False
273
+
274
+ # ์ƒˆ๋กœ์šด ๋ถ„๋ฅ˜๊ธฐ ์ถ”๊ฐ€
275
+ model = keras.Sequential([
276
+ base_model,
277
+ keras.layers.Flatten(),
278
+ keras.layers.Dense(256, activation='relu'),
279
+ keras.layers.Dropout(0.5),
280
+ keras.layers.Dense(10, activation='softmax') # ๋‚˜์˜ ๋ฌธ์ œ์— ๋งž๋Š” ์ถœ๋ ฅ์ธต
281
+ ])
282
+
283
+ # ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ ๋ถ„๋ฅ˜๊ธฐ ๋ถ€๋ถ„๋งŒ ํ•™์Šต
284
+ model.compile(...)
285
+ model.fit(...)
286
+ ```
287
+
288
+ ## 5. ๊ฒฐ๋ก 
289
+ ์˜ค๋Š˜์€, ์ด๋ ‡๊ฒŒ CNN ๋ชจ๋ธ์— ๋Œ€ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.
290
+ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์— ํŠนํ™”๋œ CNN์€ ๋‚˜์ค‘์— ํŠธ๋žœ์Šคํฌ๋จธ ๋ชจ๋ธ์ด ๋‚˜์˜ค๋ฉด์„œ Vit๋ผ๋Š” ๋ชจ๋ธ์ด ๋งŒ๋“ค์–ด์ง€๋Š”๋ฐ ํฐ ๊ธฐ์—ฌ๋ฅผ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
291
+ ์ด๋ ‡๋“ฏ ๊ทผ๋ณธ ๋„˜์น˜๋Š” CNN ๋งŽ์ด ์‚ฌ๋ž‘ํ•ด ์ฃผ์„ธ์š”!!
292
+ ๋‹ค์Œ์—๋Š” RNN๋ชจ๋ธ๋กœ ๋Œ์•„์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค
293
+ ์˜ค๋Š˜๋„ ์ข‹์€ํ•˜๋ฃจ ๋ณด๋‚ด์„ธ์šฉ!!
test.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ # hf_hub_download ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด import ํ•ฉ๋‹ˆ๋‹ค.
3
+ from huggingface_hub import hf_hub_download
4
+ from PIL import Image, ImageOps
5
+ import numpy as np
6
+ import os
7
+
8
+ def load_model_from_hf(model_id, model_filename="model.keras"):
9
+ """
10
+ Hugging Face Hub์—์„œ Keras ๋ชจ๋ธ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•œ ํ›„,
11
+ ๋กœ์ปฌ์— ์ €์žฅ๋œ ํŒŒ์ผ์„ ์ด์šฉํ•ด ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
12
+ """
13
+ try:
14
+ print(f"Downloading model '{model_id}' from Hugging Face Hub...")
15
+ # 1. Hugging Face Hub์—์„œ ๋ชจ๋ธ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ
16
+ # ์ด ํ•จ์ˆ˜๋Š” ๋‹ค์šด๋กœ๋“œ๋œ ํŒŒ์ผ์ด ์ €์žฅ๋œ ๋กœ์ปฌ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
17
+ model_path = hf_hub_download(repo_id=model_id, filename=model_filename)
18
+ print(f"Model downloaded to: {model_path}")
19
+
20
+ # 2. ๋กœ์ปฌ์— ์ €์žฅ๋œ ๋ชจ๋ธ ํŒŒ์ผ ๋กœ๋“œ
21
+ print("Loading model from local file...")
22
+ model = tf.keras.models.load_model(model_path)
23
+ print("Model loaded successfully!")
24
+ return model
25
+
26
+ except Exception as e:
27
+ print(f"Error loading model: {e}")
28
+ print("Please check if the model ID and filename are correct on Hugging Face Hub.")
29
+ return None
30
+
31
+ def preprocess_image(image_path):
32
+ """
33
+ ์‚ฌ์šฉ์ž ์ด๋ฏธ์ง€๋ฅผ MNIST ๋ฐ์ดํ„ฐ์…‹ ํ˜•์‹์— ๋งž๊ฒŒ ์ „์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
34
+ """
35
+ try:
36
+ # 1. ์ด๋ฏธ์ง€ ์—ด๊ธฐ
37
+ img = Image.open(image_path)
38
+
39
+ # 2. ํ‘๋ฐฑ(Grayscale)์œผ๋กœ ๋ณ€ํ™˜
40
+ img = img.convert('L')
41
+
42
+ # 3. ์ƒ‰์ƒ ๋ฐ˜์ „ (MNIST๋Š” ํฐ์ƒ‰ ๊ธ€์”จ/๊ฒ€์€ ๋ฐฐ๊ฒฝ, ์‚ฌ์šฉ์ž๋Š” ๋ณดํ†ต ๊ฒ€์€ ๊ธ€์”จ/ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ)
43
+ if np.mean(np.array(img)) > 128:
44
+ img = ImageOps.invert(img)
45
+
46
+ # 4. 28x28 ํฌ๊ธฐ๋กœ ๋ฆฌ์‚ฌ์ด์ฆˆ
47
+ img = img.resize((28, 28), Image.Resampling.LANCZOS)
48
+
49
+ # 5. Numpy ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  0~1 ์‚ฌ์ด ๊ฐ’์œผ๋กœ ์ •๊ทœํ™”
50
+ img_array = np.array(img).astype('float32') / 255.0
51
+
52
+ # 6. ๋ชจ๋ธ์˜ ์ž…๋ ฅ ํ˜•ํƒœ์— ๋งž๊ฒŒ ์ฐจ์› ํ™•์žฅ (1, 28, 28, 1)
53
+ processed_img = np.expand_dims(img_array, axis=0)
54
+ processed_img = np.expand_dims(processed_img, axis=-1)
55
+
56
+ return processed_img
57
+ except FileNotFoundError:
58
+ print(f"Error: The file '{image_path}' was not found.")
59
+ return None
60
+ except Exception as e:
61
+ print(f"Error processing image: {e}")
62
+ return None
63
+
64
+ def main():
65
+ # Hugging Face์— ์—…๋กœ๋“œ๋œ ๋ชจ๋ธ ID
66
+ model_id = "OneclickAI/CNN_test_Model"
67
+
68
+ # ๋ชจ๋ธ ๋กœ๋“œ (์ˆ˜์ •๋œ ํ•จ์ˆ˜ ํ˜ธ์ถœ)
69
+ # ์ด์ „ train.py์—์„œ model.save("my_keras_model.keras")๋กœ ์ €์žฅํ–ˆ์œผ๋ฏ€๋กœ,
70
+ # Hub์— ์˜ฌ๋ผ๊ฐ„ ํŒŒ์ผ ์ด๋ฆ„์€ 'my_keras_model.keras'์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
71
+ # ๋งŒ์•ฝ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ์˜ฌ๋ ธ๋‹ค๋ฉด ํ•ด๋‹น ํŒŒ์ผ๋ช…์œผ๋กœ ์ˆ˜์ •ํ•ด์ฃผ์„ธ์š”.
72
+ # (Hugging Face Hub์—์„œ๋Š” ๋ณดํ†ต 'model.keras' ๋ผ๋Š” ์ด๋ฆ„์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค)
73
+ model = load_model_from_hf(model_id, model_filename="my_keras_model.keras")
74
+
75
+ if model is None:
76
+ return # ๋ชจ๋ธ ๋กœ๋“œ ์‹คํŒจ ์‹œ ์ข…๋ฃŒ
77
+
78
+ # ์‚ฌ์šฉ์ž์—๊ฒŒ ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ๋ฅผ ๊ณ„์†ํ•ด์„œ ์ž…๋ ฅ๋ฐ›์Œ
79
+ while True:
80
+ user_input = input("\nPlease enter the path to your image (or type 'exit' to quit): ")
81
+
82
+ if user_input.lower() == 'exit':
83
+ break
84
+
85
+ if not os.path.exists(user_input):
86
+ print(f"File not found at '{user_input}'. Please check the path and try again.")
87
+ continue
88
+
89
+ # ์ด๋ฏธ์ง€ ์ „์ฒ˜๋ฆฌ
90
+ processed_image = preprocess_image(user_input)
91
+
92
+ if processed_image is not None:
93
+ # ๋ชจ๋ธ ์˜ˆ์ธก ์ˆ˜ํ–‰
94
+ predictions = model.predict(processed_image)
95
+
96
+ # ๊ฐ€์žฅ ๋†’์€ ํ™•๋ฅ ์„ ๊ฐ€์ง„ ํด๋ž˜์Šค(์ˆซ์ž)๋ฅผ ์ฐพ์Œ
97
+ predicted_digit = np.argmax(predictions[0])
98
+ confidence = np.max(predictions[0]) * 100
99
+
100
+ print("\n--- Prediction Result ---")
101
+ print(f"Predicted Digit: {predicted_digit}")
102
+ print(f"Confidence: {confidence:.2f}%")
103
+ print("-------------------------")
104
+
105
+ if __name__ == "__main__":
106
+ main()
train.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import tensorflow as tf
3
+ from tensorflow import keras
4
+ from keras import layers
5
+
6
+ # Keras ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด MNIST ๋ฐ์ดํ„ฐ์…‹์„ ์†์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
7
+ (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
8
+
9
+ # ์ •๊ทœํ™”: ํ”ฝ์…€ ๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ 0~255์—์„œ 0~1 ์‚ฌ์ด๋กœ ์กฐ์ •ํ•˜์—ฌ ํ•™์Šต ์•ˆ์ •์„ฑ ๋ฐ ์†๋„๋ฅผ ๋†’์ž…๋‹ˆ๋‹ค.
10
+ x_train = x_train.astype("float32") / 255.0
11
+ x_test = x_test.astype("float32") / 255.0
12
+
13
+ # ์ฑ„๋„ ์ฐจ์› ์ถ”๊ฐ€: ํ‘๋ฐฑ ์ด๋ฏธ์ง€(์ฑ„๋„ 1)์˜ ์ฐจ์›์„ ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
14
+ x_train = np.expand_dims(x_train, -1)
15
+ x_test = np.expand_dims(x_test, -1)
16
+
17
+ # ๋ ˆ์ด๋ธ” ์›-ํ•ซ ์ธ์ฝ”๋”ฉ: ์ˆซ์ž '5'๋ฅผ [0,0,0,0,0,1,0,0,0,0] ํ˜•ํƒœ์˜ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
18
+ num_classes = 10
19
+ y_train = keras.utils.to_categorical(y_train, num_classes)
20
+ y_test = keras.utils.to_categorical(y_test, num_classes)
21
+
22
+ model = keras.Sequential([
23
+ keras.Input(shape=(28, 28, 1)), # ์ž…๋ ฅ ๋ ˆ์ด์–ด
24
+ layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
25
+ layers.MaxPooling2D(pool_size=(2, 2)),
26
+ layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
27
+ layers.MaxPooling2D(pool_size=(2, 2)),
28
+ layers.Flatten(),
29
+ layers.Dropout(0.5),
30
+ layers.Dense(num_classes, activation="softmax")
31
+ ])
32
+
33
+ model.compile(
34
+ # ์†์‹ค ํ•จ์ˆ˜(Loss Function): ๋ชจ๋ธ์˜ ์˜ˆ์ธก์ด ์ •๋‹ต๊ณผ ์–ผ๋งˆ๋‚˜ ๋‹ค๋ฅธ์ง€ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.
35
+ loss="categorical_crossentropy",
36
+ # ์˜ตํ‹ฐ๋งˆ์ด์ €(Optimizer): ์†์‹ค์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
37
+ optimizer="adam",
38
+ # ํ‰๊ฐ€์ง€ํ‘œ(Metrics): ํ›ˆ๋ จ ๊ณผ์ •์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ง€ํ‘œ๋กœ, ์ •ํ™•๋„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
39
+ metrics=["accuracy"]
40
+ )
41
+
42
+ batch_size = 128
43
+ epochs = 15
44
+
45
+ # ๋ชจ๋ธ ํ•™์Šต ์‹คํ–‰
46
+ history = model.fit(
47
+ x_train, y_train,
48
+ batch_size=batch_size,
49
+ epochs=epochs,
50
+ validation_data=(x_test, y_test)
51
+ )
52
+
53
+ # ํ•™์Šต ์™„๋ฃŒ ํ›„ ์ตœ์ข… ์„ฑ๋Šฅ ํ‰๊ฐ€
54
+ score = model.evaluate(x_test, y_test, verbose=0)
55
+ print(f"\nTest loss: {score[0]:.4f}")
56
+ print(f"Test accuracy: {score[1]:.4f}")
57
+
58
+ # ๋ชจ๋ธ์˜ ๊ตฌ์กฐ, ๊ฐ€์ค‘์น˜, ํ•™์Šต ์„ค์ •์„ ๋ชจ๋‘ '.keras' ํŒŒ์ผ ํ•˜๋‚˜์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
59
+ model.save("my_keras_model.keras")
60
+ print("\nModel saved to my_keras_model.keras")