overview

  tensorflow는 graphs의 형태로 나타내는 프로그래밍 시스템을 말합니다. 그래프에 있는 노드들은 operations이라고 불리우는데, 줄여서 ops라고 칭합니다. op는 Tensor로 이루어져 있고, tensors간에 computaiton을 수행하게 됩니다. tensor는 multi-dimentional array형태로 되어있다. Tensorflow graph를 연산하기 위해서는 Session을 launch를 해야한다. Session은  Devices(CPUs, GPUs)위에서 연산을 실행한 후에 결과를 반환한다. 

The computation graph

  Tensorflow 프로그램은 graph의 형태로 되어 있고, 그래프에 있는 ops의 연산을 수행하기 위해  session을 이용한다. 예를들어서 뉴럴네트워크를 구성한다고 할때, 그래프를 생성하는 부분과, 반복적으로 ops를 training하는 실행하는 부분이 있습니다. Tensorflow는 C, C++ 그리고 python 프로그램이 사용될 수 있습니다. C, C++라이브러리에서는 사용할 수 없는 함수들을 사용할 수 있기 때문에 그래프를 생성하거나 할때 python을 이용하는게 쉽습니다. session 라이브러리는 기능적으로는 모두 3가지 언어가 동일합니다. 

Building the graph

  그래프프는 각 노드, 즉 ops로 이루어져 있기 때문에 아래에서 constant를 이용해서 노드를 생성해 보도록 하겠습니다. 


import tensorflow as tf


matrix1 = tf.constant([[3., 3.]])

matrix2 = tf.constant([[2.],[2.]]) 

product = tf.matmul(matrix1, matrix2)


여기서는 실제로 3개의 노드로 이루어진 그래프를 생성하였고,

실제로 두개의 matrix를 곱하는 연산을 해서 결과를 얻기 위해서는 graph를 session에 launch해야 합니다. 

Launching the graph in a session

  graph를 launch하기 위해서는 첫번째로 Session object를 생성해야 합니다. 


sess = tf.Session()

result = sess.run(product)

print result) # [[ 12. ]]

sess.close()


session에서 사용한 resources를 release하기 위해서는 반드시 closed를 해줘야 합니다. closed 대신에 with를 사용하면 block안에서만 session이 유효하게 됩니다.


with tf.Session() as sess:

    result = sess.run([product])

    print result


Tensorflow는 위에서 정의한 graph를 CPU, GPU에서 동작시킬 수 있도록 구현이 가능합니다.  tesorflow에서 만약 gpu를 사용할 수 있으면, 많은 연산이 가능합니다.  만약 gpu가 한개 이상이 있으면, 특정 gpu를 지정을 해줘야 합니다. 


with tf.Session() as sess:

    with tf.device(“/gpu:1”):

        matrix1 = tf.constant([[ 3., 3.]])

        matrix2 = tf.constant([[ 3., 3.]])

        product = tf.matmul(matrix1, matrix2)


Device는 특정 string으로 사용할 수 있습니다. 

“/cpu:0”: CPU

“/gpu:0”: gpu (만약 한개라면)

“/gpu:1”: 두번째 gpu



Launching the graph in a distributed session

  클러스터내에 Tensorflow server를 실행하면, 원격에서도 Tensorflow를 사용할 수 있습니다. 


