在訓練模型的過程中,經(jīng)常需要調(diào)試其中的參數(shù)秦爆,這就需要可視化。TensorFlow的可視化由TensorBoard完成憔披,由TensorBoard顯示已存儲的Log信息等限。代碼與多層感知機的MNIST相同,只是添加一些Log信息的存儲芬膝,用于展示望门。
本文源碼的GitHub地址,位于tensor_board
文件夾锰霜。
執(zhí)行TensorBoard的命令:
tensorboard --logdir=/tmp/tensorflow/mnist/logs/mnist_with_summaries
顯示網(wǎng)站在Log信息中筹误,如http://0.0.0.0:6006
。
Starting TensorBoard 47 at http://0.0.0.0:6006
(Press CTRL+C to quit)
WARNING:tensorflow:path ../external/data/plugin/text/runs not found, sending 404
WARNING:tensorflow:path ../external/data/plugin/text/runs not found, sending 404
WARNING:tensorflow:path ../external/data/plugin/text/runs not found, sending 404
WARNING:tensorflow:path ../external/data/plugin/text/runs not found, sending 404
顯示日志
設(shè)置參數(shù)锈遥,使用argparse.ArgumentParser()創(chuàng)建參數(shù)解析器纫事,nargs='?'
+ const=True
+ default=False
表示:當使用--fake_data
時勘畔,參數(shù)的fake_data
的值是True(const)所灸;當未使用--fake_data
時,參數(shù)的fake_data
的值是False(default)炫七;或者指定--fake_data True(Flase)
爬立,根據(jù)設(shè)置的參數(shù)賦值。type是參數(shù)類型万哪,help是幫助信息侠驯。獲取os.getenv('TEST_TMPDIR', '/tmp')
臨時文件夾,默認是/tmp
奕巍,在Mac中是根目錄下的隱藏文件夾吟策。os.path.join
將文件夾的路徑拼接在一起。
parser = argparse.ArgumentParser()
parser.add_argument('--fake_data', nargs='?', const=True, type=bool, default=False,
help='If true, uses fake data for unit testing.')
parser.add_argument('--max_steps', type=int, default=1000, # 最大步數(shù) 1000
help='Number of steps to run trainer.')
parser.add_argument('--learning_rate', type=float, default=0.001, # 學習率 0.001
help='Initial learning rate')
parser.add_argument('--dropout', type=float, default=0.9, # Dropout的保留率 0.9
help='Keep probability for training dropout.')
parser.add_argument('--data_dir', type=str, # 數(shù)據(jù)目錄
default=os.path.join(os.getenv('TEST_TMPDIR', '/tmp'), 'tensorflow/mnist/input_data'),
help='Directory for storing input data')
parser.add_argument('--log_dir', type=str, # Log目錄
default=os.path.join(os.getenv('TEST_TMPDIR', '/tmp'),
'tensorflow/mnist/logs/mnist_with_summaries'),
help='Summaries log directory')
在外部聲明FLAGS變量的止,將參數(shù)放入FLAGS中檩坚,使用tf.app.run()執(zhí)行TensorFlow的腳本,main是入口方法,argv是參數(shù)匾委。
FLAGS = None # 外部聲明
FLAGS, unparsed = parser.parse_known_args()
tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
調(diào)用tf.gfile文件處理庫拖叙,如果日志文件夾存在,則刪除赂乐,并重建薯鳍,然后執(zhí)行核心方法train()。
def main(_):
if tf.gfile.Exists(FLAGS.log_dir):
tf.gfile.DeleteRecursively(FLAGS.log_dir)
tf.gfile.MakeDirs(FLAGS.log_dir)
train()
加載數(shù)據(jù)挨措,使用MNIST數(shù)據(jù)源挖滤,創(chuàng)建可交互的Session,即tf.InteractiveSession()运嗜,張量可以自己執(zhí)行操作壶辜。
mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True, fake_data=FLAGS.fake_data) # 加載數(shù)據(jù)
sess = tf.InteractiveSession()
需要輸入的PlaceHolder,指定命名空間input担租,在繪制流程圖的時候使用砸民;將輸入數(shù)據(jù)轉(zhuǎn)換為圖像,并且保持在input_reshape/input
文件夾中奋救,圖片命名規(guī)則為input_reshape/input/image/#
岭参。
# Input placeholders
with tf.name_scope('input'): # 指定命名空間
x = tf.placeholder(tf.float32, [None, 784], name='x-input')
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.summary.image('input', image_shaped_input, 10) # 10表示只存儲10張
將創(chuàng)建權(quán)重和偏移變量的方法設(shè)置為方法。
# We can't initialize these variables to 0 - the network will get stuck.
def weight_variable(shape): # 權(quán)重
"""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)
變量信息的存儲方法尝艘,存儲為標量(tf.summary.scalar)演侯,或者直方圖(tf.summary.histogram)。
def variable_summaries(var): #
"""Attach a lot of summaries to a Tensor (for TensorBoard visualization)."""
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) # 直方圖
偏移biases的初始值均為0.1背亥,通過學習逐漸變化秒际。
偏移biases的初始值均為0.1,每一次迭代使得分布越來越平緩狡汉。
神經(jīng)網(wǎng)絡(luò)的層次娄徊,使用y=wx+b
的線性回歸,并且記錄下參數(shù)W和b的信息盾戴,還有使用激活函數(shù)前后的數(shù)據(jù)對比情況寄锐。
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)
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
由于第一層使用ReLU(校正線性單元,Rectified Linear Unit)尖啡,將小于0的值橄仆,全部抑制為0。
第一層是ReLU激活函數(shù)衅斩,第二次未使用激活函數(shù)(tf.identity)盆顾,并且將第一層的神經(jīng)元dropout,訓練小于1畏梆,測試等于1您宪。
hidden1 = 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) # 執(zhí)行dropout參數(shù)
# Do not apply softmax activation yet, see below.
y = nn_layer(dropped, 500, 10, 'layer2', act=tf.identity) # 未使用激活函數(shù)
損失函數(shù)設(shè)置為交叉熵惫搏,使用AdamOptimizer優(yōu)化損失函數(shù),并且記錄損失函數(shù)的值蚕涤,逐漸收斂筐赔。
with tf.name_scope('cross_entropy'):
diff = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)
with tf.name_scope('total'):
cross_entropy = tf.reduce_mean(diff)
tf.summary.scalar('cross_entropy', cross_entropy)
with tf.name_scope('train'):
train_step = tf.train.AdamOptimizer(FLAGS.learning_rate).minimize(
cross_entropy)
準確率,比較正確的個數(shù)揖铜,求平均茴丰,并使用標量記錄(tf.summary.scalar)。
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.summary.scalar('accuracy', accuracy)
將每次迭代的summary合并成一個文件天吓,并且創(chuàng)建兩個writer贿肩,一個用于訓練,一個用于測試龄寞,同時訓練的存儲圖信息汰规。
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')
計算圖信息的節(jié)點,就是最頂層的name_scope
物邑,點擊之后就是內(nèi)部的name_scope
溜哮。
設(shè)置feed數(shù)據(jù)的接口,訓練使用批次數(shù)據(jù)色解,每次100個茂嗓,dropout是參數(shù);測試使用全部的測試數(shù)據(jù)科阎,dropout是1述吸,保留全部信息。
def feed_dict(train):
"""Make a TensorFlow feed_dict: maps data onto Tensor placeholders."""
# 訓練與測試的dropout不同
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}
初始化變量锣笨,開始迭代執(zhí)行蝌矛。每隔10次,使用測試集驗證一次错英,sess.run()的輸入入撒,merged合并的Log信息,accuracy計算圖走趋,feed數(shù)據(jù)衅金,將信息寫入test_writer
噪伊。每隔99步簿煌,將運行時間與內(nèi)存信息,存入Log中鉴吹,其余步驟正常秩序姨伟,添加存儲信息。
tf.global_variables_initializer().run()
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)) # feed測試數(shù)據(jù)
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訓練數(shù)據(jù)
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: # Record a summary
summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True)) # feed訓練數(shù)據(jù)
train_writer.add_summary(summary, i)
最后注意關(guān)閉Log文件寫入器
train_writer.close()
test_writer.close()
內(nèi)存與計算時間
在安裝TensorFlow后豆励,TensorBoard即可使用夺荒,但是在mac系統(tǒng)中瞒渠,會報錯,由于six包的版本過低導致技扼。
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six.py", line 566, in with_metaclass
return meta("NewBase", bases, {})
File "/Library/Python/2.7/site-packages/tensorflow/python/platform/benchmark.py", line 116, in __new__
if not newclass.is_abstract():
AttributeError: type object 'NewBase' has no attribute 'is_abstract'
在Mac系統(tǒng)中伍玖,含有多個Python源,我們要確定shell使用的源
? ~ python
Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import six
>>> six.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six.pyc'
升級指定位置的six包
sudo pip install six --upgrade --target="/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/"
當然剿吻,最簡單的就是直接使用虛擬環(huán)境的TensorBoard窍箍,庫的版本可控。
OK, that's all! Enjoy it!