2 minute read

Deep Learning

  • vision(영상, 이미지) → CNN(Convolutional Neural Network)
  • NLP(자연어 처리) → RNN(Recurrent Neural Network)

Machine Learning에서 2차원 데이터를 입력합니다. 하지만 이미지를 2차원 데이터로 바꿔야하는데요. 컬러 이미지를 흑백으로 바꾸면 2차원으로 변경가능합니다. 그럼 이제 된걸까요? 사진은 한장만 있는게 아니니까 사진을 여러장을 학습시키려고 한다면 다시 2차원에서 3차원이 됩니다. 그럼 여기서 다시 어떻게 2차원으로 바꿀 수 있을까요. 높이, 너비 합쳐보겠습니다. 하지만 그렇게 해버린다면 공간 데이터가 유실되므로 결국에 학습이 잘 되지 않습니다. 이 문제를 해결하는 알고리즘이 바로 CNN입니다. Convolutional Neural Network의 약어입니다. CNN은 이미지의 특징을 추출해서 특징을 학습하는 방식입니다.

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.image as img


fig = plt.figure(figsize=(10,10))  # 그림을 그릴 영역을 준비해요!!

ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)

ori_image = img.imread('/content/girl-teddy.jpg')
print(type(ori_image), ori_image.shape)  # <class 'numpy.ndarray'>, (429, 640, 3)

ax1.imshow(ori_image)

image

이제 이 원본이미지에 대해 합성곱연산(convolution)을 수행해 봅시다. tesorflow API를 이용해서 convolution 연산을 수행하는데 이 API는 4차원 데이터만 입력받습니다. (이미지갯, height, width, color)가 됩니다. 우리는 사진이 한장이므로 (1, 429, 640, 3)이 되면 됩니다.

input_image = ori_image.reshape((1,) + ori_image.shape)
input_image = input_image.astype(np.float32)
print(input_image.shape) # (1, 429, 640, 3)

이제 이미지가 준비되었으므로 filter를 준비합니다. 필터는 (3, 3, 1, 1)과 같은 형태로 준비합니다. (filter height, filter width, filter channel, filter의 개수)가 됩니다.

filter = np.array([[[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]]])
print(filter.shape)  # (3, 3, 1, 1)

# strides=1(가로,세로 1칸씩 이동)
# padding = 'SAME' (zero padding을 수행) => 크기가 변하지 않아요!
#         = 'VALID' (padding처리수행) => 크기가 줄어들어요!
conv2d = tf.nn.conv2d(channel_1_input_image,
                      filter,
                      strides=[1,1,1,1],
                      padding='VALID')

print(type(conv2d))  # <class 'tensorflow.python.framework.ops.EagerTensor'>
conv2d_result = conv2d.numpy()
print(type(conv2d_result), conv2d_result.shape)  # <class 'numpy.ndarray'> (1, 427, 638, 1)
t_img = conv2d_result[0,:,:,:]
ax2.imshow(t_img)

fig.tight_layout()
plt.show()

image

이제 pooling처리까지 진행합니다.

pool = tf.nn.max_pool(conv2d,
                      ksize=[1,3,3,1], # [batch, height, width, channels]
                      strides=[1,3,3,1], # [batch, height, width, channels]
                      padding='VALID')

pool_result = pool.numpy()
pool_img = pool_result[0,:,:,:]
ax3.imshow(pool_img)

fig.tight_layout()
plt.show()

image

이번에는 tensorflow에서 구현해보겠습니다.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout
from tensorflow.keras.optimizers import Adam
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

데이터 불러오기

df = pd.read_csv('/content/drive/MyDrive/AI 융합 서비스 개발자 양성과정제목없는 폴더/빅데이터 과정/data/mnist/train.csv')
display(df.head(), df.shape) # (42000, 785)

데이터 전처리

# 1. 결측치처리
(((df.drop('label', axis=1, inplace=False)).isnull()).sum()).sum()
#   현재 데이터에는 결측치가 존재하지 않아요!

# 2. 이상치처리
#    현재 데이터에는 이상치도 존재하지 않아요!

# 3. 정규화처리
scaler = MinMaxScaler()
scaler.fit(df.drop('label', axis=1, inplace=False).values)
x_data_norm = scaler.transform(df.drop('label', axis=1, inplace=False).values)
t_data = df['label'].values.reshape(-1,1)

데이터 분리

# 4. 데이터 분리
x_data_train_norm, x_data_test_norm, t_data_train, t_data_test = \
train_test_split(x_data_norm,
                 t_data,
                 test_size=0.3)

keras model 구현

model = Sequential()

model.add(Conv2D(filters=32,
                 kernel_size=(3,3),
                 strides=(1, 1),
                 activation='relu',
                 input_shape=(28,28,1))) # target이 784개이므로 28*28=784

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(filters=64,
                 kernel_size=(3,3),
                 strides=(1, 1),
                 activation='relu'))

model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(filters=128,
                 kernel_size=(3,3),
                 strides=(1, 1),
                 activation='relu'))

model.add(Flatten())

model.add(Dense(units=256,
                activation='relu'))

model.add(Dense(units=10,
                activation='softmax'))

model.summary()

image

model.compile(optimizer=Adam(learning_rate=1e-3),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
# 전체이미지수는 42,000
# 학습이미지수는 29,400
# 학습이미지를 한방에 모두 다 읽어와서 처리할 수 도 있지만
# 이런경우 메모리가 부족할수 있어요! 그래서 batch로 짤라서 읽어들여서 처리해야 해요!
model_result = model.fit(x_data_train_norm.reshape(-1,28,28,1),
                         t_data_train,
                         epochs=200,
                         batch_size=100,
                         verbose=1,
                         validation_split=0.3
                         )

Updated:

Leave a comment