피곤핑
코딩일탈
피곤핑
전체 방문자
오늘
어제
  • 분류 전체보기
    • Kotlin & Java
    • Spring
      • Spring Security
      • Spring
    • 네트워크
    • JavaScript & Node js
    • Docker
    • Python3
    • Unity
    • 딥러닝
    • 객체지향프로그래밍
    • Error 보고서
    • 나의 이야기 & 회고
    • HTML & CSS
    • Archive
    • 독서

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

태그

  • TiL
  • Client
  • 항해99
  • JavaScript
  • 코딩테스트준비
  • 티스토리챌린지
  • 99클럽
  • nodejs
  • 오블완
  • 개발자취업

최근 댓글

hELLO · Designed By 정상우.
피곤핑

코딩일탈

0813 ResNet 프로젝트
딥러닝

0813 ResNet 프로젝트

2019. 8. 13. 16:11

 

F(x) = H(x) -x 에서 시작했는데 F(x)가 0이라고 생각하면 H(x) 와 x가 같을 수 밖에 없다.

여기서 시작해서 문제의 논지를 바꾸면

H(x) = F(x) + x 이렇게 볼 수 있다. x값이 커지면 F(x)값도 민감하게 바뀔 수 밖에 없다. 

=> 이것을 Skip connection 이라 부름.

 -> 스킵연결을 구현하는것은 덧셈 연산의 추가만으로 가능함. 이는 추가적인 연산량이나 파라미터가 많이 필요하지 않음. 또한 역전파 시에 그레디언트가 잘 흘러갈 수 있게 해준다는 장점이있다.

 


첫째 행과 셋째행은 사이즈만 조절하는것, 두번째행은 필터

1x1이지만 다음에 곱해지는거에 따라서 사이즈가 달라짐 

==> 이과정을 병목레이어(bottleneck layer)라 부른다.

# ResNet 블록 구조(bottleneck 구조) 
LayerBlock = namedtuple('LayerBlock', ['num_repeats', 'num_filters', 'bottleneck_size'])

 


import numpy as np
import tensorflow as tf
from collections import namedtuple 
from connections import  conv2d, linear 

 

이부분에서 에러가 날건데 잘 해결하는 방법 찾기,,,

 

 


resNet 프로젝트

 

1. connections.py를 저장하고 임포트 시킴.

  - 기본적으로 stride가 2로 돼있기 때문에 따로 풀링을 하지않아도 기본값으로 1/2 샘플링이됨.

"""APL 2.0 code from github.com/pkmital/tensorflow_tutorials w/ permission
from Parag K. Mital.
"""
import math
import tensorflow as tf


def batch_norm(x, phase_train, scope='bn', affine=True):
    """
    Batch normalization on convolutional maps.
    from: https://stackoverflow.com/questions/33949786/how-could-i-
    use-batch-normalization-in-tensorflow
    Only modified to infer shape from input tensor x.
    Parameters
    ----------
    x
        Tensor, 4D BHWD input maps
    phase_train
        boolean tf.Variable, true indicates training phase
    scope
        string, variable scope
    affine
        whether to affine-transform outputs
    Return
    ------
    normed
        batch-normalized maps
    """
    with tf.variable_scope(scope):
        og_shape = x.get_shape().as_list()
        if len(og_shape) == 2:
            x = tf.reshape(x, [-1, 1, 1, og_shape[1]])
        shape = x.get_shape().as_list()
        beta = tf.Variable(tf.constant(0.0, shape=[shape[-1]]),
                           name='beta', trainable=True)
        gamma = tf.Variable(tf.constant(1.0, shape=[shape[-1]]),
                            name='gamma', trainable=affine)

        batch_mean, batch_var = tf.nn.moments(x, [0, 1, 2], name='moments')
        ema = tf.train.ExponentialMovingAverage(decay=0.9)
        ema_apply_op = ema.apply([batch_mean, batch_var])
        ema_mean, ema_var = ema.average(batch_mean), ema.average(batch_var)

        def mean_var_with_update():
            """Summary
            Returns
            -------
            name : TYPE
                Description
            """
            with tf.control_dependencies([ema_apply_op]):
                return tf.identity(batch_mean), tf.identity(batch_var)
        mean, var = tf.cond(phase_train,
                                          mean_var_with_update,
                                          lambda: (ema_mean, ema_var))

        normed = tf.nn.batch_norm_with_global_normalization(
            x, mean, var, beta, gamma, 1e-3, affine)
        if len(og_shape) == 2:
            normed = tf.reshape(normed, [-1, og_shape[-1]])
    return normed


