빅데이터 | 머신러닝 | 딥러닝/딥러닝

[딥러닝 기초] Convolution Neuron Network 의류분류기 만들어보기

냠냠:) 2020. 6. 1. 02:32

[이 글은 "Do it 딥러닝 입문" 책을 보고 공부한 내용을 복습하고자 정리한 글입니다.]

 

Convolution Neuron Network(CNN)

 

합성곱 연산이란 ?

원본 배열과 특정배열(reversed)을 자릿수마다 곱하고 더한 결과가 새로운 배열의 하나의 원소 값으로 만드는 연산

 

* 합성곱에서는 교차상관을 사용한다

why? -> 우리는 가중치를 초기화할 때 가중치 값을 랜덤 하게 주기 때문에 reverse는 무의미하다.

 

패딩과 스트라이드

 

패딩

Valid - 원본 배열의 원소가 합성곱 연산에 참여하는 정도가 다름(원본 배열 0번째 원소가 합성곱 연산에 참여하는 횟수는 1회)

full - 원본 배열의 원소가 모두 합성곱 연산에 골고루 참여하기 위해 배열 양 끝에 빈 원소를 적절히 추가한다.

same - 합성곱 연산을 통해 나온 새로운 배열이 원본 배열과 같은 크기를 가지게 배열 양 끝에 빈 원소를 적절히 추가한다.

 

스트라이드 

- 연산에 사용되는 배열이 합성곱 연산을 할 때 어느 간격으로 연산을 시행하는지 조절

 

 

텐서플로우에서 합성곱

 

- 텐서플로우에서는 conv2d로 2차원 배열의 합성곱 연산을 지원한다.

- conv2d는 4차원 배열을 기대함.

 

입력 이미지의 차원

- 이미지의 (배치(개수), 높이, 너비, 채널 개수)

 

가중치의 차원

- (높이, 너비, 채널, 가중치 개수)

 

*텐서에서는 패딩옵션을 대문자로 사용

*가중치를 커널 또는 필터로 부른다.

 

합성곱 층, 풀링층

- 합성곱 신경망에서는 합성곱층과 풀링층, 완전 연결층이 있다.

 

*풀링이란? 특성맵을 스캔해서 최댓값 or 평균값을 계산하는 것

 

전체적인 플로우

 

1. 이미지와 커널의 합성곱 수행 (결과: 특성맵)

2. 특성맵을 활성화 함수(relu) 적용

3. 풀링층에서 풀링 (결과 : 크기가 작아진 특성맵)

4. 3의 특성맵을 완전 연결층의 입력으로 계산

5. 은닉층을 통과하여 출력

 

 

ConvolutionNetwork_2020_05_30
In [1]:
import tensorflow as tf
import numpy as np
In [2]:
class ConvolutionNetwork:
    
    def __init__(self, n_kernels=10, units= 10, batch_size =32, learning_rate= 0.1):
        self.n_kernels = n_kernels          #합성곱 커널의 개수
        self.kernel_size = 3                #커널의 사이즈
        self.optimizer = None              #옵티마이저
        self.conv_w = None                 #합성곱의 가중치
        self.conv_b = None                 #합성곱의 절편
        self.units = units                  #은닉층의 뉴런개수
        self.batch_size = batch_size        #배치 크기
        self.w1 = None                     #은닉층의 가중치 
        self.b1 = None
        self.w2 = None
        self.b2 = None
        self.a1 = None                     #은닉층의 활성화 출력
        self.losses=[]                      #훈련 손실
        self.val_losses = []                #검증 손실
        self.lr = learning_rate             #학습률
        
    def forpass(self, x):                   #정방향 연산
        #3X3 합성공 연산을 수행
        c_out = tf.nn.conv2d(x, self.conv_w, padding='SAME', strides=1) + self.conv_b
        
        #렐루 활성화 함수 적용
        r_out = tf.nn.relu(c_out)
        
        #2X2 최대 풀링 적용
        p_out = tf.nn.max_pool2d(r_out, ksize = 2, strides=2, padding='VALID')
        
        #첫 번째 배치 차원을 제외하고 출력을 일렬로 펼침
        f_out = tf.reshape(p_out, [x.shape[0], -1])
        z1 = tf.matmul(f_out, self.w1) + self.b1
        a1 = tf.nn.relu(z1)
        z2 = tf.matmul(a1, self.w2) + self.b2
        return z2
    
    def init_weights(self, input_shape, n_classes):
        g = tf.initializers.glorot_uniform()
        self.conv_w = tf.Variable(g((3,3,1,self.n_kernels)))
        self.conv_b = tf.Variable(np.zeros(self.n_kernels), dtype=float)
        n_features = 14 * 14 * self.n_kernels                                    #28 * 28 이미지를 ksize 2로 strides 2를 하면 14*14개의 특성맵이 10개가 나옴
        self.w1 = tf.Variable(g((n_features, self.units)))               #특성개수 , 은닉층 뉴런 크기
        self.b1 = tf.Variable(np.zeros(self.units), dtype=float)
        self.w2 = tf.Variable(g((self.units, n_classes)))                 #은닉층 크기, 클래스 개수
        self.b2 = tf.Variable(np.zeros(n_classes),dtype=float)       #클래스 개수
        
    def fit(self, x, y , epochs = 100, x_val=None , y_val = None):
        self.init_weights(x.shape[0], y.shape[1])                         #x의 개수와 , 원핫 코딩 된 y의 개수
        self.optimizer = tf.optimizers.SGD(learning_rate=self.lr)
        #epcchs
        for i in range(epochs):
            print("에포크",i, end = ' ')
            batch_losses = []
            for x_batch, y_batch in self.gen_batch(x,y):
                print('.', end='')
                self.training(x_batch, y_batch)
                #배치 손실을 기록합니다.
                batch_losses.append(self.get_losses(x_batch,y_batch))
            print()
            #배치 손실 평균을 내어 훈련 손실값으로 저장
            self.losses.append(np.mean(batch_losses))
            #검증 세트에 대한 손실을 계산
            self.val_losses.append(self.get_losses(x_val,y_val))
            
    
    #미니 배치 제너레이터 함수
    def gen_batch(self, x, y):
        bins = len(x) // self.batch_size                         #배치 회수
        indexes = np.random.permutation(np.arange(len(x)))       #인덱스를 섞음
        x = x[indexes]
        y = y[indexes]
        
        for i in range(bins):
            start = self.batch_size * i
            end = self.batch_size * (i + 1)
            yield x[start:end], y[start:end]                    #batch_size만큼 슬라이싱하여 반환
        
    
    def training(self, x, y):
        m = len(x)                                              #샘플 개수를 저장
        with tf.GradientTape() as tape:
            z = self.forpass(x)
            #손실을 계산
            loss = tf.nn.softmax_cross_entropy_with_logits(y,z)
            loss = tf.reduce_mean(loss)
            
        weights_list = [self.conv_w, self.conv_b, self.w1, self.b1, self.w2, self.b2]
        #가중치에 대한 그레이디언트를 계산
        grads = tape.gradient(loss, weights_list)
        #그레이디언트으로 가중치를 업데이트
        self.optimizer.apply_gradients(zip(grads,weights_list))
        
    def predict(self, x):
        z = self.forpass(x)
        return np.argmax(z.numpy(), axis = 1)        #가장 큰 인덱스를 반환 
    
    def score(self, x, y):
        #예측과 타깃 열 벡터를 비교하여 True의 비율을 반환
        return np.mean(self.predict(x) == np.argmax(y, axis=1))
    
    def get_losses(self, x, y):
        z = self.forpass(x)
        #손실을 계산해서 저장
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y,z))
        return loss.numpy()