with tf.Session(“grpc://example.org:2222”) as sess:

    # Calls to sess.run(…) will be exsecuted on the cluster.


server는 session의 master역할을 하고, master는 클러스터 내부의 다른 machines들에게 작업을 배포합니다. 

특정 workers에게 특정 그래프를 넘기고 싶으면 아래와 같이 하면 됩니다.


with tf.device(‘/job:ps/task:0’):

   weights = tf.Variable(…)

   biases = tf.Variable(…)

Interactive Usage

  Session을 생성하고, graph를 launch하기 위해 Session.run()을 실행하는 방법이 아닌, IPython과 같은 interactive하게 사용을 하기 위해서는 InteractiveSession, Tensor.eval(), Operation.run()을 이용해서 사용이 가능합니다. (session에 variable을 holding을 유지할 필요 없이)


# Enter an interactive TensorFlow Session.

import tensorflow as tf

sess = tf.InteractiveSession()


x = tf.Variable([1.0, 2.0])

a = tf.constant([3.0, 3.0])


# Initialize 'x' using the run() method of its initializer op.

x.initializer.run()


# Add an op to subtract 'a' from 'x'.  Run it and print the result

sub = tf.sub(x, a)

print(sub.eval())

# ==> [-2. -1.]


# Close the Session when we're done.

sess.close()

Tensors

  Tensorflow에서는 모든 데이터를 표현하기 위해서 tensor data를 사용합니다. tensor는 computation graph 내의 operations의 사이에서 주고 받아지는 값을 말합니다. 쉽게 생각하면 n-dimensional array또는 list의 값이라고 생각하면 됩니다. tensor는 static type, a rank, shape를 가지고 있습니다. 

Variables

  아래는 simple counter를 구현한 내용입니다. 


# Create a Variable, that will be initialized to the scalar value 0.

state = tf.Variable(0, name="counter")


# Create an Op to add one to `state`.


one = tf.constant(1)

new_value = tf.add(state, one)

update = tf.assign(state, new_value)


# Variables must be initialized by running an `init` Op after having

# launched the graph.  We first have to add the `init` Op to the graph.

init_op = tf.global_variables_initializer()


# Launch the graph and run the ops.

with tf.Session() as sess:

  # Run the 'init' op

  sess.run(init_op)

  # Print the initial value of 'state'

  print(sess.run(state))

  # Run the op that updates 'state' and print 'state'.

  for _ in range(3):

    sess.run(update)

    print(sess.run(state))


# output:


# 0

# 1

# 2

# 3


실제로 코드는 run()을 하기 전에는 동작을 하지 않습니다. 

Fetches

  fetch는 graph의  operations를 session에서 run()하기 위해 넘겨주는 것을 말합니다. 

이전에는 한개의 node만 fetch를 했다면(state), 여러개의 노드를 fetch가 가능합니다. 


input1 = tf.constant([3.0])

input2 = tf.constant([2.0])

input3 = tf.constant([5.0])

intermed = tf.add(input2, input3)

mul = tf.mul(input1, intermed)


with tf.Session() as sess:

  result = sess.run([mul, intermed])

  print(result)


# output:

# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]

Feeds 

  위에서 언급한 Constants, Variables는 값을 저장하는 형태로 소개를 했습니다. Tensorflow에서는 feed의 mechanism을 그래프의 어떤 operation에 직접적으로 tensor를 patching하기 위해 제공합니다. 


  feed는 tensor의 값과 함께 operation의 output을 일시적으로 교체하는 것을 말합니다. run()의 argument로 feed data를 넣어주면 됩니다. feed는 오직 run을 실행할때 넘겨주기가 가능합니다. feed operation을 사용하기 위해서는 tf.placeholder()를 생성을 해야합니다.


input1 = tf.placeholder(tf.float32)

input2 = tf.placeholder(tf.float32)

output = tf.mul(input1, input2)


with tf.Session() as sess:

  print(sess.run([output], feed_dict={input1:[7.], input2:[2.]}))


# output:

# [array([ 14.], dtype=float32)]


placeholder()연산은 만약에 feed를 넣어주지 않으면 에러가 발생합니다. 

  modern object recognition models은 수백만개의 파라미터의 값과 full train을 하는데 걸리는 시간이 주 단위로 걸리게 된다. Transfer learning은 여러개의 categories로 이루어진 set을 fully-trained model인 ImageNet을 대상으로, 새로운 클래스를 추가해서 기존에 존재하는 weights를 다시 retrain하는 것을 말한다. 요약해서 말하면, 이미 트레이닝이 된 모델의 수백만개의 parameters를 그대로 사용하는데, 새로운 클래스를 추가하므로서, 기존 weights를 retrain하는 것을 Transfer learning이라고 한다. 예를 들어서 마지막 final layer를 retraining하고, 그 나머지 모든 layer에 대해서는 신경쓰지 않는다. 더 자세히 알고 싶으면 아래 논문을 참고 하길 바란다. 


https://arxiv.org/pdf/1310.1531v1.pdf


비록 transfer learning을 하는게 full training을 하는 것보다 성능은 좋지 않지만, 많은 애플리케이션에서 뛰어난 효과를 얻고 있다. 일단 full training하는 시간이 엄청 긴데, GPU가 없는 laptop에서도 대략 30분이면 모든 training을 할 수 있다. 아래 예제는 어떻게 새로운 클래스를 추가해서 모델을 학습시키는지에 대한 training process에 대해서 설명을 한다. 


training을 하기 전에 학습에 사용할 새로운 클래스의 이미지들이 필요하다. 만약 없다면, 아래의 이미지를 사용하자. 


$ cd ~ 

$ curl -O http://download.tensorflow.org/example_images/flower_photos.tgz

$ tar xzf flower_photos.tgz


이미지를 다운로드 다 했다면, TensorFlow source directory로 이동을해서 retrainer를 build를 한다. 아래와 같이 입력하자.

bazel은 google의 build tool로서, 설치가 필요하다.

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

$ brew install bazel


$ bazel build tensorflow/examples/image_retraining:retrain

여기서 에러가 나는데,,,, 왜 나는지 나도 모르겠음


$ python tensorflow/examples/image_retraining/retrain.py --image_dir ~/flower_photos


으로 실행하면, [pre-trained Inception v3 모델 다운로드] - [bottleneck 생성] - [새로운 클래스 training] 순으로 진행이 된다. 


정확도를 돌려보면 대략 92%정도 나온다… 대단대단



bottleneck

bottleneck을 생성되는데 걸리는 시간은 머신에 따라 속도 차이가 있겠지만, 대략 30분 정도 소요가 된다. bottleneck은 final output layer의 전에서 사용할 정보를 가지고 있다. 



Overview


CIFAR-10 classification은  machine learning에서 공통적으로 benchmark problem이다. 여기서 문제는 RGB 32 x 32 pixel의 이미지들을 10개의 카테고리로 분류하는것이다. 


Goals


image recognition을 위한 작은 convolutional neural network를 build하는 tutorial입니다. 

- network architecture, training, evaluation을 위해서 어떻게 조직화 할 것인지.

- models을 construct하기 위한 template을 제공


CIFAR-10은 model을 만들기위해 tensorflow의 예제코드로 이루어져 있다. 현재는 작고, 빠르게 트레이닝이 가능하다. 

CIFAR-10을 기반으로 새로운 기술과, 아이디어로 모델을 구성할 수 있다. 


Highlights of the Tutorial


tensorflow에서 model을 디자인하고, 생성하기 위한 여러가지 중요한 여러 방법을 CIFAR-10에 포함하고 있다.


* Core mathematical components including convolution (wiki), rectified linear activations (wiki),max pooling (wiki) and local response normalization (Chapter 3.3 in AlexNet paper).

* Visualization of network activities during training, including input images, losses and distributions of activations and gradients.

* Routines for calculating the moving average of learned parameters and using these averages during evaluation to boost predictive performance.

* Implementation of a learning rate schedule that systematically decrements over time.

* Prefetching queues for input data to isolate the model from disk latency and expensive image pre-processing.


뿐만아니라 multi-GPU version에 대해서도 설명하고 있다. 


* Configuring a model to train across multiple GPU cards in parallel.

* Sharing and updating variables among multiple GPUs.


위 tutorials을 통해서 larger CNNs을 building하는게 목적이다. 


Model Architecture


CIFAR-10 tutorial에 있는 model은 convolutions과 nonlinearities로 구성된 multi-layer architecture이다. 

여기 layers들은 fully connected layers로 softmax classifier에 의해서 결과가 나온다. 

model은 Alex Krizhevsky의 architecture에서 몇개의 layers가 차이가 있다. 


이 model은 GPU에서 몇시간이내로 학습한 정확도의 결과가 대략 86%정도 나온다. 

l1,068,298개의 learnable parameters와19.5의 multiply-add operations로 구성되어 있다.


Code Organization


소스코드는 tensorflow git에서 쉽게 clone을 할 수 있다. 

https://github.com/tensorflow/models


소스코드의 구성은 아래와 같다.


cifar10_input.py Reads the native CIFAR-10 binary file format.

cifar10.py Builds the CIFAR-10 model.

cifar10_train.py Trains a CIFAR-10 model on a CPU or GPU.

cifar10_multi_gpu_train.py Trains a CIFAR-10 model on multiple GPUs.

cifar10_eval.py Evaluates the predictive performance of a CIFAR-10 model.


CIFAR-10 Model


cifar10.py에 주로 CIFAR-10 network가 포함되어 있다. training이 완료된 graph는 대략 765개의 operations이 포함되어 있다.

graph를 생성하기 위해서 재사용이 가능한 코드들이 포함되어 있으니, 가져다가 사용하면 된다. (아주 친절)


1. Model inputs: inputs() and distorted_inputs() add operations that read and preprocess CIFAR images for evaluation and training, respectively.

2. Model prediction: inference() adds operations that perform inference, i.e. classification, on supplied images.

3. Model training: loss() and train() add operations that compute the loss, gradients, variable updates and visualization summaries.


- model inputs

    - inputs(), distorted_inputs()은 CIFAR-10 binary data files로 부터 images를 읽는데 사용을 한다. 이 파일들은 고정된 바이트 레코드의 길이를 포함하고 있기 때문, tf.FixedLengthRecordReader를 사용한다.

    - 이미지 전처리는 아래와 같이 진행한다.

        - They are cropped to 24 x 24 pixels, centrally for evaluation or randomly for training.

        - They are approximately whitened to make the model insensitive to dynamic range.

    - 트레이닝을 하기 위해, 추가적으로 artificially 데이터 set의 사이즈를 증가시키기 위해, random distortions의 series를 적용을 한다.

        - Randomly flip the image from left to right.

        - Randomly distort the image brightness.

        - Randomly distort the image contrast.

    - image_summary를 이용해서 tensorboard에서 image를 확인이 가능하다. 

    - disk로 부터 images를 읽고, distorting하는 시간이 processing time에서 많은 양을 차지 할 수 있다. training하는 operation의 시간을 예방하기 위해서 TensorFlow queue에 16개의 operate threads를 끊임없이 사용했다.


- model prediction

    - inference()의 함수에서는 logits을 계산하기 위해서 operations을 추가한다. 모델은 아래와 같이 구성

        - layer description

        - conv1 convolution and rectified linear activation.

        - pool1 max pooling.

        - norm1 local response normalization.

        - conv2 convolution and rectified linear activation.

        - norm2 local response normalization.

        - pool2 max pooling.

        - local3 fully connected layer with rectified linear activation.

        - local4 fully connected layer with rectified linear activation.

        - softmax_linear linear transformation to produce logits.


    - inference의 ouput은 un-normalized logits이다. tf.nn.softmax()를 사용해서 normalized predictions을 반환하는 로직을 구현해보자.

    - input(), inference() 함수는 모델을 evaluation하는데 필수적으로 사용되는 components이다. 

    - inference()에서의 models architecutre는 CIFAR-10 model과는 다소 차이가 있다. 특히 기존 Alex’s의 original model의 top layers는 fully connected가 아닌, locally connected이다. 이런점을 고려해 구성을 해보는것도 좋다.


- model training

    - N-way classificatiion을 수행하기 위한 network를 training하기 위해 보편적으로 사용되는 방법은 multinomial logistic regression이다. (aka. softmax regression.). softmax regression은 softmax nonlinearity를 label의 1-hot encoding과 normalized predictions사이에서의 cross-entropy를 계산하고, network의 output에 적용하는 방법을 말한다. regularization을 위해 보통 weight decay losses를 적용한다. loss() 함수로 부터 반환된 값인 weight decay terms, cross entropy loss의 합은 모델을 위한 objective function이다.

    - gradient descent algorithm과 exponentially decays의 learning rate를 사용해서 model을 학습한다.

    - train() 함수는 gradient의 값이 최소가 되고, learned variables를 업데이트하기 위해 operations의 추가가 필요하다. 이 함수는 images의 한번의 batch를 위한 모델을 update하고, train을 하기 위해 필요한 모든계산을 하는 operation을 반환한다


Launching and Training the Model


위에서 모델을 build를 완료하였다. 모델을 launch하고, script를 통해  training operation을 수행해보자. 


$ python cifar10_train.py


최초에 dataset이 없으면, 자동으로 데이터를 다운로드 받는다. 데이터 셋의 크기는 대략 ~160MB이다. 


만약 여기서 

TypeError: strided_slice() takes at least 4 arguments (3 given)

와 같은 에러가나면, tensorflow 버전을 확인해보는게 좋다. 

import tensorflow as tf

tf.__version__


인줄 알았는데… 아니 였음. 따로 issue가 있었는데,

https://github.com/tensorflow/models/issues/817

tensorflow 버전이 아닌, cifar의 버전을 맞춰야 한다. 

https://github.com/tensorflow/models/pull/769


해결방법은 아래와 같다.

http://stackoverflow.com/questions/41195121/tensorflow-strided-slice-missing-argument-strides


tf.contrib.deprecated.image_summary('images', images)

와 같은 에러가 났으나,

tf.summary.scalar()로 대신 변경하면 동작

https://www.tensorflow.org/api_docs/python/summary/generation_of_summaries_

0.12r의 API문서를 확인하는게 좋다.



다운로드를 받고 training을 하면 아래와 같은 output을 볼 수 있을것이다.

script는 10 steps마다 화면에 결과를 출력한다.


2016-12-29 14:59:25.595257: step 1590, loss = 1.96 (195.0 examples/sec; 0.656 sec/batch)

2016-12-29 14:59:32.323162: step 1600, loss = 1.88 (171.6 examples/sec; 0.746 sec/batch)

2016-12-29 14:59:38.942774: step 1610, loss = 1.75 (195.5 examples/sec; 0.655 sec/batch)

2016-12-29 14:59:45.613060: step 1620, loss = 1.80 (194.6 examples/sec; 0.658 sec/batch)

2016-12-29 14:59:52.385803: step 1630, loss = 1.92 (196.1 examples/sec; 0.653 sec/batch)

2016-12-29 14:59:59.000392: step 1640, loss = 1.87 (195.8 examples/sec; 0.654 sec/batch)

2016-12-29 15:00:05.640369: step 1650, loss = 1.74 (193.1 examples/sec; 0.663 sec/batch)


cifar10_train.py는 주기적으로 모든 모델의 parameters을 checkpoint files에 저장한다.

이렇게 저장된 checkpoint files은 cifar10_eval.py에서 predictive performance를 측정하기 위해 사용된다. 

cifar10_train.py는 어떻게 모델을 학습시키는지에 대해서 최소한의 insight를 제공한다. 


* Is the loss really decreasing or is that just noise?

* Is the model being provided appropriate images?

* Are the gradients, activations and weights reasonable?

* What is the learning rate currently at?


TensorBoard에서 cifar10_train.py 의 SummaryWriter로 부터 주기적으로 추출된 데이터를 화면에 출력을 해준다. 

예를 들어서 activations, sparsity의 degree와 같은 분포를 알 수 있다. 


개별적으로 loss functions과 더불어 total loss, 특정 관심있는항목을 확인이 가능하다. 

그러나, loss는 training이 되는 small batch size  때문에 noise의 considerable amount를 나타낸다. (?) 무슨말이지…. 

training하는 batch size가 작기 때문에, 그 해당 small batch size에서의 loss의 양이 표시된다는 의미 같다.

특히, moving averages를 확인이 가능하기 때문에 매우 유용하다. 왜?… moving average를 보는게 의미가 있겠지? 

moving average에 대해서 자세한 내용은 사이트 참고 ExponentialMovingAverage 


Evaluating a Model


trained model 이 얼마나 잘됬는지 evaluation하는 방법이다. evaluation하기 위해서는 cifar10_eval.py를 사용하면 된다.

inference()와 10,000 images를 사용해서 model을 구성했다. 얼마나 정확하게 image를 예측하는지에 대해서 precision을 계산한다. 


trainining하는 model이 improves를 얼마나 하는지 확인하기 위해서, evaluation scripts는 주기적으로 가장 최근 checkpoint files을 실행한다. 

만약 여게서 evalution과 training binary를 같은 GPU에서 실행을 하지 않는다면 에러가 난다. 그러므로 같은 GPU에서 실행을 해야한다. 


cifar10_eval.py도 TensorBoard에 visualization을 한다. 이러한 요약은 모델을 evaluation하는데 추가적인 insight를 제공할 것이다. 


training script는 모든 learned variables에 대해서 moving average version을 계산한다. evaluation script는 모든 learned model parameters를 moving average version으로 대체한다.

이 대체는 evaluation time에서 model performance를 boosts한다. (무슨말일까? evaluation하는 step에서도 model performance를 향상을 시키나…?)


Training a Model Using Multiple GPU Cards


Tensorflow에서도 여러개의 GPU에서 training operation을 동시에 수행이 가능하다.. 

(여기는 GPU Cards가 여러개 있을때 읽어보자….) 일단 보류





 



  네트워크를 구성하고, training을 하는데, accuracy와 cross-entropy의 그래프에서 training, validation의 값이 차이가 나는게 보였다. 빨간색이 training, 파란색이 validation이다. training의 acc의 값은 증가하고, cross-entropy의 값은 계속 줄어드는데 반면, validation의 값은 반대로 유지가 되거나, 반대로 증감하는 그래프를 확인할 수 있었다. 즉 현재 네트워크는 overfitting 되었다고 말할 수 있다. 




Dropout


tensorflow에서는 fully connected layer를 일정 노드를 dropout을 함으로써,

overfitting문제를 해결한다. 


input으로는 neuron’s을 유지할 probability를 입력해주면 간단하게 구현이 가능하다. 

모든 구현은 tf.nn.dropout op가 자동적으로 scaling neuron ouptuts을 해준다.


keep_proba = tf.placeholder(tf.float32)

h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)


