본문 바로가기

멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차/DL

4/14 목

728x90

목요일!

 

오늘은 CNN을 실제 코드로 구현해본다!

 

이미지 한 장 : 2차원(X, T)

→ Convolution Layer :: Feature Map : 2차원 여러 개 → Activation Map : 3차원 → X 데이터(이미지 정보. 이미지 개수, 세로, 가로, Channel) : 4차원 Data

▶ conv : 특징을 뽑아낸 이미지가 여러 장이 되도록 반복 작업(이미지 개수, Feature Map 세로, Feature Map 가로, filter의 개수)

▶ Pooling Layer :: conv 작업을 거친 여러 장의 데이터 사이즈를 줄임

▶ conv :: Pooling Layer를 거친 데이터의 특징을 또 뽑아냄

▶ FLATTEN :: 4차원 → 2차원(batch size 포함할 때)

Feature Map Size 계산법

 

1. Channel이 3인 이미지 데이터를 Convolution 연산하는 코드

import numpy as np
import tensorflow as tf

# 입력 데이터의 형태 : (이미지 개수, 이미지 height, 이미지 width, Channel) (1, 3, 3, 3)
image = np.array([[[[1, 2, 3],
                    [1, 2, 3],
                    [1, 2, 3]],
                   [[1, 2, 3],
                    [1, 2, 3],
                    [1, 2, 3]],
                   [[1, 2, 3],
                    [1, 2, 3],
                    [1, 2, 3]]]], dtype=np.float64)

# print(image.shape) # (1, 3, 3, 3)

# filter의 형태 : (filter height, filter width, filter channel, filter 개수) (2, 2, 3, 2)
weight = np.array([[[[1,2],
                   [1,2],
                   [1,2]],
                   [[1,2],
                   [1,2],
                   [1,2]]],
                   [[[1,2],
                   [1,2],
                   [1,2]],
                   [[1,2],
                   [1,2],
                   [1,2]]]], dtype=np.float64)

# print(weight.shape) # (2, 2, 3, 2)

conv2d = tf.nn.conv2d(image, weight,
                      strides=[1,1,1,1], # 위, 아래, 좌, 우
                      padding='VALID')
                   
sess = tf.Session()
result = sess.run(conv2d)
print(result)

 

2. image CNN 구현

 

Pooling : filter의 size와 stride에 따라서 conv의 출력인 feature map은 크기가 줄어듦(same padding이 아닌 이상)

→ filter를 여러 개 사용하기 때문에 실제 데이터량은 상당히 많이 증가함

→ 이런 과정을 거쳐서 DNN으로 데이터가 전달되면 학습에 문제가 발생!

→ 이 문제를 해결하기 위해 Pooling 사용

MAX, Average, MIN

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

figure = plt.figure()

ax1 = figure.add_subplot(1,3,1)
ax2 = figure.add_subplot(1,3,2)
ax3 = figure.add_subplot(1,3,3)

ori_image = img.imread('./images/girl-teddy.jpg')
# print(type(ori_image)) # <class 'numpy.ndarray'>
# print(ori_image.shape) # (429, 640, 3) 흑백 이미지인데도 3차원? RGB 값이 다 똑같음

ax1.imshow(ori_image)

# 입력 데이터의 형태 : (이미지 개수, 이미지 height, 이미지 width, Channel) (1, 429, 640, 3)
# 이미지의 차원(3 -> 4)을 올려줘야!

input_image = ori_image.reshape((1,) + ori_image.shape) # 튜플로 차원 하나 더해주기
# print(input_image.shape)

input_image = input_image.astype(np.float32) # 데이터를 실수로 전환

# 이미지의 channel을 1로 변경
channel_1_input_image = input_image[:,:,:,0:1]
# print(channel_1_input_image.shape) # (1, 429, 640, 1)

# filter의 형태 : (filter height, filter width, filter channel, filter 개수) (3, 3, 1, 1)
weight = np.array([[[[-1]], [[0]], [[1]]],
                   [[[-1]], [[0]], [[1]]],
                   [[[-1]], [[0]], [[1]]]])

# print(weight.shape) # (3, 3, 1, 1)

# stride = 1, padding='VALID'
conv2d = tf.nn.conv2d(channel_1_input_image, weight,
                      strides=[1,1,1,1], # 위, 아래, 좌, 우
                      padding='VALID')