def lrelu(x, leak=0.2, name="lrelu"):
    """Leaky rectifier.
    Parameters
    ----------
    x : Tensor
        The tensor to apply the nonlinearity to.
    leak : float, optional
        Leakage parameter.
    name : str, optional
        Variable scope to use.
    Returns
    -------
    x : Tensor
        Output of the nonlinearity.
    """
    with tf.variable_scope(name):
        f1 = 0.5 * (1 + leak)
        f2 = 0.5 * (1 - leak)
        return f1 * x + f2 * abs(x)


def linear(x, n_units, scope=None, stddev=0.02,
           activation=lambda x: x):
    """Fully-connected network.
    Parameters
    ----------
    x : Tensor
        Input tensor to the network.
    n_units : int
        Number of units to connect to.
    scope : str, optional
        Variable scope to use.
    stddev : float, optional
        Initialization's standard deviation.
    activation : arguments, optional
        Function which applies a nonlinearity
    Returns
    -------
    x : Tensor
        Fully-connected output.
    """
    shape = x.get_shape().as_list()

    with tf.variable_scope(scope or "Linear"):
        matrix = tf.get_variable("Matrix", [shape[1], n_units], tf.float32,
                                 tf.random_normal_initializer(stddev=stddev))
        return activation(tf.matmul(x, matrix))


def conv2d(x, n_filters,
           k_h=5, k_w=5,
           stride_h=2, stride_w=2,
           stddev=0.02,
           activation=None,
           bias=True,
           padding='SAME',
           name="Conv2D"):
    """2D Convolution with options for kernel size, stride, and init deviation.

    Parameters
    ----------
    x : Tensor
        Input tensor to convolve.
    n_filters : int
        Number of filters to apply.
    k_h : int, optional
        Kernel height.
    k_w : int, optional
        Kernel width.
    stride_h : int, optional
        Stride in rows.
    stride_w : int, optional
        Stride in cols.
    stddev : float, optional
        Initialization's standard deviation.
    activation : arguments, optional
        Function which applies a nonlinearity
    padding : str, optional
        'SAME' or 'VALID'
    name : str, optional
        Variable scope to use.

    Returns
    -------
    x : Tensor
        Convolved input.
    """
    with tf.variable_scope(name):
        w = tf.get_variable(
            'w', [k_h, k_w, x.get_shape()[-1], n_filters],
            initializer=tf.truncated_normal_initializer(stddev=stddev))
        conv = tf.nn.conv2d(
            x, w, strides=[1, stride_h, stride_w, 1], padding=padding)
        if bias:
            b = tf.get_variable(
                'b', [n_filters],
                initializer=tf.truncated_normal_initializer(stddev=stddev))
            conv = tf.nn.bias_add(conv, b)
        if activation:
            conv = activation(conv)
        return conv

 

 2. 필요한 모듈 임포트.

 - 그래프 리셋은 왜?.. 어디서 쓰이지

import numpy as np
import tensorflow as tf
from collections import namedtuple 
from connections import conv2d, linear 
# 그래프 리셋
tf.reset_default_graph()
# 재현성을 위해 시드 지정
tf.set_random_seed(1)

3. 자료 입력

 - input_data를 다운받고 원핫코딩이 True인 상태로 가지고 옴.

 - learning_rate = 0.0001

 - epochs = 1 (원래는 100이나 간단히 실행시켜볼 요량으로 1이라고 지정함)

 - batch_size = 100

 - x : 28x28이므로 입력값으로 [None, 784]

 - reshape : gray level 이기 때문에 [-1, 28, 28, 1] 로 형태변형을 해줌

 - y : 10개의 숫자 분류위해서 [None, 10]

