밑바닥부터 시작하는 딥러닝 3장 - mnist

2022. 5. 18. 02:01·공부정리/Deep learnig & Machine learning
728x90
반응형

기존에는 AND게이트나 규칙이 정해져있는 개념은 모두 파이썬 코드로 작성할 수 있다. 규칙이 있었기에 컴퓨터에 쉽게 입력을 할 수 있었다.

하지만, 사람마다 다른 글씨체가 다른 것 처럼 규칙이 정해져있지 않은 것은 어떻게 컴퓨터에 입력할까?

이러한 영역은 머신러닝이라고 부른다. 머신러닝에서는 데이터를 넣어서 학습을 하여 입력된 값이 어떤 수인지 확률을 통해 맞추어볼 수 있다. 머신러닝의 기초 MNIST를 통해서 학습과정은 생략하고 추론과정을 살펴볼 것이다.

MNIST

  • MNIST 데이터셋은 0부터 9까지의 손글씨 이미지로 구성
  • 훈련 데이터가 6만장, 테스트 데이터가 1만장
  • 각 데이터는 이미지와 라벨로 이루어짐
  • 각 이미지는 28×28 해상도의 흑백 사진
  • 각 픽셀은 0에서 255로 밝기 표현

 

MNIST 코드로 살펴보기

MNIST 코드 다운로드 : https://github.com/WegraLee/deep-learning-from-scratch  

 

GitHub - WegraLee/deep-learning-from-scratch: 『밑바닥부터 시작하는 딥러닝』(한빛미디어, 2017)

『밑바닥부터 시작하는 딥러닝』(한빛미디어, 2017). Contribute to WegraLee/deep-learning-from-scratch development by creating an account on GitHub.

github.com

PIL 라이브러리로 MNIST 나타내기

# coding: utf-8
import sys, os
sys.path.append("./dataset")  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image #mnist 이미지 파일을 불러옴


def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))
    pil_img.show()

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
#flatten = Ture 을 하면 하나의 행 출력이 됨, False 는 텐서로 출력

img = x_train[0] # 훈련형 데이터 이미지
label = t_train[0] # 훈련형 데이터 라벨
print(label)  # 5

print(img.shape)  # (784,) 
img = img.reshape(28, 28)  # 형상을 원래 이미지의 크기로 변형
print(img.shape)  # (28, 28)

img_show(img)

flatten : 입력 이미지를 1차원 배열로 나타낼 지를 결정한다.

normalize : 이미지 gtayscale을 0~255에서 0.0~1.0 사이의 값으로 정규화 할지 결정한다.

더보기
def img_show(img):
  pil_img = Image.fromarray(np.uint8(img))
  pil_img.show()

위의 코드로 이미지는 일정한 형식을 가진 numpy array로 변할 수 있고, 일정한 형식을 가진 numpy array는 이미지로 변할 수 있다는 것을 알게 됩니다. img_show 함수는 numpy로 구성된 숫자로 된 배열들을 PIL 라이브러리가 읽을 수 있도록 해주는 코드입니다.

load_mnist(flatten=True, normalize=False, one_hot_label=False)

여기서는 이미지를 불러오는 형식에 대해 알 수 있는데,

  1. flatten은 이미지를 1차원 배열로 가져올 것이냐에 대한 옵션입니다. 28x28의 2차원 배열로 이루어진 이미지는 784개의 1차원 배열로 표현될 수 있습니다.
  2. normalize는 입력 이미지의 픽셀 값을 기존의 0~255 값에서 0.0~1.0 사이의 값으로 정규화할지 결정합니다.
  3. one_hot_label은 레이블(정답)을 원핫 인코딩 형태로 저장할지 결정합니다.
img = img.reshape(28, 28)

위의 코드는 flatten 옵션에 의해 불러와진 784개의 1차원 배열로 이루어진 이미지를 다시 28x28로 돌려놓는 함수입니다.

img_show(img)

위 코드는 이전에 설명했던 img_show 함수를 이용하여, 배열로 이루어진 이미지 정보를 pil 라이브러리를 통해 실제로 어떤 이미지인지 우리에게 시각적으로 보여주는 코드입니다.

flatten =True 를 하면 이미지가 3차원이었던 데이터 이미지가 1차원 벡터로 변환이 되어 출력이된다. 이 1차원값은 다시 reshape을 통해서 2차원으로 바꾸어줄 수 있다.

 

