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 포함할 때)


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()

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 |