【Tensorflow】北京大學tensorflow學習筆記

AI_TensorflowNotebook

北京大學公開課學習筆記
課程鏈接:https://www.icourse163.org/course/PKU-1002536002
課程github主頁:鏈接
推薦課程中的助教筆記,內容更加全面。筆記鏈接 提取碼: jhk5

本文相關代碼:github個人主頁

1 AI概述與環境搭建

1.1 人工智能概述

  1. 人工智能的概念、興衰史、學科帶頭人、常見消費產品。
  2. 機器學習概念、應用領域(CV、NLP)、三要素(數據、算法、算力)
  3. 深度學習概念、計算機實現。
  4. 關係:人工智能》機器學習》深度學習

1.2 環境配置

課程代碼基於python2.7,tensorflow版本:1.3.0,系統:windows10,其他環境可以自行百度或參考課程視頻安裝。

個人使用64位虛擬機:ubuntu18.04,安裝過程遇到的一些問題:

  1. 安裝pip:
    sudu apt install python-pip
  2. pip 安裝完成後去 tflearn.org 左側Installation 找到對應python版本的TensorFlow下載指令。
    如ubuntu/linux 64-bit,CPU only,python2.7對應:$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp27-none-linux_x86_64.whl
  3. 藉助輸入下面的對應python2 的安裝指令:$ sudo pip install $TF_BINARY_URL
  4. 安裝後命令行進入python,輸入:import tensorflow as tf不報錯說明安裝成功,輸入:print tf.__version__查看版本。

1.3 安裝必要包

使用清華鏡像,安裝其他需要的python包,如pandas,命令行輸入:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pandas

安裝vim:sudo apt-get install vim

替換apt軟件源爲阿里雲源:https://blog.csdn.net/zhangjiahao14/article/details/80554616
這裏ubuntu的版本影響源地址,所以之前一直替換不成功。

python2.7比較老,很多包和函數都因爲更新會出現各種各樣的問題,遇到問題多找找博客論壇。

2 編程語言基礎

2.1 常用基礎命令

  1. pwd:當前路徑
  2. ls:顯示文件
  3. cd… 返回上一級 …/…上兩級 ~ 返回home目錄
  4. mkdir:創建文件夾
  5. vim A.py 用vim打開一個py文件
  6. vim全選,全部複製,全部刪除,先按esc,分別對應ggVG、ggyG、dG
  7. :q 強制退出vim :wq保存更改退出 :q! 不保存退出 如果文件無法編輯保存退出,打開文件的時候使用sudo vim 文件命名
    其他vim指令參考:點此連接

2.2 ubuntu指令

  1. 更新源:sudo apt-get update
  2. 更新已安裝的軟件:sudo apt-get upgrade
  3. 刪除包:sudo apt-get remove package
  4. 打開命令終端:Ctrl+Alt+T
  5. 回到桌面:win+D
  6. 切換輸入法:win+空格
  7. 其他快捷鍵在:設置->設備->鍵盤 處可看。

2.3 python基礎語法

學習本課程的都是有基礎的,不再贅述。

3 Tensorflow框架介紹

3.1 張量、圖、會話

基於tensorflow的神經網絡就是用張量(Tensor)表示數據,用計算圖(Graph)搭建網絡,用會話(Sess)進行運算,優化權重參數獲得模型。
1、張量(Tensor):多維數組的特殊表示形式

#coding:utf-8
import tensorflow as tf
a=tf.constant([1.0,2.0])	#張量
b=tf.constant([3.0,4.0])
result=a+b
print result

輸出:Tensor(“add:0”, shape=(2,), dtype=float32)

2、計算圖(Graph):搭建神經網絡的計算結構(乘加),不進行計算。

#coding:utf-8
import tensorflow as tf
x = tf.constant([[1.0, 2.0]])
w = tf.constant([[3.0], [4.0]])
y=tf.matmul(x,w)
print y

輸出:
Tensor(“MatMul:0”, shape=(1, 1), dtype=float32)

3、會話(Session):會話爲執行計算結果

with tf.Session() as sess:
	print sess.run(y)

[[11.]]

4、常用參數tf.Variable()

tf.random_normal()		#生成正態分佈隨機數
tf.truncated_normal()	#去大偏離點的正態
tf.random_uniform()		#均勻分佈隨機
tf.zeros()				#全0
tf.ones()				#全1
tf.fill()				#全部爲某一個給定值
tf.constant([])		#給指定值,可不同

