tensorflow编程入门笔记之一
基本上每一個(gè)語言或者工具都有自己的“hello world” demo,那么學(xué)習(xí)它們一般都會(huì)從這個(gè)“hello world”開始。今天我們就來看看tensorflow的“hello world”(非官網(wǎng))。
在開始編寫“hello world”之前我們先看看tensorflow的編程模型。
一. tensorflow編程模型簡介
這部分的一個(gè)很好的教程是官網(wǎng)上的Basic Usage,講解的還是很清晰的。
Tensorflow中的計(jì)算可以表示為一個(gè)有向圖(directed graph),或稱計(jì)算圖(computation graph),其中每一個(gè)運(yùn)算操作將作為一個(gè)節(jié)點(diǎn)(node),節(jié)點(diǎn)與節(jié)點(diǎn)之間的連接成為邊(edge),而在計(jì)算圖的邊中流動(dòng)(flow)的數(shù)據(jù)被稱為張量(tensor),所以形象的看整個(gè)操作就好像數(shù)據(jù)(tensor)在計(jì)算圖(computation graphy)中沿著邊(edge)流過(flow)一個(gè)個(gè)節(jié)點(diǎn)(node),這就是tensorflow名字的由來的。
計(jì)算圖中的每個(gè)節(jié)點(diǎn)可以有任意多個(gè)輸入和任意多個(gè)輸出,每個(gè)節(jié)點(diǎn)描述了一種運(yùn)算操作(operation, op),節(jié)點(diǎn)可以算作運(yùn)算操作的實(shí)例化(instance)。計(jì)算圖描述了數(shù)據(jù)的計(jì)算流程,它也負(fù)責(zé)維護(hù)和更新狀態(tài),用戶可以對(duì)計(jì)算圖的分支進(jìn)行條件控制或循環(huán)操作。用戶可以使用pyton、C++、Go、Java等語言設(shè)計(jì)計(jì)算圖。tensorflow通過計(jì)算圖將所有的運(yùn)算操作全部運(yùn)行在python外面,比如通過c++運(yùn)行在cpu或通過cuda運(yùn)行在gpu 上,所以實(shí)際上python只是一種接口,真正的核心計(jì)算過程還是在底層采用c++或cuda在cpu或gpu上運(yùn)行。
一個(gè) TensorFlow圖描述了計(jì)算的過程. 為了進(jìn)行計(jì)算, 圖必須在會(huì)話(session)里被啟動(dòng). 會(huì)話將圖的op分發(fā)到諸如CPU或GPU之的備上, 同時(shí)提供執(zhí)行op的方法. 這些方法執(zhí)行后, 將產(chǎn)生的tensor返回. 在Python語言中, 返回的tensor是numpy ndarray對(duì)象; 在C和C++語言中, 返回的tensor是tensorflow::Tensor實(shí)例。
從上面的描述中我們可以看到,tensorflow的幾個(gè)比較重要的概念:tensor, computation graphy, node, session。正如前面所說,整個(gè)操作就好像數(shù)據(jù)(tensor)在計(jì)算圖(computation graphy)中沿著邊(edge)流過(flow)一個(gè)個(gè)節(jié)點(diǎn)(node),然后通過會(huì)話(session)啟動(dòng)計(jì)算。所以簡單來說,要完成這整個(gè)過程,我們需要的東西是要定義數(shù)據(jù)、計(jì)算圖和計(jì)算圖上的節(jié)點(diǎn),以及啟動(dòng)計(jì)算的會(huì)話。所以在實(shí)際使用中我們要做的大部分工作應(yīng)該就是定義這些內(nèi)容了。
二. tensorflow基本使用
正如官方教程里所說:
To use TensorFlow you need to understand how TensorFlow:
- Represents computations as graphs.
- Executes graphs in the context of Sessions.
- Represents data as tensors.
- Maintains state with Variables.
- Uses feeds and fetches to get data into and out of arbitrary operations.
我們只有理解了這些概念,明白它們分別是做什么的,才能掌握tensorflow的使用方法。下面簡單介紹下這些概念及使用。
- 計(jì)算圖(computation graphy)
計(jì)算圖是由一個(gè)個(gè)節(jié)點(diǎn)和連接各個(gè)節(jié)點(diǎn)的邊組成,因此要定義一個(gè)計(jì)算圖,只需要定義好各個(gè)節(jié)點(diǎn)以及節(jié)點(diǎn)的輸入輸出(對(duì)應(yīng)計(jì)算圖的邊)。節(jié)點(diǎn)代表各種操作,如加法、乘法、卷積運(yùn)算等等,輸入輸出主要是各種數(shù)據(jù)(tensor)。下面是一個(gè)簡單的計(jì)算圖定義方法示例(來自官網(wǎng)):
當(dāng)然,我們也可以添加更多更復(fù)雜的操作(operation)的節(jié)點(diǎn)(node)到計(jì)算圖(computation graphy)中,如果增加一些卷積網(wǎng)絡(luò)節(jié)點(diǎn)、全連接網(wǎng)絡(luò)節(jié)點(diǎn)等等就可以組建一個(gè)神經(jīng)網(wǎng)絡(luò)計(jì)算圖了。
- 節(jié)點(diǎn)(node)
計(jì)算圖中的每個(gè)節(jié)點(diǎn)可以有任意多個(gè)輸入和任意多個(gè)輸出,每個(gè)節(jié)點(diǎn)描述了一種運(yùn)算操作(operation, op),節(jié)點(diǎn)可以算作運(yùn)算操作的實(shí)例化(instance)。一種運(yùn)算操作代表了一種類型的抽象運(yùn)算,比如矩陣乘法貨響亮加法。tensorflow內(nèi)建了很多種運(yùn)算操作,如下表所示:
| 標(biāo)量運(yùn)算 | Add、Sub、Mul、Div、Exp、Log、Greater、Less、Equal |
| 向量運(yùn)算 | Concat、Slice、Splot、Constant、Rank、Shape、Shuffle |
| 矩陣運(yùn)算 | Matmul、MatrixInverse、MatrixDeterminant |
| 帶狀態(tài)的運(yùn)算 | Variable、Assign、AssignAdd |
| 神經(jīng)網(wǎng)絡(luò)組件 | SoftMax、Sigmoid、ReLU、Convolution2D、MaxPooling |
| 存儲(chǔ)、恢復(fù) | Save、Restore |
| 隊(duì)列及同步運(yùn)算 | Enqueue、Dequeue、MutexAcquire、MutexRelease |
| 控制流 | Merge、Switch、Enter、Leave、NextIteration |
在tensorflow中,也可以通過注冊(cè)機(jī)制加入新的運(yùn)算操作或者運(yùn)算核,這和torch上的注冊(cè)機(jī)制類似。
- 會(huì)話(session)
正如我們前面所說,計(jì)算圖里描述的計(jì)算并沒有真正執(zhí)行,只是進(jìn)行了定義和描述,要實(shí)際執(zhí)行我們就需要在會(huì)話(session)里被啟動(dòng). 這時(shí)session才會(huì)將計(jì)算圖上的節(jié)點(diǎn)操作op分發(fā)到諸如CPU或GPU之類的設(shè)備上, 同時(shí)提供執(zhí)行op的方法. 這些方法執(zhí)行后,將產(chǎn)生的tensor返回.
要啟動(dòng)計(jì)算圖,我們收下需要定義一個(gè)session對(duì)象:
啟動(dòng)操作,最簡單的就是調(diào)用函數(shù)run:
result = sess.run(product)tensorflow還支持分布式session,將計(jì)算圖布置到多個(gè)機(jī)器上進(jìn)行計(jì)算。由于我這邊不具備該環(huán)境,就不介紹這部分內(nèi)容了。
另外tensorflow還支持交互環(huán)境下采用InteractiveSession定義一個(gè)交互session,然后所有的操作都默認(rèn)在該session上運(yùn)行,可以直接調(diào)用Tensor.eval()和Operation.run()兩個(gè)方法,如:
- 數(shù)據(jù)(tensor)
TensorFlow程序使用tensor數(shù)據(jù)結(jié)構(gòu)來代表所有的數(shù)據(jù), 計(jì)算圖中的節(jié)點(diǎn)間傳遞的數(shù)據(jù)都是tensor. 你可以把TensorFlow tensor看作是一個(gè)n維的數(shù)組或列表. 一個(gè) tensor包含一個(gè)靜態(tài)類型rank, 和一個(gè)shape。 - 變量(Variable)
在tensorflow里有一類數(shù)據(jù)比較特殊,那就是我們需要在整個(gè)計(jì)算圖執(zhí)行過程中需要保存的狀態(tài)。比如我們?cè)谶M(jìn)行神經(jīng)網(wǎng)絡(luò)訓(xùn)練時(shí)要時(shí)刻保存并更新的網(wǎng)絡(luò)參數(shù),這時(shí)我們就需要用到Varibale來保存這些參數(shù)。其實(shí),我們?cè)谇懊娴氖纠幸呀?jīng)用到了變量的定義了,它的定義關(guān)鍵字為Variable,如上面的x = tf.Variable([1.0, 2.0])。 - feed & fetch
我們都知道,進(jìn)行機(jī)器學(xué)習(xí)或者神經(jīng)網(wǎng)絡(luò)訓(xùn)練時(shí),都需要大量的訓(xùn)練數(shù)據(jù)。細(xì)心的朋友可能注意到,我們前面一直沒講到訓(xùn)練數(shù)據(jù)怎么定義,怎么輸入到網(wǎng)絡(luò)里。實(shí)際上,tensorflow提供了一個(gè)feed機(jī)制來將tensor直接放置到計(jì)算圖的任意節(jié)點(diǎn)操作上去。“feed”這個(gè)詞用的很形象啊,就像我們?cè)谏险n學(xué)習(xí)時(shí),老師拿課本里的各種例子、習(xí)題往我們腦子里喂。那么,這個(gè)利用這個(gè)feed機(jī)制我們就可以把訓(xùn)練數(shù)據(jù)“喂”到計(jì)算圖的輸入中去。一般我們采用placeholder來指定一個(gè)feed操作,這個(gè)placeholder就像是一個(gè)容器一樣來接收訓(xùn)練數(shù)據(jù),然后在最終進(jìn)行計(jì)算時(shí)只需要用placehoder里的數(shù)據(jù)替換計(jì)算圖的輸入量就可以了。一個(gè)簡單的例子:
采用兩個(gè)placeholder操作來定義兩個(gè)輸入,在后面的see.run()里采用feed_dict替換成真正的訓(xùn)練數(shù)據(jù),feed_dict里的才是真正的數(shù)據(jù)。一般情況,placeholder和feed_dict是搭配使用的。
fetch,正如其字面意思,就是取回?cái)?shù)據(jù)的意思。我們將計(jì)算圖部署到session上進(jìn)行計(jì)算后,需要將計(jì)算結(jié)果取回,這就是一個(gè)fetch。下面是取回多個(gè)tensor的例子:
上面就是tensorflow編程模型的一些基本概念和內(nèi)容。通過上面的介紹,我們可以用一句話來總結(jié)tensorflow的一個(gè)工作流程:
那么我們也可以簡單總結(jié)出tensorflow編程的一個(gè)基本步驟:
三. 用tensorflow搭建神經(jīng)網(wǎng)絡(luò)“hello world”
按照我們上一節(jié)介紹的tensorflow編程的基本步驟,我們來搭建我們的第一個(gè)神經(jīng)網(wǎng)絡(luò)——基于mnist數(shù)據(jù)集的手寫數(shù)字識(shí)別,即基于圖片的10分類問題。
此部分可以參考官網(wǎng)教程MNIST For ML Beginners。
MNIST是一個(gè)簡單的機(jī)器視覺數(shù)據(jù)集,如下圖所示,它有幾萬張28×28像素的手寫數(shù)字組成,這些圖片只包含灰度信息,我們的任務(wù)就是對(duì)這些手寫數(shù)字進(jìn)行分類,轉(zhuǎn)成0~9一共10類。
1.定義數(shù)據(jù)
在神經(jīng)網(wǎng)絡(luò)里我們需要定義的數(shù)據(jù)就是輸入訓(xùn)練/測試數(shù)據(jù),而變量用來存儲(chǔ)網(wǎng)絡(luò)模型里的各種參數(shù)。如:
這里我們把圖片的2828個(gè)像素展開成一維列向量(2828-784)
2.定義計(jì)算圖與變量
對(duì)于神經(jīng)網(wǎng)絡(luò)來說,涉及到的操作主要有三部分:網(wǎng)絡(luò)模型定義,損失函數(shù)定義、訓(xùn)練/優(yōu)化方法定義。那么我們的計(jì)算圖基本也由這三部分的定義組成。(當(dāng)然還可能包括其它部分,如輸入數(shù)據(jù)初始化操作,網(wǎng)絡(luò)參數(shù)初始化等等,這里我們不討論)
- 網(wǎng)絡(luò)模型定義
這里我們定義一個(gè)最簡單的單層全連接網(wǎng)絡(luò),計(jì)算公式為:y=Wx+b,然后利用softmax來計(jì)算預(yù)測概率,預(yù)測概率最大的對(duì)應(yīng)預(yù)測的分類。我需要定義兩個(gè)變量來保存網(wǎng)絡(luò)參數(shù)W和b的狀態(tài)。
- 損失函數(shù)定義
采用cross-entropy作為損失函數(shù),它的公式為:$H_{y'}\left(y\right)=-\underset{i}{{\textstyle \sum}}y'{i}\log\left(y{i}\right)$。(才發(fā)現(xiàn)簡書竟然不支持Latex,尷尬。。。)
- 訓(xùn)練/優(yōu)化方法定義
神經(jīng)網(wǎng)絡(luò)常采用SGD(Stochastic Gradient Descent)進(jìn)行網(wǎng)絡(luò)的優(yōu)化訓(xùn)練。tensorflow會(huì)自動(dòng)根據(jù)前面定義的計(jì)算圖進(jìn)行forward和backward計(jì)算并更新參數(shù)。
3.定義會(huì)話
按照前面的方法,定義一個(gè)session即可。但是還要記住對(duì)所有的變量進(jìn)行全局初始化。
或者
sess = tf.Session() init = tf.global_variables_initializer() sess.run()4.進(jìn)行計(jì)算
對(duì)于神經(jīng)網(wǎng)絡(luò)來說,就是要開始迭代進(jìn)行訓(xùn)練和評(píng)估,降低損失函數(shù)。
以上就是整個(gè)神經(jīng)網(wǎng)絡(luò)的搭建過程。這里只采用的單層全連接網(wǎng)絡(luò),但是準(zhǔn)確率依然達(dá)到了92%左右,如果我們采用卷積神經(jīng)網(wǎng)絡(luò)等更復(fù)雜的網(wǎng)絡(luò),可以將準(zhǔn)確率提高到99%。
以上只是搭建一個(gè)神經(jīng)網(wǎng)絡(luò)的基本框架,當(dāng)然實(shí)際中還是數(shù)據(jù)預(yù)處理、參數(shù)初始化、超參數(shù)設(shè)置等問題,這些就需要在實(shí)際使用過程中慢慢學(xué)習(xí)了。
以下是該網(wǎng)絡(luò)的全部代碼:
作者:mac在路上
鏈接:https://www.jianshu.com/p/87581c7082ba
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的tensorflow编程入门笔记之一的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tensorflow学习入门笔记
- 下一篇: softmax函数理解