기본 콘텐츠로 건너뛰기

[Machine Learning] 합성곱 신경망(Convolution Neural Network)


합성곱 신경망(Convolution Neural Network) 이란 무엇일까요? 먼저 들어가기 전 간단한 요약을 보고 들어가겠습니다. 해당 요약을 잘 숙지해주시고 본문의 내용을 관심있게 뵈주시길 부탁드립니다.
    ⓐ 인간의 시신경을 모방(다중 퍼셉트론)하여 만든 딥러닝 구조 중 하나
    ⓑ 합성곱을 이용하여 이미지의 공간적 특징을 유지

본 글을 시작하기 앞서 알아두면 좋은 내용을 추천한다.

합성곱 신경망(CNN)의 필요성

1998년 Yann LeCun, et. al.가 손 글씨 숫자를 인식하는 딥러닝 구조 LeNet-5를 발표하며 현재 합성곱 신경망의 초석이 되었습니다. 관련해서 자세한 내용은 논문을 참고 부탁드리며, 향후 본 블로그에서 자세히 설명하도록 하겠습니다.
오늘은 합성곱 신경망의 핵심이 되는 합성곱(convolution)과 풀링(pooling), 플래튼에 대해서 살펴보도록 하겠습니다. 마지막으로 keras MNIST(Modified National Institute of Standards and Technology) 이미지 데이터를 활용한 파이썬 예제 코드를 공부하도록 하겠습니다.

우리가 알고 있는 일반적인 신경망의 학습은 입력층에서 은닉층을 거쳐갈수록 점점 복잡한 특징들을 학습해나갑니다. 일반적인 신경망의 학습과 별반 다르지 않게 합성곱 신경망 또한 모델(함수) 계수의 오차를 계산하고 오차 만큼 역 전파(오차역전파)하여 가중치를 조정해가는 학습 과정입니다. 여기서 다른 점은 일반 신경망에서는 특정 학습을 전 결합층(MLP, Fully-Connected Layer)에서 했다면, 합성곱 신경망에서는 합성곱층(convolution layer)에서 오차를 계산하고 오차만큼 역 전파하여 가중치를 조정하는 점입니다.

이미지를 벡터로 변환한 결과 (출처)

그런데 이미지 학습에 있어서 전 결합층(MLP, fully-connected layer)의 단점은 입력시 1차원 형태로 벡터 변환을 하기 때문에 공간적 특징(Spatial Structure)을 읽어버리는 것입니다. 여기서 이미지 학습에 있어 하나의 아이디어는 공간적 특징을 학습하는 부분과 분류를 학습하는 부분의 역할을 분담하여 각각의 장점을 살리는 것 입니다. 즉 공간적 특징 추출(feature extraction)은 지역적 연결을 가진 합성곱층에 맡기고 기존에 잘 수행하고 있던 분류(classification)의 역할은 그대로 전 결합층에 맡겨보는 것입니다. 본 블로그에서는 합성곱 신경망의 공간적 특징을 추출하는 부분에 대해 설명하도록 하겠습니다.

채널(Channel)이란?

들어가기 앞서 이미지 처리에 필요한 간단한 언어를 소개하겠습니다. 기계는 글자나 이미지보다 숫자 즉, 텐서를 더 잘 처리할 수 있습니다. 이미지는 (높이, 너비, 채널)이라는 3차원 텐서로 정의할 수 있습니다. 여기서 높이는 이미지의 세로 방향 픽셀 수, 너비는 이미지의 가로 방향 픽셀 수, 채널은 색 성분을 의미합니다. 흑백 이미지는 채널 수가 1이며, 각 픽셀은 0부터 255 사이의 값을 가집니다. 아래는 28 × 28 픽셀의 손 글씨 데이터를 보여줍니다.

위 손글씨 데이터는 흑백 이미지므로 채널 수가 1임을 고려하면 (28 × 28 × 1)의 크기를 가지는 3차원 텐서입니다. 그렇다면 흑백이 아닌 컬러 이미지는 어떨까요? 컬러 이미지는 적색(Red), 녹색(Green), 청색(Blue) 채널 수가 3개입니다. 하나의 픽셀은 RGB 삼원색의 조합으로 이루어집니다. 아래 그림과 같이 높이가 500, 너비가 800인 이미지가 있다면 이 이미지의 텐서는 (500 x 800 x 3)의 크기를 가지는 3차원 텐서입니다. 여기서 채널은 때로 깊이(depth)라고도 하며, 이 경우 이미지는 (높이, 너비, 깊이)라는 3차원 텐서로 표현합니다.