涉及到隨機數時給定seed即可生成相同隨機數。

3.2 前向傳播

將數據輸入,搭建好的Graph,Session結構,經卷積、池化、非線性激活等操作輸出運算結果。

#coding:utf-8
import tensorflow as tf

x = tf.constant([[0.7, 0.5]])  #輸入
w1= tf.Variable(tf.random_normal([2, 5], stddev=1, seed=1))  #兩層參數w   五個節點
w2= tf.Variable(tf.random_normal([5, 1], stddev=1, seed=1))

a = tf.matmul(x, w1)		#前向傳播計算
y = tf.matmul(a, w2)

with tf.Session() as sess: 
init_op = tf.global_variables_initializer()		#彙總變量
sess.run(init_op)					#變量初始化
print"y in test is:\n",sess.run(y) 		#計算接點輸出

使用:tf.placeholder(tf.float32, shape=(A, B))對輸入數據佔位,選擇喂入一組(A=1)或多組(A=None),以及選擇數據屬性(B=)。

喂1組,每組2列:

x = tf.placeholder(tf.float32, shape=(1, 2))
sess.run(y, feed_dict={x: [[0.6,0.4]]})

喂2組,每組3列:

x = tf.placeholder(tf.float32, shape=(None, 3))
sess.run(y, feed_dict={x: [[0.6,0.4,0.2],[0.3,0.5,0.8]]})

3.3 反向傳播

指定學習率、損失函數等參數不斷喂入數據進行參數w權重偏置b的優化,達到最小損失,參數最優。

1、損失函數(loss):預測值yu和已知答案y的差值,優化的目標,使它最小。
常用方法:
均方誤差(MSE): 預測yu和標準y差的平方和再求平均

 loss_MSE = tf.reduce_mean(tf.square(y-yu))

交叉熵(CE):概率分佈距離,只越大預測、實際差距越大。

ce = -tf.reduce_mean(yu*tf.log(tf.clip_by_value(yu,1e-12,1.0)))		#限定yu作爲log指數不爲0

自定義:其他損失函數。

2、 學習率(learning_rate)
參數更新的幅度,一般預設0.001

3、優化器選擇:

train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_MSE)		#梯度下降
train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_MSE)
train_step = tf.train.AdamOptimizer(0.001).minimize(loss_MSE)

常見優化器優缺點比較:參考博客

訓練時可以加入 time 模塊計算時間。

4、激活函數:
增加模型的表達力,提高非線性分類的能力。

  • relu函數:tf.nn.relu()
  • sigmoid函數:tf.nn.sigmoid()
  • tanh函數:tf.nn.tanh()

常用激活函數理解和總結:StevenSun2014的博客

3.4 神經網絡複雜度

與神經網絡層數和參數個數有關。

神經網絡層數爲隱含層個數+1,沒經過運算的不算(輸入層不算,輸出算)
參數:總的權重參數w個數 + 總偏置項b個數。權重參數w個數看每層前後節點乘積和,總偏置b個數看每兩層後靠後一層的節點數量。

4 神經網絡優化

4.0先導環節

tensorflow裏的一些常用函數

tf.get_collection("")
#從集合中取出全部變量形成列表
tf.add_n([])
#列表內對應元素相加
tf.cast(x,dtype)
#將x轉化爲dtype類型
f.argmax(x,axis=)
#返回最大值索引號
with tf.Graph().as_default as g:
#將()其中的節點用在計算圖 g 中,一般用於復現定義好的網絡

4.1 損失函數

MSE、CE、自定義三種,再tensorflow中的使用不再贅述,參考上節。
在交叉熵損失函數使用時如果使用softmax()轉化爲分類概率分佈:

CE = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=,labels=tf.argmax(yu,1))	#返回每行在列維度的最大值索引
CEM = tf.reduce_mean(CE)

4.2 學習率

可以設置靜態學習率爲定值,不宜過小過大,過小損失函數收斂很慢,較大容易振盪不收斂。

指數衰減學習率:根據訓練輪數動態更新學習率。

lr = lr_base * lr_decay^(global_step/lr_step)
  • lr_base:學習率初始值,學習率基數
  • lr_decay:學習率衰減率,屬於(0,1)
  • global_step:運行了多少輪batch_size
  • lr_step:多少輪更新(減低)一次學習率,取(總樣本數/batch_size)

在tensorflow中:

