從鍋爐工到AI專家(7)

說說計劃

不知不覺寫到了第七篇,理一下思路:html

  1. 學會基本的概念,瞭解什麼是什麼不是,當前的位置在哪,要去哪。這是第一篇但願作到的。同時第一篇和第二篇的開始部分,很是謹慎的考慮了非IT專業的讀者。但願藉此溝通技術人員和產品人員,甚至管理和銷售人員。我信服「上下同欲者勝」,因此也很是懼怕由於你們對概念徹底不一樣的理解而影響到團隊的合做。
  2. 從最簡單的部分入手,由概念到代碼,完成技術破冰。這是第2、三篇但願作到的。
  3. 逐步迭代,從簡單概念到複雜概念,從簡單算法到複雜算法,接觸到機器學習現實最經常使用的技術。這是4、5、六篇但願作到的。若是不是專職人工智能研究人員或專業人工智能公司,在這個基礎上開始把機器學習技術導入到本身的常規業務中,已經能夠開始動手了。
  4. 瞭解圍繞在算法周邊的模塊和功能,把算法包裝到程序,瞭解機器學習類程序開發中可能碰到的問題和解決手段。這是本篇想完成的。這篇以後,應當也是最基本的一個完整開發循環能夠開始嘗試了。
  5. 開始逐步瞭解其它領域、其它常見問題所用到的算法及代碼,每一篇都相對獨立,有興趣的能夠讀,沒興趣的也可跳過。這是下一步的連載計劃。目標是爲學習提供更多參考的案例。

從算法到產品

DNN/CNN都是目前機器學習領域最經常使用的算法,學習了這些例子,算是前進了一大步。
可是從產品的觀念看,咱們還有不少事情要作,好比如何從算法成爲一個程序?程序如何調試?技術如何產品化?
下面咱們就說一說這方面的問題。前端

不斷升級的TensorFlow

TensorFlow是一個快速迭代中的產品,欣欣向榮的同時,做爲嚐鮮者,你須要忍受API不斷的變動。
有些朋友的作法是,下載一套就一直使用,輕易不升級。並且你看python的包管理工具pip也是推薦這種模式的,pip不多像brew/apt這些包管理工具同樣每次都提醒你升級新的軟件包。
兩種狀況下,我也會推薦這種方式:python

  1. 關注的重點是業務,目標是把技術導入到業務,自身方向是業務主導而不是技術主導。
  2. 用於實際產品的生產環境。

若是是以學習爲目的,我以爲按期關注官方網站、官方的文檔,根據本身的進度適時更新仍是很重要的。
從個人體驗上,TensorFlow對於版本的更新對API的影響控制的仍是很是好的。其實前面所講解的那些例子,不少來自於0.7.x版本的TensorFlow,基本上不加修改或者不多修改就順利運行在當前1.4.x的TensorFlow中。
這一點可比革命完全的swift強多了,網上有一個很著名的梗:曾經我覺得看一本《Swift 從入門到精通》就能夠了,誰知道我還得看《Swift 2.0 從入門到精通》、《Swift 3.0 從入門到精通》,《Swift 4.0 從入門到精通》。
從這一篇開始說這個問題主要緣由也是,其實TensorFlow在主要的算法部分在各版本保持了很好的一致性。而在周邊的功能部分變化仍是比較大的,好比說XLA、對GPU的支持、整合Keras等特徵。因此我建議開發使用的版本至少是選用TensorFlow 1.x以後的版原本入手。git

用源碼來講話

在第四篇中咱們介紹了一個最簡單的機器學習算法,主體是線性迴歸方程接softmax分類。
源碼來自於老版本的TensorFlow,在最新版本中這個源碼作了修改。增長了程序結構方面的考慮。
沒有在一開始就講解新的版本,你看了下面的源碼就知道了。跟算法無關的部分太多了,實質上提升了入門的門檻。而如今咱們掌握了基本的算法,再回頭來看外圍的結構部分,理解起來就很快了。算法

#!/usr/bin/env python
# -*- coding=UTF-8 -*-

# 注意以上部分官方本來是沒有的,其中直接執行是爲了使用更方便,
# 否則須要用這種方式執行: python mnist_softmax.py
# 字體編碼是由於須要添加中文註釋,不然執行時會報錯

# ==============================================================================
# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""A very simple MNIST classifier.