합성곱(Convolution)


합성곱층은 합성곱 신경망의 핵심이며 주된 역할은 이미지의 공간적 특징을 추출해냅니다. 먼저 합성곱의 연산 부터 이해해볼까요? 합성곱은 커널(kernel) 혹은 필터(filter) 또는 윈도우(window)라는 \( n \times m \) 크기의 행렬로 높이(height) x 너비(width) 크기의 이미지를 처음부터 끝까지 겹치며 훑으면서 \( n \times m \) 크기의 겹쳐지는 부분의 각 이미지와 커널 내 원소의 값을 곱해서 모두 더한 값을 출력하는 것을 말합니다. 이때 순서는 이미지의 가장 왼쪽 위부터 가장 오른쪽 아래까지 순처적으로 훑습니다. 여기서 순차적으로 훑을 때의 이동 보폭을 스트라이드(stride)라고 합니다. 일반적으로 커널은 3 x 3 또는 5 x 5를 사용합니다.
예를 통해 알아보겠습니다. 아래 그림은 3 x 3 크기의 커널로 5 x 5의 이미지 행렬에 합성곱 연산을 수행하는 과정을 보여줍니다. 한 번의 연산을 1 스텝(Step)이라고 하였을 때, 합성곱 연산의 1 스텝까지 이미지와 식으로 표현해보았습니다.

□ 예제: 1 스텝 합성곱 연산

입력 이미지와 커널 내 원소의 값을 곱해서 모두 더한 결과 값: 
\( (1 \times 1) + (2 \times 0) + (3 \times 1) + (2 \times 1) + (1 \times 0) + ( 0 \times 1) + (3 \times 0) + (0 \times 1) + (1 \times 0) = 6 \)

위 스텝을 총 9번까지 수행하여 연산을 마쳤을 때 최종 결과는 아래 그림과 같습니다. 스텝 연산과 같이 입력으로부터 커널을 사용하여 합성곱 연산을 통해 나온 결과를 특성 맵(feature map)이라고 합니다.
위의 1 스텝 예제에서는 커널의 크기가 3 × 3이고 이동 범위가 1 스트라이드 이였지만, 커널의 크기와 이동 범위는 사용자가 정할 수 있습니다. 여기서 커널의 이동 범위를 스트라이드(stride)라고 정의 합니다. 아래는 스트라이드가 2일 경우에 5 × 5 이미지에 합성곱 연산을 수행하는 3 × 3 커널의 움직임을 보여줍니다. 최종적으로 2 × 2의 크기의 특성 맵을 얻습니다.

예제로 작은 이미지에 대한 합성곱 연산을 살펴보았습니다. 단지 5 x 5 픽셀의 이미지와 단 1개의 커널를 사용하였으며, 모든 항목은 정수형 곱셈으로 이루어졌습니다. 그럼에도 프로세싱해야 하는 곱셈 연산이 상당히 많은 것을 알 수 있는데요, 요즘에는 보통 600 필셀 이상의 이미지를 사용하고 커널의 수도 많다면 연산 프로세스는 지금 보다 더 많겠죠? 또한 요즘 이미지 모델의 학습과 추론에는 32bit 실수가 사용되어, 연산의 복잡성은 CPU 혼자서 감당하기는 힘들 것입니다. 이럴떄 GPU를 활용하면 연산 속도를 좀더 효율적으로 제어 가능할 것입니다. GPU 관련해서는 본 블로그의 [CUDA] 딥러닝의 필수 GPU와 CUDA 참고 부탁드립니다.

패딩(Padding)은 왜 사용할까?