global_step = tf.Variable(0,trainable = False)	#輪數不可訓練
lr = tf.train.exponential_decay(
				    lr_base,
				    global_step,
				    lr_step,
				    lr_decay,
				    staircase = Ture) 
#staircase = Ture 時,比值取整,梯形衰減,False平滑衰減

指數衰減的學習率,在迭代初期得到較高的下降速度,可以在較小的訓練輪數下取得更有收斂度。

注意:global_step的值是使學習率更新的關鍵:

train_step = tf.train.GradientDescentOptimizer(lr).minimize(loss, global_step=global_step)

如果不在訓練目標**minimize(loss, global_step=global_step)**里加上global_step=global_step的話這個數值不會變化,學習率也就不會變化。

4.3 滑動平均

記錄網絡中每個參數一段時間內過往值的平均值,增加模型的泛化能力。針對所有參數w和b

滑動均值初值 = 參數初值
滑動均值 = 衰減率 * 上一滑動均值 + (1-衰減率)* 更新的參數值(w或b)
衰減率 = Min{ Moving_Average_Decay,(1+global_step)/(10+global_step)}

實際使用:

ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)		#global_step當前輪數
ema_op = ema.apply(tf.trainable_variables())	#對所有待優化的參數求滑動平均
with tf.contral_dependencies([train_step,ema_op]):  #只優化這兩個參數集
train_op = tf.no_np(name='train')	#執行完上面兩之後什麼也不做

ema.average(w1)可以在運行過程調用查看參數情況

4.4 正則化

在模型損失函數中給每個參數加上權重,抑制模型訓練數據噪聲。
通常只對權重參數w使用,緩解過擬合現象。

loss_all = loss(CE,MSE等) + REGULARIZER * loss(w)  
#loss_all表示模型總的損失函數,REGULARIZER表示超參數權重,決定w在總loss中的比例。loss(w)是進行正則化的參數。

常用的兩種正則化方法:
L1正則: L1_loss=∑|w|

loss(w) = tf.contrib.layers.l1_regularizer(REGUIARIZER)(w)

L2正則:L2_loss=∑|w^2|

loss(w) = tf.contrib.layers.l2_regularizer(REGUIARIZER)(w)

tensorflow中使用方法:

loss_ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(yu, 1))
loss_cem = tf.reduce_mean(loss_ce)
loss_all = loss_cem + tf.add_n(tf.get_collection('losses')) #這裏的losses就是經過正則化的,

其他正則化方法可參考博客:Maples丶丶的博客

示例:初始分佈
在這裏插入圖片描述
無正則化訓練:60000次,學習率0.001.

在這裏插入圖片描述
有正則化訓練:60000次,學習率0.001.

在這裏插入圖片描述
可以調整其他參數查看效果:如訓練輪數爲120000次時:

在這裏插入圖片描述

4.5 神經網絡搭建樣例

1、前向傳播forward.py

def forward(x,regularizer):		#聲明權重、參數,和預測輸出的計算方法
    w = 
    b = 
    y = 
    return y		#輸出結果

def get_weight(shape,regularizer):		#shape是中間權重矩陣形狀
    w = tf.Variable()		#一般用隨機函數聲明
    if regularizer != None: tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
	#聲明如果有正則化超參數,則對w使用正則化
    return w

def get_bias(shape):		#偏置形狀和參數
    b = tf.Variable()
    return b

2、反向傳播backward.py

def backward():
    x = tf.placeholder()
    y = tf.placeholder()		#標準的x和類標籤y 數據佔位
    yu = forward.forward(x,REGULARIZER)  #調用forward.py裏的forward函數計算預測輸出
    global_step = tf.Variable(0,trainable=False)
    loss = 可視任務情況選擇加入優化方法

①正則化的優化方法:
內容參考上一節:

最終loss = 基本損失loss(CE等) + 正則化損失tf.add_n(tf.get_collection('losses'))

②指數衰減學習率優化:
調用函數參考上節。
最終的訓練目標:train_step = tf.train.GradientDesentOptimizer(lr).minimize(loss,global_step = global_step)

優化器除梯度下降也可選其他MomentumOptimizer、AdamOptimizer等。

③滑動平均優化:

ema = tf.train.ExponentialMovingAverage(M_A_DECAY,global_step)
ema_op = ema.apply(tf.trainable_variables())		#應用到所有參數求滑動平均
with tf.contral_dependencies([train_step,ema_op]):  	#只執行這兩個部分
train_op = tf.no_np(name='train')		#之後無操作

