標籤:

TensorFlow應用實戰 | TensorFlow基礎知識

查看更多的專業文章、課程信息、產品信息,請移步至:

「人工智慧LeadAI」公眾號;

官網:www.leadai.org.

作者:天涯明月笙

原文鏈接:jianshu.com/p/945dfcda4

挺長的~超出估計值了~預計閱讀時間20分鐘。

從helloworld開始

mkdir 1.helloworldcd 1.helloworldvim helloworld.py

代碼:

# -*- coding: UTF-8 -*-# 引入 TensorFlow 庫import tensorflow as tf# 設置了gpu加速提示信息太多了,設置日誌等級屏蔽一些import osos.environ[TF_CPP_MIN_LOG_LEVEL]=3# 創建一個常量 Operation (操作)hw = tf.constant("Hello World! Mtianyan love TensorFlow!")# 啟動一個 TensorFlow 的 Session (會話)sess = tf.Session()# 運行 Graph (計算圖)print (sess.run(hw))# 關閉 Session(會話)sess.close()

TensorFlow的編程模式

mark

命令式編程

容易理解,命令語句基本沒優化: C,java, C++, Python

mark

符號式編程

涉及較多的嵌入和優化,運行速度有同比提升

mark

計算流圖。c和d是可以共用內存的。有一定優化。

# -*- coding: UTF-8 -*-# 引入 TensorFlow 庫import tensorflow as tf# 設置了gpu加速提示信息太多了,設置日誌等級屏蔽一些import osos.environ[TF_CPP_MIN_LOG_LEVEL]=3a = tf.constant(2)b = tf.constant(3)c = tf.multiply(a,b)d = tf.add(c, 1)with tf.Session() as sess: print (sess.run(d))

mark

TensorFlow的計算流圖,符號式編程的範式。有節點有邊,邊是計算結果在節點中流動。

TensorFlow的基礎結構

Tensor 在 計算流圖中流動(flow)

mark

這張圖簡化一下,取其中一部分。

mark

邊就是Tensor(張量)在流動

mark

節點就是一個operation操作,數學計算或後面的激勵函數等的操作。

節點的輸入與輸出都是Tensor張量。

邊和節點共同構成了Graph 也就是數據流圖。

數據流圖會被放進session會話中進行運行。會話可以在不同的設備上去運行,比如cpu和GPU。

圖的基本構成

數據流圖:

  • Tensor (張量) 邊里流動的數據
  • Operation(操作)

mark

Tensor 會作為operation的輸入,operation輸出的依然是Tensor。

TensorFlow的基礎模型

數據模型 - Tensor(張量)

張量是TensorFlow中最重要的結構。

計算模型 - Graph(圖)

運行模型 - Session(會話)

mark

圖與會話

mark

計算流圖,也是TensorFlow的基本架構,表明了圖正在運行的狀態。

黑色的線不斷流動, 其中流動的就是Tensor,一個一個的節點就是它的操作。

數據流圖的結構

mark

mark

燒杯中進行的化學反應就是操作,其中流動的就是張量。

mark

什麼是會話

火狐打開一個瀏覽器就是打開了一個會話。

mark

使用x,y,z三行構建了一個圖,構建了一個實驗儀器。

TensorFlow使用了客戶端和服務端的經典架構。

客戶端是我們編寫的程序,程序請求服務端(C++)的運行時。

創建一個會話,使用會話中的run方法。

session的作用

靜態的圖。數據流圖。如何讓某一部分動起來?需要點燃酒精燈。

mark

要讓這一部分運行起來。就得run

mark

TensorFlow程序的流程

  1. 定義演算法的計算圖(Graph)的結構 靜態
  2. 使用會話(Session) 執行計算

Python常用庫numpy

TensorFlow和numpy有一定聯繫,有很多類似的概念和api

介紹Tensor時,有很多api名稱很相似

numpy官網,科學計算。n階數組對象。

numpy速度是非常快的,比原生快很多。

因為numpy的許多函數是用c語言來實現的。還使用了一些優化,甚至比你自己用c實現快很多.

scipy 是一個開源軟體。Matplotlib。pandas。jupyter notebook

numpy的操作對象是一個多維的數組。類似Tensor

ndarray ndim shape size dtype(同一類型元素).

import numpy as npvector = np.array([1,2,3])vector.shapevector.sizevector.ndimtype(vector)# 創建二維數組(矩陣)matrix = np.array([[1, 2],[3, 4]])matrix.shapematrix.sizematrix.ndimtype(matrix)

對於矩陣進行轉置

