기존에는 AND게이트나 규칙이 정해져있는 개념은 모두 파이썬 코드로 작성할 수 있다. 규칙이 있었기에 컴퓨터에 쉽게 입력을 할 수 있었다.
하지만, 사람마다 다른 글씨체가 다른 것 처럼 규칙이 정해져있지 않은 것은 어떻게 컴퓨터에 입력할까?
이러한 영역은 머신러닝이라고 부른다. 머신러닝에서는 데이터를 넣어서 학습을 하여 입력된 값이 어떤 수인지 확률을 통해 맞추어볼 수 있다. 머신러닝의 기초 MNIST를 통해서 학습과정은 생략하고 추론과정을 살펴볼 것이다.
MNIST
- MNIST 데이터셋은 0부터 9까지의 손글씨 이미지로 구성
- 훈련 데이터가 6만장, 테스트 데이터가 1만장
- 각 데이터는 이미지와 라벨로 이루어짐
- 각 이미지는 28×28 해상도의 흑백 사진
- 각 픽셀은 0에서 255로 밝기 표현
MNIST 코드로 살펴보기
MNIST 코드 다운로드 : https://github.com/WegraLee/deep-learning-from-scratch
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)
여기서는 이미지를 불러오는 형식에 대해 알 수 있는데,
- flatten은 이미지를 1차원 배열로 가져올 것이냐에 대한 옵션입니다. 28x28의 2차원 배열로 이루어진 이미지는 784개의 1차원 배열로 표현될 수 있습니다.
- normalize는 입력 이미지의 픽셀 값을 기존의 0~255 값에서 0.0~1.0 사이의 값으로 정규화할지 결정합니다.
- 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
'공부정리 > 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 |