File size: 14,195 Bytes
f735c49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
---

license: apache-2.0
---


์•ˆ๋…•ํ•˜์„ธ์š” Oneclick AI ์ž…๋‹ˆ๋‹ค!!  
์˜ค๋Š˜์€, CNN ๋ชจ๋ธ์— ๋Œ€ํ•ด์„œ ๊นŠ๊ฒŒ ์•Œ์•„๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณผ๊นŒ ํ•ฉ๋‹ˆ๋‹ค.  

๋”ฅ๋Ÿฌ๋‹์— ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ ์ด์œ ๊ฐ€ ๋ฐ”๋กœ CNN์˜ ํ•ฉ์„ฑ๊ณฑ ์‹ ๊ฒฝ๋ง (Convolutional Neural Network, CNN) ๋•๋ถ„์ธ๋ฐ์š”, ์˜ค๋Š˜์€ ์ด ์‹ ๊ฒฝ๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€, CNN์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์ง„ ์†์˜ ์ˆซ์ž๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.  

---

## ๋ชฉ์ฐจ  
1. CNN ํ•ต์‹ฌ ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ  
    - ์™œ ์ด๋ฏธ์ง€์— CNN์„ ์‚ฌ์šฉํ• ๊นŒ?  
    - CNN์˜ ํ•ต์‹ฌ : ์ง€์—ญ ์ˆ˜์šฉ ์˜์—ญ๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ   
    - CNN์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ  
2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ  
    - keras๋กœ ๊ตฌํ˜„ํ•œ CNN ๋ชจ๋ธ ์•„ํ‚คํ…์ณ  
    - model.summary()๋กœ ๊ตฌ์กฐ ํ™•์ธํ•˜๊ธฐ  
3. ์ง์ ‘ CNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ  
    - 1๋‹จ๊ณ„ : ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ  
    - 2๋‹จ๊ณ„ : ๋ชจ๋ธ ์ปดํŒŒ์ผ  
    - 3๋‹จ๊ณ„ : ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€  
    - 4๋‹จ๊ณ„ : ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅํ•˜๊ธฐ  
    - 5๋‹จ๊ณ„ : ๋ชจ๋ธ ์‚ฌ์šฉํ•˜๊ธฐ 
4. ๋‚˜๋งŒ์˜ CNN ๋ชจ๋ธ ๋งŒ๋“ค์–ด๋ณด๊ธฐ  
    - ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹  
    - ๋ชจ๋ธ ๊ตฌ์กฐ ๋ณ€๊ฒฝํ•˜๊ธฐ  
    - ์ „์ดํ•™์Šต์œผ๋กœ ์„ฑ๋Šฅ ๊ทน๋Œ€ํ™” ํ•˜๊ธฐ  
5. ๊ฒฐ๋ก 
---

## 1. CNN ํ•ต์‹ฌ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ
๋“ค์–ด๊ฐ€๊ธฐ ์•ž์„œ, CNN ์ด ์–ด๋–ค ์›๋ฆฌ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€ ๋จผ์ € ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.  

**์™œ ์ด๋ฏธ์ง€์— CNN์„ ์‚ฌ์šฉํ• ๊นŒ??**
๋‹จ์ˆœํ•œ ์‹ ๊ฒฝ๋ง(Fully Connected Layer)์— ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅํ•˜๋ ค๋ฉด, 2์ฐจ์›์ธ ์ด๋ฏธ์ง€๋ฅผ 1์ฐจ์›์˜ ๊ธด ๋ฐ์ดํ„ฐ๋กœ ํŽผ์น˜๋Š” ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ ๊ณผ์ •์ด ๊ผญ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.  
์ด ๊ณผ์ •์—์„œ ํ”ฝ์…€ ๊ฐ„์˜ ๊ณต๊ฐ„์ ์ธ ์ •๋ณด๊ฐ€ ์ „๋ถ€ ํŒŒ๊ดด๋ฉ๋‹ˆ๋‹ค.  
์ด๋Š” ์–ด๋–ค ํ”ฝ์…€์ด ์„œ๋กœ ์ด์›ƒํ•ด ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์–ด์ ธ์„œ ๋ˆˆ์ด ์ฝ” ์˜†์— ์žˆ๋‹ค๋Š” ์œ„์น˜์ •๋ณด ๊ฐ™์€ ๋‚ด์šฉ์ด ๊ฐ€๋ผ์ € ๋ฒ„๋ฆฐ๋‹ค๋Š” ์˜๋ฏธ ์ž…๋‹ˆ๋‹ค.  
CNN์€ ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ธ๊ฐ„์˜ ์‹œ์‹ ๊ฒฝ ๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฐฉํ•˜์—ฌ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.  

