深度學習技術一直在發展,可是caffe的更新跟不上進度,也許是維護團隊的關係:CAFFE團隊成員都是業餘時間在維護和更新。致使的結果就是不少新的技術在caffe裏用不了,好比RNN, LSTM,batch-norm等。固然這些如今也算是舊的東西了,也許caffe已經有了,我已經好久沒有關注caffe的新版本了。它的不靈活之處就是新的東西很難本身擴展,只能等版本更新,這就比較尷尬。node
所以,只學caffe一個工具看來是不行了,還得學習其它工具。該學什麼呢?固然是如日中天的tensorflow了,畢竟它背後的團隊很強大,功能也比較齊全,更新也很及時。所謂技多不壓身,學了caffe後再學tensorflow,二者結合着用。python
關於tensorflow的介紹,此處再也不囉嗦。關於gpu的安裝與配置,此處也不涉及。linux
1、安裝anacondagit
tensorflow是基於python腳本語言的,所以須要安裝python, 固然還須要安裝numpy、scipy、six、matplotlib等幾十個擴展包。若是一個個安裝,裝到啥時候去?(我曾經光安裝scipy就裝了一天。。。)github
不過如今有了集成環境anaconda,安裝就方便了。python的大部分擴展包, 都集成在anaconda裏面了,所以只須要裝這一個東西就好了。數據庫
先到https://www.continuum.io/downloads 下載anaconda, 如今的版本有python2.7版本和python3.5版本,下載好對應版本、對應系統的anaconda,它其實是一個sh腳本文件,大約300M-400M左右。推薦使用linux版的python 2.7版本,由於tensorflow中的有些東西不支持python3.5(如cPickle)。vim
下載成功後,在終端執行(2.7版本):後端
# bash Anaconda2-4.1.1-Linux-x86_64.sh
或者3.5 版本:api
# bash Anaconda3-4.1.1-Linux-x86_64.sh
在安裝的過程當中,會問你安裝路徑,直接回車默認就能夠了。有個地方問你是否將anaconda安裝路徑加入到環境變量(.bashrc)中,這個必定要輸入yesbash
安裝成功後,會有當前用戶根目錄下生成一個anaconda2的文件夾,裏面就是安裝好的內容。在終端能夠輸入
conda info 來查詢安裝信息
輸入conda list 能夠查詢你如今安裝了哪些庫,經常使用的python, numpy, scipy名列其中。若是你還有什麼包沒有安裝上,能夠運行
conda install *** 來進行安裝(***表明包名稱),若是某個包版本不是最新的,運行 conda update *** 就能夠了。
2、安裝tensorflow
先在終端執行:
anaconda search -t conda tensorflow
搜索一下有哪些tensorflow安裝包,經過查看版本,選擇最高的版本安裝。好比我看到是0.10.0rc0版本是最高的,以下圖:
所以,執行下面代碼來查看詳細信息:
anaconda show jjhelmus/tensorflow
它就會告訴你,怎麼來安裝這個包,在終端執行:
conda install --channel https://conda.anaconda.org/jjhelmus tensorflow
而後輸入"y",進行安裝。
3、調試
安裝成功與否,咱們能夠測試一下。
在終端輸入python,進入python編譯環境,而後輸入:
import tensorflow as tf
引包tensorflow包,若是沒有報錯,則安裝成功,不然就有問題。
而後能夠輸入
tf.__version__ tf.__path__
查看tensorflow的安裝版本和安裝路徑(左右各兩根下橫線)。
2、tensorflow學習筆記二:入門基礎
TensorFlow用張量這種數據結構來表示全部的數據。用一階張量來表示向量,如:v = [1.2, 2.3, 3.5] ,如二階張量表示矩陣,如:m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],能夠當作是方括號嵌套的層數。
一、編輯器
編寫tensorflow代碼,實際上就是編寫py文件,最好找一個好用的編輯器,若是你用vim或gedit比較順手,那也能夠的啦。咱們既然已經安裝了anaconda,那麼它裏面自帶一個還算不錯的編輯器,名叫spyder,用起來和matlab差很少,還能夠在右上角查看變量的值。所以我一直使用這個編輯器。它的啓動方式也很簡單,直接在終端輸入spyder就好了。
二、常量
咱們通常引入tensorflow都用語句
import tensorflow as tf
所以,之後文章中我就直接用tf來表示tensorflow了。
在tf中,常量的定義用語句:
a=tf.constant(10)
這就定義了一個值爲10的常量a
三、變量
變量用Variable來定義, 而且必須初始化,如:
x=tf.Variable(tf.ones([3,3])) y=tf.Variable(tf.zeros([3,3]))
分別定義了一個3x3的全1矩陣x,和一個3x3的全0矩陣y,0和1的值就是初始化。
變量定義完後,還必須顯式的執行一下初始化操做,即須要在後面加上一句:
init=tf.global_variables_initializer()
這句可不要忘了,不然會出錯。
例:自定義一個拉普拉斯的W變量:
import tensorflow as tf import numpy as np x=np.array([[1,1,1],[1,-8,1],[1,1,1]]) w=tf.Variable(initial_value=x) sess=tf.Session() sess.run(tf.global_variables_initializer()) print(sess.run(w))
四、佔位符
變量在定義時要初始化,可是若是有些變量剛開始咱們並不知道它們的值,沒法初始化,那怎麼辦呢?
那就用佔位符來佔個位置,如:
x = tf.placeholder(tf.float32, [None, 784])
指定這個變量的類型和shape,之後再用feed的方式來輸入值。
五、圖(graph)
若是把下面的python語句改在tf語句,該怎麼寫呢:
x=3 y=2 z=x+y print(z)
定義兩個變量,並將兩個數相加,輸出結果。若是在tf中直接像上面這樣寫,那就錯了。x,y,z分別是三個tensor對象,對象間的運算稱之爲操做(op), tf不會去一條條地執行各個操做,而是把全部的操做都放入到一個圖(graph)中,圖中的每個結點就是一個操做。而後行將整個graph 的計算過程交給一個 TensorFlow 的Session
, 此 Session
能夠運行整個計算過程,比起操做(operations)一條一條的執行效率高的多。
執行代碼以下:
import tensorflow as tf x = tf.Variable(3) y = tf.Variable(5) z=x+y init =tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(sess.run(z))
其中sess.run()便是執行,注意要先執行變量初始化操做,再執行運算操做。
Session須要先建立,使用完後還須要釋放。所以咱們使用with...as..語句,讓系統自動釋放。
例子1:hello world
import tensorflow as tf word=tf.constant('hello,world!') with tf.Session() as sess: print(sess.run(word))
例子2:加法和乘法
import tensorflow as tf a = tf.placeholder(tf.int16) b = tf.placeholder(tf.int16) add = tf.add(a, b) mul = tf.mul(a, b) with tf.Session() as sess: print('a+b=',sess.run(add, feed_dict={a: 2, b: 3})) print('a*b=',sess.run(mul, feed_dict={a: 2, b: 3}))
此處使用feed_dict以字典的方式對多個變量輸入值。
例子3: 矩陣乘法
import tensorflow as tf a=tf.Variable(tf.ones([3,2])) b=tf.Variable(tf.ones([2,3])) product=tf.matmul(5*a,4*b) init=tf.initialize_all_variables() with tf.Session() as sess: sess.run(init) print(sess.run(product))
其中
product=tf.matmul(5*a,4*b)
也能夠改爲
product=tf.matmul(tf.mul(5.0,a),tf.mul(4.0,b))
定義變量時,沒有指定數據類型,則默認爲float32,所以是5.0而不是5
3、tensorflow學習筆記三:實例數據下載與讀取
1、mnist數據
深度學習的入門實例,通常就是mnist手寫數字分類識別,所以咱們應該先下載這個數據集。
tensorflow提供一個input_data.py文件,專門用於下載mnist數據,咱們直接調用就能夠了,代碼以下:
import tensorflow.examples.tutorials.mnist.input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
執行完成後,會在當前目錄下新建一個文件夾MNIST_data, 下載的數據將放入這個文件夾內。下載的四個文件爲:
input_data文件會調用一個maybe_download函數,確保數據下載成功。這個函數還會判斷數據是否已經下載,若是已經下載好了,就再也不重複下載。
下載下來的數據集被分三個子集:5.5W行的訓練數據集(mnist.train
),5千行的驗證數據集(mnist.validation)和1W行的測試數據集(mnist.test
)。由於每張圖片爲28x28的黑白圖片,因此每行爲784維的向量。
每一個子集都由兩部分組成:圖片部分(images)和標籤部分(labels), 咱們能夠用下面的代碼來查看 :
print mnist.train.images.shape print mnist.train.labels.shape print mnist.validation.images.shape print mnist.validation.labels.shape print mnist.test.images.shape print mnist.test.labels.shape
若是想在spyder編輯器中查看具體數值,能夠將這些數據提取爲變量來查看,如:
val_data=mnist.validation.images
val_label=mnist.validation.labels
2、CSV數據
除了mnist手寫字體圖片數據,tf還提供了幾個csv的數據供你們練習,存放路徑爲:
/home/xxx/anaconda3/lib/python3.5/site-packages/tensorflow/contrib/learn/python/learn/datasets/data/text_train.csv
若是要將這些數據讀出來,可用代碼:
import tensorflow.contrib.learn.python.learn.datasets.base as base iris_data,iris_label=base.load_iris() house_data,house_label=base.load_boston()
前者爲iris鳶尾花卉數據集,後者爲波士頓房價數據。
3、cifar10數據
tf提供了cifar10數據的下載和讀取的函數,咱們直接調用就能夠了。執行下列代碼:
import tensorflow.models.image.cifar10.cifar10 as cifar10 cifar10.maybe_download_and_extract() images, labels = cifar10.distorted_inputs() print images print labels
就能夠將cifar10下載並讀取出來。
4、tensorflow學習筆記四:mnist實例--用簡單的神經網絡來訓練和測試
剛開始學習tf時,咱們從簡單的地方開始。卷積神經網絡(CNN)是由簡單的神經網絡(NN)發展而來的,所以,咱們的第一個例子,就從神經網絡開始。
神經網絡沒有卷積功能,只有簡單的三層:輸入層,隱藏層和輸出層。
數據從輸入層輸入,在隱藏層進行加權變換,最後在輸出層進行輸出。輸出的時候,咱們可使用softmax迴歸,輸出屬於每一個類別的機率值。借用極客學院的圖表示以下:
其中,x1,x2,x3爲輸入數據,通過運算後,獲得三個數據屬於某個類別的機率值y1,y2,y3. 用簡單的公式表示以下:
在訓練過程當中,咱們將真實的結果和預測的結果相比(交叉熵比較法),會獲得一個殘差。公式以下:
y 是咱們預測的機率值, y' 是實際的值。這個殘差越小越好,咱們可使用梯度降低法,不停地改變W和b的值,使得殘差逐漸變小,最後收斂到最小值。這樣訓練就完成了,咱們就獲得了一個模型(W和b的最優化值)。
完整代碼以下:
import tensorflow as tf import tensorflow.examples.tutorials.mnist.input_data as input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) x = tf.placeholder(tf.float32, [None, 784]) y_actual = tf.placeholder(tf.float32, shape=[None, 10]) W = tf.Variable(tf.zeros([784,10])) #初始化權值W b = tf.Variable(tf.zeros([10])) #初始化偏置項b y_predict = tf.nn.softmax(tf.matmul(x,W) + b) #加權變換並進行softmax迴歸,獲得預測機率 cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_actual*tf.log(y_predict),reduction_indies=1)) #求交叉熵 train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) #用梯度降低法使得殘差最小 correct_prediction = tf.equal(tf.argmax(y_predict,1), tf.argmax(y_actual,1)) #在測試階段,測試準確度計算 accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) #多個批次的準確度均值 init = tf.initialize_all_variables() with tf.Session() as sess: sess.run(init) for i in range(1000): #訓練階段,迭代1000次 batch_xs, batch_ys = mnist.train.next_batch(100) #按批次訓練,每批100行數據 sess.run(train_step, feed_dict={x: batch_xs, y_actual: batch_ys}) #執行訓練 if(i%100==0): #每訓練100次,測試一次 print "accuracy:",sess.run(accuracy, feed_dict={x: mnist.test.images, y_actual: mnist.test.labels})
每訓練100次,測試一次,隨着訓練次數的增長,測試精度也在增長。訓練結束後,1W行數據測試的平均精度爲91%左右,不是過高,確定沒有CNN高。
5、tensorflow學習筆記五:mnist實例--卷積神經網絡(CNN)
mnist的卷積神經網絡例子和上一篇博文中的神經網絡例子大部分是相同的。可是CNN層數要多一些,網絡模型須要本身來構建。
程序比較複雜,我就分紅幾個部分來敘述。
首先,下載並加載數據:
import tensorflow as tf import tensorflow.examples.tutorials.mnist.input_data as input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #下載並加載mnist數據 x = tf.placeholder(tf.float32, [None, 784]) #輸入的數據佔位符 y_actual = tf.placeholder(tf.float32, shape=[None, 10]) #輸入的標籤佔位符
定義四個函數,分別用於初始化權值W,初始化偏置項b, 構建卷積層和構建池化層。
#定義一個函數,用於初始化全部的權值 W def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) #定義一個函數,用於初始化全部的偏置項 b def bias_variable(shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) #定義一個函數,用於構建卷積層 def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') #定義一個函數,用於構建池化層 def max_pool(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')
接下來構建網絡。整個網絡由兩個卷積層(包含激活層和池化層),一個全鏈接層,一個dropout層和一個softmax層組成。
#構建網絡 x_image = tf.reshape(x, [-1,28,28,1]) #轉換輸入數據shape,以便於用於網絡中 W_conv1 = weight_variable([5, 5, 1, 32]) b_conv1 = bias_variable([32]) h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) #第一個卷積層 h_pool1 = max_pool(h_conv1) #第一個池化層 W_conv2 = weight_variable([5, 5, 32, 64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) #第二個卷積層 h_pool2 = max_pool(h_conv2) #第二個池化層 W_fc1 = weight_variable([7 * 7 * 64, 1024]) b_fc1 = bias_variable([1024]) h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) #reshape成向量 h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) #第一個全鏈接層 keep_prob = tf.placeholder("float") h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) #dropout層 W_fc2 = weight_variable([1024, 10]) b_fc2 = bias_variable([10]) y_predict=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) #softmax層
網絡構建好後,就能夠開始訓練了。
cross_entropy = -tf.reduce_sum(y_actual*tf.log(y_predict)) #交叉熵 train_step = tf.train.GradientDescentOptimizer(1e-3).minimize(cross_entropy) #梯度降低法 correct_prediction = tf.equal(tf.argmax(y_predict,1), tf.argmax(y_actual,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) #精確度計算 sess=tf.InteractiveSession() sess.run(tf.initialize_all_variables()) for i in range(20000): batch = mnist.train.next_batch(50) if i%100 == 0: #訓練100次,驗證一次 train_acc = accuracy.eval(feed_dict={x:batch[0], y_actual: batch[1], keep_prob: 1.0}) print 'step %d, training accuracy %g'%(i,train_acc) train_step.run(feed_dict={x: batch[0], y_actual: batch[1], keep_prob: 0.5}) test_acc=accuracy.eval(feed_dict={x: mnist.test.images, y_actual: mnist.test.labels, keep_prob: 1.0}) print "test accuracy %g"%test_acc
Tensorflow依賴於一個高效的C++後端來進行計算。與後端的這個鏈接叫作session。通常而言,使用TensorFlow程序的流程是先建立一個圖,而後在session中啓動它。
這裏,咱們使用更加方便的InteractiveSession
類。經過它,你能夠更加靈活地構建你的代碼。它能讓你在運行圖的時候,插入一些計算圖,這些計算圖是由某些操做(operations)構成的。這對於工做在交互式環境中的人們來講很是便利,好比使用IPython。
訓練20000次後,再進行測試,測試精度能夠達到99%。
完整代碼:
# -*- coding: utf-8 -*- """ Created on Thu Sep 8 15:29:48 2016 @author: root """ import tensorflow as tf import tensorflow.examples.tutorials.mnist.input_data as input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #下載並加載mnist數據 x = tf.placeholder(tf.float32, [None, 784]) #輸入的數據佔位符 y_actual = tf.placeholder(tf.float32, shape=[None, 10]) #輸入的標籤佔位符 #定義一個函數,用於初始化全部的權值 W def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) #定義一個函數,用於初始化全部的偏置項 b def bias_variable(shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) #定義一個函數,用於構建卷積層 def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') #定義一個函數,用於構建池化層 def max_pool(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME') #構建網絡 x_image = tf.reshape(x, [-1,28,28,1]) #轉換輸入數據shape,以便於用於網絡中 W_conv1 = weight_variable([5, 5, 1, 32]) b_conv1 = bias_variable([32]) h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) #第一個卷積層 h_pool1 = max_pool(h_conv1) #第一個池化層 W_conv2 = weight_variable([5, 5, 32, 64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) #第二個卷積層 h_pool2 = max_pool(h_conv2) #第二個池化層 W_fc1 = weight_variable([7 * 7 * 64, 1024]) b_fc1 = bias_variable([1024]) h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) #reshape成向量 h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) #第一個全鏈接層 keep_prob = tf.placeholder("float") h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) #dropout層 W_fc2 = weight_variable([1024, 10]) b_fc2 = bias_variable([10]) y_predict=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) #softmax層 cross_entropy = -tf.reduce_sum(y_actual*tf.log(y_predict)) #交叉熵 train_step = tf.train.GradientDescentOptimizer(1e-3).minimize(cross_entropy) #梯度降低法 correct_prediction = tf.equal(tf.argmax(y_predict,1), tf.argmax(y_actual,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) #精確度計算 sess=tf.InteractiveSession() sess.run(tf.initialize_all_variables()) for i in range(20000): batch = mnist.train.next_batch(50) if i%100 == 0: #訓練100次,驗證一次 train_acc = accuracy.eval(feed_dict={x:batch[0], y_actual: batch[1], keep_prob: 1.0}) print('step',i,'training accuracy',train_acc) train_step.run(feed_dict={x: batch[0], y_actual: batch[1], keep_prob: 0.5}) test_acc=accuracy.eval(feed_dict={x: mnist.test.images, y_actual: mnist.test.labels, keep_prob: 1.0}) print("test accuracy",test_acc)
6、tensorflow 1.0 學習:用CNN進行圖像分類
tensorflow升級到1.0以後,增長了一些高級模塊: 如tf.layers, tf.metrics, 和tf.losses,使得代碼稍微有些簡化。
任務:花卉分類
版本:tensorflow 1.0
數據:http://download.tensorflow.org/example_images/flower_photos.tgz
花總共有五類,分別放在5個文件夾下。
閒話很少說,直接上代碼,但願你們能看懂:)
# -*- coding: utf-8 -*- from skimage import io,transform import glob import os import tensorflow as tf import numpy as np import time path='e:/flower/' #將全部的圖片resize成100*100 w=100 h=100 c=3 #讀取圖片 def read_img(path): cate=[path+x for x in os.listdir(path) if os.path.isdir(path+x)] imgs=[] labels=[] for idx,folder in enumerate(cate): for im in glob.glob(folder+'/*.jpg'): print('reading the images:%s'%(im)) img=io.imread(im) img=transform.resize(img,(w,h)) imgs.append(img) labels.append(idx) return np.asarray(imgs,np.float32),np.asarray(labels,np.int32) data,label=read_img(path) #打亂順序 num_example=data.shape[0] arr=np.arange(num_example) np.random.shuffle(arr) data=data[arr] label=label[arr] #將全部數據分爲訓練集和驗證集 ratio=0.8 s=np.int(num_example*ratio) x_train=data[:s] y_train=label[:s] x_val=data[s:] y_val=label[s:] #-----------------構建網絡---------------------- #佔位符 x=tf.placeholder(tf.float32,shape=[None,w,h,c],name='x') y_=tf.placeholder(tf.int32,shape=[None,],name='y_') #第一個卷積層(100——>50) conv1=tf.layers.conv2d( inputs=x, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool1=tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2) #第二個卷積層(50->25) conv2=tf.layers.conv2d( inputs=pool1, filters=64, kernel_size=[5, 5], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool2=tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2) #第三個卷積層(25->12) conv3=tf.layers.conv2d( inputs=pool2, filters=128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool3=tf.layers.max_pooling2d(inputs=conv3, pool_size=[2, 2], strides=2) #第四個卷積層(12->6) conv4=tf.layers.conv2d( inputs=pool3, filters=128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool4=tf.layers.max_pooling2d(inputs=conv4, pool_size=[2, 2], strides=2) re1 = tf.reshape(pool4, [-1, 6 * 6 * 128]) #全鏈接層 dense1 = tf.layers.dense(inputs=re1, units=1024, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003)) dense2= tf.layers.dense(inputs=dense1, units=512, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003)) logits= tf.layers.dense(inputs=dense2, units=5, activation=None, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003)) #---------------------------網絡結束--------------------------- loss=tf.losses.sparse_softmax_cross_entropy(labels=y_,logits=logits) train_op=tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) correct_prediction = tf.equal(tf.cast(tf.argmax(logits,1),tf.int32), y_) acc= tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) #定義一個函數,按批次取數據 def minibatches(inputs=None, targets=None, batch_size=None, shuffle=False): assert len(inputs) == len(targets) if shuffle: indices = np.arange(len(inputs)) np.random.shuffle(indices) for start_idx in range(0, len(inputs) - batch_size + 1, batch_size): if shuffle: excerpt = indices[start_idx:start_idx + batch_size] else: excerpt = slice(start_idx, start_idx + batch_size) yield inputs[excerpt], targets[excerpt] #訓練和測試數據,可將n_epoch設置更大一些 n_epoch=10 batch_size=64 sess=tf.InteractiveSession() sess.run(tf.global_variables_initializer()) for epoch in range(n_epoch): start_time = time.time() #training train_loss, train_acc, n_batch = 0, 0, 0 for x_train_a, y_train_a in minibatches(x_train, y_train, batch_size, shuffle=True): _,err,ac=sess.run([train_op,loss,acc], feed_dict={x: x_train_a, y_: y_train_a}) train_loss += err; train_acc += ac; n_batch += 1 print(" train loss: %f" % (train_loss/ n_batch)) print(" train acc: %f" % (train_acc/ n_batch)) #validation val_loss, val_acc, n_batch = 0, 0, 0 for x_val_a, y_val_a in minibatches(x_val, y_val, batch_size, shuffle=False): err, ac = sess.run([loss,acc], feed_dict={x: x_val_a, y_: y_val_a}) val_loss += err; val_acc += ac; n_batch += 1 print(" validation loss: %f" % (val_loss/ n_batch)) print(" validation acc: %f" % (val_acc/ n_batch)) sess.close()
7、tensorflow 1.0 學習:卷積層
在tf1.0中,對卷積層從新進行了封裝,比原來版本的卷積層有了很大的簡化。
1、舊版本(1.0如下)的卷積函數:tf.nn.conv2d
conv2d( input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None )
該函數定義在tensorflow/python/ops/gen_nn_ops.py
。
參數:
input
:一個4維Tensor(N,H,W,C)
. 類型必須是如下幾種類型之一:half
,float32
,float64
.filter
:卷積核
. 類型和input
必須相同,4維tensor,[filter_height, filter_width, in_channels, out_channels],如[5,5,3,32]
strides
: 在input
上切片採樣時,每一個方向上的滑窗步長,必須和format指定的維度同階,如[1, 2, 2, 1]padding
: 指定邊緣填充類型:"SAME", "VALID"
. SAME表示卷積後圖片保持不變,VALID則會縮小。use_cudnn_on_gpu
: 可選項,bool型。表示是否在GPU上用cudnn進行加速,默認爲True.data_format
: 可選項,指定輸入數據的格式:"NHWC"或 "NCHW"
, 默認爲"NHWC"
。
NHWC格式指[batch, in_height, in_width, in_channels]
NCHW格式指[batch, in_channels, in_height, in_width]
name
: 操做名,可選.
示例:
conv1=tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
2、1.0版本中的卷積函數:tf.layers.conv2d
conv2d( inputs, filters, kernel_size, strides=(1, 1), padding='valid', data_format='channels_last', dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer=None, bias_initializer=tf.zeros_initializer(), kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, trainable=True, name=None, reuse=None )
定義在tensorflow/python/layers/convolutional.py
.
參數多了不少,但實際用起來,卻更簡單。
inputs
: 輸入數據,4維tensor.filters
: 卷積核個數。kernel_size
:卷積核大小,如【5,5】。若是長寬相等,也能夠直接設置爲一個數,如kernel_size=5strides
: 卷積過程當中的滑動步長,默認爲[1,1]. 也能夠直接設置爲一個數,如strides=2padding
: 邊緣填充,'same' 和'valid‘選其一。默認爲valid-
data_format
: 輸入數據格式,默認爲channels_last
,即(batch, height, width, channels),也能夠設置爲
channels_first
對應(batch, channels, height, width)
. -
dilation_rate
: 微步長卷積,這個比較複雜一些,請百度. activation
: 激活函數.use_bias
: Boolean型,是否使用偏置項.kernel_initializer
: 卷積核的初始化器.bias_initializer
: 偏置項的初始化器,默認初始化爲0.kernel_regularizer
: 卷積核化的正則化,可選.bias_regularizer
: 偏置項的正則化,可選.activity_regularizer
: 輸出的正則化函數.trainable
: Boolean型,代表該層的參數是否參與訓練。若是爲真則變量加入到圖集合中GraphKeys.TRAINABLE_VARIABLES
(seetf.Variable
).name
: 層的名字.reuse
: Boolean型, 是否重複使用參數.
示例:
conv1=tf.layers.conv2d( inputs=x, filters=32, kernel_size=5, padding="same", activation=tf.nn.relu,
kernel_initializer=tf.TruncatedNormal(stddev=0.01))
更復雜一點的:
conv1 = tf.layers.conv2d(batch_images, filters=64, kernel_size=7, strides=2, activation=tf.nn.relu, kernel_initializer=tf.TruncatedNormal(stddev=0.01) bias_initializer=tf.Constant(0.1), kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003), bias_regularizer=tf.contrib.layers.l2_regularizer(0.003), name='conv1')
8、tensorflow 1.0 學習:參數初始化(initializer)
CNN中最重要的就是參數了,包括W,b。 咱們訓練CNN的最終目的就是獲得最好的參數,使得目標函數取得最小值。參數的初始化也一樣重要,所以微調受到不少人的重視,那麼tf提供了哪些初始化參數的方法呢,咱們能不能本身進行初始化呢?
全部的初始化方法都定義在tensorflow/python/ops/init_ops.py
一、tf.constant_initializer()
也能夠簡寫爲tf.Constant()
初始化爲常數,這個很是有用,一般偏置項就是用它初始化的。
由它衍生出的兩個初始化方法:
a、 tf.zeros_initializer(), 也能夠簡寫爲tf.Zeros()
b、tf.ones_initializer(), 也能夠簡寫爲tf.Ones()
例:在卷積層中,將偏置項b初始化爲0,則有多種寫法:
conv1 = tf.layers.conv2d(batch_images, filters=64, kernel_size=7, strides=2, activation=tf.nn.relu, kernel_initializer=tf.TruncatedNormal(stddev=0.01) bias_initializer=tf.Constant(0), )
或者:
bias_initializer=tf.constant_initializer(0)
或者:
bias_initializer=tf.zeros_initializer()
或者:
bias_initializer=tf.Zeros()
例:如何將W初始化成拉普拉斯算子?
value = [1, 1, 1, 1, -8, 1, 1, 1,1] init = tf.constant_initializer(value) W= tf.get_variable('W', shape=[3, 3], initializer=init)
二、tf.truncated_normal_initializer()
或者簡寫爲tf.TruncatedNormal()
生成截斷正態分佈的隨機數,這個初始化方法好像在tf中用得比較多。
它有四個參數(mean=0.0, stddev=1.0, seed=None, dtype=dtypes.float32),分別用於指定均值、標準差、隨機數種子和隨機數的數據類型,通常只須要設置stddev這一個參數就能夠了。
例:
conv1 = tf.layers.conv2d(batch_images, filters=64, kernel_size=7, strides=2, activation=tf.nn.relu, kernel_initializer=tf.TruncatedNormal(stddev=0.01) bias_initializer=tf.Constant(0), )
或者:
conv1 = tf.layers.conv2d(batch_images, filters=64, kernel_size=7, strides=2, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01) bias_initializer=tf.zero_initializer(), )
三、tf.random_normal_initializer()
可簡寫爲 tf.RandomNormal()
生成標準正態分佈的隨機數,參數和truncated_normal_initializer同樣。
四、random_uniform_initializer = RandomUniform()
可簡寫爲tf.RandomUniform()
生成均勻分佈的隨機數,參數有四個(minval=0, maxval=None, seed=None, dtype=dtypes.float32),分別用於指定最小值,最大值,隨機數種子和類型。
五、tf.uniform_unit_scaling_initializer()
可簡寫爲tf.UniformUnitScaling()
和均勻分佈差很少,只是這個初始化方法不須要指定最小最大值,是經過計算出來的。參數爲(factor=1.0, seed=None, dtype=dtypes.float32)
max_val = math.sqrt(3 / input_size) * factor
這裏的input_size是指輸入數據的維數,假設輸入爲x, 運算爲x * W,則input_size= W.shape[0]
它的分佈區間爲[ -max_val, max_val]
六、tf.variance_scaling_initializer()
可簡寫爲tf.VarianceScaling()
參數爲(scale=1.0,mode="fan_in",distribution="normal",seed=None,dtype=dtypes.float32)
scale: 縮放尺度(正浮點數)
mode: "fan_in", "fan_out", "fan_avg"中的一個,用於計算標準差stddev的值。
distribution:分佈類型,"normal"或「uniform"中的一個。
當 distribution="normal" 的時候,生成truncated normal distribution(截斷正態分佈) 的隨機數,其中stddev = sqrt(scale / n) ,n的計算與mode參數有關。
若是mode = "fan_in", n爲輸入單元的結點數;
若是mode = "fan_out",n爲輸出單元的結點數;
若是mode = "fan_avg",n爲輸入和輸出單元結點數的平均值。
當distribution="uniform」的時候 ,生成均勻分佈的隨機數,假設分佈區間爲[-limit, limit],則
limit = sqrt(3 * scale / n)
七、tf.orthogonal_initializer()
簡寫爲tf.Orthogonal()
生成正交矩陣的隨機數。
當須要生成的參數是2維時,這個正交矩陣是由均勻分佈的隨機數矩陣通過SVD分解而來。
八、tf.glorot_uniform_initializer()
也稱之爲Xavier uniform initializer,由一個均勻分佈(uniform distribution)來初始化數據。
假設均勻分佈的區間是[-limit, limit],則
limit=sqrt(6 / (fan_in + fan_out))
其中的fan_in和fan_out分別表示輸入單元的結點數和輸出單元的結點數。
九、glorot_normal_initializer()
也稱之爲 Xavier normal initializer. 由一個 truncated normal distribution來初始化數據.
stddev = sqrt(2 / (fan_in + fan_out))
其中的fan_in和fan_out分別表示輸入單元的結點數和輸出單元的結點數。
9、tensorflow 1.0 學習:池化層(pooling)和全鏈接層(dense)
池化層定義在 tensorflow/python/layers/pooling.py
.
有最大值池化和均值池化。
一、tf.layers.max_pooling2d
max_pooling2d( inputs, pool_size, strides, padding='valid', data_format='channels_last', name=None )
inputs
: 進行池化的數據。pool_size
: 池化的核大小(pool_height, pool_width),如[3,3]. 若是長寬相等,也能夠直接設置爲一個數,如pool_size=3.strides
: 池化的滑動步長。能夠設置爲[1,1]這樣的兩個整數. 也能夠直接設置爲一個數,如strides=2padding
: 邊緣填充,'same' 和'valid‘選其一。默認爲validdata_format
: 輸入數據格式,默認爲channels_last
,即(batch, height, width, channels),也能夠設置爲
channels_first
對應(batch, channels, height, width)
.name
: 層的名字。
例:
pool1=tf.layers.max_pooling2d(inputs=x, pool_size=[2, 2], strides=2)
通常是放在卷積層以後,如:
conv=tf.layers.conv2d( inputs=x, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) pool=tf.layers.max_pooling2d(inputs=conv, pool_size=[2, 2], strides=2)
2.tf.layers.average_pooling2d
average_pooling2d( inputs, pool_size, strides, padding='valid', data_format='channels_last', name=None )
參數和前面的最大值池化同樣。
全鏈接dense層定義在 tensorflow/python/layers/core.py
.
三、tf.layers.dense
dense( inputs, units, activation=None, use_bias=True, kernel_initializer=None, bias_initializer=tf.zeros_initializer(), kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, trainable=True, name=None, reuse=None )
inputs
: 輸入數據,2維tensor.units
: 該層的神經單元結點數。activation
: 激活函數.use_bias
: Boolean型,是否使用偏置項.kernel_initializer
: 卷積核的初始化器.bias_initializer
: 偏置項的初始化器,默認初始化爲0.kernel_regularizer
: 卷積核化的正則化,可選.bias_regularizer
: 偏置項的正則化,可選.activity_regularizer
: 輸出的正則化函數.trainable
: Boolean型,代表該層的參數是否參與訓練。若是爲真則變量加入到圖集合中GraphKeys.TRAINABLE_VARIABLES
(seetf.Variable
).name
: 層的名字.reuse
: Boolean型, 是否重複使用參數.
全鏈接層執行操做 outputs = activation(inputs.kernel + bias)
若是執行結果不想進行激活操做,則設置activation=None。
例:
#全鏈接層 dense1 = tf.layers.dense(inputs=pool3, units=1024, activation=tf.nn.relu) dense2= tf.layers.dense(inputs=dense1, units=512, activation=tf.nn.relu) logits= tf.layers.dense(inputs=dense2, units=10, activation=None)
也能夠對全鏈接層的參數進行正則化約束:
dense1 = tf.layers.dense(inputs=pool3, units=1024, activation=tf.nn.relu,kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
10、tensorflow 1.0 學習:參數和特徵的提取
在tf中,參與訓練的參數可用 tf.trainable_variables()提取出來,如:
#取出全部參與訓練的參數 params=tf.trainable_variables() print("Trainable variables:------------------------") #循環列出參數 for idx, v in enumerate(params): print(" param {:3}: {:15} {}".format(idx, str(v.get_shape()), v.name))
這裏只能查看參數的shape和name,並無具體的值。若是要查看參數具體的值的話,必須先初始化,即:
sess=tf.Session() sess.run(tf.global_variables_initializer())
同理,咱們也能夠提取圖片通過訓練後的值。圖片通過卷積後變成了特徵,要提取這些特徵,必須先把圖片feed進去。
具體看實例:
# -*- coding: utf-8 -*- """ Created on Sat Jun 3 12:07:59 2017 @author: Administrator """ import tensorflow as tf from skimage import io,transform import numpy as np #-----------------構建網絡---------------------- #佔位符 x=tf.placeholder(tf.float32,shape=[None,100,100,3],name='x') y_=tf.placeholder(tf.int32,shape=[None,],name='y_') #第一個卷積層(100——>50) conv1=tf.layers.conv2d( inputs=x, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool1=tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2) #第二個卷積層(50->25) conv2=tf.layers.conv2d( inputs=pool1, filters=64, kernel_size=[5, 5], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool2=tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2) #第三個卷積層(25->12) conv3=tf.layers.conv2d( inputs=pool2, filters=128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool3=tf.layers.max_pooling2d(inputs=conv3, pool_size=[2, 2], strides=2) #第四個卷積層(12->6) conv4=tf.layers.conv2d( inputs=pool3, filters=128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01)) pool4=tf.layers.max_pooling2d(inputs=conv4, pool_size=[2, 2], strides=2) re1 = tf.reshape(pool4, [-1, 6 * 6 * 128]) #全鏈接層 dense1 = tf.layers.dense(inputs=re1, units=1024, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) dense2= tf.layers.dense(inputs=dense1, units=512, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) logits= tf.layers.dense(inputs=dense2, units=5, activation=None, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) #---------------------------網絡結束--------------------------- #%% #取出全部參與訓練的參數 params=tf.trainable_variables() print("Trainable variables:------------------------") #循環列出參數 for idx, v in enumerate(params): print(" param {:3}: {:15} {}".format(idx, str(v.get_shape()), v.name)) #%% #讀取圖片 img=io.imread('d:/cat.jpg') #resize成100*100 img=transform.resize(img,(100,100)) #三維變四維(100,100,3)-->(1,100,100,3) img=img[np.newaxis,:,:,:] img=np.asarray(img,np.float32) sess=tf.Session() sess.run(tf.global_variables_initializer()) #提取最後一個全鏈接層的參數 W和b W=sess.run(params[26]) b=sess.run(params[27]) #提取第二個全鏈接層的輸出值做爲特徵 fea=sess.run(dense2,feed_dict={x:img})
最後一條語句就是提取某層的數據輸出做爲特徵。
注意:這個程序並無通過訓練,所以提取出的參數只是初始化的參數。
11、tensorflow 1.0 學習:模型的保存與恢復(Saver)
將訓練好的模型參數保存起來,以便之後進行驗證或測試,這是咱們常常要作的事情。tf裏面提供模型保存的是tf.train.Saver()模塊。
模型保存,先要建立一個Saver對象:如
saver=tf.train.Saver()
在建立這個Saver對象的時候,有一個參數咱們常常會用到,就是 max_to_keep 參數,這個是用來設置保存模型的個數,默認爲5,即 max_to_keep=5,保存最近的5個模型。若是你想每訓練一代(epoch)就想保存一次模型,則能夠將 max_to_keep設置爲None或者0,如:
saver=tf.train.Saver(max_to_keep=0)
可是這樣作除了多佔用硬盤,並無實際多大的用處,所以不推薦。
固然,若是你只想保存最後一代的模型,則只須要將max_to_keep設置爲1便可,即
saver=tf.train.Saver(max_to_keep=1)
建立完saver對象後,就能夠保存訓練好的模型了,如:
saver.save(sess,'ckpt/mnist.ckpt',global_step=step)
第一個參數sess,這個就不用說了。第二個參數設定保存的路徑和名字,第三個參數將訓練的次數做爲後綴加入到模型名字中。
saver.save(sess, 'my-model', global_step=0) ==> filename: 'my-model-0'
...
saver.save(sess, 'my-model', global_step=1000) ==> filename: 'my-model-1000'
看一個mnist實例:
# -*- coding: utf-8 -*- """ Created on Sun Jun 4 10:29:48 2017 @author: Administrator """ import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=False) x = tf.placeholder(tf.float32, [None, 784]) y_=tf.placeholder(tf.int32,[None,]) dense1 = tf.layers.dense(inputs=x, units=1024, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) dense2= tf.layers.dense(inputs=dense1, units=512, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) logits= tf.layers.dense(inputs=dense2, units=10, activation=None, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) loss=tf.losses.sparse_softmax_cross_entropy(labels=y_,logits=logits) train_op=tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) correct_prediction = tf.equal(tf.cast(tf.argmax(logits,1),tf.int32), y_) acc= tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) sess=tf.InteractiveSession() sess.run(tf.global_variables_initializer()) saver=tf.train.Saver(max_to_keep=1) for i in range(100): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys}) val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc)) saver.save(sess,'ckpt/mnist.ckpt',global_step=i+1) sess.close()
代碼中紅色部分就是保存模型的代碼,雖然我在每訓練完一代的時候,都進行了保存,但後一次保存的模型會覆蓋前一次的,最終只會保存最後一次。所以咱們能夠節省時間,將保存代碼放到循環以外(僅適用max_to_keep=1,不然仍是須要放在循環內).
在實驗中,最後一代可能並非驗證精度最高的一代,所以咱們並不想默認保存最後一代,而是想保存驗證精度最高的一代,則加個中間變量和判斷語句就能夠了。
saver=tf.train.Saver(max_to_keep=1) max_acc=0 for i in range(100): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys}) val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc)) if val_acc>max_acc: max_acc=val_acc saver.save(sess,'ckpt/mnist.ckpt',global_step=i+1) sess.close()
若是咱們想保存驗證精度最高的三代,且把每次的驗證精度也隨之保存下來,則咱們能夠生成一個txt文件用於保存。
saver=tf.train.Saver(max_to_keep=3) max_acc=0 f=open('ckpt/acc.txt','w') for i in range(100): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys}) val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc)) f.write(str(i+1)+', val_acc: '+str(val_acc)+'\n') if val_acc>max_acc: max_acc=val_acc saver.save(sess,'ckpt/mnist.ckpt',global_step=i+1) f.close() sess.close()
模型的恢復用的是restore()函數,它須要兩個參數restore(sess, save_path),save_path指的是保存的模型路徑。咱們可使用tf.train.latest_checkpoint()來自動獲取最後一次保存的模型。如:
model_file=tf.train.latest_checkpoint('ckpt/') saver.restore(sess,model_file)
則程序後半段代碼咱們能夠改成:
sess=tf.InteractiveSession() sess.run(tf.global_variables_initializer()) is_train=False saver=tf.train.Saver(max_to_keep=3) #訓練階段 if is_train: max_acc=0 f=open('ckpt/acc.txt','w') for i in range(100): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys}) val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc)) f.write(str(i+1)+', val_acc: '+str(val_acc)+'\n') if val_acc>max_acc: max_acc=val_acc saver.save(sess,'ckpt/mnist.ckpt',global_step=i+1) f.close() #驗證階段 else: model_file=tf.train.latest_checkpoint('ckpt/') saver.restore(sess,model_file) val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print('val_loss:%f, val_acc:%f'%(val_loss,val_acc)) sess.close()
標紅的地方,就是與保存、恢復模型相關的代碼。用一個bool型變量is_train來控制訓練和驗證兩個階段。
整個源程序:
# -*- coding: utf-8 -*- """ Created on Sun Jun 4 10:29:48 2017 @author: Administrator """ import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=False) x = tf.placeholder(tf.float32, [None, 784]) y_=tf.placeholder(tf.int32,[None,]) dense1 = tf.layers.dense(inputs=x, units=1024, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) dense2= tf.layers.dense(inputs=dense1, units=512, activation=tf.nn.relu, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) logits= tf.layers.dense(inputs=dense2, units=10, activation=None, kernel_initializer=tf.truncated_normal_initializer(stddev=0.01), kernel_regularizer=tf.nn.l2_loss) loss=tf.losses.sparse_softmax_cross_entropy(labels=y_,logits=logits) train_op=tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) correct_prediction = tf.equal(tf.cast(tf.argmax(logits,1),tf.int32), y_) acc= tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) sess=tf.InteractiveSession() sess.run(tf.global_variables_initializer()) is_train=True saver=tf.train.Saver(max_to_keep=3) #訓練階段 if is_train: max_acc=0 f=open('ckpt/acc.txt','w') for i in range(100): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys}) val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc)) f.write(str(i+1)+', val_acc: '+str(val_acc)+'\n') if val_acc>max_acc: max_acc=val_acc saver.save(sess,'ckpt/mnist.ckpt',global_step=i+1) f.close() #驗證階段 else: model_file=tf.train.latest_checkpoint('ckpt/') saver.restore(sess,model_file) val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels}) print('val_loss:%f, val_acc:%f'%(val_loss,val_acc)) sess.close()
參考文章:http://blog.csdn.net/u011500062/article/details/51728830
12、tensorflow 1.0 學習:用別人訓練好的模型來進行圖像分類
谷歌在大型圖像數據庫ImageNet上訓練好了一個Inception-v3模型,這個模型咱們能夠直接用來進來圖像分類。
下載地址:https://storage.googleapis.com/download.tensorflow.org/models/inception_dec_2015.zip
下載完解壓後,獲得幾個文件:
其中的classify_image_graph_def.pb 文件就是訓練好的Inception-v3模型。
imagenet_synset_to_human_label_map.txt是類別文件。
隨機找一張圖片:如
對這張圖片進行識別,看它屬於什麼類?
代碼以下:先建立一個類NodeLookup來將softmax機率值映射到標籤上。
而後建立一個函數create_graph()來讀取模型。
最後讀取圖片進行分類識別:
# -*- coding: utf-8 -*- import tensorflow as tf import numpy as np import re import os model_dir='D:/tf/model/' image='d:/cat.jpg' #將類別ID轉換爲人類易讀的標籤 class NodeLookup(object): def __init__(self, label_lookup_path=None, uid_lookup_path=None): if not label_lookup_path: label_lookup_path = os.path.join( model_dir, 'imagenet_2012_challenge_label_map_proto.pbtxt') if not uid_lookup_path: uid_lookup_path = os.path.join( model_dir, 'imagenet_synset_to_human_label_map.txt') self.node_lookup = self.load(label_lookup_path, uid_lookup_path) def load(self, label_lookup_path, uid_lookup_path): if not tf.gfile.Exists(uid_lookup_path): tf.logging.fatal('File does not exist %s', uid_lookup_path) if not tf.gfile.Exists(label_lookup_path): tf.logging.fatal('File does not exist %s', label_lookup_path) # Loads mapping from string UID to human-readable string proto_as_ascii_lines = tf.gfile.GFile(uid_lookup_path).readlines() uid_to_human = {} p = re.compile(r'[n\d]*[ \S,]*') for line in proto_as_ascii_lines: parsed_items = p.findall(line) uid = parsed_items[0] human_string = parsed_items[2] uid_to_human[uid] = human_string # Loads mapping from string UID to integer node ID. node_id_to_uid = {} proto_as_ascii = tf.gfile.GFile(label_lookup_path).readlines() for line in proto_as_ascii: if line.startswith(' target_class:'): target_class = int(line.split(': ')[1]) if line.startswith(' target_class_string:'): target_class_string = line.split(': ')[1] node_id_to_uid[target_class] = target_class_string[1:-2] # Loads the final mapping of integer node ID to human-readable string node_id_to_name = {} for key, val in node_id_to_uid.items(): if val not in uid_to_human: tf.logging.fatal('Failed to locate: %s', val) name = uid_to_human[val] node_id_to_name[key] = name return node_id_to_name def id_to_string(self, node_id): if node_id not in self.node_lookup: return '' return self.node_lookup[node_id] #讀取訓練好的Inception-v3模型來建立graph def create_graph(): with tf.gfile.FastGFile(os.path.join( model_dir, 'classify_image_graph_def.pb'), 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) tf.import_graph_def(graph_def, name='') #讀取圖片 image_data = tf.gfile.FastGFile(image, 'rb').read() #建立graph create_graph() sess=tf.Session() #Inception-v3模型的最後一層softmax的輸出 softmax_tensor= sess.graph.get_tensor_by_name('softmax:0') #輸入圖像數據,獲得softmax機率值(一個shape=(1,1008)的向量) predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data}) #(1,1008)->(1008,) predictions = np.squeeze(predictions) # ID --> English string label. node_lookup = NodeLookup() #取出前5個機率最大的值(top-5) top_5 = predictions.argsort()[-5:][::-1] for node_id in top_5: human_string = node_lookup.id_to_string(node_id) score = predictions[node_id] print('%s (score = %.5f)' % (human_string, score)) sess.close()
最後輸出:
tiger cat (score = 0.40316)
Egyptian cat (score = 0.21686)
tabby, tabby cat (score = 0.21348)
lynx, catamount (score = 0.01403)
Persian cat (score = 0.00394)
十3、tensorflow 1.0 學習:十圖詳解tensorflow數據讀取機制
本文轉自:https://zhuanlan.zhihu.com/p/27238630
在學習tensorflow的過程當中,有不少小夥伴反映讀取數據這一塊很難理解。確實這一塊官方的教程比較簡略,網上也找不到什麼合適的學習材料。今天這篇文章就以圖片的形式,用最簡單的語言,爲你們詳細解釋一下tensorflow的數據讀取機制,文章的最後還會給出實戰代碼以供參考。
1、tensorflow讀取機制圖解
首先須要思考的一個問題是,什麼是數據讀取?以圖像數據爲例,讀取數據的過程能夠用下圖來表示:
假設咱們的硬盤中有一個圖片數據集0001.jpg,0002.jpg,0003.jpg……咱們只須要把它們讀取到內存中,而後提供給GPU或是CPU進行計算就能夠了。這聽起來很容易,但事實遠沒有那麼簡單。事實上,咱們必需要把數據先讀入後才能進行計算,假設讀入用時0.1s,計算用時0.9s,那麼就意味着每過1s,GPU都會有0.1s無事可作,這就大大下降了運算的效率。
如何解決這個問題?方法就是將讀入數據和計算分別放在兩個線程中,將數據讀入內存的一個隊列,以下圖所示:
讀取線程源源不斷地將文件系統中的圖片讀入到一個內存的隊列中,而負責計算的是另外一個線程,計算須要數據時,直接從內存隊列中取就能夠了。這樣就能夠解決GPU由於IO而空閒的問題!
而在tensorflow中,爲了方便管理,在內存隊列前又添加了一層所謂的「文件名隊列」。
爲何要添加這一層文件名隊列?咱們首先得了解機器學習中的一個概念:epoch。對於一個數據集來說,運行一個epoch就是將這個數據集中的圖片所有計算一遍。如一個數據集中有三張圖片A.jpg、B.jpg、C.jpg,那麼跑一個epoch就是指對A、B、C三張圖片都計算了一遍。兩個epoch就是指先對A、B、C各計算一遍,而後再所有計算一遍,也就是說每張圖片都計算了兩遍。
tensorflow使用文件名隊列+內存隊列雙隊列的形式讀入文件,能夠很好地管理epoch。下面咱們用圖片的形式來講明這個機制的運行方式。以下圖,仍是以數據集A.jpg, B.jpg, C.jpg爲例,假定咱們要跑一個epoch,那麼咱們就在文件名隊列中把A、B、C各放入一次,並在以後標註隊列結束。
程序運行後,內存隊列首先讀入A(此時A從文件名隊列中出隊):
再依次讀入B和C:
此時,若是再嘗試讀入,系統因爲檢測到了「結束」,就會自動拋出一個異常(OutOfRange)。外部捕捉到這個異常後就能夠結束程序了。這就是tensorflow中讀取數據的基本機制。若是咱們要跑2個epoch而不是1個epoch,那隻要在文件名隊列中將A、B、C依次放入兩次再標記結束就能夠了。
2、tensorflow讀取數據機制的對應函數
如何在tensorflow中建立上述的兩個隊列呢?
對於文件名隊列,咱們使用tf.train.string_input_producer函數。這個函數須要傳入一個文件名list,系統會自動將它轉爲一個文件名隊列。
此外tf.train.string_input_producer還有兩個重要的參數,一個是num_epochs,它就是咱們上文中提到的epoch數。另一個就是shuffle,shuffle是指在一個epoch內文件的順序是否被打亂。若設置shuffle=False,以下圖,每一個epoch內,數據仍是按照A、B、C的順序進入文件名隊列,這個順序不會改變:
若是設置shuffle=True,那麼在一個epoch內,數據的先後順序就會被打亂,以下圖所示:
在tensorflow中,內存隊列不須要咱們本身創建,咱們只須要使用reader對象從文件名隊列中讀取數據就能夠了,具體實現能夠參考下面的實戰代碼。
除了tf.train.string_input_producer外,咱們還要額外介紹一個函數:tf.train.start_queue_runners。初學者會常常在代碼中看到這個函數,但每每很難理解它的用處,在這裏,有了上面的鋪墊後,咱們就能夠解釋這個函數的做用了。
在咱們使用tf.train.string_input_producer建立文件名隊列後,整個系統其實仍是處於「停滯狀態」的,也就是說,咱們文件名並無真正被加入到隊列中(以下圖所示)。此時若是咱們開始計算,由於內存隊列中什麼也沒有,計算單元就會一直等待,致使整個系統被阻塞。
而使用tf.train.start_queue_runners以後,纔會啓動填充隊列的線程,這時系統就再也不「停滯」。此後計算單元就能夠拿到數據並進行計算,整個程序也就跑起來了,這就是函數tf.train.start_queue_runners的用處。
3、實戰代碼
咱們用一個具體的例子感覺tensorflow中的數據讀取。如圖,假設咱們在當前文件夾中已經有A.jpg、B.jpg、C.jpg三張圖片,咱們但願讀取這三張圖片5個epoch而且把讀取的結果從新存到read文件夾中。
對應的代碼以下:
# 導入tensorflow import tensorflow as tf # 新建一個Session with tf.Session() as sess: # 咱們要讀三幅圖片A.jpg, B.jpg, C.jpg filename = ['A.jpg', 'B.jpg', 'C.jpg'] # string_input_producer會產生一個文件名隊列 filename_queue = tf.train.string_input_producer(filename, shuffle=False, num_epochs=5) # reader從文件名隊列中讀數據。對應的方法是reader.read reader = tf.WholeFileReader() key, value = reader.read(filename_queue) # tf.train.string_input_producer定義了一個epoch變量,要對它進行初始化 tf.local_variables_initializer().run() # 使用start_queue_runners以後,纔會開始填充隊列 threads = tf.train.start_queue_runners(sess=sess) i = 0 while True: i += 1 # 獲取圖片數據並保存 image_data = sess.run(value) with open('read/test_%d.jpg' % i, 'wb') as f: f.write(image_data)
咱們這裏使用filename_queue = tf.train.string_input_producer(filename, shuffle=False, num_epochs=5)創建了一個會跑5個epoch的文件名隊列。並使用reader讀取,reader每次讀取一張圖片並保存。
運行代碼後,咱們獲得就能夠看到read文件夾中的圖片,正好是按順序的5個epoch:
若是咱們設置filename_queue = tf.train.string_input_producer(filename, shuffle=False, num_epochs=5)中的shuffle=True,那麼在每一個epoch內圖像就會被打亂,如圖所示:
咱們這裏只是用三張圖片舉例,實際應用中一個數據集確定不止3張圖片,不過涉及到的原理都是共通的。