[AI 기초] 8. 딥러닝
8.1 더 깊게
8.1.1 더 깊은 신경망으로
[그림 8-1]과 같이 구성된 CNN을 만들어보자 (VGG 신경망 참고)
- 지금까지 구현한 신경망보다 층이 깊음
- 여기에서 사용하는 합성곱 계층은 모두 3x3 크기의 작은 필터, 층이 깊어지면서 채널수 늘어남
(합성곱 계층의 채널 수는 앞 계층에서부터 순서대로 16, 16, 32, 32, 64, 64로 늘어감) - 그림과 같이 풀링 계층을 추가하여 중간 데이터의 공간 크기를 점차 줄여감
- 마지막 단의 완전연결 계층에서는 드롭아웃 계층을 사용
이 신경망의 특징
- 3x3의 작은 필터를 사용한 합성곱 계층
- 활성화 함수는 ReLU
- 완전연결 계층 뒤에 드롭아웃 계층 사용
- Adam을 사용해 최적화
- 가중치 초깃값은 'He의 초깃값'
- 정확도 99.38%
(신경망 구현 소스 코드)
신경망 구현 소스 코드 : deep_convnet.py
(학습 시간이 오래 걸리므로, 학습된 가중치 매개변수 모델)
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import pickle
import numpy as np
from collections import OrderedDict
from common.layers import *
class DeepConvNet:
"""정확도 99% 이상의 고정밀 합성곱 신경망
네트워크 구성은 아래와 같음
conv - relu - conv- relu - pool -
conv - relu - conv- relu - pool -
conv - relu - conv- relu - pool -
affine - relu - dropout - affine - dropout - softmax
"""
def __init__(self, input_dim=(1, 28, 28),
conv_param_1 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
conv_param_2 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
conv_param_3 = {'filter_num':32, 'filter_size':3, 'pad':1, 'stride':1},
conv_param_4 = {'filter_num':32, 'filter_size':3, 'pad':2, 'stride':1},
conv_param_5 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
conv_param_6 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
hidden_size=50, output_size=10):
# 가중치 초기화===========
# 각 층의 뉴런 하나당 앞 층의 몇 개 뉴런과 연결되는가(TODO: 자동 계산되게 바꿀 것)
pre_node_nums = np.array([1*3*3, 16*3*3, 16*3*3, 32*3*3, 32*3*3, 64*3*3, 64*4*4, hidden_size])
wight_init_scales = np.sqrt(2.0 / pre_node_nums) # ReLU를 사용할 때의 권장 초깃값
self.params = {}
pre_channel_num = input_dim[0]
for idx, conv_param in enumerate([conv_param_1, conv_param_2, conv_param_3, conv_param_4, conv_param_5, conv_param_6]):
self.params['W' + str(idx+1)] = wight_init_scales[idx] * np.random.randn(conv_param['filter_num'], pre_channel_num, conv_param['filter_size'], conv_param['filter_size'])
self.params['b' + str(idx+1)] = np.zeros(conv_param['filter_num'])
pre_channel_num = conv_param['filter_num']
self.params['W7'] = wight_init_scales[6] * np.random.randn(64*4*4, hidden_size)
self.params['b7'] = np.zeros(hidden_size)
self.params['W8'] = wight_init_scales[7] * np.random.randn(hidden_size, output_size)
self.params['b8'] = np.zeros(output_size)
# 계층 생성===========
self.layers = []
self.layers.append(Convolution(self.params['W1'], self.params['b1'],
conv_param_1['stride'], conv_param_1['pad']))
self.layers.append(Relu())
self.layers.append(Convolution(self.params['W2'], self.params['b2'],
conv_param_2['stride'], conv_param_2['pad']))
self.layers.append(Relu())
self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))
self.layers.append(Convolution(self.params['W3'], self.params['b3'],
conv_param_3['stride'], conv_param_3['pad']))
self.layers.append(Relu())
self.layers.append(Convolution(self.params['W4'], self.params['b4'],
conv_param_4['stride'], conv_param_4['pad']))
self.layers.append(Relu())
self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))
self.layers.append(Convolution(self.params['W5'], self.params['b5'],
conv_param_5['stride'], conv_param_5['pad']))
self.layers.append(Relu())
self.layers.append(Convolution(self.params['W6'], self.params['b6'],
conv_param_6['stride'], conv_param_6['pad']))
self.layers.append(Relu())
self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))
self.layers.append(Affine(self.params['W7'], self.params['b7']))
self.layers.append(Relu())
self.layers.append(Dropout(0.5))
self.layers.append(Affine(self.params['W8'], self.params['b8']))
self.layers.append(Dropout(0.5))
self.last_layer = SoftmaxWithLoss()
def predict(self, x, train_flg=False):
for layer in self.layers:
if isinstance(layer, Dropout):
x = layer.forward(x, train_flg)
else:
x = layer.forward(x)
return x
def loss(self, x, t):
y = self.predict(x, train_flg=True)
return self.last_layer.forward(y, t)
def accuracy(self, x, t, batch_size=100):
if t.ndim != 1 : t = np.argmax(t, axis=1)
acc = 0.0
for i in range(int(x.shape[0] / batch_size)):
tx = x[i*batch_size:(i+1)*batch_size]
tt = t[i*batch_size:(i+1)*batch_size]
y = self.predict(tx, train_flg=False)
y = np.argmax(y, axis=1)
acc += np.sum(y == tt)
return acc / x.shape[0]
def gradient(self, x, t):
# forward
self.loss(x, t)
# backward
dout = 1
dout = self.last_layer.backward(dout)
tmp_layers = self.layers.copy()
tmp_layers.reverse()
for layer in tmp_layers:
dout = layer.backward(dout)
# 결과 저장
grads = {}
for i, layer_idx in enumerate((0, 2, 5, 7, 10, 12, 15, 18)):
grads['W' + str(i+1)] = self.layers[layer_idx].dW
grads['b' + str(i+1)] = self.layers[layer_idx].db
return grads
def save_params(self, file_name="params.pkl"):
params = {}
for key, val in self.params.items():
params[key] = val
with open(file_name, 'wb') as f:
pickle.dump(params, f)
def load_params(self, file_name="params.pkl"):
with open(file_name, 'rb') as f:
params = pickle.load(f)
for key, val in params.items():
self.params[key] = val
for i, layer_idx in enumerate((0, 2, 5, 7, 10, 12, 15, 18)):
self.layers[layer_idx].W = self.params['W' + str(i+1)]
self.layers[layer_idx].b = self.params['b' + str(i+1)]
훈련용 코드 : train_deepnet.py
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from deep_convnet import DeepConvNet
from common.trainer import Trainer
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)
network = DeepConvNet()
trainer = Trainer(network, x_train, t_train, x_test, t_test,
epochs=20, mini_batch_size=100,
optimizer='Adam', optimizer_param={'lr':0.001},
evaluate_sample_num_per_epoch=1000)
trainer.train()
# 매개변수 보관
network.save_params("deep_convnet_params.pkl")
print("Saved Network Parameters!")
인간도 판단하기 어려운 이미지가 많음
8.1.2 정확도를 더 높이려면
<What is the class of this image?> 웹 사이트
- 다양한 데이터셋을 대상으로 그동안 논문 등에서 발표한 기법들의 정확도 순위를 정리해둠
- 상위권은 CNN 기초로 한 기법들이 점령
* NOTE
- MNIST 데이터셋은 층을 깊게 하지 않고도 최고 수준의 결과가 나옴
- 대규모 일반 사물 인식엣는 문제가 훨씬 복잡해지므로 층을 깊게 하면 정확도 끌어올릴 수 있음
[그림 8-3]의 상위 기법들을 참고하면 정확도 더 높일 수 있는 기술이나 힌트 발견할 수 있음
- ex) 앙상블 학습, 학습률 감소, 데이터 확장 등 특히 데이터 확장은 손쉽고 정확도 개선에 효과적
데이터 확장(data augmentation)
- 입력 이미지(훈련 이미지)를 알고리즘을 동원해 '인위적'으로 확장
- 입력 이미지를 회전하거나 세로로 이동하는 등 미세한 변화를 주어 이미지 개수 늘림
- 이미지 일부 자르는 crop, 좌우 뒤집는 flip, 밝기 등의 외형 변화, 확대 축소 등 스케일 변화
- 데이터가 몇 개 없을 때 특히 효과적
8.1.3 깊게 하는 이유
'층을 깊게 하는 것'이 왜 중요한가
- 이론적인 근거는 아직 부족
- 그래도 실험 결과를 바탕으로 몇 가지 설명
ILSVRC로 대표되는 대규모 이미지 인식 대회의 결과
- 상위 기법 대부분 딥러닝 기반
- 신경망을 더 깊게 만드는 방향의 경향성
이점
- 신경망의 매개변수 수가 줄어듦
- 층이 깊은 신경망은 깊지 않은 것보다 적은 매개변수로 같은 (혹은 그 이상) 수준의 표현력
주목할 점 : 출력 데이터의 각 노드가 입력 데이터의 어느 영역으로부터 계산되었는가
- [그림 8-5]의 예에서 각각의 출력 노드는 입력 데이터의 5x5 크기 영역에서 계산
3x3 합성곱 연산을 2회 반복하는 경우
- 중간 데이터는 5x5 영역에서 계산
- 출력 노드 하나는 중간 데이터의 3x3 영역에서 계산
5x5 합성곱 연산 1회는 3x3 합성곱 연산을 2회 수행하여 대체
- 전자의 매개변수 25개(5x5), 후자 18개(2x3x3) → 층을 반복할수록 적어짐
- 같은 크기의 영역을 1회의 합성곱 연산으로 '보기' 위해서는 7x7 크기의 필터, 즉 매개변수 49개 필요
* NOTE : 작은 필터를 겹처 신경망을 깊게 할 때의 장점
- 매개변수 수를 줄여 넓은 수용 영역(receptive field)을 소화할 수 있음
(수용 영역 : 뉴런에 변화를 일으키는 국소적인 공간 영역) - 층을 거듭하면서 ReLU 등의 활성화 함수를 합성곱 계층 사이에 끼움으로써 신경망의 표현력 개선
→ 활성화 함수가 신경망에 '비선형' 힘을 가하고, 비선형 함수가 겹치면서 더 복잡한 것도 표현할 수 있게 됨
층을 깊게 하여 학습 데이터의 양을 줄여 학습을 고속으로 수행할 수 있음
→ 직관 : 7.6, 단순한 패턴에 뉴런이 반응하고, 층이 깊어지면서 텍스처와 사물의 일부와 같이 점차 더 복잡한 것에 반응
ex) '개'를 인식하는 문제
- 얕은 신경망은 합성곱 계층이 개의 특징 대부분을 한 번에 '이해'해야 함
- 개의 특징을 이해하려면 변화가 풍부하고 많은 학습 데이터가 필요
→ 결과적으로 학습 시간이 오래 걸림 - 층을 깊게 하면 정보를 계층적으로 전달할 수 있음
신경망을 깊게 하면 학습해야 할 문제를 계층적으로 분해할 수 있음
- = 각 층이 학습해야 할 문제를 더 단순한 문제로 대체할 수 있음
8.2 딥러닝의 초기 역사
- 딥러닝이 큰 주목을 받게 된 계기는 이미지 인식 기술을 겨루는 ILSVRC의 2012년 대회
- AlexNet이 압도적인 성적으로 우승하며, 이미지 인식에 대한 접근법을 뒤흔듬
8.2.1 이미지넷
이미지넷
- 100만 장이 넘는 이미지를 담고 있는 데이터셋
- 각 이미지에는 레이블(클래스 이름)이 붙어있음
- 분류(classification) : 1,000개의 클래스를 제대로 분류하는지 겨룸
- 톱-5 오류 : 확률이 가장 높다고 생각하는 후보 클래스 5개 안에 정답이 포함되지 않은, 즉 5개 모두가 틀린 비율
- AlexNet이 오류율을 크게 낮췄고, 이후 딥러닝을 활용한 기법이 꾸준히 정확도를 개선해 옴
8.2.2 VGG
VGG 합성곱 계층과 풀링 계층으로 구성되는 '기본적'인 CNN
- 3x3의 작은 필터를 사용한 합성곱 계층을 연속으로 거침
- 2~4회 연속으로 풀링 계층을 두어 크기를 절반으로 줄이는 처리 반복
- 마지막에 완전연결 계층을 통과시켜 결과 출력
* NOTE
- VGG는 2014년 대회 2위, 성능은 1위 GoogLeNet에 뒤지지만, VGG는 구성이 간단하여 응용이 좋음
- 많은 기술자가 VGG 기반의 신경망 즐겨 사용
8.2.3 GoogLeNet
그림의 사각형이 합성곱 계층과 풀링 계층 등의 계층 나타냄
- 그림은 구성이 복잡해 보이지만, CNN과 다르지 않음
- GoogLeNet은 세로 방향 깊이뿐 아니라 가로 방향도 깊다는 점이 특징
GoogLeNet에는 가로 방향에 '폭'이 있음 = 인셉션 구조
인셉션 구조
- 크기가 다른 필터(와 풀링)를 여러 개 적용하여 그 결과를 결합
- 1x1의 합성곱 연산은 채널 쪽으로 크기를 줄이는 것, 매개변수 제거와 고속 처리에 기여
8.2.4 ResNet
ResNet(Residual Network)
- 마이크로 소프트 팀이 개발한 네트워크
- 특징 : 지금까지보다 층을 더 깊게 할 수 있는 특별한 '장치'
딥러닝의 학습에서 층이 지나치게 깊으면 학습이 잘 되지 않고 성능이 떨어지는 문제
ResNet의 해결책
- 스킵 연결(skip connection) 도입
- 층의 깊이에 비례해 성능을 향상시킬 수 있게 함
(물론 층을 깊게 하는 데에 여전히 한계)
스킵 연결
- 입력 데이터를 합성곱 계층을 건너뛰어 출력에 바로 더하는 구조 [그림 8-12]
- [그림 8-12]에서는 입력 x를 연속한 두 합성곱 계층을 건너뛰어 출력에 바로 연결
- 이게 없었다면 두 합성곱 계층의 출력 F(x)
- 스킵 연결로 F(x) + x 가 되는 것이 핵심
- 스킵 연결은 층이 깊어져도 학습을 효율적으로 할 수 있도록 함
→ 역전파 때 스깁 연결이 신호 감쇠를 막아주기 때문
* NOTE
- 스킵 여결은 입력 데이터를 '그대로' 흘리는 것
- 역전파 때도 상류의 기울기를 그대로 하류로 보냄
- 상류의 기울기에 아무런 수정도 가하지 않고 '그대로' 흘림
→ 스킵 연결로 기울기가 작아지거나 지나치게 커질 걱정 없이 앞 층에 '의미 있는 기울기' 전해짐 - 층을 깊게 할수록 기울기가 작아지는 소실 문제를 스킵 연결이 줄여줌
ResNet의 스킵 연결
- ResNet은 VGG 신경망을 기반으로 스킵 연결을 도입하여 층을 깊게 함
- ResNet은 합성곱 계층을 2개 층마다 건너뛰면서 층을 깊게 함
- 실험 결과 150층 이상으로 해도 정확도 오르는 모습
* NOTE : 전이 학습(transfer learning)
- 이미지넷이 제공하는 거대한 데이터셋으로 학습한 가중치 값들은 실제 제품에 활용해도 효과적
- 학습된 가중치(또는 그 일부)를 다른 신경망에 복사, 그 상태로 재학습을 수행
- 전이 학습은 보유한 데이터셋이 적을 때 특히 유용
ex)
- VGG와 구성이 같은 신경망 준비
- 미리 학습된 가중치를 초깃값으로 설정
- 새로운 데이터셋을 대상으로 재학습(fine tuning) 수행
8.3 더 빠르게(딥러닝 고속화)
- 딥러닝에서 대량의 연산 수행
- GPU(Graphics Processing Unit)를 활용해 대량의 연산 고속으로 처리
8.3.1 풀어야 할 숙제
- AlexNet에서는 오랜 시간을 합성곱 계층에서 소요
합성곱 계층에서 이뤄지는 연산을 어떻게 고속으로 효율적으로 하느냐가 딥러닝의 과제
= '단일 곱셈 - 누산' 고속 계산
8.3.2 GPU를 활용한 고속화
GPU 컴퓨팅
- 병렬 수치 연산을 고속으로 처리, 그 압도적인 힘을 다양한 용도로 활용하자
- GPU로 범용 수치 연산을 수행하는 것
- CPU에서는 40여 일이나 걸리지만 GPU로는 6일까지 단축
- cuDNN이라는 딥러닝에 최적화된 라이브러리를 이용하면 더욱 빨라짐
- GPU는 주로 엔비디아, AMD 두 회사가 제공
- 대부분의 딥러닝 프레임워크는 엔비디아 GPU에서만 혜택
→ 엔비디아 GPU 컴퓨팅용 통합 개발 환경인 CUDA를 사용하므로
→ cuDNN은 CUDA 위에서 동작하는 라이브러리
* NOTE
- 합성곱 계층에서 행하는 연산은 im2col을 이용해 큰 행렬의 곱으로 변환
- 이러한 im2col의 방식은 GPU로 구현하기에도 적합
- GPU는 '작은' 단위로 계산하기보다는 큰 덩어리를 한 번에 계산하는 데 유리
- IM2COL의 거대한 행렬의 곱으로 한 번에 계산하여 GKKPU의 잠재력 끌어냄
8.3.3 분산 학습
- 여전히 시간이 걸림
- 딥러닝 학습을 수평 확장(scale out)하자는 아이디어(=분산 학습)
다수의 GPU와 기기로 계산을 분산
- 구글 텐서플로, 마이크로소프트 CNTK는 분산 학습에 역점을 두고 개발
- 거대한 데이터센터의 저지연, 고처리량 네트워크 위에서 이 프레임워크들의 분산 학습 놀라운 효과
= 분산 학습의 놀라운 효과
'계산을 어떻게 분산시키느냐'는 몹시 어려운 문제
- 텐서플로 같은 뛰어난 프레임워크에 맡기는 것이 좋음
8.3.4 연산 정밀도와 비트 줄이기
메모리 용량과 버스 대역폭 등이 병목이 될 수 있음
- 메모리 용량 면에서는 대량의 가중치 매개변수와 중간 데이터를 메모리에 저장해야 함
- 버스 대역폭 면에서는 GPU(or CPU)의 버스를 흐르는 데이터가 많아져 한계를 넘어서면 병목
→ 네트워크로 주고받는 데이터의 비트수는 최소로 만드는 것이 바람직
컴퓨터는 주로 64비트나 32비트 부동소수점 수 사용해 실수 표현
- 많은 비트 사용할수록 계산 비용, 메모리 사용량 늘어남
- 버스 대역폭에 부담
딥러닝은 높은 수치 정밀도 요구하지 않음
- 32비트 단정밀도 vs 16비트 배정밀도 vs 16비트 반정밀도
- 16비트 반정밀도만 사용해도 학습에 문제 없다고 알려짐
넘파이는 16비트 반정밀도 부동소수점 지원
- 정확도 떨어지지 않음
- (단, 스토리지로서 16비트라는 틀, 연산 자체는 16비트로 수행하지 않음)
(구현 코드)
# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import matplotlib.pyplot as plt
from deep_convnet import DeepConvNet
from dataset.mnist import load_mnist
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)
network = DeepConvNet()
network.load_params("deep_convnet_params.pkl")
sampled = 1000 # 고속화를 위한 표본추출
x_test = x_test[:sampled]
t_test = t_test[:sampled]
print("caluculate accuracy (float64) ... ")
print(network.accuracy(x_test, t_test))
# float16(반정밀도)로 형변환
x_test = x_test.astype(np.float16)
for param in network.params.values():
param[...] = param.astype(np.float16)
print("caluculate accuracy (float16) ... ")
print(network.accuracy(x_test, t_test))
8.4 딥러닝의 활용
- 딥러닝은 사물 인식뿐 아니라 온갖 문제에 적용할 수 있음
- 이미지, 음성, 자연어 등 수많은 분야에서 뛰어난 성능
8.4.1 사물 검출
- 이미지 어딘가에 있을 사물의 위치 알아냄
- 한 이미지에 여러 사물 존재할 수 있음
CNN을 기반으로 한 사물 검출 문제 기법
- R-CNN(Regions with Convolutional Neural Network)
- 사물이 위치한 영역을 (어떤 방법으로) 찾아냄
- 추출한 각 영역에 CNN을 적용하여 클래스를 분류
(이미지를 사각형으로 변형하거나 분류할 때 서포트 벡터 머신(SVM)을 사용)
후보영역 추출
- = 사물처럼 보이는 물체를 찾아 처리
- 컴퓨터 비전 분야에서 발전해온 다양한 기법 사용
- 최근에는 이 후모 영역 추출도 CNN으로 처리하는 Faster R-CNN 기법도 등장
→ 모든 일을 하나의 CNN에서 처리하므로 아주 빠름
8.4.2 분할
분할(segmentation)
: 이미지를 픽셀 수준에서 분류하는 문제
- 다음과 같이 픽셀 단위로 객체마다 채색된 지도(supervised) 데이터를 사용해 학습
- 추론할 때 입력 이미지의 모든 픽셀을 분류
신경망을 이용해 분할하는 가장 단순한 방법
- 모든 픽셀 각각을 추론하는 것
ex) 어떤 직사각형 영역의 중심 픽셀의 클래스를 분류하는 신경망을 만들어, 모든 픽셀을 대상으로 하나씩 추론 작업
- 픽셀 수만큼 forward 처리 해야 하여 긴 시간 소요
낭비를 줄여주는 기법으로 FCN(Fully Convolutional Network) 고안
- = 한 번의 forward 처리로 모든 픽셀의 클래스 분류
Fully Convolutional Network
직역 : 합성곱 계층만으로 구성된 네트워크
차이점1
- 일반적인 CNN → 완전연결 계층 이용
- FCN → 완전연결 계층을 '같은 기능을 하는 합성곱 계층'으로 바꿈
차이점2
- 사물 인식에서 사용한 신경망의 완전연결 계층
→ 중간 데이터의 공간 볼륨(다차원 형태)를 1차원으로 변환하여 한 줄로 늘어선 노드들이 처리 - FCN : 공간 볼륨을 유지한 채 마지막까지 처리
특징
- 마지막에 공간 크기를 확대하는 처리 도입
- 확대 처리로 줄어든 중간 데이터를 입력 이미지와 같은 크기까지 단번에 확대
= 이중 선형 보간, 이를 역합성곱 연산으로 구현
* NOTE
- 완전연결 계층에서는 출력이 모든 입력과 연결
- 이와 같은 구성을 합성곱 계층으로도 구현할 수 있음
ex) 32x10x10인 데이터에 대한 완전연결 계층 → 필터 크기가 32x10x10인 합성곱 계층으로 대체
- 완전연결 계층의 출력 노드가 100개라면 합성곱 계층에서는 기존의 32x10x10 필터를 100개 준비하면 완전히 같은 처리
8.4.3 사진 캡션 생성
- 컴퓨터 비전과 자연어를 융합한 재미있는 연구
- NIC(Nural Image Caption) 모델이 대표적
NIC
- [그림 8-22]와 같이 심층 CNN과 자연어를 다루는 순환 신경망(Recurrent Neural Network, RNN)으로 구성
- RNN은 순환적 관계를 갖는 신경망으로 자연어나 시계열 데이터 등의 연속된 데이터를 다룰 때 많이 사용
- RNN은 CNN이 추출한 특징을 초깃값으로 해서 텍스트를 '순환적'으로 생성
- 2개의 신경망(CNN, RNN)을 조합한 간단한 구성
- 멀티모달 처리 : 여러 종류의 정보를 조합하고 처리하는 것
* NOTE : RNN
- R은 Recurrent(순환적)을 의미
- 신경망의 순환적 네트워크 구조
- 순환적인 구조 : 이전에 생성한 정보에 영향을 받음(과거 정보 기억)
ex)
나 ~~~잤다
자동으로 '는'이라는 조사가 자동으로 생성
8.5 딥러닝의 미래
8.5.1 이미지 스타일(화풍) 변환
- 네트워크의 중간 데이터가 콘텐츠 이미지의 중간 데이터와 비슷해지도록 학습
- '스타일 행렬' 개념 도입 : 스타일 이미지의 화풍 흡수
- 스타일 행렬의 오차를 줄이도록 학습하여 입력 이미지를 고흐의 화풍과 비슷해지게 만듦
8.5.2 이미지 생성
아무런 입력 이미지 없이도 새로운 이미지를 그려내는 연구 진행 중
- 이미지를 생성하는 과정을 모델화
- 모델을 대량의 이미지를 사용해 학습
- 학습이 끝나면 그 모델을 이용하여 새로운 그림을 생성
- DCGAN도 딥러닝 사용
GAN
- 생성자(Generator)와 식별자(Discriminator)로 불리는 2개의 신경망 이용
- 생성자가 진짜와 똑같은 이미지 생성, 식별자는 진실 판별
- 둘을 겨루도록 학습시켜, 생성자는 정교한 가짜 이미지 생성, 식별자는 더 정확한 감정사로 성장
* NOTE
지도학습(supervised learning)
- 이미지 데이터와 정답 레이블을 짝지은 데이터셋 이용
비지도 학습(unsupervised learning)
- 지도용 데이터는 주어지지 않고, 단지 대량의 이미지(이미지의 집합)만 주어짐
ex) GAN
8.5.3 자율 주행
- 자율주행은 다양한 기술을 모아 구현
- 그중에서도 주위 환경 올바르게 인식하는 기술이 가장 중요한 문제
ex) SegNet
- CNN 기반 신경망
8.5.4 Deep Q-Network(강화학습)
강화학습(reinforcement learning)
- 에이전트라는 것이 환경에 맞게 행동을 선택, 그 행동에 의해서 환경이 변함
- 환경이 변화하면 에이전트는 보상을 얻음
- 보상을 받는 쪽으로 에이전트의 행동 지침을 바로잡는 것
Deep Q-Network(DQN)
- Q학습이라는 강화학습 알고리즘을 기초로 함
- Q학습에서는 최적 행동 가치 함수로 최저인 행동을 정함
- 함수를 딥러닝(CNN)으로 비슷하게 흉내 내어 사용하는 것
8.6 정리