In [3]:
#텐서플로의 tape 기능 살펴보기

x = tf.Variable(np.array([1.0, 2.0, 3.0]))
with tf.GradientTape() as tape:
    y = x ** 3 + 2 * x +5
    
print(tape.gradient(y,x))
WARNING:tensorflow:From C:\Users\USER\Anaconda3\lib\site-packages\tensorflow\python\ops\math_grad.py:1205: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where
tf.Tensor([ 5. 14. 29.], shape=(3,), dtype=float64)
In [4]:
(x_train_all, y_train_all), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
In [5]:
from sklearn.model_selection import train_test_split

x_train, x_val, y_train, y_val = train_test_split(x_train_all, y_train_all,stratify = y_train_all, test_size=0.2, random_state=42)
In [6]:
#y값 원-핫 인코딩으로 변경
y_train_encoded = tf.keras.utils.to_categorical(y_train)
y_val_encoded = tf.keras.utils.to_categorical(y_val)
In [7]:
x_train = x_train.reshape(-1, 28,28,1)
x_val = x_val.reshape(-1,28,28,1)
print()

In [8]:
#이미지 전처리
x_train = x_train / 255
x_val = x_val /255
In [9]:
cn = ConvolutionNetwork(n_kernels=10, units=100, batch_size=128, learning_rate=0.01)
cn.fit(x_train,y_train_encoded, x_val=x_val, y_val = y_val_encoded, epochs=20)
에포크 0 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 1 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 2 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 3 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 4 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 5 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 6 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 7 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 8 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 9 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 10 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 11 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 12 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 13 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 14 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 15 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 16 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 17 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 18 .......................................................................................................................................................................................................................................................................................................................................................................................
에포크 19 .......................................................................................................................................................................................................................................................................................................................................................................................
In [10]:
import matplotlib.pyplot as plt

plt.plot(cn.losses)
plt.plot(cn.val_losses)
plt.ylabel('loss')
plt.xlabel('iteration')
plt.legend(['train_loss', 'val_loss'])
plt.show()
In [11]:
cn.score(x_val,y_val_encoded)
Out[11]:
0.8808333333333334
In [12]:
x_test = x_test.reshape(-1,28,28,1)
y_test_encoded = tf.keras.utils.to_categorical(y_test)

x_test = x_test/255
cn.score(x_test,y_test_encoded)
Out[12]:
0.8652
In [15]:
image = tf.keras.preprocessing.image
img = image.load_img('a.jpg',target_size = (28,28))
plt.imshow(img)
class_names =['티셔츠/윗도리','바지', '스웨터','드레스','코트','샌들','셔츠','스니커즈','가방','앵글부츠']
In [20]:
img_tensor = image.img_to_array(img)
#shirt = np.resize(img_tensor,(1,28,28,1))
shirt = shirt.reshape(1,28,28,1)
shirt = shirt / 255
pre = cn.predict(shirt)
print(class_names[pre.argmax()])
티셔츠/윗도리

 

 

 

느낀 점 : 이제까지 수행해온 의류분류기로 셔츠를 분류했을 때는 가방, 신발 등 잘못 분류했었는데 이번에는 상의 정도로 맞추는 모습을 볼 수 있었다. 다음에는 케라스를 이용해서 분류를 해보겠다.

반응형