앞선 예제에서 5 × 5 이미지에 3 × 3의 커널로 합성곱 연산을 하였을 때, 스트라이드가 1일 경우에는 3 × 3의 특성 맵을 얻었습니다. 이와 같이 합성곱 연산의 결과로 얻은 특성 맵은 입력보다 크기가 작아진다는 특징이 있습니다. 만약, 합성곱 층을 여러개 쌓았다면 최종적으로 얻은 특성 맵은 초기 입력보다 매우 작아진 상태가 되버립니다. 합성곱 연산 이후에도 특성 맵의 크기가 입력의 크기와 동일하게 유지되도록 하고 싶다면 패딩(padding)을 사용하면 됩니다.
패딩은 합성곱 연산을 하기 전에 입력 이지미의 가장자리에 지정된 개수의 폭만큼 행과 열을 추가해주는 것을 말합니다. 주로 0 값을 채우는 제로 패딩(zero padding)을 사용합니다. 아래 그림은 5 x 5 이미지에 1폭짜리 제로 패딩을 사용한 예제입니다.

시각적인 자료를 활용하면 아래 그림과 같습니다.
커널(3x3), 스트라이드 1, 패딩을 적용한 예시 (출처)

그렇다면 여기까지 학습한 내용을 바탕으로 tensorflow 코드로 어떻게 작성하는지 한번 볼까요? 우선 임의의 데이터를 생성해주고 합성곱 층에 커널과 스트라이드 및 패딩까지 적용해보겠습니다.

1
2
3
4
5
6
7
8
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Conv2D, MaxPooling2D
 