**CNN์˜ ํ•ต์‹ฌ ์•„์ด๋””์–ด**  
์ด๊ฒƒ์ด ๋ฐ”๋กœ ์ง€์—ญ์  ์ˆ˜์šฉ์˜์—ญ๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ  ์ž…๋‹ˆ๋‹ค.  
-  ์ง€์—ญ์  ์ˆ˜์šฉ ์˜์—ญ(Local Receptive Fields)  
์‹ ๊ฒฝ๋ง์˜ ๊ฐ ๋‰ด๋Ÿฐ์ด ์ด๋ฏธ์ง€ ์ „์ฒด๊ฐ€ ์•„๋‹Œ, ์ž‘์€ ์ผ๋ถ€์—๋งŒ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.  
์ด๋Š” ์ „์ฒด ํ”ฝ์…€์— ๋Œ€ํ•ด์„œ๊ฐ€ ์•„๋‹Œ ์˜ˆ์‹œ๋ฅผ ๋“ค๋ฉด 3 * 3 ํ”ฝ์…€์—๋งŒ ์ ์šฉ๋˜๋Š” ๋ฐฉ์‹์ธ๋ฐ์š”, ์ด๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์€ ์ด๋ฏธ์ง€์˜ ์ „์ฒด ๋งฅ๋ฝ๋ณด๋‹ค ์„ , ๋ชจ์„œ๋ฆฌ, ์งˆ๊ฐ๊ณผ ๊ฐ™์€ ์ง€์—ญ์ ์ธ ํŒจํ„ด์„ ๋จผ์ € ํ•™์Šตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.  

- ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ (Parameter Sharing)
CNN์€ ์ด๋ฏธ์ง€ ์ „์ฒด๋ฅผ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด์„œ ์Šค์บ”ํ•˜๋Š” ๋А๋‚Œ์œผ๋กœ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.  
๋”ฐ๋ผ์„œ, ํ•œ๋ฒˆ ์ด๋ฏธ์ง€์˜ ํŠน์ง•์„ ํ•™์Šตํ•˜๋ฉด, ์ด๋ฏธ์ง€์˜ ๋ชจ๋“  ์œ„์น˜์—์„œ ํ•ด๋‹น ํŠน์ง•์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  
์ด๋ฅผ ํ†ตํ•ด์„œ ํ•™์Šตํ•  ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜๋ฅผ ๋งŽ์ด ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  

**CNN์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ**
์•ž์„  ์•„์ด๋””์–ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, CNN์€ ๋‹ค์Œ 3๊ฐ€์ง€์˜ ๊ณ„์ธต์„ ์กฐํ•ฉํ•ด์„œ ๋งŒ๋“ญ๋‹ˆ๋‹ค.  
- ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต (Convolutional Layer)
ํ•™์Šต ๊ฐ€๋Šฅํ•œ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฏธ์ง€์˜ ํŠน์ง•์„ ์ถ”์ถœํ•ด ๋ƒ…๋‹ˆ๋‹ค.  
edge, corner ๋“ฑ์„ ์ถ”์ถœํ•˜์—ฌ ์–ป๋Š” ๊ฒฐ๊ณผ๋ฌผ์„ ํŠน์ง• ๋งต(Feature Map) ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.  

- ํ’€๋ง ๊ณ„์ธต (Pooling Layer)
์•ž์„œ ๋งŒ๋“  ๋งต์˜ ํฌ๊ธฐ๋ฅผ ์ค„์ด๋Š” ์š”์•ฝ๋‹จ๊ณ„ ์ž…๋‹ˆ๋‹ค.  
์ตœ๋Œ€ ํ’€๋ง(Max Pooling)์€ ํŠน์ • ์˜์—ญํ—ค์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŠน์ง•(๊ฐ€์žฅ ํฐ ๊ฐ’)๋งŒ ๋‚จ๊ฒจ ๊ณ„์‚ฐ๋Ÿ‰์„ ์ค„์ด๊ณ , ๋ชจ๋ธ์ด ํŠน์ง•์˜ ๋ฏธ์„ธํ•œ ์œ„์น˜ ๋ณ€ํ™”์— ๋œ ๋ฏผ๊ฐํ•ด ํ•˜๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.  