# 자료 입력
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets("MNIST_data/",one_hot=True)
learning_rate=0.0001; epochs=1; batch_size=100
X=tf.placeholder(tf.float32,[None,784])  # 28x28
X_img=tf.reshape(X,[-1,28,28,1]) 
Y=tf.placeholder(tf.float32,[None,10]) 

4. 병목레이어를 만들기전 블록 구조 생성

 - nametuplel : 이름과 값이 리스트로 들어가있는 튜플을 만듦

 - 병목레이어를 만들 각 단계의 블록을 구성 (반복시킬 횟수, 필터수, 병목사이즈)

 - 위에 resNet 구조에서 보았다시피 우리는 기본적으로 7x7 커널에 채널 64, stride를 2로 줌.

(* 이때 conv2d 함수안에 stride가 기본으로 2가 들어가 있기때문에 별도의 파라미터를 넣지않았는데도 14x14로 들어감)

 - tf.nn.max_pool : 3x3 크기로 2칸씩 건너뛰며 맥스풀링을 해줌 -> 7x7x64

# ResNet 블록 구조(bottleneck 구조) 
LayerBlock = namedtuple('LayerBlock', ['num_repeats', 'num_filters', 'bottleneck_size'])
blocks = [LayerBlock(3, 128, 32),LayerBlock(3, 256, 64),LayerBlock(3, 512, 128),
          LayerBlock(3, 1024, 256)]

# 채널수 64의 합성곱 출력을 만들고 다운샘플링
net = conv2d(X_img, 64, k_h=7, k_w=7, name='conv1', activation=tf.nn.relu)
# 14x14
net = tf.nn.max_pool(net, [1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME')

5. resNet 구조로 반복시켜 생성할 층 설계

 - blocks[0].num_fileters : 128의 필터로 컨볼루션 층을 만듦 -> 7x7x128

 - padding : VALID : 패딩을 전혀 넣지않음 (입출력이 같지 않아도 된다는말) - 왜?

 - 첫번째 for문으로 blocks의 개수만큼 인덱스와 값을 가져옴

   num_repeats의 개수만큼 두번째 for문안의 층을 다시 곱해줌

   이때 conv1 층 padding : VALID, conv2 층 padding : SAME, conv3 층 padding : VALID 임을 주의. 

 - try~ except 구문은 단순히 예외처리인 부분일까 아니면 반드시 거치는 부분일까,,?

  => 이게 identity block

 - net = conv3 + net : residual block의 연산

# ResNet 블록구조의 입력 생성 
net = conv2d(net, blocks[0].num_filters, k_h=1, k_w=1, stride_h=1, stride_w=1, 
      padding='VALID', name='conv2')
 ## (입력값, num_filters=128, )
# ResNet 블록 반복 
for block_i, block in enumerate(blocks):
    for repeat_i in range(block.num_repeats):
        name = 'block_%d/repeat_%d' % (block_i, repeat_i)
        conv1 = conv2d(net, block.bottleneck_size, k_h=1, k_w=1, 
                         padding='VALID', stride_h=1, stride_w=1, 
                         activation=tf.nn.relu,name=name + '/conv_in')                      
        conv2 = conv2d(conv1, block.bottleneck_size, k_h=3, k_w=3,
                         padding='SAME', stride_h=1, stride_w=1,
                         activation=tf.nn.relu,name=name + '/conv_bottleneck')
        conv3 = conv2d(conv2, block.num_filters, k_h=1, k_w=1,
                         padding='VALID', stride_h=1, stride_w=1,
                         activation=tf.nn.relu, name=name + '/conv_out')

        net = conv3 + net
    try:
# upscale to the next block size
        next_block = blocks[block_i + 1]
        net = conv2d(net, next_block.num_filters, k_h=1, k_w=1,
                         padding='SAME', stride_h=1, stride_w=1, bias=False,
                         name='block_%d/conv_upscale' % block_i)
    except IndexError:
        pass

 

6. 평균풀링과 softmax를 하기위해 최종출력을 1D 텐서로 바꿈

 - avg_pool : flat 들어가기전에 global evg_pool 을 사용 (원래는 local) -> 레이어 사이즈가 줄지않음

# 평균 풀링을 이용하여 블록 구조의 최종 출력의 차원 변환
net = tf.nn.avg_pool(net, ksize=[1, net.get_shape().as_list()[1],net.get_shape().as_list()[2], 1],
                     strides=[1, 1, 1, 1], padding='VALID')
#ResNet 블록 구조의 최종 출력을 1D로 변환
Flat=tf.reshape(net,[-1, net.get_shape().as_list()[1] *net.get_shape().as_list()[2] 
               *net.get_shape().as_list()[3]])

7. 최종출력

 - activation으로 tf.nn.softmax 함수 지정

 - cost는 사실상 여태 다뤄왔던 loss라고 볼 수 있음 - 최소제곱오차? 를 구함

 - 옵티마이저 설정

# 최종 출력을 위해 소프트맥스함수 지정
Y_pred =linear(Flat, 10, activation=tf.nn.softmax)
cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=Y_pred, labels=Y)) ## 손실..
optim=tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