④實例化聲明:用以保存模型參數:

 saver = tf.train.Saver()

⑤所有變量環節初始化

with tf.Session() as sess:
	init_op = tf.global_variables_initializer()
	sess.run(init_op)		#生成會話, 初始化變量

for i in range(STEPS):
	sess.run(train_step,feed_dict={x: ,y_: })		#喂數
		if i % 輪數 ==0:	
			print 		#每多少輪顯示輪數或者loss損失值
			saver.save()	#保存模型及參數

⑥判斷backward是否爲主文件:

if __name__ = '__main__':
    backward()

3 測試文件test.py

def test():
    with tf.Graph().as_default() as g:  #復現計算圖
    x = tf.placeholder(tf.float32, [None, ])
    y = tf.placeholder(tf.float32, [None, ])		#輸入x y 佔位
    yu = forward.forward(x, None)  #前向傳播計算輸出yu

實例化帶滑動平均的saver對象,所有參數在會話中被加載時會被賦值爲各自的滑動平均值。就是調用以前經過滑動平均的參數。

    ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
    ema_restore = ema.variables_to_restore()
    saver = tf.train.Saver(ema_restore)

計算準確率

    correct_prediction = tf.equal(tf.argmax(yu, 1), tf.argmax(y, 1))
	#yu是神經網絡喂入的batch_size組數據後計算的結果,是batchsiZe組*10(單個標籤所含10分類)的二維數組。
	#1表示argmax函數選取最大值的操作僅在第一個維度,就是返回每行裏的最大值對應索引。

    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
	#cast()把equal()函數獲取的布爾值轉化爲實數,再用tf.reduce_mean()求平均,獲得準確率

    while True:
        with tf.Session() as sess:
            ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
            #加載模型,賦參數滑動平均值
            if ckpt and ckpt.model_checkpoint_path:		#確認模型路徑和文件都存在
                saver.restore(sess, ckpt.model_checkpoint_path) #恢復到當前會話
                global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1] 
                accuracy_score = sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
                print("經過 %s 訓練輪數, 準確率爲: %g" % (global_step, accuracy_score))
            else:
                print('沒有對應模型')
                return
        time.sleep(T)		#測試進行的快,訓練保存模型進行的慢,不延遲可能多次調用的是同一個模型的參數,若不是一起運行則無影響

5 全連接網絡基礎

5.1 MNIST數據集

mnist爲黑底白字的手寫數字數據集,每行圖片大小爲28*28像素,附帶每張圖片的標籤信息。純黑像素爲 0,純白色像素爲1.
數據集分爲train, validation 和 test 三個數據集。訓練集和驗證集一般用來訓練。

  • train:一般用來訓練調整網絡權重參數,計算訓練集準確率。
  • validation:一般只用來計算準確率,達到閾值就退出訓練。**不使用該數據集調整參數權重。**如果訓練驗證過程中訓練集的準確率仍然不斷上升,但是驗證集準確率不變或者降低了,就過擬合了,停止訓練。
  • test:用來測試網絡的實際預測能力

0加載數據集到指定路徑:

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./python/pymnist/data/", one_hot=True)

1查看各個數據集樣本數量:

print "train sets size:\n",mnist.train.num_examples  
print "validation sets size:\n",mnist.validation.num_examples
print "test sets size:\n",mnist.test.num_examples

2 查看制動數據集、指定圖片的標籤和像素值:

#訓練集中第6張圖片的標籤和像素值    
mnist.train.labels[6]
>>>array([0., 1., 0., 0., 0., 0., 0., 0., 0., 0.])
#該數字爲2

mnist.train.images[6]

3 喂入網絡數據

xs,ys = mnist.train.next_batch(batchsize)

參數 batchsize,表示隨機從訓
練集中抽取 batchsize 個樣本輸入神經網絡,並將樣本的像素值和標籤分別賦
給 xs 和 ys。

5.2 模型的保存、複用和斷點續訓

保存:

saver = tf.train.Saver()
#聲明實例對象

with tf.Session() as sess:
...    
	for i in range(STEPS):
		xs, ys = mnist.train.next_batch(BATCH_SIZE)
		if i % 輪數 == 0:
			saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
#保存模型到當前會話,標註保存時的訓練輪數

模型加載:

with tf.Session() as sess:
	ckpt = tf.train.get_checkpoint_state( 存儲路徑) )
	if ckpt and ckpt.model_checkpoint_path:
		saver.restore(sess, ckpt.model_checkpoint_path)