# 임의 데이터 생성
= tf.random.normal(shape=(128,28,28,1), mean=0., stddev=1.# [batch size, W, H, channel]
 
# 입력과 출력의 크기가 같게 패딩 설정하기
hiddens = Conv2D(filters=32, kernel_size=(3,3), strides=2, padding='same', activation="relu")(X)
print('After Convolution: ', hiddens.shape)
cs

결과는 다음과 같이 (128, 14, 14, 32) 출력됩니다.
지금까지 정리한 내용을 간단하게 수식으로 표현해볼까요? 한 층의 합성곱을 일반화한 식을 다음과 같이 정리할 수 있습니다. 여기서 아랫첨자 1, 2는 각각 입력과 출력입니다.

입력 데이터
    \( H_{1} \times W_{1} \times D_{1} \) 
    \( H_{1} \)는 높이, \( W_{1} \)는 너비, \( C_{1} \)는 채널 또는 깊이

하이퍼 파라미터(Hyper-Parameters)
여기서 커널의 높이와 너비는 같다고 가정하였습니다. 다를 경우 높이와 너비 별로 각 각 계산하면 됩니다.
    커널의 수: \( K \) 
    커널의 크기: \( F \) 
    스트라이드: \( S \) 
    패딩: \( P \) 

출력 테이터
여기서 계산한 출력 데이터에서 소수점 이하는 버립니다.
    \( H_{2} = \frac{H_{1} - F + 2P} {S} + 1 \) 
    \( W_{2} = \frac{ W_{1} - F + 2P} {S} + 1 \)
    \( D_{2} = K \) 

가중치의 수
    \( \left [F_{2} \times D_{1} + D_{1} \right ] \times K \)

풀링(Poolling)

앞에서 소개한 그림 처럼 합성곱 층(합성곱 연산과 활성화 함수) 다음에는 풀링(pooling) 층을 추가하는 것이 일반적입니다. 풀링 층에서는 특성 맵을 다운샘플링(down-sampling)하여 특성 맵의 크기를 줄이는 풀링 연산이 이루어집니다. 풀링 연산에는 일반적으로 최대 풀링(max pooling)평균 풀링(average pooling)이 사용됩니다.
풀링 연산에서도 합성곱 연산과 마찬가지로 커널과 스트라이드의 개념을 가집니다. 아래 그림과 같이 스트라이드가 2일 때, 2 x 2 크기 커널로 맥스 풀링 연산을 했을 때 특성맵이 절반의 크기로 다운샘플링되는 것을 보여줍니다. 맥스 풀링은 커널과 겹치는 영역 안에서 최대값을 추출하는 방식으로 다운샘플링합니다.


풀링 연산은 커널과 스트라이드 개념이 존재한다는 점에서 합성곱 연산과 유사하지만, 합성곱 연산과의 차이점은 학습해야 할 가중치가 없으며 연산 후에 채널 수가 변하지 않는다는 점입니다.
앞서 소개한 tensorflow 코드에 풀링까지 적용한 결과를 확인해 볼 까요?

1
2
3
4
5
6
7
8
9
10
11
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Conv2D, MaxPooling2D
 
# 임의 데이터 생성
= tf.random.normal(shape=(128,28,28,1), mean=0., stddev=1.# [batch size, W, H, channel]
 
# 입력과 출력의 크기가 같게 패딩 설정하기
hiddens = Conv2D(filters=32, kernel_size=(3,3), strides=2, padding='same', activation="relu")(X)
hiddens_pool = MaxPooling2D(pool_size=(2,2), strides=(2,2))(hiddens)
print('After Pooling: ', hiddens_pool.shape)
 
//After Pooling:  (1287732)
cs

합성곱 신경망의 가중치와 편향

합성곱 신경망에서의 가중치와 편향을 이해하기 위해서 다층 퍼셉트론(multi-layer perceptron)과 비교해보겠습니다. 3 x 3 크기의 이미지를 처리하여 2 x 2 특성맵을 계산하는 예로 비교하면 아래 그림과 같이 표현 할 수 있습니다. 인공 신경망으로 3 x 3 이미지를 배열로 펼처서(flattening) 각 픽셀에 가중치를 곱하여 은닉충에 전달하는 것과 같습니다. 이렇게 펼치게 되면 앞서 말한 바와 같이 공간적 특성을 유지하는 것이 어렵게 되겠죠?


합성곱 신경망에서는 특성 맵을 얻기 위해서 커널로 이미지 전체를 훑으며 합성곱 연산을 진행합니다. 이 때 사용되는 가중치는 \( w_{0}, w_{1}, w_{2}, w_{3} \) 4개 뿐입니다. 즉, 위 그림에서 이미지의 모든 픽셀 수에 대응하는 가중치를 사용하는 것이 아니라, 커널의 수에 대응하는 가중치를 사용하여 커널과 매핑되는 픽셀만을 입력으로 사용하는 것을 볼 수 있습니다. 하지만 다층 퍼셉트론의 경우 입력층에서 은닉층으로 통과시키기 위해 각 은닉층의 노드 값마다 입력층에 대응하는 가중치를 사용한 것을 알 수 있습니다. 결국 합성곱 신경망은 다층 퍼셉트론을 사용할 때보다 훨씬 적은 수의 가중치를 사용하여 공간적 구조 정보를 보존하는 특징을 알 수 있습니다.
다층 퍼셉트론의 은닉층에서는 가중치 연산 후에 비선형성을  추가하기 위해 활성화 함수를 통과시켰습니다. 이와 마찬가지로 합성곱 신경망의 은닉층에서도 활성화 함수를 통과시키며, 이때 렐루 함수나 렐루 함수의 변형들이 주로 사용됩니다. 이와 같이 합성곱 연산을 통해서 특성 맵을 얻고, 활성화 함수를 지나는 연산을 하는 신경망의 층을 합성곱 층(convolution layer)이라고 합니다.


합성곱 신경망에도 편향(bias)를 추가할 수 있습니다. 편향을 사용한다면 일반적으로 커널을 적용한 뒤에 더해집니다. 여기서 편향은 하나의 값만 존재하며, 커널이 적용된 결과의 모든 원소에 더해진 특성맵을 산출하게 됩니다.

채널 개수가 2이상인 합성곱 연산

지금까지는 채널의 개수를 고려하지 않은 2차원 텐서를 가정하여 설명하였습니다. 그렇다면 다수의 채널을 가질 경우, 즉 3차원 텐서인 경우에 합성곱 연산을 어떻게 하는지 예제를 통해 알아보도록 하겠습니다. 결과적으로 채널의 수에 대응하는 특성 맵을 산출하고, 그리고 그 결과를 모두 더하여 최종 특성 맵을 얻습니다.


위 그림은 3개의 채널을 가진 입력 데이터와 3개의 채널을 가진 커널의 합성곱 연산을 보여줍니다. 여기서 각 커널과 채널끼리의 크기는 같아야 합니다. 각 채널 간 합성곱 연산을 마치고, 그 결과를 모두 더해서 하나의 채널을 가지는 특성 맵을 만듭니다. 주의할 점은 위의 연산에서 사용되는 커널은 3개의 커널이 아니라 3개의 채널을 가진 1개의 커널 입니다.

필터 개수가 2이상인 합성곱 연산

그렇다면 이번에는 필터의 개수가 2 이상인 합성곱 연산에 대해 예제를 통해 알아보도록 하겠습니다. 결론적으로 필터 각각으로 특성맵을 얻게됩니다.


전결합층

합성곱 신경망의 마지막에서 분류(classification)를 결정하는 단계입니다. 여기서 플래튼(flatten)은 각 풀링 레이어(pooling layer)에서 얻은 특성맵을 1차원 벡터로 변환하는 것을 말합니다. 이 후 1차원 벡터로 변환된 레이어를  하나의 벡터로 연결하여 전결합층(fully-connected layer)만들고 softmax 등의 함수를 이용하여 가장 확률이 높은 class를 결과 값으로 분류합니다. 아래 그림은 플래튼과 전결합층 중간 단계를 보여주고 있습니다. (원래는 16행이여야 하지만, 시각적 표현을 위해 8행으로 축소한 점 양해 부탁드립니다)


다음은 keras MNIST(Modified National Institute of Standards and Technology) 이미지 데이터를 활용한 파이썬 예제 코드입니다. 단순 합성곱 신경망 모델을 구축하였습니다. 딥러닝 관련해서 개인적으로 감명 받았던 김경원 교수님의 github를 공유드립니다. CNN등 관련해서 더 공부가 필요하시면 깃허브 링크 참고 부탁드립니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import warnings
warnings.filterwarnings('ignore')
import os
import pandas as pd
pd.options.display.float_format = '{:,.2f}'.format
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import preprocessing
 
import statsmodels.api as sm
from scipy import stats
import tensorflow as tf
import tensorflow_addons as tfa
from tensorflow import keras
from tensorflow.keras import layers, regularizers, callbacks
from tensorflow.keras.models import Sequential, Model, load_model
from tensorflow.keras.layers import Input, Dense, Activation, Flatten, Dropout, Reshape
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Conv2D, MaxPooling2D
from tensorflow.keras.applications import ResNet50
from tensorflow.python.keras.utils import np_utils
from tensorflow.keras.utils import plot_model
 
from sklearn.model_selection import train_test_split, GridSearchCV
 
# Evaluation metrics
from sklearn import metrics
# for regression
from sklearn.metrics import mean_squared_error,  mean_absolute_error, mean_absolute_percentage_error
# for classification
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score
from sklearn.metrics import roc_curve, auc, precision_recall_curve
 
# 하이퍼파라미터
tf.random.set_seed(1)
KERNEL_SIZE = (3,3)
STRIDE = 1
POOL_SIZE = (2,2)
POOL_STRIDE = 2
PADDING = 'same'
HIDDEN_ACTIVATION = 'relu'
OUTPUT_ACTIVATION = 'softmax'
LOSS = 'sparse_categorical_crossentropy'
LEARNING_RATE = 0.01
OPTIMIZER = keras.optimizers.Adam(learning_rate=LEARNING_RATE)
METRICS = ['accuracy']
BATCH_SIZE = 64
EPOCHS = 5
VERBOSE = 1
 
mnist = keras.datasets.mnist
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
 
X_train = X_train.astype("float32")/255
X_test = X_test.astype("float32")/255
print('normalized X: ', X_train.shape, X_train.min(), X_train.max())
print('normalized X: ', X_test.shape, X_test.min(), X_test.max())
 
X_train = X_train.reshape(-1, X_train.shape[1], X_train.shape[2], 1)
X_test = X_test.reshape(-1, X_test.shape[1], X_train.shape[2], 1)
print('X_train:', X_train.shape, 'Y_train:', Y_train.shape)
print('X_test:', X_test.shape, 'Y_test:', Y_test.shape)
 
# CNN 구축
inputs = Input(shape=(X_train.shape[1], X_train.shape[2], X_train.shape[3]))   
hiddens = Conv2D(128 
                 , kernel_size=KERNEL_SIZE
                 , strides=STRIDE
                 , padding=PADDING 
                 , activation=HIDDEN_ACTIVATION)(inputs)
hiddens = MaxPooling2D(pool_size=POOL_SIZE, strides=POOL_STRIDE)(hiddens)
hiddens = Flatten()(hiddens)
output = Dense(10, activation=OUTPUT_ACTIVATION)(hiddens)  
model = Model(inputs, output)  
model.summary() 
plot_model(model) 
 
# 학습하기
model.compile(loss=LOSS, optimizer=OPTIMIZER, metrics=METRICS)
model_fit = model.fit(X_train, Y_train, validation_split=0.2,
                      batch_size=BATCH_SIZE, epochs=EPOCHS, verbose=VERBOSE)
plt.plot(pd.DataFrame(model_fit.history[METRICS[0]]))
plt.plot(pd.DataFrame(model_fit.history['val_'+METRICS[0]]))
plt.legend([METRICS[0], 'val_'+METRICS[0]])
plt.show()
 
model.evaluate(X_train, Y_train)
 
model.evaluate(X_test, Y_test)
print('\nTest Confusion Maxtrix: ')
pd.crosstab(Y_test, np.argmax(model.predict(X_test), axis=1),
            rownames=['True'], colnames=['Pred'])
cs


참고자료
⒜ https://velog.io/@seongguk/AI-CNNConvolutional-Neural-Network-%ED%95%99%EC%8A%B5
⒝ https://wikidocs.net/64066
⒞ https://ieeexplore.ieee.org/document/6795724
⒟ https://proceedings.neurips.cc/paper_files/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf

댓글

이 블로그의 인기 게시물

[AI] RAG란 무엇인가?

자고 일어나면 인공지능 관련 기사와 내용이 참 많습니다. 소위 AI시대 대격변 속에서 무엇을 해야할지 고민이 많습니다. AI의 기본적인 이론도 중요하지만, 최근 트렌드를 잘 알고 잘 써먹을 수 있는 것도 개인의 역량이 아닐까 싶습니다. 즉 AI를 하나의 도구로 생각하고 도구를 잘 써먹으면 좋지 않을까요? 오늘은 RAG(검색-증강-생성)이란 무엇인지 간략하게 끄적여보겠습니다. 3줄 요약 ⓐ 검색(Retrieval)은 요청된 외부 지식 을 가져온다. ⓑ 증강(Augmented)은 질문 것에 요청된 것을 더한다 . ⓒ 생성(Generation)은 사용자의 질문에 더한 것을 받아 텍스트로 생성 한다.   ⅰ RAG(검색-증강-생성)이란 무엇인가? 최근 인공지능 기술의 발전은 다양한 분야에서 혁신을 일으키고 있으며, 그 중에서도 텍스트 기반의 생성형 AI는 특히 주목받고 있습니다. 하지만 이러한 인공지능 기술이 가진 정확성과 신뢰성의 문제는 사용자와 개발자 모두에게 중요한 과제로 남아 있습니다. 이 문제를 해결하기 위해 등장한 기술 중 하나가 바로 RAG(Retrieval-Augmented Generation)입니다. 자세한 기술적 내용은 RAG 용어가 등장한 2020년 아래의 논문을 참고하기 바랍니다. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks(2020) (본지는 간단한 내용 만을 기술할 목적이기 때문에 IT 기업의 설명 자료를 참고하여 본인이 이해한 내용을 작성 하였습니다. 혹시나 잘못된 정보가 있다면 알려주세요.) RAG(Retrieval-Augmented Generation)는 단어 풀이 그대로 '검색 증강 생성'이란 뜻 입니다. 먼저 Retrieval 이란 의미는 검색이란 뜻보다는 외부 지식 데이터베이스에서 가져오는 것, 어딘가에서 요청된 무엇인가를 가져오는 것 을 이야기합니다. 그리고 Augmented 는 증강이란 뜻으로 원래 것에 뭔가를 더하거나 보태어 더 실해졌다 는 ...

[Machine Learning] 경사 하강법 (Gradient Descent)

모델의 오류는 왜 중요할까? 들어가기 전에 한 줄 요약해보겠습니다. 의심하며 본문의 내용을 읽어주세요. 혹시나 다른 내용이 있다면 덧글 부탁드립니다. 모델의 계수를 구하기 위해 가중치를 바꿔가며 전역(global) 기울기가 0인 곳을 잘 찾아보자 . 들어가기 머신러닝 혹은 딥러닝의 가장 적합한 모델 이라 함은 대부분 모델의 오류(error)를 최소화 하는 것을 의미한다. 즉, 어떤 모델(단변량 함수)의 계수의 최적값을 찾는 것으로 생각 할 수 있다. 최적화 문제를 풀기위해 경사 하강법 이라 부르는 방법을 사용할텐데, 이는 곧 함수의  기울기 를 계산하고 경사의 이동방향의 반대 방향으로 이동하여 극값 (=0) 을 찾는 문제 와 같다. 접선의 오류를 찾는 손실함수는 다음 포스트에서 다루도록 하겠다. (즉 머신러닝/딥러닝 최적 모델은 함수의  기울기와 접선의 오차를 줄이는  것이다) 본 포스트에서는 경사 하강법의 기본 개념에 한하여 설명하도록 하겠다. 우리가 생각하는 1차원 혹은 2차원에서의 기울기 최소값이 아닌 아래 그림과 같이 3차원 이상의 다차원에서는 함수에 하나의 전역 최소값(global minimum) 이 존재하는 경우 꽤 쓸만하지만, 함수에 지역 최소값(local minimum) 여러 개 있는 경우에는 시작점을 어디에 잡냐에 따라 잘못된 곳으로 빠질 수 있다. (*딥러닝의 경우 때에 따라 다차원 함수의 최소값을 찾아야 한다. 이는 인간의 머리로는 한계가 있다.) Python 코드를 활용해 간단한 그라디언트 함수를 만들어 보자. f가 단변수 함수인 경우, 점 x 에서의 미분값은 x가 아주 조금 변했을 때 f(x)의 변화량 을 의미한다. x의 변화량을 식에서는 h로 표기한다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from  typing  import  Callable def  difference_quoitemt(f: Callab...

[Machine Learning] 데이터 증강 (Data Augmentation) 이란?

데이터 증강 (Data Augmentation)이란? 본격적으로 들어가기전 내용을 간략하게 요약하자면 다음과 같다. 요약을 바탕으로 본문에서는 좀더 깊이있게 설명하도록 하겠다. 이미지 데이터의 증강은 회전, 크기 조절, 색생 변화 등 다양한 변환을 통해 학습데이터의 다양성을 인위적으로 늘려 모델의 성능을 형상 시키는 방법 시계열 데이터의 증강은 시간 축 변환, 크기 조절, 시간 이동 등 다양한 기법을 통해 원본 데이터를 변형하여 학습 데이터의 다양성을 높이고 모델의 일반화를 향상 시키는 기법 CNN, R-CNN, YOLO 등 모델의 성능을 높이고 오버피팅을 극복할 수 있는 가장 좋은 방법은 다양한 유형의 학습 이미지 불균형 극복을 위한 데이터 양을 늘리는 것입니다. 하지만 사진, 동영상과 같은 이미지 데이터의 경우 학습 데이터 량을 늘리는 것은 쉽지가 않다. 이미지 데이터의 양을 늘리긴 위해서는 결국 클라스(라벨링)의 수도 증가하며, 이는 곧 엄청난 노가다가 필요하기 때문이다. 데이터 증강은 학습 이미지의 개수를 늘리는 것이 아니고 학습 시(epoch) 마다 개별 원본 이미지를 변형해서 학습하는 것 이다. 아래 첨부의 그림과 같이 학습 이미지를 변형할 수 있다. (출처:  https://blog.insightdatascience.com/automl-for-data-augmentation-e87cf692c366) 데이터 증강을 우리 일상생활로 쉽게 설면하자면 우리가 핸드폰 카메라를 통해 사진을 촬영하고 사진의 밝기, 크기, 좌우반전 등을 행하는 것을 이미지 데이터의 증강으로 이해하면 쉽다. tensorflow 에서 간단한 예제를 활용하여 이미지 데이터의 증강을 설명하고 있다. 본 블로그에서는 몇 가지 대표적인 데이터 증강 종류를 간단히 설명하고 마무리 하겠다. 기회가 된다면 텍스트 및 시계열 데이터의 증강 방법도 간략히 소개 후 마무리 하겠다. 이미지 데이터의 증강 (출처:  https://www.invivoo.com/ ) 이미지에 아래와 같이...