Readout Layer


softmax regression 바로 위의 layer인 readout layer에 추가를 하면된다. 


W_fc2 = weight_variable([1024, 10])

b_fc2 = bias_variable([10])


y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2


Train and Evaluate the model


run()할때, feed_dict에 keep_prob을 추가하면 된다.  





[참고]

https://www.tensorflow.org/tutorials/mnist/pros/

  이미 google에서 만들어서 deep learning하는 플랫폼중에 가장 유명하다고 할 수 있는... Tensorflow를 설치하는 방법에 대해서 정리를 해보았다. Tensorflow는 설치하기 아주 간단하다. 하지만 처음부터 pip 설치하고 번거로운 일이 있기에 그냥 정리해 보았다. 



$ sudo apt-get install python-pip python-dev

$ sudo pip install —upgrade pip


$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.1-cp27-none-linux_x86_64.whl

$ sudo pip install --upgrade $TF_BINARY_URL


Python 2.7 설치


$ wget http://www.python.org/ftp/python/2.7.13/Python-2.7.13.tar.xz

$ wget http://www.python.org/ftp/python/3.3.3/Python-3.3.3.tar.xz


$ tar -xvf Python-2.7.13

$ cd Python-2.7.13

$ ./configure --prefix=/usr/local --enable-shared

$ ./configure --enable-optimizations

$ sudo make

$ sudo make altinstall


$ sudo yum groupinstall "Development tools"

$ sudo yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel

$ cd /opt

$ sudo wget --no-check-certificate https://www.python.org/ftp/python/2.7.6/Python-2.7.6.tar.xz

$ sudo tar xf Python-2.7.6.tar.xz

$ cd Python-2.7.6

$ sudo ./configure --prefix=/usr/local

$ sudo make && sudo make altinstall

$ vi ~/.bashrc

alias python=/usr/local/bin/python2.7

$ source ~/.bashrc

 


[참고]

https://www.tensorflow.org/get_started/os_setup#pip_installation

http://tuxlabs.com/?p=194

+ Recent posts