- ์™„์ „ ์—ฐ๊ฒฐ ๊ณ„์ธต (Dense Layer)
์ถ”์ถœ๋œ ํŠน์ง•๋“ค์„ ์ข…ํ•ฉํ•˜์—ฌ ์ตœ์ข…์ ์œผ๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์–ด๋–ค ํด๋ž˜์Šค์— ์†ํ•˜๋Š”์ง€ ๋ถ„๋ฅ˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.  

---

## 2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ
์ด์ œ, ์•ž์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ, ์‹ค์ œ TensorFlow Keras ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์‹ค๊ฐํ•ด ๋ด…์‹œ๋‹ค.  
๋‹ค์Œ์€, Keras๋กœ ๊ตฌํ˜„ํ•œ CNN ๋ชจ๋ธ ์•„ํ‚คํ…์ณ ์ž…๋‹ˆ๋‹ค.  
```python

import tensorflow as tf

from tensorflow import keras



# ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜ ์ •์˜

model = keras.Sequential([

    # Input: (28, 28, 1) ์ด๋ฏธ์ง€

    # ์ฒซ ๋ฒˆ์งธ Conv-Pool ๋ธ”๋ก

    keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1)),

    keras.layers.MaxPooling2D(pool_size=(2, 2)),

    

    # ๋‘ ๋ฒˆ์งธ Conv-Pool ๋ธ”๋ก

    keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),

    keras.layers.MaxPooling2D(pool_size=(2, 2)),

    

    # ๋ถ„๋ฅ˜๊ธฐ(Classifier)

    keras.layers.Flatten(),

    keras.layers.Dropout(0.5),

    keras.layers.Dense(10, activation="softmax"),

])

```
์ด์ œ, ์•ž์„œ ์„ค๋ช…ํ–ˆ๋˜ ์ด๋ก ์ด ์ด ์ฝ”๋“œ์— ์–ด๋–ป๊ฒŒ ๋…น์•„์žˆ๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.  

- **ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต(Conv2D)**
```python

keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1))

```
์ด ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ, ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต์„ ํ˜•์„ฑ, ๋‹ค์Œ ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.  
1. ์ง€์—ญ ์ˆ˜์šฉ์˜์—ญ  
```kernel_size(3, 3)```์„ ํ†ตํ•ด์„œ ์ด๋ฏธ์ง€ ์ „์ฒด๊ฐ€ ์•„๋‹Œ 3 * 3 ํฌ๊ธฐ์˜ ์ž‘์€ ์˜์—ญ๋งŒ ๋ณด๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.  
์ด๋ ‡๊ฒŒ, ์ง€์—ญ์  ์ˆ˜์šฉ์˜์—ญ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค

2. ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ 
```Conv2D``` ๊ณ„์ธต์€ 32๊ฐœ์˜ ํ•„ํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.  
3 * 3ํ•„ํ„ฐ๋Š” ๊ณ ์œ ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ(๊ฐ€์ค‘์น˜)์„ธํŠธ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์ด ํ•„ํ„ฐ ํ•˜๋‚˜๊ฐ€ ์ด๋ฏธ์ง€ ์ „์ฒด๋ฅผ ์Šค์บ”ํ•ฉ๋‹ˆ๋‹ค.  
๋งŒ์•ฝ, ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ ๊ฐ€ ์—†๋‹ค๋ฉด, ๊ฐ 3 * 3 ์œ„์น˜๋งˆ๋‹ค ๋ณ„๋„์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฏ€๋กœ ํฌ๊ธฐ๊ฐ€ ์—„์ฒญ ์ปค์ง‘๋‹ˆ๋‹ค.  
ํ•˜์ง€๋งŒ, ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ  ๋•๋ถ„์—, ์ด ๊ฒฝ์šฐ์—์„œ ```(3 * 3 * 1 +1) * 32 = 320``` ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋งŒ์œผ๋กœ ์ด๋ฏธ์ง€ ์ „์ฒด์˜ ํŠน์ง•์„ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  

