본문 바로가기
ML & DL/tensorflow

Cat Classification (1) : simple neural network

by 별준 2020. 11. 15.

이번에는 Courser Deep learning 특화과정 첫번째강의 2주차 수업에서 실습했던, cat classification을 구현해보도록 하겠습니다. 

2020/09/24 - [Coursera 강의/Deep Learning] - [실습] Logistic Regression with a Neural Network(can / non-cat classifier)

 

[실습] Logistic Regression with a Neural Network(can / non-cat classifier)

해당 내용은 Coursera의 딥러닝 특화과정(Deep Learning Specialization)의 첫 번째 강의 Neural Networks and Deep Learning를 듣고 정리한 내용입니다. (Week 2) 딥러닝 특화과정 첫 번째 강의 2주차 실습을 진..

junstar92.tistory.com

바로 시작해보도록 하겠습니다.

 

1. 필요한 package import

import tensorflow as tf
import h5py
import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline
print(tf.__version__)

>> 2.1.0

 

 

2. Dataset 준비

dataset은 coursera 강의에서 사용되었던 training data와 test data를 사용합니다. (필요하시면 댓글 주세요)

dataset이 h5파일이기 때문에, h5py를 사용해서 읽어오고, numpy array로 data를 input과 output으로 나누어줍니다. 각 data의 shape를 확인하면 아래와 같습니다.

# Load dataset
train_dataset = h5py.File('dataset/train_catvnoncat.h5', 'r')
test_dataset = h5py.File('dataset/test_catvnoncat.h5', 'r')

train_x_orig = np.array(train_dataset['train_set_x'][:], np.float32)
train_y = np.array(train_dataset['train_set_y'][:], np.float32)
test_x_orig = np.array(test_dataset['test_set_x'][:], np.float32)
test_y = np.array(test_dataset['test_set_y'][:], np.float32)
classes = np.array(train_dataset['list_classes'][:])


print("train set x shape :", train_x_orig.shape)
print("train set y shape :", train_y.shape)
print("test set x shape :", test_x_orig.shape)
print("test set y shape :", test_y.shape)

# example
index = 50
plt.imshow(train_x_orig[index].astype(np.int32))
print("y =", train_y[index].astype(np.int32), ", It is a " + str(classes[train_y[index].astype(np.int32)].decode("ascii")))

입력의 경우에는 위와 같은 이미지입니다.

 

입력의 shape가 (64, 64, 3)의 3차원이므로, flatten 작업을 해줍니다. 그래서 우리는 feature가 총 12288개인 1차원 입력으로 변경을 해주게 됩니다.

# flatten
train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1)
train_y = train_y.reshape(train_y.shape[0], -1)
test_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1)
test_y = test_y.reshape(test_y.shape[0], -1)

print ("train_x_flatten shape: " + str(train_x_flatten.shape))
print ("train_y_orig shape: " + str(train_y.shape))
print ("test_x_flatten shape: " + str(test_x_flatten.shape))
print ("test_y_orig shape: " + str(test_y.shape))
print ("sanity check after reshaping: " + str(train_x_flatten[0:5,0]))

그리고, 입력은 RGB로 0~255의 값을 가집니다. 그래서 학습속도를 높이기 위해서 255로 나누어서 normalization을 진행합니다. 

# normalization
train_x = train_x_flatten / 255.
test_x = test_x_flatten / 255.

train_x

이로써 data의 전처리를 모두 진행하였습니다.

 

3. 학습

우선 학습에 필요한 함수들을 정의합니다.

  • parameter_initialization_with_zeros(dim) : 파라미터 W, b 초기화
  • forward_propagation(W, b, X) : FP를 수행해 \(\hat{y}\)를 구하는 함수
  • predict(W, b, X) : 학습한 파라미터로 label을 예측하는 함수
  • accuracy(Y_pred, Y) : 예측한 label과 실제 label을 비교하고 정확도를 반환하는 함수
def parameter_initialization_with_zeros(dim):
    W = tf.Variable(np.zeros((dim, 1)), dtype=tf.float32)
    b = tf.Variable([0.], dtype=tf.float32)
    
    return W, b

def forward_propagation(W, b, X):
    z = tf.matmul(X, W) + b
    return tf.math.sigmoid(z)

def predict(W, b, X):
    pred = forward_propagation(W, b, X)
    pred = tf.cast(pred > 0.5, dtype=tf.float32)
    
    return pred

def accuracy(Y_pred, Y):
    acc = tf.reduce_mean(tf.cast(tf.equal(Y_pred, Y), dtype=tf.float32))
    
    return acc

그리고, 학습을 위한 model 함수를 생성합니다. 이 함수는 매 iteration마다의 cost와 학습된 파라미터 W, b, 그리고 예측한 label(train, test)을 반환합니다.

def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.01):
    W, b = parameter_initialization_with_zeros(X_train.shape[1])
    costs = []
    
    optimizer = tf.optimizers.SGD(learning_rate)
    
    for iter in range(1, num_iterations + 1):
        with tf.GradientTape() as tape:
            pred = forward_propagation(W, b, X_train)
            cost = tf.reduce_mean(-tf.reduce_sum(Y_train*tf.math.log(pred) + (1 - Y_train)*tf.math.log(1 - pred), 1))
        
        # compute gradient
        grad = tape.gradient(cost, [W, b])
        
        # update gradient
        optimizer.apply_gradients(zip(grad, [W, b]))
        
        if iter % 100 == 0:
            acc = accuracy(predict(W, b, X_train), Y_train)
            costs.append(cost)
            print(f"Cost after iteratioin {iter} : {cost} / train acc : {acc*100} %")
    
    Y_pred_train = predict(W, b, X_train)
    Y_pred_test = predict(W, b, X_test)
    
    print(f"train accuracy : {accuracy(Y_pred_train, Y_train) * 100} %")
    print(f"test accuracy : {accuracy(Y_pred_test, Y_test) * 100} %")
    
    ret = {"costs" : costs,
           "Y_pred_train" : Y_pred_train,
           "Y_pred_test" : Y_pred_test,
           "W" : W,
           "b" : b}
    
    return ret

그리고 학습을 진행합니다. learning rate는 0.005, iteration은 2000으로 설정해주었습니다.

result = model(train_x, train_y, test_x, test_y, 2000, 0.005)

학습결과 99%의 train accuracy와 70%의 test accuracy를 얻었습니다. train accuracy가 압도적으로 높은 것으로 보아 이 모델은 training data에 overfitting(과적합)된 것으로 추측할 수 있습니다. 추후에 이 overfitting을 해결해보도록 하겠습니다.

 

cost 변화의 추이를 살펴보면 다음과 같습니다.

costs = np.squeeze(result['costs'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per 100)')
plt.show()

댓글