숫자 이미지를 살짝 움직여도 같은 숫자라는 성질을 이용해서 데이터를 늘려보기
데이터가 zip으로 묶여 있으면 먼저 풀어서 쓸 준비를 해요.
import zipfile# zip 파일을 다루는 도구예요
with zipfile.ZipFile('c:/data/mnist/dataset.zip') as zip_ref:# mnist 데이터 zip을 열어요
zip_ref.extractall('c:/data/mnist/')# 지정한 폴더로 전부 풀어요
(출력 없음)
여기서는 MNIST를 가져와서 X(이미지)와 y(정답)를 준비해요.
from sklearn.datasets import fetch_openml# 공개 데이터셋을 쉽게 가져오는 도구예요
mnist = fetch_openml('mnist_784', version=1, data_home='c:/data/mnist', as_frame=False)# MNIST를 불러와요
mnist.data[:5]# 데이터가 들어왔는지 살짝 확인해요
(출력 없음 또는 일부 데이터가 보임)
X는 이미지(784 길이), y는 정답(0~9)이에요. 모양(shape)을 먼저 확인해요.
import numpy as np# 배열 계산을 할 거라 numpy를 써요
X, y = mnist["data"], mnist["target"]# 입력(X)과 정답(y)을 꺼내요
y = y.astype(np.int64)# 정답을 숫자형으로 바꿔요
print(X.shape, y.shape)# 전체 개수가 맞는지 확인해요
(70000, 784) (70000,) (예시)
숫자 하나를 실제로 그려보면, 우리가 다루는 게 어떤 데이터인지 감이 와요.
import matplotlib.pyplot as plt# 이미지를 그릴 도구예요
plt.imshow(X[0].reshape(28, 28))# 784를 28x28로 다시 펴서 보여줘요
plt.show()# 화면에 보여줘요
숫자 이미지 1장이 출력됨
학습용(앞 60000장)과 테스트용(뒤 10000장)으로 나누고, 학습 데이터는 섞어서 편향을 줄여요.
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]# 6만/1만으로 나눠요
shuffle_index = np.random.permutation(60000)# 0~59999를 랜덤 순서로 섞어요
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]# 그 순서대로 학습 데이터를 섞어요
(출력 없음)
이미지를 상/하/좌/우로 살짝 움직여서 데이터 양을 늘리고, KNN으로 간단히 성능을 확인해요.
from scipy.ndimage import shift# 이미지를 이동시키는 도구예요
def shift_image(image, dx, dy):# dx, dy만큼 이동하는 함수를 만들어요
image = image.reshape((28, 28))# 784를 28x28로 바꿔요
shifted_image = shift(image, [dy, dx])# (dy, dx)만큼 이동시켜요
return shifted_image.reshape([-1])# 다시 784 형태로 돌려줘요
image = X_train[70]# 예시 이미지 하나를 잡아요
shifted_image_down = shift_image(image, 0, 5)# 아래로 5칸 이동
shifted_image_left = shift_image(image, -5, 0)# 왼쪽으로 5칸 이동
plt.figure(figsize=(12, 3))# 3장을 한 줄로 보여줄게요
plt.subplot(131); plt.title('Original', fontsize=14); plt.imshow(image.reshape(28, 28), cmap='Greys')# 원본
plt.subplot(132); plt.title('Shifted down', fontsize=14); plt.imshow(shifted_image_down.reshape(28, 28), cmap='Greys')# 아래
plt.subplot(133); plt.title('Shifted left', fontsize=14); plt.imshow(shifted_image_left.reshape(28, 28), cmap='Greys')# 왼쪽
plt.show()# 화면에 표시
# 오래 걸림: 아래는 원본 6만 + 이동 24만 = 총 30만을 만드는 과정이에요
X_train_augmented = [image for image in X_train]# 원본을 먼저 넣어요
y_train_augmented = [label for label in y_train]# 정답도 같이 넣어요
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):# 네 방향 이동을 돌려요
for image, label in zip(X_train, y_train):# 이미지/정답을 같이 순회해요
X_train_augmented.append(shift_image(image, dx, dy))# 이동된 이미지를 추가해요
y_train_augmented.append(label)# 정답은 그대로 추가해요
X_train_augmented = np.array(X_train_augmented)# 리스트를 배열로 바꿔요
y_train_augmented = np.array(y_train_augmented)# 정답도 배열로 바꿔요
shuffle_idx = np.random.permutation(len(X_train_augmented))# 전체를 한 번 더 섞어요
X_train_augmented = X_train_augmented[shuffle_idx]# 섞인 순서로 적용
y_train_augmented = y_train_augmented[shuffle_idx]# 섞인 순서로 적용
from sklearn.neighbors import KNeighborsClassifier# 가까운 이웃으로 분류하는 모델(KNN)
knn_clf = KNeighborsClassifier(n_neighbors=1)# 가장 가까운 1개 이웃을 써요
knn_clf.fit(X_train_augmented[:1000], y_train_augmented[:1000])# 예시는 빠르게 1000개만 학습해요
from sklearn.metrics import accuracy_score# 정확도 계산 도구
y_pred = knn_clf.predict(X_test[:1000])# 테스트 1000개 예측
accuracy_score(y_test[:1000], y_pred[:1000])# 정확도 계산
정확도 숫자(0~1 사이)가 출력됨(예: 0.92)