sess = tf.Session()
result = sess.run(conv2d)
# print(result.shape) # (1, 427, 638, 1) (이미지 개수, feature map 세로, feature map 가로, filter 개수)

t_img = result[0,:,:,:]
# print(t_img.shape) # (427, 638, 1)

ax2.imshow(t_img)

# pooling 처리
pooling_result = tf.nn.max_pool(result,
                                ksize=[1,3,3,1], # 3 * 3 kernel
                                strides=[1,3,3,1], # kernel size와 동일하게 설정
                                padding='VALID')

pool_img = sess.run(pooling_result)
pool_img = pool_img[0,:,:,:]
# print(pool_img.shape) # (142, 212, 1)
ax3.imshow(pool_img)

plt.tight_layout()
plt.show()

원본, Convolution, Pooling

 

3. MNIST 예제를 이용해서 학습시킬 이미지들을 만들어 보자

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

# Raw Data Loading
df = pd.read_csv('./data/mnist/train.csv')
# display(df.head())

# subplot 생성
figure = plt.figure()

ax = list()

for i in range(5):
    ax.append(figure.add_subplot(1,5,i+1))

# 이미지 확인
img_data = df.drop('label', axis=1, inplace=False).values

ori_image = img_data[5:6].reshape(28,28) # 2차원 이미지 형태
ax[0].imshow(ori_image, cmap='Greys')

# 입력 데이터의 형태 : (이미지 개수, 이미지 height, 이미지 width, Channel) (1, 28, 28, 1)
input_image = ori_image.reshape((1,) + ori_image.shape + (1,)) # 2차원 이미지를 4차원으로
# print(input_image.shape)
input_image = input_image.astype(np.float32) # 데이터를 실수로 변환

# filter의 형태 : (filter height, filter width, filter channel, filter 개수) (3,3,1,4)
weight = np.random.rand(3,3,1,4)
# print(weight.shape)

conv2d = tf.nn.conv2d(input_image,
                     weight,
                     strides=[1,1,1,1],
                     padding='VALID')

sess = tf.Session()
conv2d_result = sess.run(conv2d)

# ReLU 처리
relu_ = tf.nn.relu(conv2d_result)
result_result = sess.run(relu_)

# pooling 처리
pool = tf.nn.max_pool(result_result,
                      ksize=[1,2,2,1], # 2 * 2 kernel
                      strides=[1,2,2,1],
                      padding='VALID')

pool_result = sess.run(pool)
# print(pool_result.shape) # (이미지 개수, feature map 세로, feature map 가로, filter 개수) (1, 13, 13, 4)

# 1과 4의 위치를 swap
i = np.swapaxes(pool_result,0,3)
# print(i.shape) # (4, 13, 13, 1)

for idx, image in enumerate(i):
    ax[idx+1].imshow(image.squeeze(), cmap='Greys') # squeeze는 numpy에서 차원이 1인 것을 제거
    
plt.tight_layout()
plt.show()

 

4. MNIST 예제 CNN 구현

import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import warnings
warnings.filterwarnings('ignore')

tf.reset_default_graph() # 그래프 리셋

# Raw Data Loading
df = pd.read_csv('./data/mnist/train.csv')

# Data Split
train_x_data, test_x_data, train_t_data, test_t_data = \
train_test_split(df.drop('label', axis=1, inplace=False),
                df['label'],
                test_size=0.3,
                random_state=1,
                stratify=df['label'])

# x_data는 정규화 진행
scaler = MinMaxScaler()
scaler.fit(train_x_data)
norm_train_x_data = scaler.transform(train_x_data)
norm_test_x_data = scaler.transform(test_x_data)

# t_data는 One-Hot Encoding 진행
sess = tf.Session()
onehot_train_t_data = sess.run(tf.one_hot(train_t_data, depth=10))
onehot_test_t_data = sess.run(tf.one_hot(test_t_data, depth=10))

# Tensorflow 구현

# placeholder
X = tf.placeholder(shape=[None,784], dtype=tf.float32)
T = tf.placeholder(shape=[None,10], dtype=tf.float32)

# 입력 x_data의 shape를 변경
# (이미지 개수 - '-1', 이미지 height - '28', 이미지 width - '28', Channel - '1'). 행의 개수 알 수 없으므로 -1
x_img = tf.reshape(X, [-1,28,28,1])