flatten = False 를 할 시 코드는 아래와 같다.

 

def img_show(img): 
    pil_img = Image.fromarray(np.uint8(img))
    pil_img.show()

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False, normalize=False)
#flatten = False 1차원으로 출력하지 않는다.

img = x_train[0][0] # 훈련형 데이터 이미지 행렬로 출력
label = t_train[0] # 훈련형 데이터 라벨
print(label)  # 5

print(img.shape)  # (28, 28)

img_show(img)

 

# flatten 하는 이유 3차원 텐서라서 True인 상태에서(1차원) reshape으로 해주면 행열의 형태로 출력된다.
# flatten을 하지 않고 출력하면  reshape을 안해주어도 되지만, 행열의 형태로 출력해야하므로
# x_train[0][0] 을 해주어서 해당 0번째층에 있는 행열 출력한다.

 

 

실행결과

 

 

훈련데이터 0번째에 있는 숫자 5가 출력이 된다.

여기서 print(img)를 해보자.

 

이렇게 5가 그려진 곳에는 0보다 큰 숫자로 출력이 되는 것을 알 수 있다.

이는 255로 각 픽셀의 밝기를 표현한것이므로 0~255로 나타내고있다. 이렇게 0~255까지의 수로 출력이 되는것은 해당 자료형이 uint8로, 

 

np.uint8(255)

uint은 0을 포함한 양수 혹은 부호가 없는 정수를 나타낸다.

uint8은 2^8개만큼의 표현이 가능하다.(0~255)

 

 

이렇게 코드를 실행해보면 수가 0~255사이로만 출력이 되는 것을 볼 수 있다.

만약 256을 출력하면 255가 최대이므로 다시 0으로 돌아와 값을 출력한다.

 

그럼 위의 이미지의 흑백을 반전하여 출력하려면 어떻게할까?

답은 간단하다.

 

 

print(np.uint8(255-img))
img_show(np.uint8(255-img))

단순히 img에 해당되는 값들을 빼주면 흑백이 바뀌어 출력이 된다.

더보기
# coding: utf-8
import sys, os
sys.path.append("./dataset")  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image #mnist 이미지 파일을 불러옴


def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))
    pil_img.show()

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
#flatten = Ture 을 하면 하나의 행 출력이 됨, False 는 행열로 출력
#normalize = True 을 하면

img = x_train[0] # 훈련형 데이터 이미지
label = t_train[0] # 훈련형 데이터 라벨
print(label)  # 5

print(img.shape)  # (784,) 28X28 을 곱한 값으로 flatten = False 를 하면 (1,28,28) 출력
img = img.reshape(28, 28)  # 형상을 원래 이미지의 크기로 변형
print(img.shape)  # (28, 28)

img_show(np.uint8(255-img))

 

실행 결과

 

 

matploltlib로 MNIST 나타내기

import sys, os
sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
from dataset.mnist import load_mnist
import matplotlib.pyplot as plt

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False, normalize=False)

plt.figure()
plt.imshow(x_train[0][0])
plt.colorbar()
plt.show()


plt.figure(figsize=(10,10)) # 도화지 사이즈 10*10
for i in range(25):
    plt.subplot(5,5,i+1) # 5 x 5 바둑판 생성 1번~25번째 까지
    plt.xticks([]) #눈금 설정
    plt.yticks([]) #눈금 설정
    plt.imshow(x_train[i][0], cmap=plt.cm.binary) #색깔 뽑아내기
    plt.xlabel(t_train[i]) #라벨
plt.show()

 

실행결과

 

 

잘못 분류한 결과 출력하기

전체 소스코드 

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import matplotlib.pyplot as plt
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test


