TensorFlow 패키지는 Theano 패키지와 마찬가지로 선형 대수 심볼 컴파일러(Symbolic Linear Algebra Compiler)이다. Theano에 비해 분산처리 기능이 강화되어 있다.
Theano와 유사하게 TensorFlow도 다음과 같은 과정을 거쳐 사용한다.
세션(Session)은 Theano의 함수와 유사한 역할을 하며 실제 심볼 변수의 관계를 분석하고 값을 계산해준다.
TensorFlow는 Variable 명령으로 정의하며 Theano와 달리 각 심볼 변수의 형태를 스칼라, 벡터, 행렬 등으로 명시적으로 정의하지 않는 대신 초기값을 이용해서 형태를 지정한다.
심볼 변수는 보통 입력한 값들에 대한 정의다
In [1]:
import tensorflow as tf
In [2]:
x = tf.Variable(1.0)
y = tf.Variable(2.0)
In [3]:
type(x), type(y)
Out[3]:
이미 만들어진 심볼 변수에 일반 사칙연산이나 TensorFlow 수학 함수를 사용하여 종속 변수 역할을 하는 심볼 변수를 만들 수 있다.
In [4]:
z = x + y
In [5]:
type(z)
Out[5]:
In [6]:
u = tf.log(z)
In [7]:
type(u)
Out[7]:
TensorFlow의 세션은 Theano의 함수와 유사한 역할을 하며 실제로 계산 그래프를 생성하고 값을 계산하기 위한 환경을 제공한다. Theano의 함수와 달리 세션 생성과 실행 시작, 종료를 명시해야 한다.
Session 객체 생성run 메서드close 메서드. with 문으로 대체하기도 한다.세션은 지금 만든 심볼을 뒤쪽에서 쓸 수 있도록 정의한다
In [8]:
with tf.Session() as sess:
tf.initialize_all_variables().run()
print(sess.run(z))
print(sess.run(u))
TensorFlow 도 심볼릭 연산에 의한 미분 계산이 가능하다.
In [9]:
f = x ** 2
fx = tf.gradients(f, [x])
with tf.Session() as sess:
tf.initialize_all_variables().run()
print(sess.run(f))
print(sess.run(fx))
TensorFlow에는 Theano와 달리 최적화를 위한 GradientDescentOptimizer 등의 클래스가 미리 구현되어 있으므로 사용자가 구현할 필요가 없다.
In [10]:
# Create 100 phony x, y data points in NumPy, y = x * 0.1 + 0.3
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data * 0.1 + 0.3 #w가 0.1, b가 0.3
# Try to find values for W and b that compute y_data = W * x_data + b
# (We know that W should be 0.1 and b 0.3, but Tensorflow will
# figure that out for us.)
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) #w와 b를 우리가 찾아야 하기 때문에 심볼로 정의했다.
b = tf.Variable(tf.zeros([1])) #b는 0으로 이니셜라이즈 했다.
y = W * x_data + b #y도 심볼 변수가 된 것이다.
# 여기서 중요한 것은 y와 loss가 핵심이다.
# Minimize the mean squared errors.
loss = tf.reduce_mean(tf.square(y - y_data)) #MSE나 RSS와 같은 방식의 에러를 정의한 것이다.
optimizer = tf.train.GradientDescentOptimizer(0.5) #데아노 같은 경우에는 최적화 과정을 구하는 것이 어려웠으나
#여기서는 이미 구현된 것 사용
train = optimizer.minimize(loss) #그러면 트리이닝 객체가 만들어진다.
# Before starting, initialize the variables. We will 'run' this first.
init = tf.initialize_all_variables()
# Launch the graph.
sess = tf.Session()
sess.run(init)
# Fit the line.
for step in range(201): #iteration을 201번 돌렸다.
sess.run(train)
if step % 20 == 0: #20의 배수가 될 때마다 상태를 확인한다.
print(step, sess.run(loss), sess.run(W), sess.run(b)) #W와 b값이 현재 어디까지 왔는지 확인한다.
# Learns best fit is W: [0.1], b: [0.3]
sess.close()
In [11]:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import argparse
tf.app.flags.FLAGS = tf.python.platform.flags._FlagValues()
tf.app.flags._global_parser = argparse.ArgumentParser()
#이건 사실 아무 상관이 없는 코드다. argument 주는 부분이다.
flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_boolean('fake_data', False, 'If true, uses fake data for unit testing.')
flags.DEFINE_integer('max_steps', 200, 'Number of steps to run trainer.')
flags.DEFINE_float('learning_rate', 0.001, 'Initial learning rate.')
flags.DEFINE_float('dropout', 0.9, 'Keep probability for training dropout.')
flags.DEFINE_string('data_dir', '/home/dockeruser/data', 'Directory for storing data')
flags.DEFINE_string('summaries_dir', '/home/dockeruser/logs', 'Summaries directory')
def train():
# Import data
mnist = input_data.read_data_sets(FLAGS.data_dir,
one_hot=True,
fake_data=FLAGS.fake_data)
sess = tf.InteractiveSession()
# Create a multilayer model.
# Input placehoolders
with tf.name_scope('input'):
x = tf.placeholder(tf.float32, [None, 784], name='x-input') #placeholder 나중에 시작할 때 들어가는 값 변경 가능
y_ = tf.placeholder(tf.float32, [None, 10], name='y-input')
with tf.name_scope('input_reshape'):
image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
tf.image_summary('input', image_shaped_input, 10)
# We can't initialize these variables to 0 - the network will get stuck.
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)
def variable_summaries(var, name):
"""Attach a lot of summaries to a Tensor."""
with tf.name_scope('summaries'):
mean = tf.reduce_mean(var)
tf.scalar_summary('mean/' + name, mean)
with tf.name_scope('stddev'):
stddev = tf.sqrt(tf.reduce_sum(tf.square(var - mean)))
tf.scalar_summary('sttdev/' + name, stddev)
tf.scalar_summary('max/' + name, tf.reduce_max(var))
tf.scalar_summary('min/' + name, tf.reduce_min(var))
tf.histogram_summary(name, var)
def nn_layer(input_tensor, input_dim, output_dim, layer_name, act=tf.nn.relu):
"""Reusable code for making a simple neural net layer.
It does a matrix multiply, bias add, and then uses relu to nonlinearize.
It also sets up name scoping so that the resultant graph is easy to read,
and adds a number of summary ops.
"""
# Adding a name scope ensures logical grouping of the layers in the graph.
with tf.name_scope(layer_name):
# This Variable will hold the state of the weights for the layer
with tf.name_scope('weights'):
weights = weight_variable([input_dim, output_dim])
variable_summaries(weights, layer_name + '/weights')
with tf.name_scope('biases'):
biases = bias_variable([output_dim])
variable_summaries(biases, layer_name + '/biases')
with tf.name_scope('Wx_plus_b'):
preactivate = tf.matmul(input_tensor, weights) + biases
tf.histogram_summary(layer_name + '/pre_activations', preactivate)
activations = act(preactivate, 'activation')
tf.histogram_summary(layer_name + '/activations', activations)
return activations
hidden1 = nn_layer(x, 784, 500, 'layer1')
with tf.name_scope('dropout'):
keep_prob = tf.placeholder(tf.float32)
tf.scalar_summary('dropout_keep_probability', keep_prob)
dropped = tf.nn.dropout(hidden1, keep_prob)
y = nn_layer(dropped, 500, 10, 'layer2', act=tf.nn.softmax)
with tf.name_scope('cross_entropy'):
diff = y_ * tf.log(y)
with tf.name_scope('total'):
cross_entropy = -tf.reduce_mean(diff)
tf.scalar_summary('cross entropy', cross_entropy)
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), tf.argmax(y_, 1))
with tf.name_scope('accuracy'):
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.scalar_summary('accuracy', accuracy)
# Merge all the summaries and write them out to /tmp/mnist_logs (by default)
merged = tf.merge_all_summaries()
train_writer = tf.train.SummaryWriter(FLAGS.summaries_dir + '/train', sess.graph)
test_writer = tf.train.SummaryWriter(FLAGS.summaries_dir + '/test')
tf.initialize_all_variables().run()
# Train the model, and also write summaries.
# Every 10th step, measure test-set accuracy, and write test summaries
# All other steps, run train_step on training data, & add training summaries
def feed_dict(train):
"""Make a TensorFlow feed_dict: maps data onto Tensor placeholders."""
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}
for i in range(FLAGS.max_steps):
if i % 10 == 0: # Record summaries and test-set accuracy
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: # Record train set summaries, and train
if i % 100 == 99: # Record execution stats
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%d' % i)
train_writer.add_summary(summary, i)
print('Adding run metadata for', i)
else: # Record a summary
summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True))
train_writer.add_summary(summary, i)
def main(_):
if tf.gfile.Exists(FLAGS.summaries_dir):
tf.gfile.DeleteRecursively(FLAGS.summaries_dir)
tf.gfile.MakeDirs(FLAGS.summaries_dir)
train()
main("")
TensorFlow는 theano와 달리 모형 내부와 결과를 모니터링 할 수 있는 TensorBoard 라는 웹서버를 제공한다.
TensorBoard 웹서버는 포트 6006을 사용하므로 만약 도커를 사용하는 경우에는 다음과 같이 포트를 열고 실행해야 한다.
docker run --name rpython -it -p 8888:8888 -p 6006:6006 datascienceschool/rpython
TensorBoard를 가동하기 위해서는 콘솔에서 다음과 같이 로그 디렉토리를 설정하여 실행한다.
$ tensorboard --logdir=/home/dockeruser/logs &
위와 같이 실행한 다음에는 다음 주소로 연결하면 TensorBoard 화면을 볼 수 있다.
TensorFlow는 Theano처럼 theano.printing.pydotprint 명령을 지원하지 않는 대신 TensorBoard를 통해 그래프를 보여줄 수 있다.