01 ANN - 다중 분류
02 PCA + KNN 모델을 이용한 이미지 분석
03 ANN 모델을 사용한 이미지 분석
04 CNN 모델을 사용한 이미지 분석
01 ann - 다중 분류
1) 데이터 로딩
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
X.shape
y.shape
X.shape
Out[4]: (150, 4)
y.shape
Out[5]: (150,)
# target 변수 원핫 인코딩 (3개 클래스)
import pandas as pd
y3 = pd.get_dummies(y, prefix='Y').astype('int')
pd.get_dummies(y, prefix='Y').astype('int')
Out[9]:
Y_0 Y_1 Y_2
0 1 0 0
1 1 0 0
2 1 0 0
3 1 0 0
4 1 0 0
.. ... ... ...
145 0 0 1
146 0 0 1
147 0 0 1
148 0 0 1
149 0 0 1
[150 rows x 3 columns]
2) 스케일링
from sklearn.preprocessing import StandardScaler, MinMaxScaler
m_sc = MinMaxScaler()
X_sc = m_sc.fit_transform(X)
3) 데이터 분리
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(X, y, random_state=0, stratify=y)
4) 모델링
# 1) seed 고정
import numpy as np
import tensorflow as tf
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
# 2) 모델 정의
from tensorflow.keras.layers import Input
from keras import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Input(shape=(train_x.shape[1], )))
model.add(Dense(2, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# 3) 오차함수, 최적화 결정
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 4) early stopping rule
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights = True)
# 5) 학습
hist = model.fit(train_x, train_y, validation_split=0.25,
batch_size = 10, epochs=50000, callbacks=[es])
Epoch 1/50000
C:\Users\itwill\anaconda3\Lib\site-packages\keras\src\losses\losses.py:34: SyntaxWarning: In loss categorical_crossentropy, expected y_pred.shape to be (batch_size, num_classes) with num_classes > 1. Received: y_pred.shape=(None, 1). Consider using 'binary_crossentropy' if you only have 2 classes.
return self.fn(y_true, y_pred, **self._fn_kwargs)
9/9 ━━━━━━━━━━━━━━━━━━━━ 1s 23ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 2/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 8ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 3/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 8ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 4/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 5/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 6/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 8ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 7/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 8ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 8/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 8ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 9/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 10/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
Epoch 11/50000
9/9 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - accuracy: 0.3571 - loss: 0.0000e+00 - val_accuracy: 0.2500 - val_loss: 0.0000e+00
# 1. 데이터 로딩
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
X.shape
y.shape
# target 변수 원핫 인코딩(3개 클래스)
import pandas as pd
y3 = pd.get_dummies(y, prefix='Y').astype('int')
# 2. 스케일링
from sklearn.preprocessing import StandardScaler, MinMaxScaler
m_sc = MinMaxScaler()
X_sc = m_sc.fit_transform(X)
# 3. 데이터 분리
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y, train_y3, test_y3 = train_test_split(X, y, y3, random_state=0, stratify=y)
# 4. 모델링
# 1) seed 고정
import numpy as np
import tensorflow as tf
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
# 2) 모델 정의
from tensorflow.keras.layers import Input
from keras import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Input(shape=(train_x.shape[1], )))
model.add(Dense(2, activation='relu'))
model.add(Dense(3, activation='softmax')) # 다중분류일때 출력층 활성함수는 sigmoid 또는 softmax 적합
# 3) 오차함수, 최적화 결정
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 4) early stopping rule
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights = True)
# 5) 학습
hist = model.fit(train_x, train_y3, validation_split=0.25,
batch_size = 10, epochs=50000, callbacks=[es])
02 PCA + KNN 모델을 이용한 이미지 분석
이미지는 비정형데이터이므로, 우선 분석을 위해서는 정형데이터처럼 컴퓨터가 인식가능한 형태로 변형되어야 한다.
이미지 데이터는 픽셀로 나누어져 있으며 각 픽셀은 RGB 코드에 의해 0~255의 값을 각각 가지게 된다.
예를 들어 4 X 5의 해상도를 가지는 파일의 경우, 20개의 픽셀을 가지게 된다.
즉, 20개의 열이 생성된다.
PCA 또는 KNN과 같은 머신러닝 모델은 일반적으로 2차원 표 형태의 입력을 사용하기 때문에 위와 같은 과정을 통해 이미지 한 장의 높이 X 너비 배열을 하나의 긴 벡터로 펼치는 작업이 필요하다. 이를 flatten이라고 한다.
즉, 이미지 한 장이 1차원 벡터로 펼쳐지며 전체 이미지 데이터셋이 2차원 표가 된다.
이미지를 flatten하는 과정에서 픽셀 하나하나가 변수가 되므로 해상도에 따라 변수의 수가 매우 많아지게 되는데, 이 과정에서 계산량 증가, 거리 계산의 의미가 약해지는 차원의 저주 등 여러가지 문제가 발생하게 된다.
따라서 PCA를 통해 데이터의 분산을 최대한 많이 설명할 수 있는 새로운 축인 주성분을 만들게 된다.
이는 여러 픽셀값을 선형적으로 조합하여 이미지 사이의 주요 변화 패턴을 나타내는 축을 찾는 과정이다.
=> PCA는 가장 큰 분산을 설명하는 주성분을 만들어줌으로써, 특정 픽셀의 변동이 심한 사진의 유사성을 판별/분류할 수 있게 도와준다.
PCA로 차원을 축소한 이후에는 각 이미지가 몇 개의 주성분 점수로 표현되며, KNN을 통해 새로운 이미지와 기존 학습 이미지 사이에서 가까운 학습 이미지들을 찾아 주변 이웃이 가장 많이 속한 클래스로 분류한다.
그러나 차원 압축 / 분류 등을 통해 원래 이미지가 가지고 있던 픽셀들의 신호가 약해지는 경향을 보완하기 위하여 이 neural network를 통한 학습/분류가 이후에 발전하게 된다.
# 1) 데이터 로딩 (RGB로 변환된 데이터)
from tensorflow.keras.datasets import mnist
(train_x, train_y), (test_x, test_y) = mnist.load_data() # mnist는 train / test가 사전에 나누어져 있다.
(train_x, train_y), (test_x, test_y) = mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11490434/11490434 ━━━━━━━━━━━━━━━━━━━━ 1s 0us/step
train_x.shape
# 층 6만개, 28 X 28의 해상도
train_x.shape
Out[132]: (60000, 28, 28)
train_y
train_y
Out[134]: array([5, 0, 4, ..., 5, 6, 8], shape=(60000,), dtype=uint8)
import numpy as np
np.unique(train_y)
# 숫자 손글씨이기 때문에 0~9의 값을 가진다.
np.unique(train_y)
Out[136]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8)
# 데이터 확인
import matplotlib.pyplot as plt
첫 번째 사진의 값을 확인해본다.
28 X 28 의 해상도를 가지고 있다.
train_x[0].shape
train_x[0].shape
Out[138]: (28, 28)
이미 RGB 변환이 완료되었기에 2차원의 형태로 출력된다.
train_x[0]
train_x[0]
Out[137]:
array([[ 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
18, 18, 18, 126, 136, 175, 26, 166, 255, 247, 127, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 30, 36, 94, 154, 170,
253, 253, 253, 253, 253, 225, 172, 253, 242, 195, 64, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 49, 238, 253, 253, 253, 253,
253, 253, 253, 253, 251, 93, 82, 82, 56, 39, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 18, 219, 253, 253, 253, 253,
253, 198, 182, 247, 241, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 80, 156, 107, 253, 253,
205, 11, 0, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 1, 154, 253,
90, 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, 139, 253,
190, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 190,
253, 70, 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, 35,
241, 225, 160, 108, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81, 240, 253, 253, 119, 25, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 45, 186, 253, 253, 150, 27, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 16, 93, 252, 253, 187, 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, 249, 253, 249, 64, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 46, 130, 183, 253, 253, 207, 2, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39,
148, 229, 253, 253, 253, 250, 182, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 114, 221,
253, 253, 253, 253, 201, 78, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 23, 66, 213, 253, 253,
253, 253, 198, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 0, 0, 18, 171, 219, 253, 253, 253, 253,
195, 80, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 55, 172, 226, 253, 253, 253, 253, 244, 133,
11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0],
[ 0, 0, 0, 0, 136, 253, 253, 253, 212, 135, 132, 16, 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, 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, 0, 0, 0, 0,
0, 0]], dtype=uint8)
plt.imshow(train_x[0])