def init_network():
    with open("sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
    return network


def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y


x, t = get_data()
network = init_network()
error=[]
for i in range(len(x)):
    y = predict(network, x[i])
    p= np.argmax(y) # 확률이 가장 높은 원소의 인덱스를 얻는다.
    if p != t[i]: # 오답 분류하기
        error.append(i)
        
print(error)

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(x[error[i]].reshape(28,28), cmap=plt.cm.binary)
    plt.xlabel(t[error[i]])
plt.show()

 

자세히 봐야할 코드

x, t = get_data()
network = init_network()
error=[]
for i in range(len(x)):
    y = predict(network, x[i])
    p= np.argmax(y) # 확률이 가장 높은 원소의 인덱스를 얻는다.
    if p != t[i]: # 오답 분류하기
        error.append(i)
        
print(error)

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(x[error[i]].reshape(28,28), cmap=plt.cm.binary)
    plt.xlabel(t[error[i]])
plt.show()

출력 결과 (x레이블에 테스트 이미지가 적힌 원래 숫자가 출력됨)

y 레이블에 mnist가 분류 했던 값 넣기

x, t = get_data()
network = init_network()
error=[]
sorted_mnist = []
for i in range(len(x)):
    y = predict(network, x[i])
    p= np.argmax(y) # 확률이 가장 높은 원소의 인덱스를 얻는다.
    if p != t[i]:
        error.append(i)
        sorted_mnist.append(p)
        
print(error)
print(sorted_mnist)

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(x[error[i]].reshape(28,28), cmap=plt.cm.binary)
    plt.ylabel(sorted_mnist[i])
    plt.xlabel(t[error[i]])
plt.show()

 

 

 

 

 

REFERENCE

https://pbj0812.tistory.com/286

 

https://www.youtube.com/watch?v=ojMAFoH7MxA&list=PLBiQZMT3oSxW1RS1hn2jWBgswh0nlcgQZ&index=4 

 

https://velog.io/@jakeseo_me/%EB%B0%91%EB%B0%94%EB%8B%A5%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91%ED%95%98%EB%8A%94-%EB%94%A5%EB%9F%AC%EB%8B%9D-2-2-MNIST-%EC%86%90%EA%B8%80%EC%94%A8-%EC%88%AB%EC%9E%90-%EC%9D%B8%EC%8B%9D

 

728x90
반응형

'공부정리 > Deep learnig & Machine learning' 카테고리의 다른 글

밑바닥부터 시작하는 딥러닝 4장 - 신경망 학습  (0) 2022.06.26
활성화함수를 사용하는 이유  (0) 2022.05.18
밑바닥부터 시작하는 딥러닝 3장  (0) 2022.05.17
밑바닥부터 시작하는 딥러닝 2장  (0) 2022.05.17
밑바닥부터 시작하는 딥러닝 1장- Numpy  (0) 2022.05.17
'공부정리/Deep learnig & Machine learning' 카테고리의 다른 글
  • 밑바닥부터 시작하는 딥러닝 4장 - 신경망 학습
  • 활성화함수를 사용하는 이유
  • 밑바닥부터 시작하는 딥러닝 3장
  • 밑바닥부터 시작하는 딥러닝 2장
sillon
sillon
꾸준해지려고 합니다..
    반응형
  • sillon
    sillon coding
    sillon
  • 전체
    오늘
    어제
    • menu (614)
      • notice (2)
      • python (68)
        • 자료구조 & 알고리즘 (23)
        • 라이브러리 (19)
        • 기초 (8)
        • 자동화 (14)
        • 보안 (1)
      • coding test - python (301)
        • Programmers (166)
        • 백준 (76)
        • Code Tree (22)
        • 기본기 문제 (37)
      • coding test - C++ (5)
        • Programmers (4)
        • 백준 (1)
        • 기본기문제 (0)
      • 공부정리 (5)
        • 신호처리 시스템 (0)
        • Deep learnig & Machine lear.. (41)
        • Data Science (18)
        • Computer Vision (17)
        • NLP (40)
        • Dacon (2)
        • 모두를 위한 딥러닝 (강의 정리) (4)
        • 모두의 딥러닝 (교재 정리) (9)
        • 통계 (2)
      • HCI (23)
        • Haptics (7)
        • Graphics (11)
        • Arduino (4)
      • Project (21)
        • Web Project (1)
        • App Project (1)
        • Paper Project (1)
        • 캡스톤디자인2 (17)
        • etc (1)
      • OS (10)
        • Ubuntu (9)
        • Rasberry pi (1)
      • App & Web (9)
        • Android (7)
        • javascript (2)
      • C++ (5)
        • 기초 (5)
      • Cloud & SERVER (8)
        • Git (2)
        • Docker (1)
        • DB (4)
      • Paper (7)
        • NLP Paper review (6)
      • 데이터 분석 (0)
        • GIS (0)
      • daily (2)
        • 대학원 준비 (0)
      • 영어공부 (6)
        • job interview (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Python
    programmers
    백준
    소수
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
sillon
밑바닥부터 시작하는 딥러닝 3장 - mnist
상단으로

티스토리툴바