- **ํ’€๋ง ๊ณ„์ธต(MaxPooling2D)**
```python

keras.layers.MaxPooling2D(pool_size=(2, 2))

```
์•ž์„  ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต์ด ์ƒ์„ฑํ•œ ํŠน์ง•๋งต์„ 2* 2 ํฌ๊ธฐ์˜ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ์˜์—ญ์—์„œ ๊ฐ€์žฅ ํฐ ๊ฐ’๋งŒ ๋‚จ๊ธฐ๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.  
์ด๋ฅผ ํ†ตํ•ด ๋งต ํฌ๊ธฐ๊ฐ€ ์ ˆ๋ฐ˜์œผ๋กœ ์ค„์–ด๋“œ๋Š” **๋‹ค์šด ์ƒ˜ํ”Œ๋ง**์ด ์ผ์–ด๋‚˜๊ณ , ๊ณ„์‚ฐ ํšจ์œจ์„ฑ์ด ๋†’์•„์ ธ ๋ชจ๋ธ ํ•™์Šต์ด ๋” ๊ฐ€๋ฒผ์›Œ ์ง‘๋‹ˆ๋‹ค.  

- **์™„์ „ ์—ฐ๊ฒฐ ๊ณ„์ธต(Dense Layer)**
```python

keras.layers.Flatten()

keras.layers.Dense(10, activation="softmax")

```
์ตœ์ข… ๋ถ„๋ฅ˜๊ธฐ ์ด๋ฉฐ, ์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต ์ž…๋‹ˆ๋‹ค.  
1. ```keras.layers.Flatten()```
์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต์€ 1์ฐจ์› ๋ฐฑํ„ฐ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—, Flastten ๊ณ„์ธต์ด ๋จผ์ € ๋“ค์–ด์™€ 2์ฐจ์› ํ˜•ํƒœ์˜ ํŠน์ง• ๋งต์„ ํ•œ ์ค„๋กœ ํŽผ์ณ์ค๋‹ˆ๋‹ค.  

2. ```keras.layers.Dense(10, activation="softmax")```
์ด ์ฝ”๋“œ๊ฐ€ ์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต์ด๋ฉฐ, ๋ณดํ†ต Dense Layer ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.  
ํŠน์ง•๋ฐฑํ„ฐ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ 10๊ฐœ์˜ ํด๋ž˜์Šค ์ค‘ ์–ด๋А ํด๋ž˜์Šค์— ํ• ๋‹นํ• ์ง€ ์ตœ์ข…์ ์œผ๋กœ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.  
```activation="softmax"```๋Š” ๊ฐ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์˜ˆ์ธก๊ฐ’์„ 0 ๊ณผ 1 ์‚ฌ์ด์˜ ํ™•๋ฅ ๊ฐ’์œผ๋กœ ํ•˜๊ฒŒ ํ•˜์—ฌ ๋ชจ๋“  ํ™•๋ฅ ์˜ ํ•ฉ์ด `์ด ๋˜๋„๋ก ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.  

---

## 3. ์ง์ ‘ CNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ
์ด์ œ, ์ง์ ‘ CNN ํ•™์Šต ์ฝ”๋“œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ๊ตฌํ˜„ํ•ด ๋ด…์‹œ๋‹ค.  

**1๋‹จ๊ณ„. ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ**  
๋ชจ๋ธ์ด ํ•™์Šตํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ค๋‹ˆ๋‹ค.  
์ด๋ฒˆ์—”, ์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š” MNIST ์†๊ธ€์”จ ์ˆซ์ž ๋ฐ์ดํ„ฐ์…‹์„ ๊ฐ€์ ธ์™€ ์ ์ ˆํ•œ ํ˜•ํƒœ๋กœ ์ „์ฒ˜๋ฆฌ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.  

```python

import numpy as np

import tensorflow as tf

from tensorflow import keras

from keras import layers



# Keras ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด MNIST ๋ฐ์ดํ„ฐ์…‹์„ ์†์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()