8. 모델 정확도 분석위해 변수 선언, 정의

## 모델 정확도
correct_predict=tf.equal(tf.argmax(Y_pred,1), tf.argmax(Y,1))
accuracy=tf.reduce_mean(tf.cast(correct_predict, tf.float32))

9. 세션열고 초기화 (반드시 해야하는 부분)

 - tf.global_variables : 반드시 global 초기화

 

sess=tf.Session(); 
sess.run(tf.global_variables_initializer())

10. epochs 만큼 훈련

 - total_batch : 배치사이즈만큼 나누어진 집단을 받음

 - 지정해준 optimizer 사용하여 최적화 하고 loss값을 구하고 평균 손실을 구함

 - 정확도도 같이구함

 - feed_dict : 무조건 placeholder -> 초기선언시

 - W, b : 무조건 Variable -> 초기선언시

for epoch in range(epochs):
    avg_cost=0
    total_batch=int(mnist.train.num_examples/batch_size)
    for i in range(total_batch):
        batch_xs,batch_ys=mnist.train.next_batch(batch_size)
        
        feed_dict={X:batch_xs, Y:batch_ys}
        sess.run(optim, feed_dict=feed_dict)
        ccost=sess.run(cost, feed_dict=feed_dict)
        ## 평균손실
        avg_cost+=ccost/total_batch
        ## 왜?
        acc=sess.run(accuracy, feed_dict=feed_dict) 
    print('Epoch: %d' %(epoch+1),'cost= %f, accuracy= %f' %(avg_cost, acc))
    
    

11.

# 훈련 데이터, 검정 데이터의 오분류율
acc_tr=0; acc_ts=0
for ii in range(100): #메모리 문제를 피하기 위해 자료를 100개로 분할
    xr,yr=mnist.train.next_batch(550)
    acc_tr= acc_tr+ 0.01*sess.run(accuracy, feed_dict={X:xr, Y:yr}) 
    xt,yt=mnist.test.next_batch(100)
    acc_ts= acc_ts+ 0.01*sess.run(accuracy, feed_dict={X:xt, Y:yt})    
print('misclassification error(tr):', 1-acc_tr)
print('misclassification error(ts):', 1-acc_ts)

 


Padding 계산하기

Output Size = (Input Size + 2 x Padding - Filter Size) / Stride + 1

'딥러닝' 카테고리의 다른 글

0814 RNN 구조로 뒤에올 문자 예측하기  (0) 2019.08.14
0814 embedding으로 단어 연관성 예측하기  (0) 2019.08.14
0813 CNN으로 MNIST 분류기 구현하기  (0) 2019.08.13
0812 ANN을 이용한 MNIST 숫자 분류기 구현  (0) 2019.08.12
0812 소프트맥스 회귀로 MNIST 데이터 분석하기  (0) 2019.08.12
    '딥러닝' 카테고리의 다른 글
    • 0814 RNN 구조로 뒤에올 문자 예측하기
    • 0814 embedding으로 단어 연관성 예측하기
    • 0813 CNN으로 MNIST 분류기 구현하기
    • 0812 ANN을 이용한 MNIST 숫자 분류기 구현
    피곤핑
    피곤핑

    티스토리툴바