#如果ckpt模型和保存路徑都存在,複用

斷點續訓:一般加在會話sess開始後初始化的後面,可以繼續之前意外中斷的訓練過程。

ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
if ckpt and  ckpt.model_checkpoint_path:
	saver.restore(sess, ckpt.model_checkpoint_path)

5.3 全連接神經網絡識別手寫體數據

對應文件在文件夾chapter5_fullyConect中。
包含幾個部分:

  • data文件夾:存放下載的mnist數據文件。
  • model文件夾:存放訓練完成保存的模型及各個參數,默認只保存最近的5個。
  • pic文件夾:爲待識別的手寫數字圖片。
  • mnist_backward.py:反向傳播過程,及常見優化方法。
  • mnist_forward.py:定義輸入參數、網絡結構。
  • mnist_test.py:複用模型進行測試,查看準確率。
  • mnist_app.py:應用訓練好的模型實現手寫數字預測。

使用時注意各文件存放路徑,避免使用時調用路徑錯誤,進行圖片預測測試時待判別圖片路徑輸入要完整。

反向傳播:
注意訓練過程可以按 ctrl+Z中斷訓練,模型下次訓練可以繼續,若要重新開始先刪除model文件夾裏的文件。
在這裏插入圖片描述
測試:
在這裏插入圖片描述
應用預測:
在這裏插入圖片描述

6 全連接神經網絡實戰

6.1 與第五章內容重合,不贅述

6.2 以mnist爲例自制數據集

6.2.1 什麼是tfrecords文件

1、tfrecords文件:
一種二進制文件,可先將圖片和標籤製作成該格式的文件。使用這種格式進行數據讀取,會提高內存利用率。
2、 tf.train.Example():
用來存儲訓練數據。tf.train.Example中包含了一個從屬性名稱及取值的字典,其中屬性名稱爲一個字符串,屬性的取值可以爲字符串(BytesList ),實數列表(FloatList )或整數列表(Int64List )。
訓練數據的特徵用 鍵值對 的形式表示。
如:

'img_raw':值 
'label':值 

值取:Byteslist/FloatList/Int64List

3、 SerializeToString( ) :
把數據序列化成字符串存儲。

6.2.2 生成 tfrecords文件

writer = tf.python_io.TFRecordWriter('train.tfrecords') #新建writer文件
.
.#中間讀待制作數據文件過程
.
for content in contents:	#對每個數據處理
	.
	.#取數據路徑、轉爲二進制,打標籤
	.
	example = tf.train.Example(features=tf.train.Features(feature={
            'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
            'label': tf.train.Feature(int64_list=tf.train.Int64List(value=labels))
            }))     #標準封裝格式 每張圖片和標籤封裝到example中
	writer.write(example.SerializeToString())       #序列化存儲
writer.close()	#完成

6.2.3 解析 tfrecords文件

filename_queue = tf.train.string_input_producer([tfRecord_path], shuffle=True)  #解析隊列
reader = tf.TFRecordReader()        #新建reader文件
_, serialized_example = reader.read(filename_queue)     #讀出來的每一個樣本保存
features = tf.parse_single_example(serialized_example,
                                   features={
                                    'label': tf.FixedLenFeature([10], tf.int64),
                                    'img_raw': tf.FixedLenFeature([], tf.string)
                                    })  #解序列化
img = tf.decode_raw(features['img_raw'], tf.uint8)  #恢復圖片
.
.
. #降維,整形 主要是符合選用網絡的輸入要求
.

6.2.4 獲取展示 tfrecords文件

tfrecords_file = '.../train.tfrecords'
image_batch, label_batch = read_tfrecord(tfrecords_file)
img_batch, label_batch = tf.train.shuffle_batch([img, label],
					    batch_size= batch_size,
					    num_threads=2,
					    capacity=2000,
					    min_after_dequeue=1500,
										)
#從總樣本中順序取出capacity組數據,每次打亂順序輸出batch_size組,
#如果capacity小於min_after_dequeue,會再從總樣本中取出數據填滿capacity,
#結果輸出爲隨即取出的batchsize組圖像和標籤數據

此章數據集tfrecords文件製作有部分內容參考博客:鏈接

最後修改測試我沒有成功復現:可參考博客young liu

這部分內容數據及源碼鏈接:鏈接
試了幾次數據文件解壓都有問題。

卷積神經網絡的內容之後單獨整理

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章