one = np.arange(12)# 0 - 11one.reshape((3,4))two = one.reshape((3,4))two.shapetwo.sizetwo.ndim

什麼是Tensor(張量)

不斷流動的東西就是張量。節點就是operation計算:

mark

TensorFlow里的數據都是Tensor,所以它可以說是一個張量的流圖

mark

張量的維度(秩):rank/order dimension

mark

維度是0的話,是一個標量(Scalar)

vector & Matrixnumpy中的基礎要素就是array,和Tensor 差不多的一種表述。import numpy as npzeros = np.zeros((3,4))zerosones = np.ones((5,6))ones# 對角矩陣: 必須是一個方陣.對角線是1,其他都是0的方陣ident = np.eye(4)

mark

一個張量裡面的元素類型都是一樣的。

mark

Tensor的屬性

因為一個tensor 只能包含一種數據類型。dtype

TensorFlow.datatype list

tensorflow.org/api_docs

mark

TensorFlow數據類型有很多。

其他屬性:

tensorflow.org/api_docs

可以通過搜索Tensor 查看到它的其他屬性。

A Tensor是一個輸出的符號句柄 Operation。它不包含該操作輸出的值,而是提供了在TensorFlow中計算這些值的方法tf.Session。

device,在哪個設備上被計算出來的。

Graph 這個Tensor 所屬的一個圖;name 是我們可以給張量起的名字;op 是產生這個Tensor 的一個操作。

幾種Tensor

  • Constant
  • Variable
  • Placeholder
  • SparseTensor

constant(常量)

值不能改變的一種Tensor

但取這個Tensor值有可能還是會變

定義在tf.constant類

tf.constant( value, dtype=None, shape=None, name=Const, verify_shape=False)

數值:標量,向量,矩陣;verify_shape 驗證形狀

官網例子:

# Constant 1-D Tensor populated with value list.tensor = tf.constant([1, 2, 3, 4, 5, 6, 7]) => [1 2 3 4 5 6 7]# Constant 2-D tensor populated with scalar value -1.tensor = tf.constant(-1.0, shape=[2, 3]) => [[-1. -1. -1.] [-1. -1. -1.]]

我們的代碼

const = tf.constant(3)const # 輸出const:0 shape=() dtype=int32

run之後才能得到具體的數。與普通的變數常量是不一樣的。

variable變數

值可以改變的一種tensor

定義在tf.Variable. 注意這個v是大寫的,和constant是不一樣的。

屬性: initial_value

__init__( initial_value=None, trainable=True, collections=None, validate_shape=True, caching_device=None, name=None, variable_def=None, dtype=None, expected_shape=None, import_scope=None, constraint=None)

定義一個變數的張量。

var = tf.Variable(3)

var

# 不會輸出真實值,只會輸出數據類型等特徵量

我們可以在創建變數的時候指定好它的數據類型

var1 = tf.Variable(4, dtype=tf.int64)

var1# 默認系統給的變數名會自動遞增

PlaceHolder(佔位符)

先佔住一個固定的位置,等著你之後往裡面添加值的一種Tensor

mark

例子: 圖書館佔座

tf.placeholder

tensorflow.org/api_docs

tf.placeholder( dtype, shape=None, name=None)

屬性少。沒有值。形狀。賦值的機制用到了python中字典的機制

x = tf.placeholder(tf.float32, shape=(1024, 1024))y = tf.matmul(x, x)with tf.Session() as sess:print(sess.run(y)) # ERROR: will fail because x was not fed.rand_array = np.random.rand(1024, 1024)print(sess.run(y, feed_dict={x: rand_array})) # Will succeed.

feed_dict 真正運行時才通過feed_dict關鍵字以字典形式向裡面傳值。

sparse Tensor(稀疏張量)

一種"稀疏"的Tensor,類似線性代數裡面的稀疏矩陣的概念

tf.SparseTensor

在矩陣中,若數值為0的元素數目遠遠多於非0元素的數目,並且非0元素分布沒有規律時,則稱該矩陣為稀疏矩陣;與之相反,若非0元素數目佔大多數時,則稱該矩陣為稠密矩陣。 定義非零元素的總數比上矩陣所有元素的總數為矩陣的稠密度。

定義稀疏矩陣,只需要定義非0的數,其他為0的數會自動的填充。

SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4])

指定坐標,對應坐標的值,以及它的形狀。

[[1, 0, 0, 0]

[0, 0, 2, 0]

[0, 0, 0, 0]]

Tensor表示法

Tensor("MUL:0", shape=(),dtype=float32)

類型 : tf.Variable

名字: MUL

0表示索引

你是operation產生的第幾個張量