원본 데이터를 확인할 수 있다.
# 위 이미지의 실제 정답 찾기
train_y[0]
train_y[0]
Out[142]: np.uint8(5)
2) 데이터 변환
train_x.reshape(60000, -1) # 28 * 28 로 펼쳐짐 (flatten)
train_x.reshape(60000, -1)
Out[143]:
array([[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]], shape=(60000, 784), dtype=uint8)
train_x.reshape(60000, -1) / 255 # 0~255 => 0~1의 범위로 변환
MinMaxScaling과 같은 scaling 효과를 낸다.
train_x_sc = train_x.reshape(60000, -1) / 255
test_x_sc = test_x.reshape(10000, -1) / 255 # test는 1만건
3) 모델링
# (1) knn
from sklearn.neighbors import KNeighborsClassifier
m_knn = KNeighborsClassifier()
m_knn.fit(train_x_sc, train_y)
m_knn.score(train_x_sc, train_y)
m_knn.score(test_x_sc, test_y)
m_knn.score(train_x_sc, train_y)
Out[151]: 0.9819166666666667
m_knn.score(test_x_sc, test_y)
Out[152]: 0.9688
# (2) pca + knn
from sklearn.neighbors import KNeighborsClassifier
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
# 스케일링은 아까 수행했기 때문에 생략한다.
pipe = make_pipeline(PCA(100), KNeighborsClassifier(5))
pipe.fit(train_x_sc, train_y)
pipe.score(train_x_sc, train_y)
pipe.score(test_x_sc, test_y)
pipe.score(train_x_sc, train_y)
Out[159]: 0.9840333333333333
pipe.score(test_x_sc, test_y)
Out[160]: 0.9727
knn만 사용하는 것보다 pca + knn 을 같이 수행한 경우 score가 조금 더 향상되었다.
# 4) 예측 실패한 데이터 확인
pre_te = pipe.predict(test_x_sc)
pre_te
Out[162]: array([7, 2, 1, ..., 4, 5, 6], shape=(10000,), dtype=uint8)
pre_te != test_y
pre_te != test_y
Out[163]: array([False, False, False, ..., False, False, False], shape=(10000,))
test_fail = test_x[pre_te != test_y, :, :]
# 10,000개 중 273개를 예측 실패하였음을 확인할 수 있다.
test_x[pre_te != test_y, :, :]
Out[165]:
array([[[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, 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, 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, ..., 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, 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]]], shape=(273, 28, 28), dtype=uint8)
y 역시 틀린 값만 추출해준다.
y_true_fail = test_y[pre_te != test_y]
y_pre_fail = pre_te[pre_te != test_y]
plt.imshow(test_fail[0])