# 첫번째 Convolution Layer

# filter의 형태 : (filter height, filter width, filter channel, filter 개수) 
W2 = tf.Variable(tf.random.normal([3,3,1,32])) # filter == Weight. 3 * 3 사이즈
L1 = tf.nn.conv2d(x_img, W2, strides=[1,1,1,1], padding='SAME')
L1 = tf.nn.relu(L1)
# (이미지 개수, feature map 세로, feature map 가로, filter 개수)
# print('L1의 Conv 결과 데이터 shape : {}'.format(L1.shape)) # (?, 28, 28, 32)

# 첫번째 Pooling
L1 = tf.nn.max_pool(L1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
# print('L1의 Pooling 결과 데이터 shape : {}'.format(L1.shape)) # (?, 14, 14, 32)

# 두번째 Convolution Layer
W3 = tf.Variable(tf.random.normal([3,3,32,64]))
L2 = tf.nn.conv2d(L1, W3, strides=[1,1,1,1], padding='SAME')
L2 = tf.nn.relu(L2)
# print('L2의 Conv 결과 데이터 shape : {}'.format(L2.shape)) # (?, 14, 14, 64)

# 두번째 Pooling
L2 = tf.nn.max_pool(L2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
# print('L2의 Pooling 결과 데이터 shape : {}'.format(L2.shape)) # (?, 7, 7, 64)

# 결과 데이터를 DNN에 넣어서 학습
L2 = tf.reshape(L2, [-1, 7*7*64]) # 2차원으로 만들어주기

# Weight & bias
W4 = tf.get_variable('W4', shape=[7*7*64, 256], # hidden layer는 1개, node
                    initializer=tf.contrib.layers.variance_scaling_initializer())
b4 = tf.Variable(tf.random.normal([256]))

_layer3 = tf.matmul(L2, W4) + b4
layer3 = tf.nn.relu(_layer3)
layer3 = tf.nn.dropout(layer3, rate=0.3)

# Out-put Layer
W5 = tf.get_variable('W5', shape=[256, 10],
                    initializer=tf.contrib.layers.variance_scaling_initializer())
b5 = tf.Variable(tf.random.normal([10]))

# Hypothesis, model
logit = tf.matmul(layer3, W5) + b5
H = tf.nn.softmax(logit)

# loss function
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logit, labels=T))

# Train
train = tf.train.GradientDescentOptimizer(learning_rate=1e-3).minimize(loss)

# session 및 초기화
sess.run(tf.global_variables_initializer())

# 반복학습 (+ batch 처리)
for step in range(200):
    
    tmp, loss_val = sess.run([train, loss],
                            feed_dict={X:norm_train_x_data,
                                      T:onehot_train_t_data})
    if step % 20 == 0:
        print('loss value : {}'.format(loss_val))

 

# 성능평가(Accuracy)
predict = tf.argmax(H,1)
correct = tf.equal(predict, tf.argmax(T,1))
accuracy = tf.reduce_mean(tf.cast(correct, dtype=tf.float32))

result = sess.run(accuracy, feed_dict={X:norm_test_x_data, T:onehot_test_t_data})
print('정확도 : {}'.format(result)) # 0.833730161190033

 

1. 4/11 월 2. 4/12 화 3. 4/13 수 4. 4/14 목 5. 4/15 금
Deep Learning
Perceptron,
Nueral Network
Deep Learning
Initialization,

ReLU,
Drop-out,
Early-Stopping
Deep Learning
Image,

CNN,
Convolution Layer,
Channel,
Filter,
Stride,
Padding,
Feature Map,
Activation Map
Deep Learning
CNN,

Feature Extraction,
Pooling
Deep Learning
CNN
6. 4/18 월 7. 4/19 화 8. 4/20 수 9. 4/21 목 10. 4/22 금
Deep Learning
전이학습,
Generator
Deep Learning

Deep Learning

Deep Learning

Deep Learning

11. 4/25 월 4/26 화 ~ 5/19 목
Deep Learning

AI 프로젝트

* 수업에 집중하자!

728x90

'멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차 > DL' 카테고리의 다른 글

4/18 월  (0) 2022.04.18
4/15 금  (0) 2022.04.15
4/13 수  (0) 2022.04.13
4/12 화  (0) 2022.04.12
4/11 월  (0) 2022.04.11