shape 就是形狀 dtype 數據類型

定義一個有名字的Variable

named_var = tf.Variable([5,6], name="named_var")

named_var

自動生成的會以數據類型為名字。

圖和會話原理及案例

Graph(圖)的形象比喻

mark

每個節點可以想像成一個儀器,在對我們的實驗品進行操作。

mark

儀器中被操作,以及在各個儀器中流動的是tensor。

TensorFlow程序的流程

  1. 定義演算法的計算圖(Graph)結構

把實驗的器材等組裝好

  1. 使用會話(Session)執行圖的一部分(計算)

開始點燃酒精燈等操作

Graph tf.Graph

tensorflow.org/api_docs

如果你沒有顯式的去創建圖,它其實已經幫你註冊了一個默認的圖。

默認Graph總是已註冊,並可通過調用訪問 tf.get_default_graph。

mark

沒有輸出值是因為我們還沒有用會話運行這一部分。

創建sess對象

我們可以看一下Session這個類

tensorflow.org/api_docs

一個Session對象封裝了Operation 執行對象的環境,並對Tensor對象進行評估。例如:

OPeration是圖上的節點,輸入張量,產生張量。

mark

run( fetches, feed_dict=None, options=None, run_metadata=None)

mark

run返回的結果就是一個張量。

>>> tf.get_default_graph()<tensorflow.python.framework.ops.Graph object at 0x000001EC0C5EE160>>>> if c.graph is tf.get_default_graph():... print("The Graph of c is the default graph")...

The Graph of c is the default graph

可以看到c所屬的圖確實是默認圖。

程序小例子

# -*- coding: UTF-8 -*-# 引入tensorflowimport tensorflow as tf# 設置了gpu加速提示信息太多了,設置日誌等級屏蔽一些import osos.environ[TF_CPP_MIN_LOG_LEVEL]=2# 創建兩個常量 Tensor.第一個為1行2列,第二個為二行一列。# 也就是矩陣乘法必須滿足,列等於行。const1 = tf.constant([[2, 2]])const2 = tf.constant([[4], [4]])# 矩陣乘法運算matrix mul tf.add()multiple = tf.matmul(const1, const2)# 嘗試用print輸出multiple的值, 不會輸出真實值。因為沒運行print(multiple)# 創建了 Session (會話) 對象sess = tf.Session()# 用Session的run方法來實際運行multiple這個矩陣乘法操作# 並把操作執行的結果賦值給 resultresult = sess.run(multiple)# 用print列印矩陣乘法的結果print(result)if const1.graph is tf.get_default_graph(): print("const1所在的圖(Graph)是當前上下文默認的圖")# 關閉已用完的Session(會話)sess.close()# 第二種方法來創建和關閉Session,更安全with tf.Session() as sess: result2 = sess.run(multiple) print("Multiple的結果是 %s " % result2)

mark

用顯示的close和with上下文管理器兩種方式實現.

可視化利器Tensorboard

展示構建的計算圖和節點等信息在瀏覽器里。

人工智慧的黑盒

mark

mark

輸入手寫4等相關4的圖片。輸出這是4

mark

輸入狗狗圖片,輸出可能是狗狗

mark

輸入歷史的股票曲線,預測出未來這一年的市值。

Tensorboard的作用

mark

打開黑盒,照亮。方便調參等操作。

節點和操作。

上層節點可以打開,看到下層節點。

之後可能會加入debug功能,目前還只是一種展示。

用TensorFlow保存圖的信息到日誌中

# 第一個參數為指定的保存路徑,第二個參數為要保存的圖

tf.summary.FileWriter("日誌保存路徑", sess.graph)

tensorflow.org/api_docs

注意我們這裡的summary是小寫的summary。

張量摘要用於導出關於模型的信息。

官網的develop 中的get Started 裡面有關於TensorBoard的信息。

開源的github源代碼。

使用Tensorboard讀取並展示日誌

tensorboard --logdir=日誌所在路徑

Tensorflow安裝之後,會默認安裝有TensorBoard

summary(總結,概覽)

上一節的代碼中自行添加一行

# 第一個參數為指定的保存路徑,第二個參數為要保存的圖

tf.summary.FileWriter("./", sess.graph)

  • 用於導出關於模型的精簡信息的方法
  • 可以使用TensorBoard等工具訪問這些信息

打開瀏覽器會有一系列菜單。

mark

6006埠打開。

mark

菜單分別是標量,圖片,音頻,圖。

mark

可以點擊節點,如果有加號打開節點裡面內容。節點含義會列在右邊。

distributions 訓練的一些分布。histograms 直方圖。