y_true_fail[0]
y_pre_fail[0]
y_true_fail[0]
Out[171]: np.uint8(4)
y_pre_fail[0]
Out[172]: np.uint8(9)
실제값은 4, 예측값은 7로 예측실패하였음을 알 수 있다.
plt.imshow(test_fail[1])

y_true_fail[1]
y_pre_fail[1]
y_true_fail[1]
Out[174]: np.uint8(4)
y_pre_fail[1]
Out[175]: np.uint8(0)
# 여러 그래프를 동시에 시각화
fig, ax = plt.subplots(2,5)
# i는 y축 좌표
for i in range(0,10) :
if i <= 4 :
ax[0,i].imshow(test_fail[i])
ax[0,i].set_title('true : %s, pre : %s' %(y_true_fail[i], y_pre_fail[i]))
else :
ax[1,i-5].imshow(test_fail[i])
ax[1,i-5].set_title('true : %s, pre : %s' %(y_true_fail[i], y_pre_fail[i]))

03 ANN 모델을 사용한 이미지 분석
# 1. 데이터 로딩(RGB로 변환된 데이터)
from tensorflow.keras.datasets import mnist
import numpy as np
(train_x, train_y), (test_x, test_y) = mnist.load_data()
# 2. 데이터 변환
train_x_sc = train_x.reshape(60000, -1) / 255 # 0~255 -> 0~1 범위로 변환(minmax 스케일링 효과)
test_x_sc = test_x.reshape(10000, -1) / 255 # 0~255 -> 0~1 범위로 변환(minmax 스케일링 효과)
# 원핫 인코딩
import pandas as pd
train_y10 = pd.get_dummies(train_y, prefix='Y').astype(int).values
test_y10 = pd.get_dummies(test_y, prefix='Y').astype(int).values
# 3. 모델링
# 1) seed 고정
import numpy as np
import tensorflow as tf
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
# 2) 모델 정의
from tensorflow.keras.layers import Input
from keras import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Input(shape=(train_x_sc.shape[1], )))
model.add(Dense(392, activation='relu'))
model.add(Dense(196, activation='relu'))
model.add(Dense(98, activation='relu'))
model.add(Dense(10, activation='softmax'))
# 3) 오차함수, 최적화 결정
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 4) early stopping rule
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights = True)
# 5) 학습
# * 각 에포크마다 반복 수 = 60000 * 0.75 / 10 = 4500
hist = model.fit(train_x_sc, train_y10, validation_split=0.25,
batch_size = 10, epochs=50000, callbacks=[es])
# 6) 평가
model.evaluate(train_x_sc, train_y10)[1] # 0.9829
model.evaluate(test_x_sc, test_y10)[1] # 0.9763
acc = hist.history['accuracy']
plt.plot(range(1, len(acc)+1), hist.history['accuracy'], label = 'train')
plt.plot(range(1, len(acc)+1), hist.history['val_accuracy'], label = 'val')
plt.legend()
plt.xticks(range(1, len(acc)+1))
# 4. 예측 실패한 데이터 시각화
pre_te = model.predict(test_x_sc).argmax(axis=1)
test_fail = test_x[ pre_te != test_y, :, :]
y_true_fail = test_y[ pre_te != test_y]
y_pre_fail = pre_te[ pre_te != test_y]
# 시각화
fig, ax = plt.subplots(5,5)
for i in range(0,25) : # i는 y축 좌표
row = i // 5 # 5로 나눈 몫
col = i % 5 # 5로 나눈 나머지
ax[row, col].imshow(test_fail[i])
ax[row, col].set_title('true : %s, pre : %s' % (y_true_fail[i], y_pre_fail[i]))
ax[row, col].axis('off')