# ์ •๊ทœํ™”: ํ”ฝ์…€ ๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ 0~255์—์„œ 0~1 ์‚ฌ์ด๋กœ ์กฐ์ •ํ•˜์—ฌ ํ•™์Šต ์•ˆ์ •์„ฑ ๋ฐ ์†๋„๋ฅผ ๋†’์ž…๋‹ˆ๋‹ค.

x_train = x_train.astype("float32") / 255.0

x_test = x_test.astype("float32") / 255.0



# ์ฑ„๋„ ์ฐจ์› ์ถ”๊ฐ€: ํ‘๋ฐฑ ์ด๋ฏธ์ง€(์ฑ„๋„ 1)์˜ ์ฐจ์›์„ ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

x_train = np.expand_dims(x_train, -1)

x_test = np.expand_dims(x_test, -1)



# ๋ ˆ์ด๋ธ” ์›-ํ•ซ ์ธ์ฝ”๋”ฉ: ์ˆซ์ž '5'๋ฅผ [0,0,0,0,0,1,0,0,0,0] ํ˜•ํƒœ์˜ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

num_classes = 10

y_train = keras.utils.to_categorical(y_train, num_classes)

y_test = keras.utils.to_categorical(y_test, num_classes)

```

**2๋‹จ๊ณ„. ๋ชจ๋ธ ์ปดํŒŒ์ผ**  
๋ชจ๋ธ ์•„ํ‚คํ…์ณ๋ฅผ ์ •์˜ํ•˜๊ณ  ๋ชจ๋ธ์„ ์–ด๋–ป๊ฒŒ ํ•™์Šต์‹œํ‚ฌ์ง€์— ๋Œ€ํ•ด ์ •ํ•ฉ๋‹ˆ๋‹ค.  
```python

model = keras.Sequential([

    keras.Input(shape=(28, 28, 1)),  # ์ž…๋ ฅ ๋ ˆ์ด์–ด

    layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),

    layers.MaxPooling2D(pool_size=(2, 2)),

    layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),

    layers.MaxPooling2D(pool_size=(2, 2)),

    layers.Flatten(),

    layers.Dropout(0.5),

    layers.Dense(num_classes, activation="softmax")

])



model.compile(

    # ์†์‹ค ํ•จ์ˆ˜(Loss Function): ๋ชจ๋ธ์˜ ์˜ˆ์ธก์ด ์ •๋‹ต๊ณผ ์–ผ๋งˆ๋‚˜ ๋‹ค๋ฅธ์ง€ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.

    loss="categorical_crossentropy",

    # ์˜ตํ‹ฐ๋งˆ์ด์ €(Optimizer): ์†์‹ค์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

    optimizer="adam",

    # ํ‰๊ฐ€์ง€ํ‘œ(Metrics): ํ›ˆ๋ จ ๊ณผ์ •์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ง€ํ‘œ๋กœ, ์ •ํ™•๋„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    metrics=["accuracy"]

)

```

**3๋‹จ๊ณ„. ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€**  
```model.fit()```ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ํ•™์Šต์„ ์‹œ์ž‘ํ•˜๊ณ , ํ•™์Šต์ด ๋๋‚œ ํ›„ ```model.evaluate()```๋กœ ์ตœ์ข… ์„ฑ๋Šฅ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.  
```python

batch_size = 128

epochs = 15



# ๋ชจ๋ธ ํ•™์Šต ์‹คํ–‰

history = model.fit(

    x_train, y_train,

    batch_size=batch_size,

    epochs=epochs,

    validation_data=(x_test, y_test)

)



# ํ•™์Šต ์™„๋ฃŒ ํ›„ ์ตœ์ข… ์„ฑ๋Šฅ ํ‰๊ฐ€

score = model.evaluate(x_test, y_test, verbose=0)

print(f"\nTest loss: {score[0]:.4f}")

print(f"Test accuracy: {score[1]:.4f}")

```

**4๋‹จ๊ณ„. ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅํ•˜๊ธฐ**
๋ชจ๋ธ์„ ์ €์žฅํ•˜๊ณ , ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.  
```python

# ๋ชจ๋ธ์˜ ๊ตฌ์กฐ, ๊ฐ€์ค‘์น˜, ํ•™์Šต ์„ค์ •์„ ๋ชจ๋‘ '.keras' ํŒŒ์ผ ํ•˜๋‚˜์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

model.save("my_keras_model.keras")