對於數字進行分類。

可以分類進行顏色加顏色。

nameEspace(命名空間)

我們剛才點擊過的雙擊圖形,節點裡面又有子節點。很像一些編程語言(如 c++) 的namespace, 包含嵌套的關係。卷積神經網路下的偏差,adam方法(一種優化方法)。

mark

符號的含義

mark

一般的操作不會改變輸入的Tensor,如果是一條黃線,表示操作節點可以改變輸入的Tensor。

使用Tensorboard展示圖代碼示例

# -*- coding: UTF-8 -*-# 引入tensorflowimport tensorflow as tf# 設置了gpu加速提示信息太多了,設置日誌等級屏蔽一些import osos.environ[TF_CPP_MIN_LOG_LEVEL]=3# 構造圖(Graph)的結構# 用一個線性方程的例子 y = W * x + b# 梯度下降法求w和bW = tf.Variable(2.0, dtype=tf.float32, name="Weight") # 權重b = tf.Variable(1.0, dtype=tf.float32, name="Bias") # 偏差x = tf.placeholder(dtype=tf.float32, name="Input") # 輸入with tf.name_scope("Output"): # 輸出的命名空間 y = W * x + b # 輸出#const = tf.constant(2.0) # 常量,不需要初始化# 定義保存日誌的路徑path = "./log"# 創建用於初始化所有變數 (Variable) 的操作init = tf.global_variables_initializer()# 創建Session(會話)with tf.Session() as sess: sess.run(init) # 初始化變數 # 寫入日誌文件 writer = tf.summary.FileWriter(path, sess.graph) # 因為x是一個placeholder,需要進行值的填充 result = sess.run(y, {x: 3.0}) print("y = %s" % result) # 列印 y = W * x + b 的值,就是 7

使用tensorBoard

tensorboard --logdir=./log

6006類似於GOOGle的goog

不像之前的例子有很多菜單,只打開了一個graph菜單。

之後的圖有可能很複雜,查看損失函數,優化計算流圖。

mark

酷炫模擬遊樂場playground

mark

生活中所見的遊樂園。

展示了基本的神經網路結構

  • JavaScript編寫的網頁應用
  • 通過瀏覽器就可以訓練簡單的神經網路
  • 訓練過程可視化,高度定製化

playground.tensorflow.org

不用擔心運行複雜的神經網路而搞垮。

數據集 - 特徵 - 隱藏層(深度: 很多層) - 輸出

測試的損失。訓練的損失。越接近0越好。

epoch是完整的運行過程。

黃色越黃越接近-1

點亮輸入。選擇激勵函數。問題類型分類還是回歸。

遊樂場對神經網路有更形象的認識。

常用的Python繪圖庫matplotlib

mark

一個極其強大的python繪圖庫:

matplotlib.org/

官網有很多例子。

scipy下的一個組件。

  • 很少的代碼即可繪製2d 3d 靜態動態等各種圖形
  • 一般常用的是它的子包: pyplot 提供類似matlab的繪圖框架

Matplotlib的一般繪圖流

mark

sudo pip install matplotlib

代碼:

# -*- coding: UTF-8 -*-# 引入 Matplotlib 的分模塊 pyplotimport matplotlib.pyplot as plt# 引入 numpyimport numpy as np# 創建數據# Linespace創建一定範圍內的圖線。-2到2之間等分100個點x = np.linspace(-2, 2, 100)#y = 3 * x + 4y1 = 3 * x + 4y2 = x ** 3# 創建圖像#plt.plot(x, y)plt.plot(x, y1)plt.plot(x, y2)# 顯示圖像plt.show()

mark

藍色的為y1.從-2到2的一條直線。

代碼示例2:

# -*- coding: UTF-8 -*-import matplotlib.pyplot as pltimport numpy as np# 創建數據x = np.linspace(-4, 4, 50)y1 = 3 * x + 2y2 = x ** 2# 第一張圖# 指定圖的大小plt.figure(num=1, figsize=(7, 6))# 第一張圖兩個線plt.plot(x, y1)plt.plot(x, y2, color="red", linewidth_=3.0, linestylex="--")# 第二張圖plt.figure(num=2)plt.plot(x, y2, color="green")# 顯示所有圖像plt.show()

mark

代碼示例3:

子圖的繪製

