# Ch13_2 MNIST(Tenserflow) 텐서플로 공식 예제 Deep MNIST를 살펴보도록 한다. <br> Ch13_2 : http://202.31.200.194:8888/notebooks/ml_face/mnist.ipynb <br> ___ ### Deep MNIST 구조 <br> ![](https://i.imgur.com/VwDj4au.png) 그림을 보면 Conv Layer 두 개를 사용한다. 입력 데이터를 받아 local 정보를 추출하고, pooling을 통해 의미 있는 값만 뽑아 정보를 추출한다. 이렇게 추출한 피처를 각 레이블과 연결 짓기 위해 FullyConnectedLayer를 사용하는데, 그 과정에서 Drop-out을 이용하여 과학습을 막는다. ___ ### 피처 생성 CNN을 이용한 피처 생산 과정을 볼 것이다. 전통적인 머신러닝과 딥러닝의 차이점은 피처 생성 방법이며, 딥러닝은 사전에 피처를 정의하지 않고 학습 과정에 만들어 간다. 이때 피처를 생성하기 위해 다양한 레이어를 활용한다. 1. 합성곱 레이어 합성곱을 계산하기 위해서 4차원 텐서 형태의 이미지 데이터 (이미지 데이터 수 * 높이 * 넓이 * 채널)와 4차원 필터를 입력받아 합성곱을 적용한 텐서를 반환하는 conv2d 함수를 사용한다. ``` def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME', name='conv') ``` - x : input, Tensor 형 데이터 - W : filter, Tensor 형 데이터. input과 같은 형의 요소를 가지는 텐서여야 한다 - strides : 길이가 4인 int 형 요소의 리스트. 몇 픽셀씩 옮겨가며 필터를 적용할지 결정한다 strides[0], [4]는 항상 1이며 [1], [2]에 같은 수가 들어가는 것이 일반적이다 - padding : 'SAME' or 'VALID'의 string 값을 가지며, 'SAME'은 필터 적용 시 이미지 가장자리를 제로 패딩, 'VALID'는 패딩 없이 필터를 적용한다 - name : 연산명 <br> 가중치인 필터 텐서는 처음에 임의로 정한 후 학습이 진행됨에 따라 업데이트하게 된다. 보통 필터 텐서를 임의의 수로 채우기 위해 절단정규분포를 이용한다. (정규분포에서 표준편차의 절댓값이 2이상인 값을 버리는 분포이다) <br> 합성곱을 적용한 텐서들을 활성화함수의 입력으로 주어 비선형 요소를 적용한다. ReLU를 사용하며, 입력값이 0보다 크면 그대로, 작으면 0을 리턴하는 함수이다. <br> 2. 풀링 예제에서는 최댓값 풀링을 사용하기 위해 다음 함수를 이용한다. 풀링은 비선형 요소가 적용된 텐서들을 받아서 다음 레이어로 넘길 값들을 샘플링한다. ``` tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME', name='pool') ``` - x : value, 4차원 텐서 - ksize : 입력 텐서의 각 차원에 해당하는 윈도우 크기의 리스트 <br> 3. 완전연결 레이어 합성곱이나 풀링 없이 현재 입력텐서의 모든 값을 다음 단계로 넘긴다. 이를 위해 reshape 함수를 이용하여 텐서의 모양을 데이터수*피처 수로 바꾼다. 일부 값만 연결해서 과학습을 막기위해 드랍-아웃 함수를 이용하여 연결을 어느 정도 끊을지 결정한다. ``` tf.nn.dropout(h_fc1, keep_prob) ``` - h_fc1 : x, 입력 텐서 - keep_prob : 스칼라 값 0~1의 값을 가지며 0.5면 50% 확률로 넘긴다. --- ### 학습 및 평가 1. 소프트맥스와 교차 엔트로피 텐서값을 타깃값과 비교하기 위해 소프트맥스 함수를 이용하여 각 텐서를 각숫자에 대한 확률로 바꾼다. 이렇게 얻어진 확률을 실제 타깃값과 비교한 후 교차 엔트로피 함수를 이용하여 차이를 계산한 뒤, 차이를 줄이도록 가중치 필터를 갱신한다. ``` cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits( logits = y_conv, labels = y_),name='cross_ent') train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) ``` - logits : 로짓 함수의 입력. 타깃값을 갖는다. - labels : 각 행이 유효한 확률 분포여야 한다. <br> 2. 최적화함수 교차 엔트로피로 얻은 학습 결과와 실제 결과의 차이를 줄이기 위해 그 차이를 역전파하면서 가중치 필터를 갱신해나간다. MNIST 예제에서는 AdamOptimizer 클래스를 사용한다. 경사를 갱신할 때 beta 값을 이용하여 하강률을 조정하기 때문이다. 학습률을 입력 데이터에 따라 바꿈으로써 최적값을 효율적으로 찾을 수 있다. 3. 정확도 평가 정확도를 평가하기 위해 예측된 클래스와 실제 클래스가 같은지 살핀 후 '맞게 예측한 데이터 / 전체 데이터 수'를 출력한다. 이때 입력 데이터 값의 클래스를 알아내기 위해 argmax를 사용한다. ``` tf.argmax(y_conv, 1), tf.argmax(y_, 1) ```