print("\nModel saved to my_keras_model.keras")

```

์œ„ ๋‹จ๊ณ„๋ฅผ ์ „๋ถ€ ์ˆ˜ํ–‰ํ•œ ๋ชจ๋ธ์ด ์ง€๊ธˆ ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋“ค์–ด์žˆ๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ์ด์–ด์„œ, ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด ๋ณผ ๋–„, ์œ„ ์ฝ”๋“œ๋ฅผ์€ ์ง์ ‘ ์‹คํ–‰ํ•˜์ง€ ๋ง๊ณ , ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ฃผ์„ธ์š”!  
๋งŒ์ผ, ์œ„ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ง์ ‘ ๋”ฅ๋Ÿฌ๋‹์„ ์‹œ์ผญ๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด, Files์˜ 
train.py๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ฃผ์„ธ์š”!  

**5๋‹จ๊ณ„. ๋ชจ๋ธ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ**
์•ž์„  ๋‹จ๊ณ„๋“ค์„ ๊ฑฐ์ณ ์™„์„ฑํ•œ ๋ชจ๋ธ์ด ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ํŽ˜์ด์ง€์— ์˜ฌ๋ผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.  
์ด์ œ, ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ํŽ˜์ด์ง€์˜ ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์™€์„œ, ์ง์ ‘ ์‚ฌ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.  
Files์˜ test.py๋ฅผ ์‹คํ–‰์‹œ์ผœ ๋ณด์„ธ์š”!!
์ง์ ‘ ์ค€๋น„ํ•œ ์ˆซ์ž ์†๊ธ€์”จ๋ฅผ ๋ชจ๋ธ์— ์ž…๋ ฅ์œผ๋กœ ๋„ฃ์œผ๋ฉด, ๊ทธ ์ˆซ์ž๊ฐ€ ์–ด๋–ค ์ˆซ์ž์ธ์ง€ ๋งž์ถฐ์ค„ ๊ฒ๋‹ˆ๋‹ค!!  
์ฝ”๋“œ ์‹คํ–‰์„ ์œ„ํ•ด์„œ, ์ด ์ข…์†์„ฑ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.  
cmd ์ฐฝ์„ ์—ด๊ณ , ์ด ์ฝ”๋“œ๋ฅผ ๋„ฃ๊ณ  ์‹คํ–‰ํ•˜์—ฌ ๋จผ์ € ์ข…์†์„ฑ์„ ๋ฐ›์•„์ฃผ์„ธ์š”
```bash

pip install tensorflow huggingface_hub Pillow numpy

```
## 4. ๋‚˜๋งŒ์˜ CNN ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ
์ด์ œ, ์„ฑ๋Šฅ์„ ๋” ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•ด, ๋˜ ์›ํ•˜๋Š” ๋ชฉ์ ์— ๋งž๊ฒŒ ๋ชจ๋ธ์„ ์ˆ˜์ •ํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค.  

- **ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹**
๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” batch_size, epochs, ์˜ตํ‹ฐ๋‚˜์ด์ €์˜ leaarning_rate๋“ฑ์„ ์กฐํ•ฉํ•˜์—ฌ ์ตœ์ ํ™” ํ•ฉ๋‹ˆ๋‹ค.  
๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๊ฑด๋“œ๋ ค์„œ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.  
```python

# ์˜ˆ: Adam ์˜ตํ‹ฐ๋งˆ์ด์ €์˜ ํ•™์Šต๋ฅ (learning_rate)์„ ์ง์ ‘ ์„ค์ •

optimizer = keras.optimizers.Adam(learning_rate=0.001)

model.compile(loss="categorical_crossentropy", optimizer=optimizer, metrics=["accuracy"])

```

- **๋ชจ๋ธ ๊ตฌ์กฐ ๋ณ€๊ฒฝ**
๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์„ ์œ„ํ•ด์„œ, ```Conv2D-MaxPooling2D``` ๋ธ”๋ก์„ ๋” ๊นŠ๊ฒŒ, ```Conv2D``` ๊ณ„์ธต์˜ ํ•„ํ„ฐ ์ˆ˜๋ฅผ ๋Š˜๋ ค ๋” ํ’๋ถ€ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  
```python