import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.ticker import NullFormatter # useful for `logit` scale# Fixing random state for reproducibility# 為了重現結果,設置隨機種子np.random.seed(19680801)# make up some data in the interval ]0, 1[y = np.random.normal(loc=0.5, scale=0.4, size=1000)y = y[(y > 0) & (y < 1)]y.sort()x = np.arange(len(y))# plot with various axes scalesplt.figure(1)# linear# 兩行兩列子圖中第一個plt.subplot(221)plt.plot(x, y)plt.yscale(linear)plt.title(linear)plt.grid(True)# logplt.subplot(222)plt.plot(x, y)plt.yscale(log)plt.title(log)plt.grid(True)# symmetric logplt.subplot(223)plt.plot(x, y - y.mean())plt.yscale(symlog, linthreshy=0.01)plt.title(symlog)plt.grid(True)# logitplt.subplot(224)plt.plot(x, y)plt.yscale(logit)plt.title(logit)plt.grid(True)# Format the minor tick labels of the y-axis into empty strings with# `NullFormatter`, to avoid cumbering the axis with too many labels.plt.gca().yaxis.set_minor_formatter(NullFormatter())# Adjust the subplot layout, because the logit one may take more space# than usual, due to y-tick labels like "1 - 10^{-3}"plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25, wspace=0.35)plt.show()

mark

繪製一個像碗一樣的圖像。

from mpl_toolkits.mplot3d.axes3d import Axes3Dimport matplotlib.pyplot as pltimport numpy as npfig, ax1 = plt.subplots(figsize=(8, 5), subplot_kw={projection: 3d})alpha = 0.8r = np.linspace(-alpha,alpha,100)X,Y= np.meshgrid(r,r)l = 1./(1+np.exp(-(X**2+Y**2)))ax1.plot_wireframe(X,Y,l)ax1.plot_surface(X,Y,l, cmap=plt.get_cmap("rainbow"))ax1.set_title("Bowl shape")plt.show()

mark

製作靜態圖像,製作動態圖像。

示例5:

import numpy as npfrom matplotlib import cmimport matplotlib.pyplot as pltimport mpl_toolkits.mplot3d.axes3d as p3import matplotlib.animation as animationdef cost_function(x): return x[0]**2 + x[1]**2def gradient_cost_function(x): return np.array([2*x[0], 2*x[1]])nb_steps = 20x0 = np.array([0.8, 0.8])learning_rate = 0.1def gen_line(): x = x0.copy() data = np.empty((3, nb_steps+1)) data[:, 0] = np.concatenate((x, [cost_function(x)])) for t in range(1, nb_steps+1): grad = gradient_cost_function(x) x -= learning_rate * grad data[:, t] = np.concatenate((x, [cost_function(x)])) return datadef update_line(num, data, line): # NOTE: there is no .set_data() for 3 dim data... line.set_data(data[:2, :num]) line.set_3d_properties(data[2, :num]) return line# Attaching 3D axis to the figurefig = plt.figure()ax = p3.Axes3D(fig)# Plot cost surfaceX = np.arange(-0.5, 1, 0.1)Y = np.arange(-1, 1, 0.1)X, Y = np.meshgrid(X, Y)Z = cost_function((X, Y))surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth_=0, antialiased=False)# Optimizedata = gen_line()# Creating line objects# NOTE: Cant pass empty arrays into 3d version of plot()line = ax.plot(data[0, 0:1], data[0, 0:1], data[0, 0:1], rx-, linewidth_=2)[0]# Setting the axes propertiesax.view_init(30, -160)ax.set_xlim3d([-1.0, 1.0])ax.set_xlabel(X)ax.set_ylim3d([-1.0, 1.0])ax.set_ylabel(Y)ax.set_zlim3d([0.0, 2.0])ax.set_zlabel(Z)# Creating the Animation objectline_ani = animation.FuncAnimation(fig, update_line, nb_steps+1, fargs=(data, line), interval=200, blit=False)# line_ani.save(gradient_descent.gif, dpi=80, writer=imagemagick)plt.show()

mark

演示了梯度下降的示例。

TensorFlow-mnist-tutorial的代碼示例

代碼下載地址:

github.com/martin-gorne

注意錯誤:

ImportError: No module named tensorflowvisu

是因為這個tensorflowvisu.py的文件得位於同一級目錄。

mark

mark

可以看到精度在不斷上升。損失在不斷降低。可以看到他訓練了哪些數字。

weights,權重。Biases,偏差。 測試的手寫數字。

這個例子是用TensorFlow結合Matplotlib來繪製一個實時的動圖。


推薦閱讀:

乾脆面君,你給我站住!你已經被TensorFlow盯上了
Berkeley CS294-112 深度增強學習 筆記 (4) 策略梯度法
TensorFlow 的簡單例子
使用TensorFlow時輸入數據的三個姿勢

TAG:TensorFlow |