See extensive documentation at
https://www.tensorflow.org/get_started/mnist/beginners
"""
#下面三行是爲了利用python3中的一些先進特徵而添加,
#實際在本代碼中並無使用這些特徵,所以技術上說是能夠屏蔽的,
#但無論是否使用,每次引入避免由於習慣引發的低級錯誤也是推薦的,
#由於python大多當作腳運行,極可能執行到的時候纔會報錯。
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

#引入命令行參數解析庫
import argparse
import sys

#全部的示例,若是使用官方推薦的方式安裝tensorflow包,
#都應當已經已經安裝在本地,好比mac上路徑是:
#/usr/local/lib/python2.7/site-packages/tensorflow/examples/tutorials/mnist
#因此下面這個是直接從系統包中引用數據準備腳本
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

#這個變量將用來保存命令行參數,首先清空
#在這裏聲明是爲了成爲全局變量,能夠直接在函數中調用
FLAGS = None

#主程序,其實python做爲重要的腳本語言,
#並非必須定義主函數,但顯然這種方式讓程序更規範
def main(_):
  # Import data
  #下面的算法部分基本不須要重複解釋,能夠看之前版本的註釋
  #FLAGS.data_dir是從命令行傳遞來的參數,
  #表明數據目錄
  mnist = input_data.read_data_sets(FLAGS.data_dir)

  # Create the model
  x = tf.placeholder(tf.float32, [None, 784])
  W = tf.Variable(tf.zeros([784, 10]))
  b = tf.Variable(tf.zeros([10]))
  y = tf.matmul(x, W) + b

  # Define loss and optimizer
  y_ = tf.placeholder(tf.int64, [None])

  # The raw formulation of cross-entropy,
  #
  #   tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)),
  #                                 reduction_indices=[1]))
  #
  # can be numerically unstable.
  #
  # So here we use tf.losses.sparse_softmax_cross_entropy on the raw
  # outputs of 'y', and then average across the batch.
  #交叉熵的計算,系統已經有內置的函數,
  #不須要本身計算了,對比原來的源碼能夠看一下,
  #上面英文也寫出了本身計算的缺陷
  #注意參數:labels表示認爲標註的正確值,logits是模型計算出的值
  cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=y)
  train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

  sess = tf.InteractiveSession()
  tf.global_variables_initializer().run()
  # Train
  for _ in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

  # Test trained model
  #注意這裏的比較,y_沒有跟之前版本同樣作argmax,
  #由於y_的值mnist.test.labes已是數字自己,
  #而不是原來表明10個分類的一維數組,
  #這個是由上面read_data_sets函數中one_hot=True參數決定的,
  #沒有這個參數表明直接讀數值數據,實際上在下載的數據包中就是數值
  correct_prediction = tf.equal(tf.argmax(y, 1), y_)
  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
  print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                      y_: mnist.test.labels}))

if __name__ == '__main__':
  #使用引入的argparse庫解析命令行參數
  parser = argparse.ArgumentParser()
  #本腳本只支持一個參數,用於指定測試數據集文件夾
  #默認的文件夾路徑作了修改,指向本地已有的數據集,
  #省得每次啓動時用參數從新指定
  parser.add_argument('--data_dir', type=str, default='MNIST_data',
                      help='Directory for storing input data')
  #解析的參數存入FLAGS,注意這是全局變量
  FLAGS, unparsed = parser.parse_known_args()
  #tf的架構定義,
  #包裝了main主函數,熟悉c語言之類的用戶看起來確定更親切
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

粗看起來源碼比咱們最先看到的複雜了不少是吧?其實有效的代碼並無多少,這裏作幾個解釋:express

  • 最大的變化是全部的代碼放到了main()函數裏面,腳本語言日常是沒有這個必要的。但放到main中會更規範,tensorflow在這方面提供了tf.app.run支持。
  • 全部可變的參數,儘量用命令行參數或者參數文件的方式來指定,而不是每次修改源碼。這是全部編程語言都應當遵循的規範。python中主要是經過argparse擴展包來完成的這方面支持,這個不是tensorflow的功能。
  • 新的交叉熵計算方法和最後驗證階段y_再也不作argmax這兩點比較重要,請仔細看註釋搞清楚

保存訓練的數據

前面的例子咱們體會很深了,隨着算法的複雜度提升,訓練所耗費的時間愈來愈長。這還只是10M左右的數據集和一個小的練習。在大型的系統中,可能須要一個集羣的工做環境作幾周的運算。
在真正投產的時候,實際就只是用訓練的數據配合預測部分的代碼完成工做便可。這就須要把訓練數據保存下來。
TensorFlow的保存、恢復很是容易,首先要生成一個保存器:apache

filesaver = tf.train.Saver()

隨後在要保存數據的位置,把數據保存到文件中:編程

datafile='data/softmax_data.tfdata'
    filesaver.save(sess,datafile)

在須要用到數據的位置,再把數據還原回來,一般產品化的時候,都是利用這個還原來替代大量長時間的運算,而且也保護了真正重要的數據:小程序

datafile='data/softmax_data.tfdata'
    filesaver.restore(sess,datafile)

應用到程序中,程序的主要變更通常是結構上的。或者訓練、預測分紅兩個程序。或者用開關判斷分紅兩個部分。下面就用本篇上面的代碼做爲例子添加上數據保存、恢復的功能:swift

#!/usr/bin/env python
# -*- coding=UTF-8 -*-

# ==============================================================================
# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""A very simple MNIST classifier.

See extensive documentation at
https://www.tensorflow.org/get_started/mnist/beginners
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import sys,os

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

FLAGS = None

 #數據文件保存的位置
datafile='data/softmax_data.tfdata'
 #增長一個函數用於判斷數據文件是否已經存在
def datafile_exist():
    #tf寫出的數據文件實際是分了幾部分,
    #咱們判斷其中的索引文件是否存在
    #假設索引文件存在,就有完整的數據文件
    return os.path.exists(datafile+".index")

def main(_):    
    # Import data
    mnist = input_data.read_data_sets(FLAGS.data_dir)

    # Create the model
    x = tf.placeholder(tf.float32, [None, 784])
    W = tf.Variable(tf.zeros([784, 10]))
    b = tf.Variable(tf.zeros([10]))
    y = tf.matmul(x, W) + b

    # Define loss and optimizer
    y_ = tf.placeholder(tf.int64, [None])

    cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=y)
    train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

    filesaver = tf.train.Saver()
    
    sess = tf.InteractiveSession()
    tf.global_variables_initializer().run()
    
    if FLAGS.train or (not datafile_exist()):
        #若是命令行指定訓練模式,或者數據文件根本不存在則執行訓練流程
        # Train
        for _ in range(1000):
            batch_xs, batch_ys = mnist.train.next_batch(100)
            sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
        print("Training finished, data write to file.")
        #訓練結束,寫出數據
        filesaver.save(sess,datafile)

        # Test trained model
        correct_prediction = tf.equal(tf.argmax(y, 1), y_)
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                      y_: mnist.test.labels}))
    if (not FLAGS.train) and datafile_exist():
        #若是已經存在數據文件,而且沒有要求強行從新訓練,則恢復文件
        print("Restore data...")
        #恢復數據
        filesaver.restore(sess,datafile)
        # Test trained model
        correct_prediction = tf.equal(tf.argmax(y, 1), y_)
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                      y_: mnist.test.labels}))
        
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--data_dir', type=str, default='MNIST_data',
                      help='Directory for storing input data')
    #添加了一個參數,用於強制程序運行在訓練數據狀態
    #使用時,若是添加-t或者--train參數執行,則運行在訓練模式
    #若是沒有參數,則判斷數據文件是否存在,已經存在直接進入測試模式
    #沒有存在,則先訓練,寫出數據集,再恢復數據集作一次測試
    parser.add_argument('-t','--train', action='store_true',default=False,
                      help='Force do train')
    FLAGS, unparsed = parser.parse_known_args()
    tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

JIT XLA

在機器學習領域,學習算法作練習問題不大,實際應用,不管性能多強的電腦你都老是感受慢。
JIT XLA是TensorFlow推出的一項新特徵,就是運行時編譯器。主要功能是把數學模型部分進行運行時編譯,融合可組合的op以提升性能,內存需求也會下降不少。
XLA全稱:Accelerated Linear Algebra,也就是加速線性代數。
使用XLA很是容易,只要在Session初始化的時候添加以下代碼:

config = tf.ConfigProto()
jit_level = tf.OptimizerOptions.ON_1
config.graph_options.optimizer_options.global_jit_level = jit_level
with tf.Session(config=config) as sess:
   ...

Session的運行就會在XLA方式之下。實際上XLA的運行須要CPU或者GPU的支持。在個人老電腦上,雖然硬件不支持XLA的加速,但內存的需求也下降了大概一倍左右,可說效果明顯。

TensorBoard

不一樣於傳統程序的DEBUG,機器學習類的程序,在程序邏輯上大多不會犯什麼大錯誤,畢竟整個流程很簡單。
大多的過程其實是在「調優」而不是「調試」。在調優中須要關注到的,主要是數據方面的問題。而數據無論原來是什麼格式,進入機器學習系統後,每每都已經變成了抽象的矩陣。因此整個調優過程每每充滿着痛苦和無力感。
TensorBoard是一個官方出品的優秀工具,能夠經過讀取事件文件的形式把數據圖形化的顯示出來,從而大幅下降調優難度。
使用TensorBoard自己很簡單,是一個B/S結構的程序,在瀏覽器中就能夠操做全部功能。比較麻煩的是生成事件文件,須要在程序代碼中嵌入不少用於監控的語句,用於輸出數據留待tensorboard分析。
官方有一個寫的很好的樣例:mnist_with_summaries.py,可是這個源碼看上去偏於複雜。咱們仍是以上面的softmax分類識別的源碼爲例,對此作一個介紹。有了這個基礎,官方的樣例留給讀者在讀完這裏的內容以後,本身嘗試去分析。
生成事件數據文件只須要兩行語句:

#在Session創建後執行:
    train_writer = tf.summary.FileWriter('logs/train', sess.graph)
 #在Session關閉前執行:
    train_writer.close()

程序執行完成後,將在./logs/train/目錄下生成事件數據文件。隨後能夠用tensorboard來分析和顯示數據文件:

> tensorboard --logdir=logs/
TensorBoard 0.4.0rc3 at http://127.0.0.1:6006 (Press CTRL+C to quit)

命令中指定數據文件路徑只須要指定到上一級便可,由於tensorbaord支持多組數據文件對比顯示,這個咱們後面再介紹。
查看圖形化的分析結果可使用瀏覽器訪問:http://127.0.0.1:6006

可以顯示出來完整的數學模型,只是圖的可讀性感受仍是比較差,大多節點要思考一下才能明白表明的是什麼。並且除了圖基本也沒有提供其它參數,難以作更深刻的分析。
咱們還能夠繼續定義一些輸出來改善數學模型的顯示:
咱們能夠監控常量的狀態:

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
 #第一個參數是指定顯示時圖表的名字,第二個參數是監控的值
tf.summary.scalar('accuracy', accuracy)

能夠監控變量的狀態:

cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=y)
 #第一個參數是指定顯示圖表的名字,第二個參數是監控的值
tf.summary.histogram('cost', cross_entropy)

能夠對節點命名以便更直觀的看到圖形化後模型的結構:

with tf.name_scope("pic_samples"):
    x = tf.placeholder(tf.float32, [None, 784])
with tf.name_scope("weight"):
    W = tf.Variable(tf.zeros([784, 10]))

注意:with tf.name_scope("pic_samples"):這種形式,其實也是TensorFlow中的變量做用域的定義。
由於機器學習中的變量通常都佔用了比較大的空間,咱們確定但願儘量重複使用變量,因此若是在大系統中,會存在不少變量。這時候就須要有做用域在對變量作出管理。這方面的功能,初學確定用到不到,用到的時候看看手冊就夠了,這裏很少說。
咱們既然監控了變量、常量,必然須要tensorflow的運算才能獲得這些值,雖然這些值只是輸出到事件文件中的。因此記住一點,只要使用了任何的summary操做,咱們就須要在FileWriter定義的同時,定義一個運算操做,並在以後在Session.run中運算這個操做,隨後把返回的結果添加到事件文件中去,這樣才能真正把監控的值輸出到事件文件中去:

#注意這一行應當在全部須要監控的變量、常量、圖片等都設置好後,最後運行
    #此語句以後定義的觀察器將都不會被輸出到事件文件。也就沒法被查看了
    merged = tf.summary.merge_all()
    train_writer = tf.summary.FileWriter('logs/train', sess.graph)
    ...
    summary,_ = sess.run([merged,train_step], feed_dict={x: batch_xs, y_: batch_ys})
    train_writer.add_summary(summary, i)

由於定義了placeholder,因此每次sess.run()都是須要喂數據的。即使咱們定義的merged這個操做並不須要數據。因此若是單獨運行這個操做,附帶喂入數據確定是很不經濟。所以一般的方法,都是跟主要的操做一塊兒運行。同時運行多個操做,而且同時獲得多個返回值的語法既是python的語言特點,也是TensorFlow支持的功能。
如今重複運行程序,獲得新的事件文件,再次啓動tensorboard而後用瀏覽器查看,咱們能夠看到更多的內容了:

請注意看兩個命名的節點,都已經有更友好的節點名了。

咱們監控的變量,能清晰的看到代價函數的值逐漸變小,表示逐漸趨於收斂。(請忽略這個粗糙示例中的抖動,這裏僅是爲了示例可視化的效果。)
其它監控的各類值基本相似,這裏就不一一貼出圖片了,建議你把源碼執行一下而後看看效果。

TensorBoard功能很是強大,不少功能超乎咱們的想象。前面咱們介紹過一個小程序,本身把輸入的數據圖形化,而後寫出到一個圖片文件。
這樣的功能,若是使用TensorBoard將更加容易,好比下面代碼監控輸入矩陣及計算的權重值,並以圖片的形式顯示出來:

x = tf.placeholder(tf.float32, [None, 784])
image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
tf.summary.image('input_images', image_shaped_input, 10)
...
W = tf.Variable(tf.zeros([784, 10]))
Wt=tf.transpose(W)  #由於權重值跟圖片數據定義不一樣,要先轉置一下,再轉成圖片
image_shaped_weight = tf.reshape(Wt, [-1, 28, 28, 1])
tf.summary.image('weight_images', image_shaped_weight, 10)

最終生成圖片的樣子咱們前面的內容中見過,這裏也不貼圖了。
其中權重部分,由於不是[None,784]這樣的形式,而是[784,10],因此要先使用tf.transpose轉換成[10,784]的形式,再reshape成28x28的圖片,最後才能以圖片的方式顯示出來。

這一節的最後部分,把上面示例的完整代碼列出來,以供你參考實驗,由於上面講解都很詳細了,例子中就沒有加過多的註釋。請注意這個例子由於經歷了屢次的補丁和無邏輯意義的做用域定義,程序結構上比較混亂,你們在正式的項目中可千萬不要模仿。

#!/usr/bin/env python
# -*- coding=UTF-8 -*-

# ==============================================================================
# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""A very simple MNIST classifier.

See extensive documentation at
https://www.tensorflow.org/get_started/mnist/beginners
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import sys,os

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

FLAGS = None

datafile='data/softmax_data.tfdata'
def datafile_exist():
    return os.path.exists(datafile+".index")

def main(_):    
    # Import data
    mnist = input_data.read_data_sets(FLAGS.data_dir)

    # Create the model
    with tf.name_scope("pic_samples"):
        x = tf.placeholder(tf.float32, [None, 784])
        image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
        tf.summary.image('input_images', image_shaped_input, 10)
    with tf.name_scope("weight"):
        W = tf.Variable(tf.zeros([784, 10]))
        Wt=tf.transpose(W)
        image_shaped_weight = tf.reshape(Wt, [-1, 28, 28, 1])
        tf.summary.image('weight_images', image_shaped_weight, 10)
    b = tf.Variable(tf.zeros([10]))
    tf.summary.histogram('bias', b)
    y = tf.matmul(x, W) + b

    # Define loss and optimizer
    y_ = tf.placeholder(tf.int64, [None])

    cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=y)
    tf.summary.histogram('cost', cross_entropy)
    train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

    filesaver = tf.train.Saver()
    
    
    sess = tf.InteractiveSession()
    tf.global_variables_initializer().run()
    
    correct_prediction = tf.equal(tf.argmax(y, 1), y_)
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.summary.scalar('accuracy', accuracy)

    merged = tf.summary.merge_all()
    train_writer = tf.summary.FileWriter('logs/train', sess.graph)

    if FLAGS.train or (not datafile_exist()):
        # Train
        for i in range(1000):
            batch_xs, batch_ys = mnist.train.next_batch(100)
            sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
            summary,_ = sess.run([merged,train_step], feed_dict={x: batch_xs, y_: batch_ys})
            train_writer.add_summary(summary, i)
            # Test trained model
            if (i % 100 == 0):
                summary1,ac = sess.run([merged,accuracy], feed_dict={x: mnist.test.images,
                                              y_: mnist.test.labels})
                train_writer.add_summary(summary1,i)
        print("Training finished, data write to file.")
        
        filesaver.save(sess,datafile)
        print(ac)   

        train_writer.close()
    if (not FLAGS.train) and datafile_exist():
        print("Restore data...")
        filesaver.restore(sess,datafile)
        # Test trained model
        correct_prediction = tf.equal(tf.argmax(y, 1), y_)
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        
        print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                      y_: mnist.test.labels}))

        
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--data_dir', type=str, default='MNIST_data',
                      help='Directory for storing input data')
    parser.add_argument('-t','--train', action='store_true',default=False,
                      help='Force do train')
    FLAGS, unparsed = parser.parse_known_args()
    tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

注意程序運行的時候要使用-t參數,由於圖示部分的代碼主要加在了訓練環節。
讀完了這個程序,再去讀官方的示例應當容易不少,很是建議你以官方程序爲範例仔細閱讀。

團隊合做

做爲實踐環節的最後一部分,介紹一下一般機器學習項目的通常工做流程和團隊。

  • 幾乎大多數的項目都是從肯定需求入手的。最初的需求可能來自於內、外部客戶,若是能明確到文檔化這就是最幸福的開始了。不過還有不少不是這樣,不少公司可能只是爲了趕時髦創建了一個小團隊開始人工智能的嘗試。這時候每每還不知道要作什麼,許多也只能模仿成熟業界流行的應用入手。或者從一大堆漫無目標、或者不屬於人工智能甚至當前技術還沒法作到的需求中去梳理、尋找最基本的需求。
  • 隨後通常就須要算法的專家上場。不過大多數公司在開始都沒有這樣的人才,所以更多的多是程序人員代替,或者太獨特的項目就須要外援專家。這一環節通常是根據需求,來肯定初步的數學模型,若是是比較生僻的項目,通常須要進行大量的數學實驗最後肯定幾個可能的模型來進行規模化測試。在正規的IT公司通常是聘請比較資深的數學專家配合技術人員完成這部分工做。
  • 接下來會根據數學模型的要求,肯定須要收集的數據,並預估數據量。大多數狀況都須要組建數據小組,有專門技術人員帶領,編寫數據收集的代碼,開始收集數據。數據的預處理和標註一般能用程序解決一部分,但最終通常仍是要人工進行標註,最終彙總成規範化的數據集。
  • 跟數據組並行,會有程序人員把數學的算法代碼化。若是是圖像識別等比較成熟的例子固然容易了不少,通常用成熟的框架就可以工做。但無論哪一種狀況,通常最初的模型都須要監控儘量多的指標,以供效果評估和調優。
  • 最後實現的訓練代碼會在預先挑選的小數據集上工做,對算法進行調優和最終算法的選擇。這部分工做通常須要數學的專家和程序人員配合一塊兒完成。因此這時候程序人員要多聽取算法人員的意見,挑選更能說明算法問題的監控環節。調優完成後通常能夠去掉大部分耗時的監視代碼,只留下算法核心的部分。
  • 最終完成的機器學習內核部分,會一邊進行正式的訓練進程,一邊由前端人員完成產品化和用戶體驗優化的工做,最終達成一個可輸出的產品。

稍微成熟的公司,通常都已經有本身規範的研發流程和管理方式,此處列出的流程僅供參考。其實主要是強調算法專家的角色和數據收集的工做。這兩組人員在通常的項目中是沒有或者位置並非很重要的。可是在機器學習項目中,每每是核心部分。在圖像識別等監督學習領域,數據收集、標註成本每每佔了最主要的預算。
(待續...)

引文及參考

TensorBoard:可視化學習
tensorflow裏面name_scope, variable_scope等如何理解?
python argparse用法總結
谷歌官博詳解XLA:可在保留TensorFlow靈活性的同時提高效率
完整機器學習項目的工做流程

另請參考官方示例源碼:

mnist_softmax_xla.py
mnist_deep.py
mnist_with_summaries.py
相關文章
相關標籤/搜索