Upload
Browse files- .gitattributes +1 -0
- README.md +226 -0
- config.json +20 -0
- my_keras_model.keras +3 -0
- test.py +33 -0
- train.py +60 -0
.gitattributes
CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
my_keras_model.keras filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
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 |
+
|
225 |
+
|
226 |
+
## 4. 나만의 CNN 모델 만들기
|
config.json
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"_from_model_id": "keras-model",
|
3 |
+
"architectures": [
|
4 |
+
"CNN"
|
5 |
+
],
|
6 |
+
"model_type": "Keras",
|
7 |
+
"pipeline_tag": "image-classification",
|
8 |
+
"task_tags": [
|
9 |
+
"image-classification"
|
10 |
+
],
|
11 |
+
"tags": [
|
12 |
+
"tensorflow",
|
13 |
+
"keras",
|
14 |
+
"mnist",
|
15 |
+
"cnn"
|
16 |
+
],
|
17 |
+
"datasets": [
|
18 |
+
"mnist"
|
19 |
+
]
|
20 |
+
}
|
my_keras_model.keras
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:abc240116caa1e68bc7a2006d6725bf11170157e0e43c3d2e2b88600b810fafa
|
3 |
+
size 452579
|
test.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from huggingface_hub import hf_hub_download
|
2 |
+
import tensorflow as tf
|
3 |
+
from tensorflow import keras
|
4 |
+
|
5 |
+
# Replace 'your-username/your-model-name' with your actual Hugging Face model repository ID.
|
6 |
+
repo_id = "your-username/your-model-name"
|
7 |
+
# Replace 'my_keras_model.keras' with the name of the file you uploaded.
|
8 |
+
filename = "my_keras_model.keras"
|
9 |
+
|
10 |
+
# Download the model file from the Hugging Face Hub.
|
11 |
+
model_path = hf_hub_download(repo_id=repo_id, filename=filename)
|
12 |
+
|
13 |
+
# Load the model using Keras's built-in function.
|
14 |
+
# The 'safe_mode=False' argument is often necessary when loading models saved from older TensorFlow versions
|
15 |
+
# or if the model contains custom layers.
|
16 |
+
model = keras.models.load_model(model_path, safe_mode=False)
|
17 |
+
|
18 |
+
# Now you can use the loaded model for inference.
|
19 |
+
# Example: Load a single MNIST test image and make a prediction.
|
20 |
+
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
|
21 |
+
x_test = x_test.astype("float32") / 255.0
|
22 |
+
x_test = tf.expand_dims(x_test, -1)
|
23 |
+
image_to_predict = x_test[0:1]
|
24 |
+
|
25 |
+
# Get the model's prediction.
|
26 |
+
predictions = model.predict(image_to_predict)
|
27 |
+
|
28 |
+
# Print the predicted class (the one with the highest probability).
|
29 |
+
predicted_class = tf.argmax(predictions[0]).numpy()
|
30 |
+
print(f"Predicted class: {predicted_class}")
|
31 |
+
|
32 |
+
# Display the model summary to confirm it's loaded correctly.
|
33 |
+
model.summary()
|
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")
|