• 텐서보드

    2019. 2. 20. 18:30

    by. 위지원

    준비물은

    0. 버츄어 박스 6버전

    1. 버츄어 박스에 설치한 우분투 18.0.4.2.LTS

    2. pip3

    3. tensorflow로 텐서플로우 설치

    4. virtualenv 설치


    텐서플로우 원리와 응용을 읽고 공부한 내용



    텐서보드란?

    - 텐서플로우의 공식 시각화 도구로 scala,이미지,오디오등 여러 요약 데이터를 표시 할 수 있다.

    - 설계한 신경망을 이해하고, 디버그, 최적화를 위해 사용할 수 있다.


    어떻게?

    1. 텐서플로우 계싼 그래프를 실행한는 동한 데이터를 요약하고 로그에 기록한다.

    2. 이 로그 파일을 텐서보드에서 읽어 해석및 시각화 하는 웹페이지를 생성한다.


    사용방법은?


    아래와 같이 --logdir로 텐서플로우 로그 경로를 지정한 뒤 실행하면 바로 다음에 오는 경로로 TensorBorad 웹페이지로 접속 할 수 있다.


    (tensorEnv) weejiwon@weeserver:~/tensorEnv/exampleCode$ tensorboard --logdir=/tmp/tensorflow/mnist/logs/mnist_with_summaries
    TensorBoard 1.12.2 at http://weeserver:6006 (Press CTRL+C to quit)




    전체 소스코드는 이곳에 있다.

    https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/mnist/mnist_with_summaries.py



    한쪽에서 코드를 실행시켜서 데이터를 생성하고 텐서보드를 실행해주면 log_dir에 test/train폴더가 생기고 log파일이 생겨서 텐서보드에서는 그 폴더에 기록되는 log를 보고 화면에 출력해준다.





    코드를 좀 보자..(+_+)


    #Train

    1. input_data.read_data_sets를 이용하여 데이터를 읽어오고 tensorflow의 기본 Session을 만든다.

    텐서플로우에서 Session은 그래프의 실행환경을 캡슐화한것으로 캡슈로하된 실행환경을 객체화하기 위해 Session객체를 만들어 그래프를 실행한것이다. 자세한 설명은 https://dohkstalks.blogspot.com/2017/01/tensorflow-concept-tensorflow.html

    세션은 fetche와 feeds 두가지 방법으로 처리가 된다.
    연산의 결과를 fetch(가져오는)방법 / placeholder에 값을 넣어 실행하는 방법( feed_dict 을 이용하여 값을 넣어줘야합니당)

    1
    2
    3
    4
    mnist = input_data.read_data_sets(FLAGS.data_dir,
                                       fake_data=FLAGS.fake_data) //책에는 두번째 argu가 one_hot=True로 되어있다.
     
    sess = tf.InteractiveSession()
    cs

    *코드에 FLAGS.data_dir로 되어있는건 깃 헙 코드에 보면 프로그램(.py파일)실행시 파라미터로 받아서 parser를 이용해 삽입하고 받지 않으면 기본으로 값을 지정해주는 부분이 있기 때문!

    one_hot=Ture 는 one_hot Encoding을 이야기한다.

    2. 텐서보드에서 노드 이름을 표시하기 위해 with tf.name_scope를 사용하여

    1
    2
    3
    4
    5
    6
    7
    with tf.name_scope('input'):
            x = tf.placeholder(tf.float32, [None, 784], name='x-input')
            y_ = tf.placeholder(tf.int64, [None], name='y-input')
     
    with tf.name_scope('input_reshape'):
            image_shaped_input = tf.reshape(x, [-128281])
            tf.summary.image('input', image_shaped_input, 10)    
    cs

    line 6: tf.reshape를 이용하여 입력 1차원 데이터를 28x28이미지로 변환한다.
    line 7: tf.summary.image 함수를 이용하여 데이터를 요약하여 텐서보드에 표시할 수 있다. 아래처럼


    3. 신경망 모델의 매개 변수의 초기화 메서드를 정의한다.  weight와 bias값을 초기화 해주는 코드

    weight를 초기화해줄때는 truncated_normal 함수를 자주 사용한다고 한다. 이는 찾아보니 평균이 0에 가깝고 값이 0에 가까운 정규 분포에서 난수를 선택하는 것이다(ex:=0.1~0.1)


    1
    2
    3
    4
    5
    6
    7
    8
    9
     def weight_variable(shape):
            """Create a weight variable with appropriate initialization."""
            initial = tf.truncated_normal(shape, stddev=0.1)
            return tf.Variable(initial)
     
     def bias_variable(shape):
            """Create a bias variable with appropriate initialization."""
            initial = tf.constant(0.1, shape=shape)
            return tf.Variable(initial)   
    cs


    4. Variable 변수에 대한 데이터 요약 함수

    Variable의 mean,max,min등을 요약하는 함수로 tf.summary.scalar를 사용하여 스칼라 데이터를 요약하고 기록한다. 같은 느낌으로 summary.histogram 함수는 변수 var의 히스토그램 데이터를 기록한다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def variable_summaries(var):
            with tf.name_scope('summaries'):
                mean = tf.reduce_mean(var)
                tf.summary.scalar('mean', mean)
                with tf.name_scope('stddev'):
                    stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
                tf.summary.scalar('stddev', stddev)
                tf.summary.scalar('max', tf.reduce_max(var))
                tf.summary.scalar('min', tf.reduce_min(var))
                tf.summary.histogram('histogram', var)
    cs



    5. MLP( 멀티 레이어 신경망 )을 설계 후 데이터 훈련

    파라미터는 입력 데이터/입력 차원/출력 차원/레이어 이름/활성화 함수 이며, 활성화 함수는 기본적으로 ReLU를 사용한다.


    ReLU는 Rectified Linear Unit의 약자로 기존의 linear 함수인 sigmoid를 개선한 함수이다. sigmoid함수의 문제인 Graient Vanishing문제(sigmoid 함수는 0~1 값을 가지는데 gradient descent를 사용해 backpropagation을 수행할때 gradient를 계속 곱하다 보면 0으로 수렴해서 layer가 많아지면 잘 작동하지 못함)를 해결하려고 한것.


    ReLu는 입력값이 0보다 작으면 0이고 0보다 크면 입력값이 곧 출력값이 된다.


    더 자세한 설명은 https://mongxmongx2.tistory.com/25


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def nn_layer(input_tensor, input_dim, output_dim, layer_name, act=tf.nn.relu):=
            with tf.name_scope(layer_name):
                with tf.name_scope('weights'):
                    weights = weight_variable([input_dim, output_dim])
                    variable_summaries(weights)
                with tf.name_scope('biases'):
                    biases = bias_variable([output_dim])
                    variable_summaries(biases)
                with tf.name_scope('Wx_plus_b'):
                    preactivate = tf.matmul(input_tensor, weights) + biases
                    tf.summary.histogram('pre_activations', preactivate)
                activations = act(preactivate, name='activation')
                tf.summary.histogram('activations', activations)
                return activations
    cs

    1) 신경망의 weight와 bias를 초기화 한다.

    2) 10line에서 행렬 곱셈을 실행하고 vias를 더하고 활성화되지 않은 결과에 대해 히스토 그램을 계산 (11line)

    3) 12line 활성화 후 다시 히스토그램 계산


    6. 신경망 레이어 생성과 dropout 설정


    hidden1이라는 변수를 이용해 방금 정의한 함수를 이용해 784(28*28)크기의 입력차원과 숨겨진 노드 수 500으로 출력차원을 설정한다.

    dropout 함수를 정의한 후  출력레이어 y를 정의한다. 숨겨진 노드 수 500, 차원 범주 수 10, 활성화 함수는 identity로 맵핑하여 softmax는 당분간 사용하지 않고 나중에 처리한다.


    keep_prob는 dropout을 위한 scala placeholder이다.

    dropout은 네트워크의 일부를 생략해 오버피팅의 문제를 해결함  자세한 설명은 http://blog.naver.com/PostView.nhn?blogId=laonple&logNo=220818841217&categoryNo=0&parentCategoryNo=0&viewDate=¤tPage=1&postListTopCurrentPage=1&from=postView


    1
    2
    3
    4
    5
    6
    7
    8
    hidden1 = nn_layer(x, 784500'layer1')
     
    with tf.name_scope('dropout'):
            keep_prob = tf.placeholder(tf.float32)
            tf.summary.scalar('dropout_keep_probability', keep_prob)
            dropped = tf.nn.dropout(hidden1, keep_prob)
     
     y = nn_layer(dropped, 50010'layer2', act=tf.identity)      
    cs


    7. 출력레이어에 대한 softmax처리를 하고 cross entropy를 계산하고 계산의 내용을 요약한다.


    cross entropy는 손실함수다.  자세한 설명은 http://blog.naver.com/PostView.nhn?blogId=gyrbsdl18&logNo=221013188633&parentCategoryNo=3&categoryNo=&viewDate=&isShowPopularPosts=true&from=search 이 블로그가 좀 잘해주셨다.


    1
    2
    3
    4
    with tf.name_scope('cross_entropy'):
        with tf.name_scope('total'):
            cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=y)
    tf.summary.scalar('cross_entropy', cross_entropy)
    cs


    8.  Adam Optimizer를 이용해 손실 최적화하 정화학 sample수 예측 accuracy를 계산한다. (동일하게 요약을 진행한다)


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    with tf.name_scope('train'):
            train_step = tf.train.AdamOptimizer(FLAGS.learning_rate).minimize(
                cross_entropy)
     
    with tf.name_scope('accuracy'):
            with tf.name_scope('correct_prediction'):
                correct_prediction = tf.equal(tf.argmax(y, 1), y_)
            with tf.name_scope('accuracy'):
                accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))    
     
    tf.summary.scalar('accuracy', accuracy)    
    cs


    9. merge_all함수를 이용해서 앞서 요약한 모든 작업을 가져와서 이후에 실행한다. 

    그리고..로그 파일을 저장하고 global_bariables_initializer().run()으로 모든 변수를 초기화 한다.


    1
    2
    3
    4
    merged = tf.summary.merge_all()
    train_writer = tf.summary.FileWriter(FLAGS.log_dir + '/train', sess.graph)
    test_writer = tf.summary.FileWriter(FLAGS.log_dir + '/test')
    tf.global_variables_initializer().run()
    cs


    10. feed_dict의 손실함수를 정의한다.

    train이 True이면 mnist.train에서 batch 샘플을 얻고 dropout값을 설정한다

    train이 False이면 test data를 얻고 keep_prob을 1로 설정한다(dropout효과가 없는 것과 같다) ..사실 지금은 뭔소린지 모르겠다. 일단 한번 더 읽을거니까...


    1
    2
    3
    4
    5
    6
    7
    8
    def feed_dict(train): 
        if train or FLAGS.fake_data:
            xs, ys = mnist.train.next_batch(100, fake_data=FLAGS.fake_data)
            k = FLAGS.dropout
        else:
            xs, ys = mnist.test.images, mnist.test.labels
            k = 1.0
        return {x: xs, y_: ys, keep_prob: k}
    cs


    11. 실제로 작업을 실행하는 부분



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    for i in range(FLAGS.max_steps):
        if i % 10 == 0
            summary, acc = sess.run([merged, accuracy], feed_dict=feed_dict(False))
            test_writer.add_summary(summary, i)
            print('Accuracy at step %s: %s' % (i, acc))
        else:  
            if i % 100 == 99
                run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
                run_metadata = tf.RunMetadata()
                summary, _ = sess.run([merged, train_step],
                                      feed_dict=feed_dict(True),
                                      options=run_options,
                                      run_metadata=run_metadata)
                train_writer.add_run_metadata(run_metadata, 'step%03d' % i)
                train_writer.add_summary(summary, i)
                print('Adding run metadata for', i)
            else
                summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True))
                train_writer.add_summary(summary, i)
    train_writer.close()
    test_writer.close()   
    cs


    1) line2 : 10단계 마다 merged(데이터 요약) accuracy(테스트 set을 이용한 예측 정확도를 구하는 과정)을 수행한다. 다음 라인에서 이작업 역시 요약하여 log파일에 작성한다.

    2) line7 : 100단계마다 8line에 사용된 RunOption을 이용하여 텐서플로우 실행 옵션을 정의하고 9line에서 metaData까지 설정하면 훈련 중 연산 시간, 메모리 사용과 같은 정보를 기록 가능하다.

    3) line10 : 실제로 작업을 수행하고 요약결과를 write해준다.


    텐서보드를 좀 더 구경해보자



    아래처럼 그래프도 그려주고... 텐서플로우는 그래프식이니껜..



    여기서 layer2를 클릭해보면 아래와 같이 가중치나 바이어스 연산 을 활성하하는 연산을 볼 수 있다.



    오~..이렇게 distributions도 볼 수 있고..(신경망 레이어 출력의 분산을 보여주는 것이다. 그래서 신경망 노드의 출력이 유효한디 dead neurons가 과다한지를 알 수 있다고 한다.)



    히스토그램도 당연 보여준다




    그리고 정확도와 손실함수가 점점 좋아지는 모습도 보여준다.



    '2019년' 카테고리의 다른 글

    텐서플로우 분산 병렬 처리  (0) 2019.02.21
    텐서플로우 GPU병렬성  (0) 2019.02.20
    설치 메모  (0) 2019.02.19
    curl을 이용한 pip 설치  (0) 2019.02.19
    python3 설치  (0) 2019.02.19

    대화의 장 💬