model = keras.Sequential([

    keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1)),

    keras.layers.MaxPooling2D(pool_size=(2, 2)),

    # ๋ธ”๋ก ์ถ”๊ฐ€!

    keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),

    keras.layers.MaxPooling2D(pool_size=(2, 2)),

    # ํ•„ํ„ฐ ์ˆ˜๋ฅผ ๋Š˜๋ฆฐ ๋ธ”๋ก ์ถ”๊ฐ€!

    keras.layers.Conv2D(128, kernel_size=(3, 3), activation="relu"),

    keras.layers.MaxPooling2D(pool_size=(2, 2)),



    keras.layers.Flatten(),

    keras.layers.Dense(128, activation='relu'), # Dense ์ธต ์ถ”๊ฐ€

    keras.layers.Dropout(0.5),

    keras.layers.Dense(10, activation="softmax"),

])

```

- **์ „์ดํ•™์Šต**
์•„์ฃผ ํฐ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ํ•™์Šต๋œ ์ด๋ฏธ ๊ฐ•๋ ฅํ•œ ๋ชจ๋ธ์„ ๊ฐ€์ ธ์™€, ๊ทธ ๋ชจ๋ธ์ด ํ•™์Šตํ•œ ์ด๋ฏธ์ง€ ํŠน์ง•์ถ”์ถœ๋Šฅ๋ ฅ๋งŒ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์ž…๋‹ˆ๋‹ค.  
์ ์€ ๋ฐ์ดํ„ฐ๋กœ๋„ ๋†’์€ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  
```python

# Keras์—์„œ ์ œ๊ณตํ•˜๋Š” ์‚ฌ์ „ ํ•™์Šต๋œ VGG16 ๋ชจ๋ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ (๋ถ„๋ฅ˜๊ธฐ๋Š” ์ œ์™ธ)

base_model = keras.applications.VGG16(

    weights='imagenet',  # ImageNet์œผ๋กœ ์‚ฌ์ „ ํ•™์Šต๋œ ๊ฐ€์ค‘์น˜ ์‚ฌ์šฉ

    include_top=False,   # ๋ถ„๋ฅ˜๊ธฐ(Dense ์ธต)๋Š” ์ œ์™ธ

    input_shape=(32, 32, 3) # VGG16์€ ์ตœ์†Œ 32x32 ์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Œ

)



# ๋ถˆ๋Ÿฌ์˜จ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋Š” ๊ณ ์ •(freeze)

base_model.trainable = False



# ์ƒˆ๋กœ์šด ๋ถ„๋ฅ˜๊ธฐ ์ถ”๊ฐ€

model = keras.Sequential([

    base_model,

    keras.layers.Flatten(),

    keras.layers.Dense(256, activation='relu'),

    keras.layers.Dropout(0.5),

    keras.layers.Dense(10, activation='softmax') # ๋‚˜์˜ ๋ฌธ์ œ์— ๋งž๋Š” ์ถœ๋ ฅ์ธต

])



# ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ ๋ถ„๋ฅ˜๊ธฐ ๋ถ€๋ถ„๋งŒ ํ•™์Šต

model.compile(...)

model.fit(...)

```

## 5. ๊ฒฐ๋ก 
์˜ค๋Š˜์€, ์ด๋ ‡๊ฒŒ CNN ๋ชจ๋ธ์— ๋Œ€ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.  
์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์— ํŠนํ™”๋œ CNN์€ ๋‚˜์ค‘์— ํŠธ๋žœ์Šคํฌ๋จธ ๋ชจ๋ธ์ด ๋‚˜์˜ค๋ฉด์„œ Vit๋ผ๋Š” ๋ชจ๋ธ์ด ๋งŒ๋“ค์–ด์ง€๋Š”๋ฐ ํฐ ๊ธฐ์—ฌ๋ฅผ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.  
์ด๋ ‡๋“ฏ ๊ทผ๋ณธ ๋„˜์น˜๋Š” CNN ๋งŽ์ด ์‚ฌ๋ž‘ํ•ด ์ฃผ์„ธ์š”!!  
๋‹ค์Œ์—๋Š” RNN๋ชจ๋ธ๋กœ ๋Œ์•„์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค  
์˜ค๋Š˜๋„ ์ข‹์€ํ•˜๋ฃจ ๋ณด๋‚ด์„ธ์šฉ!!