作者:陳貽東|騰訊移動(dòng)客戶端開發(fā)工程師
源碼下載地址:https://share.weiyun.com/a0c1664d334c4c67ed51fc5e0ac5f2b2
初學(xué)機(jī)器學(xué)習(xí),寫篇文章mark一下,希望能為將入坑者解點(diǎn)惑。本文介紹一些機(jī)器學(xué)習(xí)的入門知識(shí),從安裝環(huán)境到跑通機(jī)器學(xué)習(xí)入門程序MNIST demo。
內(nèi)容提綱: 環(huán)境搭建 了解Tensorflow運(yùn)行機(jī)制 MNIST(手寫數(shù)字識(shí)別 ) softmax性線回歸 MNIST 深度卷積神經(jīng)網(wǎng)絡(luò)(CNN) tools 工具類 CPU & GPU & multi GPU 學(xué)習(xí)資料 1 環(huán)境搭建 (Windows) 安裝虛擬環(huán)境 Anaconda ,方便python包管理和環(huán)境隔離。 Anaconda3 4.2 https://www.anaconda.com/downloads ,自帶python 3.5。
創(chuàng)建tensorflow隔離環(huán)境。打開Anaconda安裝后的終端Anaconda Prompt,執(zhí)行下面命令 conda create - n tensorflow python= 3.5 #創(chuàng)建名為tensorflow,python版本為3.5 的虛擬環(huán)境activate tensorflow #激活這個(gè)環(huán)境 deactivate #退出當(dāng)前虛擬環(huán)境。這個(gè)不用執(zhí)行
CPU 版本
pip install tensorflow #通過包管理來安裝pip install whl- file #通過下載 whl 文件安裝,tensorflow- cpu安裝包:http: / / mirrors. oa. com/ tensorflow/ windows/ cpu/ tensorflow-1.2 . 1 - cp35- cp35m- win_amd64. whl, cp35是指python3.5
GPU 版本。 我的筆記本是技持NVIDIA顯卡的,可以安裝cuda,GPU比CPU快很多,不過筆記本的顯存不大,小模型還可以跑,大模型建議在本地用CPU跑通,到Tesla平臺(tái)上訓(xùn)練。
注意點(diǎn):選擇正確的 CUDA 和 cuDNN 版本搭配,不要只安裝最新版本,tensorflow可能不支持。
目前Tensorflow已支持到CUDA 9 & cuDNN 7,之前本人安裝只支持CUDA 8 & cuDNN 6,所以用是的:
CUDA8.1 https://developer.nvidia.com/cuda-80-ga2-download-archive
cudnn 6 https://developer.nvidia.com/cudnn ,將cudnn包解壓,把文件放到cuda安裝的對(duì)應(yīng)目錄中,C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0,bin對(duì)應(yīng)bin,include對(duì)應(yīng)include,再添加bin目錄到環(huán)境變量 path中。
pip install tensorflow- gpu #通過包管理來安裝pip install whl- file #http: / / mirrors. oa. com/ tensorflow/ windows/ gpu/ tensorflow_gpu-1.2 . 1 - cp35- cp35m- win_amd64. whl
一些python工具包安裝。用到啥安啥就行, pip install,不行就找源碼編譯安裝 ( tensorflow) D: \> pip install opencv- python #opencv, tensoflow 虛擬環(huán)境中 ( tensorflow) D: \> pip install scipy #圖片讀取寫入,scipy. misc. imread ( tensorflow) D: \> pip install Pillow #PIL/ Pillow,這里有個(gè)坑,壓縮過的PNG圖,在1 . x版本解析會(huì)出現(xiàn)透明通道質(zhì)量下降,升級(jí)
2 了解Tensorflow運(yùn)行機(jī)制 import tensorflow as tfhello_world = tf. constant ( 'Hello World!' , dtype= tf. string) #常量tensorprint ( hello_world) #這時(shí)hello_world是一個(gè)tensor,代表一個(gè)運(yùn)算的輸出#out: Tensor ( 'Const:0' , shape= ( ) , dtype= string) hello = tf. placeholder ( dtype= tf. string, shape= [ None] ) #占位符tensor,在sess. run時(shí)賦值world = tf. placeholder ( dtype= tf. string, shape= [ None] ) hello_world2 = hello+ world #加法運(yùn)算tensorprint ( hello_world2) #out: Tensor ( 'add:0' , shape= ( ? , ) , dtype= string) #mathx = tf. Variable ( [ 1.0 , 2.0 ] ) #變量tensor,可變。y = tf. constant ( [ 3.0 , 3.0 ] ) mul = tf. multiply ( x, y) #點(diǎn)乘運(yùn)算tensor#logicalrgb = tf. constant ( [ [ [ 255 ] , [ 0 ] , [ 126 ] ] ] , dtype= tf. float32) logical = tf. logical_or ( tf. greater ( rgb, 250 . ) , tf. less ( rgb, 5 . ) ) #邏輯運(yùn)算,rgb中> 250 or 5 的位置被標(biāo)為True,其它Falsewhere = tf. where ( logical, tf. fill ( tf. shape ( rgb) , 1 . ) , tf. fill ( tf. shape ( rgb) , 5 . ) ) #True的位置賦值1 ,F(xiàn)alse位置賦值5 # 啟動(dòng)默認(rèn)圖. # sess = tf. Session ( ) with tf. Session ( ) as sess: sess. run ( tf. global_variables_initializer ( ) ) #變量初始化 result = sess. run ( hello_world) #Fetch, 獲取tensor運(yùn)算結(jié)果 print ( result, result. decode ( ) , hello_world. eval ( ) ) #`t.eval()` is a shortcut for calling `tf.get_default_session().run(t)` . #out: b'Hello World!' Hello World! b'Hello World!' #前輟'b' 表示bytestring格式,decode解成string格式 print ( sess. run ( hello, feed_dict= { hello: [ 'Hello' ] } ) ) #out: [ 'Hello' ] print ( sess. run ( hello_world2, feed_dict= { hello: [ 'Hello' ] , world: [ ' World!' ] } ) ) #Feed,占位符賦值 #out: [ b'Hello World!' ] print ( sess. run ( mul) ) #out: [ 3 . 6 . ] print ( sess. run ( logical) ) #out: [ [ [ True] [ True] [ False] ] ] #rgb中> 250 or 5 的位置被標(biāo)為True,其它False print ( sess. run ( where) ) #out: [ [ [ 1 . ] [ 1 . ] [ 5 . ] ] ] #True的位置賦值1 ,F(xiàn)alse位置賦值5 #sess. close ( ) #sess如果不是用with 方式定義,需要close
Tensor。是一個(gè)句柄,代表一個(gè)運(yùn)算的輸出,但并沒有存儲(chǔ)運(yùn)算輸出的結(jié)果,需要通過tf.Session.run(Tensor)或者Tensor.eval()執(zhí)行運(yùn)算過程后,才能得到輸出結(jié)果。A Tensor is a symbolic handle to one of the outputs of an Operation,It does not hold the values of that operation's output, but instead provides a means of computing those values in a TensorFlow. Tensorflow運(yùn)行過程:定義計(jì)算邏輯,構(gòu)建圖(Graph) => 通過會(huì)話(Session),獲取結(jié)果數(shù)據(jù)?;居梅▍⒁婃溄?。 3 MNIST(手寫數(shù)字識(shí)別 ) softmax性線回歸 MNIST是一個(gè)入門級(jí)的計(jì)算機(jī)視覺數(shù)據(jù)集,它包含各種手寫數(shù)字圖片:
它也包含每一張圖片對(duì)應(yīng)的標(biāo)簽,告訴我們這個(gè)是數(shù)字幾。比如,上面這四張圖片的標(biāo)簽分別是5,0,4,1。
數(shù)據(jù)集圖片大小28x28,單通道灰度圖。存儲(chǔ)樣式如下:
MNIST手寫數(shù)字識(shí)別的目的是輸入這樣的包含手寫數(shù)字的28x28的圖片,預(yù)測(cè)出圖片中包含的數(shù)字。
softmax線性回歸認(rèn)為圖片中數(shù)字是N可能性由圖像中每個(gè)像素點(diǎn)用
表示是 數(shù)字 i 的可能性,計(jì)算出所有數(shù)字(0-9)的可能性,也就是所有數(shù)字置信度,然后把可能性最高的數(shù)字作為預(yù)測(cè)值。
evidence的計(jì)算方式如下:
其中
代表權(quán)重,
代表數(shù)字 i 類的偏置量,j 代表給定圖片 x 的像素索引(0~28x28=784),用于像素求和。即圖片每個(gè)像素值x權(quán)重之和,再加上一個(gè)偏置b,得到可能性值。
引入softmax的目的是對(duì)可能性值做歸一化normalize ,讓所有可能性之和為1。這樣可以把這些可能性轉(zhuǎn)換成概率 y :
數(shù)據(jù)
X樣本 size 28x28 = 784
Y樣本 ,樣式如
讀取
from tensorflow. examples. tutorials. mnist import input_datamnist = input_data. read_data_sets ( FLAGS. data_dir, one_hot= True) #total 55000 ,one_hot方式,圖片x格式為1 維數(shù)組,大小784 batch_xs, batch_ys = mnist. train. next_batch ( batch_size) #分batch讀取
構(gòu)建圖(Graph)
Inference推理,由輸入 x 到輸出預(yù)測(cè)值 y 的推理過程
x = tf. placeholder ( tf. float32, [ None, 784 ] , name= 'input' ) #None表示batch size待定with tf. variable_scope ( 'inference' ) : #定義作用域,名子inference W = tf. Variable ( tf. zeros ( [ 784 , 10 ] ) ) #初值為0 ,size 784x10 b = tf. Variable ( tf. zeros ( [ 10 ] ) ) #初值為0 size 10 y = tf. matmul ( x, W) + b #矩陣相乘
Loss 損失函數(shù),分類一般采用交叉熵,這里用的是softmax交交叉熵。交叉熵是用來度量?jī)蓚€(gè)概率分布間的差異性信息,交叉熵公式如下:
with tf. variable_scope ( 'loss' ) : loss = tf. reduce_mean ( tf. nn. softmax_cross_entropy_with_logits ( labels= y_, logits= y) , name= 'loss' ) #softmax交叉熵公式: z * - log ( softmax ( x) ) + ( 1 - z) * - log ( 1 - softmax ( x) ) # x: logits, z: label
計(jì)算loss的方法有很多種,常見的還有L1 loss 、L2 loss、sigmoid 交叉熵、聯(lián)合loss、自定義loss...
Accuracy 準(zhǔn)確率,預(yù)測(cè)值與真實(shí)值相同的概率。矩陣相乘輸出y值是一個(gè)數(shù)組,tf.argmax函數(shù)可能從數(shù)據(jù)中找出最大元素下標(biāo),預(yù)測(cè)值的最大值下標(biāo)和真值的最大值下標(biāo)一致即為正確。
with tf. variable_scope ( 'accuracy' ) : accuracy = tf. reduce_mean ( tf. cast ( tf. equal ( tf. argmax ( y, 1 ) , tf. argmax ( y_, 1 ) ) , tf. float32) , name= 'accuracy' )
Training 訓(xùn)練,訓(xùn)練的目的是讓Loss接近最小化,預(yù)測(cè)值接近真值,Tensorflow通過優(yōu)化器Optimizers來實(shí)現(xiàn)。在y = Wx+b中,W、b在訓(xùn)練之初會(huì)賦初值(隨機(jī) or 0),經(jīng)過Optimizer不短優(yōu)化,Loss逼近最小值,使W、b不斷接近理想值。 W、b一起共784x10+10個(gè)參數(shù)。
train_step = tf. train. GradientDescentOptimizer ( FLAGS. learning_rate) . minimize ( loss)
minimize函數(shù):更新參數(shù),讓Loss最小化,包含兩個(gè)步驟:計(jì)算梯度;更新參數(shù)。
grad_var = compute_gradients ( loss) # return ( gradient, variable) pairsapply_gradients ( grad_var) #沿著參數(shù)的梯度反方向更新參數(shù),讓Loss變小
GradientDescentOptimizer:梯度下降算法優(yōu)化器, Tensorflow實(shí)現(xiàn)的是SGD(隨機(jī)梯度下降)。其缺點(diǎn)是依賴當(dāng)前batch,波動(dòng)較大。
其它一些增強(qiáng)版Optimizers:參考鏈接。 MomentumOptimizer、AdadeltaOptimizer、AdamOptimizer、RMSPropOptimizer、AdadeltaOptimizer ...
Session:Tensorflow需要通過Session(會(huì)話)來執(zhí)行推理運(yùn)算,有兩種創(chuàng)建方式,兩者差別在于InteractiveSession會(huì)將自己設(shè)置為默認(rèn)session,有了默認(rèn)session,tensor.eval()才能執(zhí)行。
sess = tf. Session ( ) sess = tf. InteractiveSession ( )
也可以通過下設(shè)置默認(rèn)session:
with sess. as_default ( ) : xx. eval ( ) with tf. Session ( ) as sess: xx. eval ( )
配置gpu相關(guān)session參數(shù):
sess_config = tf. ConfigProto ( allow_soft_placement= True, log_device_placement= False) #允許沒有g(shù)pu或者gpu不足時(shí)用軟件模擬sess_config. gpu_options. allow_growth = True #動(dòng)態(tài)申請(qǐng)顯存。不加會(huì)申請(qǐng)全部,導(dǎo)致其他訓(xùn)練程序不能運(yùn)行#sess_config. gpu_options. per_process_gpu_memory_fraction = 0.8 #按比例申請(qǐng)顯存sess = tf. InteractiveSession ( config= sess_config)
一個(gè)網(wǎng)絡(luò)的訓(xùn)練過程是一個(gè)不斷迭代(前向+反向)的過程。前向算法由前向后計(jì)算網(wǎng)絡(luò)各層輸出,反向算法由后向前計(jì)算參數(shù)梯度,優(yōu)化參數(shù),減小Loss。流程如圖:
注意:每隔一段時(shí)間輸出一下網(wǎng)絡(luò)Loss和Accuracy,查看效果。每隔一段時(shí)間緩存一下網(wǎng)絡(luò)參數(shù),防止被突然中斷,可再恢復(fù)。
模型參數(shù)的保存與恢復(fù):
check point:默認(rèn)保存方式。
pb:mobile使用。
npz:字典保存方式,{name: value}, numpy的一種保存方式。對(duì)參數(shù)按名保存,按名恢復(fù)。save和restore方法自己控制,可以選擇性保存和恢復(fù)。參見附近代碼中【tools.py】save_npz_dict & load_and_assign_npz_dict方法。
saver = tf. train. Saver ( max_to_keep = 3 , write_version = 2 ) save_path = saver. save ( sess, FLAGS. out_model_dir+ '/model.ckpt' ) # check point方式output_graph_def = tf. graph_util. convert_variables_to_constants ( sess, sess. graph_def, output_node_names= [ 'output' ] ) #指定輸出節(jié)點(diǎn)名稱,這個(gè)需要在網(wǎng)絡(luò)中定義with tf. gfile. FastGFile ( FLAGS. out_model_dir+ '/mobile-model.pb' , mode= 'wb' ) as f: f. write ( output_graph_def. SerializeToString ( ) ) #pb方式tools. save_npz_dict ( save_list= tf. global_variables ( ) , name= FLAGS. out_model_dir+ '/model.npz' , sess= sess) #pnz方式
恢復(fù):
#check pointsaver = tf. train. Saver ( max_to_keep = 3 , write_version = 2 ) model_file= tf. train. latest_checkpoint ( FLAGS. log_dir) if model_file: saver. restore ( sess, model_file) #npztools. load_and_assign_npz_dict ( name= FLAGS. log_dir+ '/model.npz' , sess= sess) ) 打印網(wǎng)絡(luò)中各參數(shù)信息:方便查看網(wǎng)絡(luò)參數(shù)是否正確。
def print_all_variables ( train_only= False) : if train_only: t_vars = tf. trainable_variables ( ) print ( ' [*] printing trainable variables' ) else : t_vars = tf. global_variables ( ) print ( ' [*] printing global variables' ) for idx, v in enumerate ( t_vars) : print ( ' var {:3}: {:15} {}' . format ( idx, str ( v. get_shape ( ) ) , v. name) )
可視化。Tensorflow提供tensorboard可視化工具,通過命令打開web服務(wù),由瀏覽器查看,輸入網(wǎng)址http://localhost:6006 tensorboard -- logdir= your- log- path #path中不要出現(xiàn)中文# 需要在訓(xùn)練過程指定相應(yīng)log路徑,寫入相關(guān)信息# 參考附件【sample. py】中summary、writer相關(guān)關(guān)鍵字代碼。
Graph可視化:
訓(xùn)練過程可視化:
batch size = 128, 訓(xùn)練集,驗(yàn)證集??梢钥吹絣oss在收斂,accuracy在提高。由于訓(xùn)練集曲線反應(yīng)的是當(dāng)前batch的loss和accuracy,batch size相對(duì)不高,抖動(dòng)較大。而驗(yàn)證集是全部圖片進(jìn)行測(cè)試,曲線較平滑。
4 MNIST深度卷積神經(jīng)網(wǎng)絡(luò)(CNN) Softmax性線回歸網(wǎng)絡(luò)中,輸出y是輸入x的線性組合,即y = Wx+b,這是線性關(guān)系。在很多問題中其解法并非線性關(guān)系能完成的,在深度學(xué)習(xí),能過能多層卷積神經(jīng)網(wǎng)絡(luò)組合非線性激活函數(shù)來模擬更復(fù)雜的非線性關(guān)系,效果往往比單一的線性關(guān)系更好。先看深度卷積神經(jīng)網(wǎng)絡(luò)(CNN,Convolutional Neural Network)構(gòu)建的MNIST預(yù)測(cè)模型,再逐一介紹各網(wǎng)絡(luò)層。
MNIST CNN Inference推理圖 。從輸入到輸出中間包含多個(gè)網(wǎng)絡(luò)層:reshape、conv卷積、pool池化、fc全鏈接、dropout。自底向上輸入原始圖片數(shù)據(jù)x經(jīng)過各層串行處理,得到各數(shù)字分類概率預(yù)測(cè)輸出y。Inference的結(jié)果轉(zhuǎn)給loss用作迭代訓(xùn)練,圖中的可以看出用的是AdamOptimizer優(yōu)化器。
reshape 變形 ,對(duì)數(shù)據(jù)的邏輯結(jié)構(gòu)進(jìn)行改變,如二維變四維:[1, 784] => [1, 28, 28, 1],數(shù)據(jù)存儲(chǔ)內(nèi)容未發(fā)生改變。這里由于輸入數(shù)據(jù)存儲(chǔ)的手寫圖片是一維數(shù)據(jù),轉(zhuǎn)成[batch_size, height, width, channels]格式 with tf. name_scope ( 'reshape' ) : #scope inputs = tf. reshape ( inputs, [ - 1 , 28 , 28 , 1 ] ) #[ batch_size, height, width, channels] , batch size= - 1 表示由inputs決定, #batch_size= inputs_size/ ( 28x28x1)
conv2d 卷積 , 卷積核(yellow)與Image元(green)素相乘,累加得到輸出元素值(red)。Image的每個(gè)Channel(通道)都對(duì)應(yīng)一個(gè)不同的卷積核,Channel內(nèi)卷積核參數(shù)共享。所有輸入channel與其kernel相乘累加多層得到輸出的一個(gè)channel值。輸出如有多個(gè)channel,則會(huì)重復(fù)多次,kernel也是不同的。所以會(huì)有input_channel_count * output_channel_count個(gè)卷積核 。在卷積層中訓(xùn)練的是卷積核 。 def conv2d ( x, W) : #W: filter [ kernel[ 0 ] , kernel[ 1 ] , in_channels, out_channels] return tf. nn. conv2d ( x, W, strides= [ 1 , 1 , 1 , 1 ] , padding= 'SAME' )
tf.nn.conv2d:
data_format : input和output數(shù)據(jù)的邏輯結(jié)構(gòu),NHWC : batch height width channel。NCHW : batch channel height width。常用的是NHWC格式;在一些輸入數(shù)據(jù)中各通道數(shù)據(jù)分開存放,這種更適合NCHW。
input :輸入,data_format=NHWC時(shí),shape為batch, in_height, in_width, in_channels ,Tensor。
filter :卷積核,shape為filter_height, filter_width, in_channels, out_channels ,共有in_channels*out_channels個(gè)filter_height, filter_width的卷積核,輸入輸出channel越多,計(jì)算量越大。
strides : 步長(zhǎng),shape為1, stride_h, stride_w, 1,通常stride_h和stride_w相等,表示卷積核延縱橫方向上每次前進(jìn)的步數(shù)。上gif圖stride為1。
padding :卷積計(jì)算時(shí)數(shù)據(jù)不對(duì)齊時(shí)填充方式,VALID :丟棄多余;SAME :兩端補(bǔ)0,讓多余部分可被計(jì)算。
output :輸出,shape為batch, out_height, out_width, out_channels
output[ b, i, j, k] = sum_{ di, dj, q} input[ b, strides[ 1 ] * i + di, strides[ 2 ] * j + dj, q] * filter[ di, dj, q, k]
激活函數(shù) ,與卷積搭配使用。激活函數(shù)不是真的要去激活什么,在神經(jīng)網(wǎng)絡(luò)中,激活函數(shù)的作用是能夠給神經(jīng)網(wǎng)絡(luò)加入一些非線性因素,使得神經(jīng)網(wǎng)絡(luò)可以更好地解決較為復(fù)雜的問題。 tf.nn.relu 即是激活函數(shù),對(duì)卷積輸出作非線性處理,其函數(shù)如下:
其它還有如sigmoid:
tanh:
Pool池化 ,有最大池化和平均值池化,計(jì)算與卷積計(jì)算類似,但無卷積核,求核所覆蓋范圍的最大值或平均值,輸入channel對(duì)應(yīng)輸出channel,沒有多層累加情況。輸入與輸出 channel數(shù)相同,輸出height、width取決于strides。if is_max_pool: x = tf. nn. max_pool ( x, [ 1 , kernel[ 0 ] , kernel[ 1 ] , 1 ] , strides= [ 1 , stride[ 0 ] , stride[ 1 ] , 1 ] , padding= padding, name= 'pool' ) else : x = tf. nn. avg_pool ( x, [ 1 , kernel[ 0 ] , kernel[ 1 ] , 1 ] , strides= [ 1 , stride[ 0 ] , stride[ 1 ] , 1 ] , padding= padding, name= 'pool' )
Dropout ,隨機(jī)刪除一些數(shù)據(jù),讓網(wǎng)絡(luò)在這些刪除的數(shù)據(jù)上也能訓(xùn)練出準(zhǔn)確的結(jié)果,讓網(wǎng)絡(luò)有更強(qiáng)的適應(yīng)性,減少過擬合 。x = tf. nn. dropout ( x, keep_prob) #keep_prob 保留比例,keep_prob= 1.0 表示無dropout
BN(batch normalize) ,批規(guī)范化。Inference中未標(biāo)出,demo中未使用,但也是網(wǎng)絡(luò)中很常用的一層。BN常作用在非線性映射前,即對(duì)Conv結(jié)果做規(guī)范化。一般的順序是 卷積-> BN -> 激活函數(shù)。 BN好處:提升訓(xùn)練速度,加快loss收斂,增加網(wǎng)絡(luò)適應(yīng)性,一定程序的解決反向傳播過程中的梯度消失和爆炸問題。詳細(xì)請(qǐng)戳。
FC(Full Connection)全連接 ,核心是矩陣相乘,softmax性線回歸就是一個(gè)FC。在CNN中全連接常出現(xiàn)在最后幾層,用于對(duì)前面設(shè)計(jì)的特征做加權(quán)和。Tensorflow提供了相應(yīng)函數(shù)tf.layers.dense。
日志 ,下圖打印了模型中需要訓(xùn)練的參數(shù) 的shape 和 各層輸出 數(shù)據(jù)的shape(batch_size=1時(shí)),附件【tool.py】中有相關(guān)代碼。目的是方便觀自己搭的網(wǎng)絡(luò)結(jié)構(gòu)是否符合預(yù)期。數(shù)據(jù)由[1x784] -reshape-> [1x28x28x1] (batch_size, height, width, channels) -conv-> [1x28x28x32] -pool-> [1x14x14x32] -conv-> [1x14x14x64] -pool-> [1x7x7x64] -fc-> [1x1024] -fc-> [1x10] (每類數(shù)字的概率)
訓(xùn)練效果,詳細(xì)代碼參考附件【cnn.py】 VGG,如下圖,非常有名的特征提取和分類網(wǎng)絡(luò)。由多層卷積池化層組成,最后用FC做特征融合實(shí)現(xiàn)分類,很多網(wǎng)絡(luò)基于其前幾層卷積池化層做特征提取,再發(fā)展自己的業(yè)務(wù)。
5 tool工具類 【tool.py】是一個(gè)自己基于tensorflow二次封裝的工具類,位于附件中。好處是以后編程更方便,代碼結(jié)構(gòu)更好看。網(wǎng)上也有現(xiàn)成的開源庫(kù),如TensorLayer、Keras、Tflearn ,自己封裝的目的是更好的理解tensorflow API,自己造可控性也更強(qiáng)一些,如果控制是參數(shù)是否被訓(xùn)練、log打印。
下圖是MNIST CNN網(wǎng)絡(luò)的Inference 推理代碼:
6 CPU & GPU & multi GPU CPU , Tensorflow默認(rèn)所有cpu都是/cpu:0,默認(rèn)占所有cpu,可以通過代碼指定占用數(shù)。sess_config = tf. ConfigProto ( device_count= { 'CPU' : 14 } , allow_soft_placement= True, log_device_placement= False) sess_config. intra_op_parallelism_threads = 56 sess_config. inter_op_parallelism_threads = 56 sess = tf. InteractiveSession ( config= sess_config)
GPU,Tensorflow默認(rèn)占用/gpu:0, 可通過指定device來確定代碼運(yùn)行在哪個(gè)gpu。下面 with tf. device ( '/device:GPU:2' ) : a = tf. constant ( [ 1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 ] , shape= [ 2 , 3 ] , name= 'a' ) b = tf. constant ( [ 1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 ] , shape= [ 3 , 2 ] , name= 'b' ) c = tf. matmul ( a, b) #下面的代碼配置可以避免GPU被占滿,用多少內(nèi)存占多少sess_config = tf. ConfigProto ( allow_soft_placement= True, log_device_placement= False) sess_config. gpu_options. allow_growth = Truesess_config. gpu_options. per_process_gpu_memory_fraction = 0.8 sess = tf. InteractiveSession ( config= sess_config)
多塊GPU時(shí),可以通過在終端運(yùn)行下面指令來設(shè)置CUDA可見GPU塊來控制程序使用哪些GPU。
export CUDA_VISIBLE_DEVICES= 2 , 3
多GPU使用 ,在Tensorflow中多GPU編程比較尷尬,資料較好,代碼寫起比較復(fù)雜,這一點(diǎn)不如Caffe。在Tensorflow中你需要自己寫代碼控制多GPU的loss和gradient的合并,這里有個(gè)官方例子請(qǐng)戳。自己也寫過多GPU的工程,附件代碼【tmp-main-gpus-不可用.py】可做參考,但此處不可用,來自它工程。
7 學(xué)習(xí)資料 收藏了一些機(jī)器學(xué)習(xí)相關(guān)資料,分享一下。自己也只看過很小一部分,仍在學(xué)習(xí)中....