ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 6. CNN(4)
    AI 모델(딥러닝 기초)/6. CNN 2023. 2. 18. 15:27
    728x90

    ※ CNN 모델 구현

    ■ CNN 모델

    (Convolution-ReLU-Pooling)-(Affine-ReLU)-(Affine-Softmax) 의 순서로 흐른다.

    이제 위 순서를 따라 3층 신경망을 가진 CNN 모델을 만들어보자.

     

    1. 초기화 단계

    - 합성곱 계층 출력 크기, 풀링 계층 출력 크기를 수식으로 설정

    - 3층 신경망 구성을 위한 가중치 w1,w2,w3, 편향 b1,b2,b3 만들기

     

    2. 계층 생성

    - collection 모듈에 들어있는 OrderDict()를 불러와서 순서대로 정렬

    - (Convolution-ReLU-Pooling)-(Affine-ReLU)-(Affine-Softmax) 순서대로 각 계층을 설정

     

    3. 예측 predict, 손실함수 loss, 정확도 accuracy 함수 구현

     

    4. 오차역전파법을 이용하여 gradient 함수 구현

     

    import sys, os
    sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
    import numpy as np
    import pickle
    from collections import OrderedDict
    from common.layers import *
    from common.gradient import numerical_gradient
    
    class SimpleConvNet:
        '''
        input_dim - 입력 데이터(채널 수, 높이, 너비)
        conv_param - 합성곱 계층의 하이퍼파라미터(딕셔너리)
        -- filter_num = 필터수
        -- filter_size = 필터 크기
        -- stride = 스트라이드
        -- pad = 패딩
        -- hidden_size = 은닉층(완전연결)의 뉴런 수
        -- output_size = 출력층(완전연결)의 뉴런 수
        -- weight_init_std = 초기화 때의 가중치 표준편차
        '''
        
        def __init__(self, input_dim=(1, 28, 28),
                    conv_param = {'filter_num}':30, 'filter_size':5, 'pad':0, 'stride':1},
                    hidden_size=100, output_size=10, weight_init_std=0.01):
            filter_num = conv_param['filter_num']
            filter_size = conv_param['filter_size']
            filter_pad = conv_param['pad']
            filter_stride = conv_param['stride']
            input_size = input_dim[1]
            
            # 합성곱 계층의 출력 크기
            conv_output_size = (input_size - filter_size + 2*filter_pad) / filter_stride + 1
            
            # 풀링 계층의 출력 크기
            pool_output_size = int(filter_num * (conv_output_size / 2) * (conv_output_size / 2))
            
            # 가중치 초기화
            self.params = {}
            self.params['W1'] = weight_init_std * \
                                np.random.randn(filter_num, input_dim[0], filter_size, filter_size)
            self.params['b1'] = np.zeros(filter_num)
            self.params['W2'] = weight_init_std * \
                                np.random.randn(pool_output_size, hidden_size)
            self.params['b2'] = np.zeros(hidden_size)
            self.params['W3'] = weight_init_std * \
                                np.random.randn(hidden_size, output_size)
            self.params['b3'] = np.zeros(output_size)
            
            # 계층 생성
            self.layers = OrderDict()
            self.layers['Conv'] = Convolution(self.params['W1'], self.params['b1'], conv_param['stride'], conv_param['pad'])
            self.layers['Relu1'] = Relu()
            self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)
            self.layers['Affine1'] = Affine(self.parmas['W2'], self.params['b2'])
            self.layers['Relu2'] = Relu()
            self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])
            
            self.last_layer = SoftmaxWithLoss()
            
        def predict(self, x):
            for layer in self.layers.values():
                x = layer.forward(x)
            
            return x
        
        def loss(self, x, t):
            y = self.predict(x)
            
            return self.last_layer.forward(y, t)
        
        def gradient(self, x, t):
            
            # forward
            self.loss(x, t)
    
            # backward
            dout = 1
            dout = self.last_layer.backward(dout)
    
            layers = list(self.layers.values())
            layers.reverse()
            for layer in layers:
                dout = layer.backward(dout)
    
            # 결과 저장
            grads = {}
            grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].db
            grads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
            grads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].db
    
            return grads
        
        def accuracy(self, x, t, batch_size=100):
            if t.ndim != 1 : t = np.argmax(t, axis=1)
            
            acc = 0.0
            
            for i in range(int(x.shape[0] / batch_size)):
                tx = x[i*batch_size:(i+1)*batch_size]
                tt = t[i*batch_size:(i+1)*batch_size]
                y = self.predict(tx)
                y = np.argmax(y, axis=1)
                acc += np.sum(y == tt) 
            
            return acc / x.shape[0]

     

    이렇게 CNN의 기본모델을 3층 신경망을 통해서 구현해 보았다.

     

     

    ※ MNIST 데이터셋을 CNN에 적용 시키기

    이미지 처리에 좋은 CNN 모델을 MNIST 데이터셋을 통해 적용시켜 정확도를 확인해보자.

     

    import matplotlib.pyplot as plt
    from dataset.mnist import load_mnist
    from simple_convnet import SimpleConvNet
    from common.trainer import Trainer
    
    # 데이터 읽기
    (x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)
    
    # 시간이 오래 걸릴 경우 데이터를 줄인다.
    #x_train, t_train = x_train[:5000], t_train[:5000]
    #x_test, t_test = x_test[:1000], t_test[:1000]
    
    max_epochs = 20
    
    network = SimpleConvNet(input_dim=(1,28,28), 
                            conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},
                            hidden_size=100, output_size=10, weight_init_std=0.01)
                            
    trainer = Trainer(network, x_train, t_train, x_test, t_test,
                      epochs=max_epochs, mini_batch_size=100,
                      optimizer='Adam', optimizer_param={'lr': 0.001},
                      evaluate_sample_num_per_epoch=1000)
    trainer.train()
    
    # 매개변수 보존
    network.save_params("params.pkl")
    print("Saved Network Parameters!")
    
    # 그래프 그리기
    markers = {'train': 'o', 'test': 's'}
    x = np.arange(max_epochs)
    plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
    plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
    plt.xlabel("epochs")
    plt.ylabel("accuracy")
    plt.ylim(0, 1.0)
    plt.legend(loc='lower right')
    plt.show()

     

    train함수를 구현하여 epoch=20 정도로 설정하고 CNN모델을 mnist 데이터셋에서 학습시켜보았다.

     

    거의 98%에 가까운 정확도를 보였다. 3층 신경망 정도에서 CNN을 적용시켰을 때도 이미지 데이터셋에서는 이정도의 성능을 보이게 된다

    728x90

    'AI 모델(딥러닝 기초) > 6. CNN' 카테고리의 다른 글

    6. CNN(5)  (0) 2023.02.19
    6. CNN(3)  (0) 2023.02.17
    6. CNN(2)  (0) 2023.02.17
    6. CNN(1)  (0) 2023.02.14
Designed by Tistory.