-
준비물은
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)전체 소스코드는 이곳에 있다.
한쪽에서 코드를 실행시켜서 데이터를 생성하고 텐서보드를 실행해주면 log_dir에 test/train폴더가 생기고 log파일이 생겨서 텐서보드에서는 그 폴더에 기록되는 log를 보고 화면에 출력해준다.
코드를 좀 보자..(+_+)
#Train1. 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 을 이용하여 값을 넣어줘야합니당)1234mnist = 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를 사용하여1234567with 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, [-1, 28, 28, 1])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)
123456789def 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의 히스토그램 데이터를 기록한다.
12345678910def 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
1234567891011121314def 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) + biasestf.summary.histogram('pre_activations', preactivate)activations = act(preactivate, name='activation')tf.summary.histogram('activations', activations)return activationscs 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
12345678hidden1 = nn_layer(x, 784, 500, '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, 500, 10, '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 이 블로그가 좀 잘해주셨다.
1234with 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를 계산한다. (동일하게 요약을 진행한다)
1234567891011with 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()으로 모든 변수를 초기화 한다.
1234merged = 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효과가 없는 것과 같다)
..사실 지금은 뭔소린지 모르겠다. 일단 한번 더 읽을거니까...12345678def feed_dict(train):if train or FLAGS.fake_data:xs, ys = mnist.train.next_batch(100, fake_data=FLAGS.fake_data)k = FLAGS.dropoutelse:xs, ys = mnist.test.images, mnist.test.labelsk = 1.0return {x: xs, y_: ys, keep_prob: k}cs 11. 실제로 작업을 실행하는 부분
123456789101112131415161718192021for 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