04 CNN 모델을 사용한 이미지 분석
컨볼루션 신경망 (CNN)은 입력된 이미지에서 다시 한 번 특징을 추출하기 위해 마스크 (필터, 윈도 또는 커널)을 도입하는 기법이다. (마스크가 가중치이다.)
즉, 하나의 레이어가 필터를 입혀서 기존 이미지를 요약하는 역할을 하게 된다.
마스크의 크기 및 개수는 개인이 설정하는 하이퍼파라미터로, 마스크의 크기 자체는 모델을 설계하는 사람이 선택한다.
마스크의 크기가 작아질수록 처리 시간이 오래 걸린다.
각 마스크가 공간의 패턴에 집중하며 돌아다니면서 가중치를 각 픽셀에 곱하고, 그러한 과정을 반복해서 새롭게 만들어진 층을 컨볼루션 (합성곱)이라고 부른다.
이미지 내에서도 불필요한 특징이 있을 수 있다.
이미지 데이터셋 자체가 원체 크기 때문에 불필요한 특징을 제하고 의미있는 신호만 남기는 것을 풀링이라고 한다.
이 때 풀링을 어떻게 지정하냐에 따라 달라지는데, 평균으로 요약해 도출하면 average pooling, 최소로 요약해 도출하면 min pooling, 최대로 요약해 도출하면 max pooling이라고 한다.
(일반적으로 신호가 강할수록 의미가 있기 때문에 max pooling을 사용한다.)
이 과정을 통해 불필요한 정보를 간추리게 된다.
1) 데이터 로딩(RGB로 변환된 데이터)
from tensorflow.keras.datasets import mnist
import numpy as np
(train_x, train_y), (test_x, test_y) = mnist.load_data()
# 데이터 확인
train_x.shape
train_x[0].shape
plt.imshow(train_x[0])
2) 변환
# 1) 설명변수 (스케일링, 차원 변경)
** Conv2D 층은 한 데이터의 입력을 (높이, 너비, 채널) 형태로 요구
(채널 : 흑백의 이미지인지 (1) 컬러의 이미지인지 (3)에 대한 차이)
** NN 모델은 스케일링에 매우 민감 -> 사전 스케일링이 필수적
train_x_sc = train_x / 255
test_x_sc = test_x / 255
train_x_sc = train_x_sc.reshape((60000, 28, 28, 1))
test_x_sc = test_x_sc.reshape((10000, 28, 28, 1))
# 2) 종속변수
train_y10 = pd.get_dummies(train_y).astype(int).values
test_y10 = pd.get_dummies(test_y).astype(int).values
# ** 참고 : 원핫 인코딩
# 1) pandas
pd.get_dummies(train_y).astype(int).values
# 2) keras
from tensorflow.keras.utils import to_categorical
to_categorical(train_y)
3) 모델링
# 1) seed 고정
import numpy as np
import tensorflow as tf
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
# 2) 모델 정의
from tensorflow.keras.layers import Input
from keras import Sequential
from keras.layers import Dense, Conv2D, Dropout, Flatten, MaxPooling2D, Input
model = Sequential()
model.add(Input(shape=(28, 28, 1))) # 한 데이터 기준 사이즈 전달
model.add(Conv2D(32, kernel_size = (2,2), activation='relu')) # 2*2 크기의 마스크를 32개 씌움
model.add(Conv2D(32, kernel_size = (2,2), activation='relu'))
model.add(MaxPooling2D(2,2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
# 3) compile
model.compile('adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 4) early stopping rule
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights = True)
# 5) 학습
# * 각 에포크마다 반복 수 = 60000 * 0.75 / 10 = 4500
hist = model.fit(train_x_sc, train_y10, validation_split=0.25,
batch_size = 10, epochs=50000, callbacks=[es])
# 6) 평가
model.evaluate(train_x_sc, train_y10)[1] # 0.9939
model.evaluate(test_x_sc, test_y10)[1] # 0.9869
model.evaluate(train_x_sc, train_y10)[1] # 0.9829
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9939 - loss: 0.0221
Out[269]: 0.9938666820526123
model.evaluate(test_x_sc, test_y10)[1] # 0.9763
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9869 - loss: 0.0499
Out[270]: 0.9868999719619751
acc = hist.history['accuracy']
plt.plot(range(1, len(acc)+1), hist.history['accuracy'], label = 'train')
plt.plot(range(1, len(acc)+1), hist.history['val_accuracy'], label = 'val')
plt.legend()
plt.xticks(range(1, len(acc)+1))

4) 예측 실패한 데이터 시각화
pre_te = model.predict(test_x_sc).argmax(axis=1)
test_fail = test_x[ pre_te != test_y, :, :]
y_true_fail = test_y[ pre_te != test_y]
y_pre_fail = pre_te[ pre_te != test_y]
# 시각화
fig, ax = plt.subplots(5,5)
for i in range(0,25) : # i는 y축 좌표
row = i // 5 # 5로 나눈 몫
col = i % 5 # 5로 나눈 나머지
ax[row, col].imshow(test_fail[i])
ax[row, col].set_title('true : %s, pre : %s' % (y_true_fail[i], y_pre_fail[i]))
ax[row, col].axis('off')

'아이티윌_데이터 분석 55기 > 강의내용_딥러닝' 카테고리의 다른 글
| #5 5일차_감성 분석 (나이브베이즈, RNN) (0) | 2026.07.29 |
|---|---|
| #4 4일차_CNN, 얼굴 사진 분류하기, 쇼핑몰 후기 감성 분석 (0) | 2026.07.28 |
| #2 2일차_인공신경망의 구조, 실습 (0) | 2026.07.24 |
| #1 1일차_tensorflow, keras 설치하기 (0) | 2026.07.23 |