在我們使用TensorFlow的時候,有時候需要訓練一個比較復雜的網絡,比如后面的AlexNet,ResNet,GoogleNet等等,由於訓練這些網絡花費的時間比較長,因此我們需要保存模型的參數。
編程基礎案例中主要講解模型的保存和恢復,以及使用幾個案例使我們更好的理解這一塊內容。
一 保存和載入模型
1.保存模型
首先需要建立一個saver,然后在session中通過saver的save即可將模型保存起來,代碼如下:
''' 1.保存模型 ''' ''' 這里是各種構建模型graph的操作,省略.... ''' #創建saver對象 saver = tf.train.Saver() with tf.Session() as sess: #初始化張量 sess.run(tf.global_variables_initializer()) ''' 這里是將數據喂入模型進行訓練,省略... ''' #訓練完成后,保存模型,如果file_name不存在,會自動創建 saver.save(sess,'save_path/file_name')
2.載入模型
載入模型只需要調用saver對象的restore()函數,會從指定的路徑找到模型文件,並覆蓋到相關參數中,代碼如下:
''' 2.載入模型 ''' #創建saver對象 saver = tf.train.Saver() with tf.Session() as sess: #參數可以進行初始化,也可以不進行初始化,即使進行了初始化,初始化的值也會被restore的值覆蓋掉 sess.run(tf.global_variables_initializer()) saver.restore(sess,'save_path/file_name')
二 保存/載入線性回歸模型
在第四節我們講了線性回歸的案列,這里我們就保存這個案例的模型,然后恢復
''' 3.保存和恢復線性回歸模型 ''' import numpy as np import matplotlib.pyplot as plt import os ''' 一准備數據 ''' #設定訓練集數據長度 n_train = 100 #生成x數據,[-1,1]之間,均分成n_train個數據 train_x = np.linspace(-1,1,n_train).reshape(n_train,1) #把x乘以2,在加入(0,0.3)的高斯正太分布 train_y = 2*train_x + np.random.normal(loc=0.0,scale=0.3,size=[n_train,1]) #繪制x,y波形 plt.figure() plt.plot(train_x,train_y,'ro',label='y=2x') #o使用圓點標記一個點 plt.legend() plt.show() #重置圖 (不清空該圖的所有緩存) tf.reset_default_graph() ''' 二 搭建模型 ''' ''' 前向反饋 ''' #創建占位符 input_x = tf.placeholder(dtype=tf.float32) input_y = tf.placeholder(dtype=tf.float32) #模型參數 w = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='w') #設置正太分布參數 初始化權重 b = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='b') #設置正太分布參數 初始化偏置 #前向結構 pred = tf.multiply(w,input_x) + b ''' 反向傳播bp ''' #定義代價函數 選取二次代價函數 cost = tf.reduce_mean(tf.square(input_y - pred)) #設置求解器 采用梯度下降法 學習了設置為0.001 train = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost) ''' 三 迭代模型 ''' #設置迭代次數 training_epochs = 200 display_step = 20 #創建saver對象 在張量聲明之后創建 saver = tf.train.Saver() #生成模型的路徑 savedir = './LinearRegression' #模型文件 savefile = 'linearmodel.cpkt' #路徑不存在創建目錄 if not os.path.isdir(savedir): os.mkdir(savedir) with tf.Session() as sess: #初始化所有張量 sess.run(tf.global_variables_initializer()) #恢復模型 if os.path.isfile(os.path.join(savedir, savefile)+'.meta'): saver.restore(sess,os.path.join(savedir,savefile)) #存放批次值和代價值 plotdata = {'batch_size':[],'loss':[]} #開始迭代 for epoch in range(training_epochs): for (x,y) in zip(train_x,train_y): #開始執行圖 sess.run(train,feed_dict={input_x:x,input_y:y}) #一輪訓練完成后 打印輸出信息 if epoch % display_step == 0: #計算代價值 loss = sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}) print('Epoch {0} cost {1} w {2} b{3}'.format(epoch,loss,sess.run(w),sess.run(b))) #保存每display_step輪訓練后的代價值以及當前迭代輪數 if not loss == np.nan: plotdata['batch_size'].append(epoch) plotdata['loss'].append(loss) #輸出最終結果 print('Finished!') print('cost {0} w {1} b {2}'.format(sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}),sess.run(w),sess.run(b))) #預測 test_x = [2,4,5,7] test_y = sess.run(pred,feed_dict={input_x:test_x}) print('prediction ',test_y) ''' 四 可視化顯示 ''' #繪制原數據點,和估計曲線 plt.figure(figsize=(4.2*2,3.2*1)) plt.subplot(121) plt.plot(train_x,train_y,'ro',label='Original data') plt.plot(train_x,sess.run(w)*train_x + sess.run(b),label ='Estimate data') plt.legend() #繪制代價曲線 plt.subplot(122) plt.plot(plotdata['batch_size'],plotdata['loss'],'b--') plt.xlabel('batch_size') plt.ylabel('loss') plt.title('Minibatch run vs. Training loss') plt.show() #保存參數 saver.save(sess,os.path.join(savedir, savefile))
我們可以看到在LinearRegression文件夾下面生成了四個文件:

這四個文件主要是:
- .meta(存儲網絡結構)、包含了這個TF圖完整信息:如所有變量等。
- .data和.index(存儲訓練好的參數,也叫檢查點文件)、這是一個二進制文件,包含所有權重,偏置,梯度和所有其他存儲的變量的值。
- checkpoint(記錄最新的模型)。保存最后的檢查點的文件 ,如果同時保存了幾個模型,則在這個文件還有這幾個模型的變量數據,由於在這幾個模型中可能存在同名變量,所以取得的數據可能有問題。所以解決方案是最后把不同模型保存在不同文件夾下,或者使用 tf.variable_scope指定變量名字分組。
我們運行多次這個代碼,我們會發現我們每次都是在之前訓練的基礎上繼續訓練模型,這是因為每次訓練我們都先恢復模型再繼續訓練。


三 分析模型內容
如何將我們保存的模型內容打印出來呢?這一節將教你如何將生成的模型的內容打印出來,並觀察其存放的具體數據方式,同時顯示如何將指定內容保存到模型文件中。
1.查看模型內容
''' 3.查看模型內容 ''' from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file print_tensors_in_checkpoint_file(os.path.join(savedir,savefile),None,True)

tensor_name后面是創建的張量名稱,接着是它的數值。
2.保存模型的其它方法
前面我們在創建saver對象的時候沒有傳入任何參數,實際上,tf.train.Saver()函數還可以傳入參數來實現更高級的功能,可以指定存儲張量名字與張量的對應關系,可以寫成這樣:
#或者指定保存參數 代表將張量w,b的值分別放到變量w和b名字中 saver = tf.train.Saver({'w':w,'b':b})
我們也可以這么寫:
saver = tf.train.Saver([w,b]) #存放到一個list里面 savee = tf.train.Saver({v.opname:v for v in [w,b]}) #將op的name當做名字
下面展示一個例子:我們可以看到張量a的值被保存到張量名為b_param上,張量b的值保存到張量名為a_param上。
#給a和b分別指定一個固定的值,將它們顛倒文職存放 a = tf.Variable(1.0,name='a') b = tf.Variable(2.0,name='b') #指定保存參數 saver = tf.train.Saver({'b_param':a,'a_param':b}) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) #保存參數 saver.save(sess,'./test.cpkt') print_tensors_in_checkpoint_file('./test.cpkt',None,True)

注意:當我們在Saver()中指定了保存和恢復的變量時,在恢復的時候我們要保證模型文件中有該變量,不然會報錯。保存的時候模型文件也只會保存指定的變量。如果我們想保存時除了恢復時指定的變量,還保存其他的所有變量,最好的解決方法是創建兩個Saver()對象,一個用於恢復模型,一個用於保存模型。
四 檢查點
由於我們在訓練過程中可能會出現錯誤,如果我們在訓練一個很大的網絡的時候,訓練到快結束的時候,突然報錯,這樣會導致我們之前的訓練功虧一簣,我們心里可能就會很崩潰,因此最好的方法就是能夠在訓練的過程中也保存模型。TensorFlow就提供了一個這樣的功能。
在訓練中保存模型,我們習慣上稱之為保存檢查點(checkpoint)。
1.為模型添加保存檢查點
為我們之前線性回歸的案例追加'保存檢查點'功能,通過該功能,可以生成檢查點文件,並能夠制定生成檢查點文件的個數。
這個例子與保存模型的功能類似,只是保存的位置發生了變化,我們希望在顯示信息是將檢查點保存下來,因此需要在打印信息后面添加檢查點。
另外在這里我們會用到Saver()類的另一個參數,max_to_keep = 1,表名最多保存一個檢查點文件,這樣在迭代過程中,新生成的模型就會覆蓋以前的模型。
在保存時使用了如下代碼傳入了迭代次數:
#每隔display_step輪后保存一次檢查點 saver.save(sess,os.path.join(savedir,savefile),global_step = epoch)
TensorFlow會將迭代次數一起放在檢查點的文件上,所以在載入時,同樣也要指定迭代次數。
# -*- coding: utf-8 -*- """ Created on Wed Apr 18 09:20:53 2018 @author: zy """ ''' 4.檢查點(模型訓練中保存模型) ''' ''' (1)為模型添加保存檢查點(即訓練中保存檢查點) ''' import tensorflow as tf import numpy as np import matplotlib.pyplot as plt import os ''' 一准備數據 ''' #設定訓練集數據長度 n_train = 100 #生成x數據,[-1,1]之間,均分成n_train個數據 train_x = np.linspace(-1,1,n_train).reshape(n_train,1) #把x乘以2,在加入(0,0.3)的高斯正太分布 train_y = 2*train_x + np.random.normal(loc=0.0,scale=0.3,size=[n_train,1]) #繪制x,y波形 plt.figure() plt.plot(train_x,train_y,'ro',label='y=2x') #o使用圓點標記一個點 plt.legend() plt.show() tf.reset_default_graph() ''' 二 搭建模型 ''' ''' 前向反饋 ''' #創建占位符 input_x = tf.placeholder(dtype=tf.float32) input_y = tf.placeholder(dtype=tf.float32) #模型參數 w = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='w') #設置正太分布參數 初始化權重 b = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='b') #設置正太分布參數 初始化偏置 #前向結構 pred = tf.multiply(w,input_x) + b ''' 反向傳播bp ''' #定義代價函數 選取二次代價函數 cost = tf.reduce_mean(tf.square(input_y - pred)) #設置求解器 采用梯度下降法 學習了設置為0.001 train = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost) ''' 三 迭代模型 ''' #設置迭代次數 training_epochs = 200 display_step = 20 #生成Saver對象 saver = tf.train.Saver(max_to_keep = 1) #生成模型的路徑 savedir = './LinearRegression' #模型文件 savefile = 'linearmodel.cpkt' #路徑不存在創建目錄 if not os.path.isdir(savedir): os.mkdir(savedir) with tf.Session() as sess: #初始化所有張量 sess.run(tf.global_variables_initializer()) #恢復模型 if os.path.isfile(os.path.join(savedir, savefile)+'.meta'): saver.restore(sess,os.path.join(savedir,savefile)) #存放批次值和代價值 plotdata = {'batch_size':[],'loss':[]} #開始迭代 for epoch in range(training_epochs): for (x,y) in zip(train_x,train_y): #開始執行圖 sess.run(train,feed_dict={input_x:x,input_y:y}) #一輪訓練完成后 打印輸出信息 if epoch % display_step == 0: #計算代價值 loss = sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}) print('Epoch {0} cost {1} w {2} b{3}'.format(epoch,loss,sess.run(w),sess.run(b))) #保存每display_step輪訓練后的代價值以及當前迭代輪數 if not loss == np.nan: plotdata['batch_size'].append(epoch) plotdata['loss'].append(loss) #每隔display_step輪后保存一次檢查點 saver.save(sess,os.path.join(savedir,savefile),global_step = epoch) #輸出最終結果 print('Finished!') print('cost {0} w {1} b {2}'.format(sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}),sess.run(w),sess.run(b))) #預測 test_x = [2,4,5,7] test_y = sess.run(pred,feed_dict={input_x:test_x}) print('prediction ',test_y) ''' 四 可視化顯示 ''' #繪制原數據點,和估計曲線 plt.figure(figsize=(4.2*2,3.2*1)) plt.subplot(121) plt.plot(train_x,train_y,'ro',label='Original data') plt.plot(train_x,sess.run(w)*train_x + sess.run(b),label ='Estimate data') plt.legend() #繪制代價曲線 plt.subplot(122) plt.plot(plotdata['batch_size'],plotdata['loss'],'b--') plt.xlabel('batch_size') plt.ylabel('loss') plt.title('Minibatch run vs. Training loss') plt.show() #重啟一個session,載入檢查點 方法一 load_epoch = 180 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.restore(sess,os.path.join(savedir,savefile+'-'+str(load_epoch))) test_x = [2,4,5,7] test_y = sess.run(pred,feed_dict={input_x:test_x}) print('prediction ',test_y)
運行完后,我們會看到多了幾個文件,多的那幾個文件就是檢查點文件:這里有必要說一下180怎么來的,180就是我們最后一次保存檢查點的迭代次數

在載入模型時,我們每次都要指定迭代次數,因此會比較麻煩,這里有幾種種方法,直接載入最近保存的檢查點文件,個人推薦第三種代碼如下:、
''' 由於恢復模型,需要指定迭代次數,比較麻煩,我們可以直接載入最近保存的檢查點文件 方法二 ''' with tf.Session() as sess: #需要指定檢查點文件所在目錄 ckpt = tf.train.get_checkpoint_state(savedir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess,ckpt.model_checkpoint_path) ''' 或者 方法三 ''' with tf.Session() as sess: ckpt = tf.train.latest_checkpoint(savedir) if ckpt != None: #恢復模型 saver.restore(sess,ckpt) #使用默認圖,即我們定義的線性回歸模型 並獲取模型中的tensor graph = tf.get_default_graph() weight = graph.get_tensor_by_name('w:0') bias = graph.get_tensor_by_name('b:0') print(sess.run([w,b])) #在加載的模型后繼續加載新的網絡層 add_on_op = tf.multiply(w,2) print(sess.run(add_on_op)) ''' 或者 直接把網絡結構加載進來(.meta),不可以重寫網絡結構,不然會出現變量重命名沖突問題。 方法四 ''' #清空默認圖的內容 tf.reset_default_graph() with tf.Session() as sess: #加載以前保存的網絡 將保存在.meta文件中的圖添加到當前的圖中 new_saver = tf.train.import_meta_graph(os.path.join(savedir,savefile)+'.meta') #從指定目錄下獲取最近一次檢查點 new_saver.restore(sess,tf.train.latest_checkpoint(savedir)) #使用加載的模型 並獲取模型中的tensor graph = tf.get_default_graph() weight = graph.get_tensor_by_name('w:0') bias = graph.get_tensor_by_name('b:0') print(sess.run([weight,bias])) #在加載的模型后繼續加載新的網絡層 add_on_op = tf.multiply(weight,2) print(sess.run(add_on_op))
運行結果如下:

這里有幾點需要注意:上面介紹了四種類恢復模型的方法,前三種類似,可以概括為一類,最后一種比較特殊:
- 第一種是saver.restore(sess, 'aaaa.ckpt')類型的,這種方法的本質是讀取全部參數,並加載到已經定義好的網絡結構上,因此相當於給網絡的weights和biases賦值並執行tf.global_variables_initializer()。這種方法的缺點是使用前必須重寫網絡結構,而且網絡結構要和保存的參數完全對上。
- 第二種就比較高端,直接把網絡結構加載進來(.meta),不可以重寫網絡結構,不然會出現變量重命名沖突問題。
2.更簡便地保存檢查點
這里介紹使用tf.train.MonitoredTrainingSession函數來保存檢查點,該函數可以直接實現保存和載入檢查點模型的文件。與上一個案例不同的是,這里並不是按照循環步數來保存,而是按照訓練時間來保存,通過指定save_checkpoint_secs參數的具體秒數,來設置每訓練多久保存一次檢查點。
''' (2) 使用tf.train.MonitoredTrainingSession按時間來保存檢查點 ''' #清空默認圖的內容 tf.reset_default_graph() #設置檢查點路徑 savedir = './LinearRegression/checkpoints' global_step = tf.train.get_or_create_global_step() #通過向 "ref" 添加 "value" 來更新 "ref"。此操作在更新完成后輸出 "ref"。 step = tf.assign_add(global_step,1) with tf.train.MonitoredTrainingSession(checkpoint_dir = savedir,save_checkpoint_secs = 2) as sess: print(sess.run([global_step])) #啟用死循環,當sess不結束時就不停止 while not sess.should_stop(): #運行自加1操作 i =sess.run(step) print(i)
巡行結果如下:

並且在檢查點路徑下生成如下文件:

在使用該方法有兩點需要注意:
- save_checkpoint_secs參數默認時間是10分鍾。
- 使用該方法,必須定義global_step變量,否則會報錯。
注意:程序中如果有定義檢查點文件的保存路徑savedir,則該路徑必須是相對路徑,且以./開頭,比如./data,不然運行時加載模型可能會出錯。
完整代碼:
# -*- coding: utf-8 -*- """ Created on Tue Apr 17 20:56:00 2018 @author: zy """ import tensorflow as tf ''' TensorFlow 編程基礎上 這一節主要講解模型的保存和恢復,以及使用幾個案例使我們更好的理解這一塊內容。 ''' ''' 1.保存模型 ''' ''' 這里是各種構建模型graph的操作,省略.... ''' #創建saver對象 saver = tf.train.Saver() with tf.Session() as sess: #初始化張量 sess.run(tf.global_variables_initializer()) ''' 這里是將數據喂如模型進行訓練,省略... ''' #訓練完成后,保存模型,如果file_name不存在,會自動創建 saver.save(sess,'save_path/file_name') ''' 2.載入模型 ''' #創建saver對象 saver = tf.train.Saver() with tf.Session() as sess: #參數可以進行初始化,也可以不進行初始化,即使進行了初始化,初始化的值也會被restore的值覆蓋掉 sess.run(tf.global_variables_initializer()) saver.restore(sess,'save_path/file_name') ''' 3.保存和恢復線性回歸模型 ''' import numpy as np import matplotlib.pyplot as plt import os ''' 一准備數據 ''' #設定訓練集數據長度 n_train = 100 #生成x數據,[-1,1]之間,均分成n_train個數據 train_x = np.linspace(-1,1,n_train).reshape(n_train,1) #把x乘以2,在加入(0,0.3)的高斯正太分布 train_y = 2*train_x + np.random.normal(loc=0.0,scale=0.3,size=[n_train,1]) #繪制x,y波形 plt.figure() plt.plot(train_x,train_y,'ro',label='y=2x') #o使用圓點標記一個點 plt.legend() plt.show() #重置圖 tf.reset_default_graph() ''' 二 搭建模型 ''' ''' 前向反饋 ''' #創建占位符 input_x = tf.placeholder(dtype=tf.float32) input_y = tf.placeholder(dtype=tf.float32) #模型參數 w = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='w') #設置正太分布參數 初始化權重 b = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='b') #設置正太分布參數 初始化偏置 #前向結構 pred = tf.multiply(w,input_x) + b ''' 反向傳播bp ''' #定義代價函數 選取二次代價函數 cost = tf.reduce_mean(tf.square(input_y - pred)) #設置求解器 采用梯度下降法 學習了設置為0.001 train = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost) ''' 三 迭代模型 ''' #設置迭代次數 training_epochs = 200 display_step = 20 #創建saver對象 在張量聲明之后創建 #saver = tf.train.Saver() #或者指定保存參數 代表將張量w,b的值分別放到變量w和b名字中 saver = tf.train.Saver({'w':w,'b':b}) #或者寫成 #saver = tf.train.Saver([w,b]) #存放到一個list里面 #savee = tf.train.Saver({v.opname:v for v in [w,b]}) #將op的name當做名字 #生成模型的路徑 savedir = './LinearRegression' #模型文件 savefile = 'linearmodel.cpkt' #路徑不存在創建目錄 if not os.path.isdir(savedir): os.mkdir(savedir) with tf.Session() as sess: #初始化所有張量 sess.run(tf.global_variables_initializer()) #恢復模型 if os.path.isfile(os.path.join(savedir, savefile)+'.meta'): saver.restore(sess,os.path.join(savedir,savefile)) #存放批次值和代價值 plotdata = {'batch_size':[],'loss':[]} #開始迭代 for epoch in range(training_epochs): for (x,y) in zip(train_x,train_y): #開始執行圖 sess.run(train,feed_dict={input_x:x,input_y:y}) #一輪訓練完成后 打印輸出信息 if epoch % display_step == 0: #計算代價值 loss = sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}) print('Epoch {0} cost {1} w {2} b{3}'.format(epoch,loss,sess.run(w),sess.run(b))) #保存每display_step輪訓練后的代價值以及當前迭代輪數 if not loss == np.nan: plotdata['batch_size'].append(epoch) plotdata['loss'].append(loss) #輸出最終結果 print('Finished!') print('cost {0} w {1} b {2}'.format(sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}),sess.run(w),sess.run(b))) #預測 test_x = [2,4,5,7] test_y = sess.run(pred,feed_dict={input_x:test_x}) print('prediction ',test_y) ''' 四 可視化顯示 ''' #繪制原數據點,和估計曲線 plt.figure(figsize=(4.2*2,3.2*1)) plt.subplot(121) plt.plot(train_x,train_y,'ro',label='Original data') plt.plot(train_x,sess.run(w)*train_x + sess.run(b),label ='Estimate data') plt.legend() #繪制代價曲線 plt.subplot(122) plt.plot(plotdata['batch_size'],plotdata['loss'],'b--') plt.xlabel('batch_size') plt.ylabel('loss') plt.title('Minibatch run vs. Training loss') plt.show() #保存參數 saver.save(sess,os.path.join(savedir, savefile)) ''' 3.查看模型內容 ''' from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file print_tensors_in_checkpoint_file(os.path.join(savedir,savefile),None,True) #給a和b分別指定一個固定的值,將它們顛倒文職存放 a = tf.Variable(1.0,name='a') b = tf.Variable(2.0,name='b') #指定保存參數 saver = tf.train.Saver({'b_param':a,'a_param':b}) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) #保存參數 saver.save(sess,'./test.cpkt') print_tensors_in_checkpoint_file('./test.cpkt',None,True)
# -*- coding: utf-8 -*- """ Created on Wed Apr 18 09:20:53 2018 @author: zy """ ''' 4.檢查點的適用(模型訓練中保存模型) ''' ''' (1)為模型添加保存檢查點(即訓練中保存檢查點) ''' import tensorflow as tf import numpy as np import matplotlib.pyplot as plt import os ''' 一准備數據 ''' #設定訓練集數據長度 n_train = 100 #生成x數據,[-1,1]之間,均分成n_train個數據 train_x = np.linspace(-1,1,n_train).reshape(n_train,1) #把x乘以2,在加入(0,0.3)的高斯正太分布 train_y = 2*train_x + np.random.normal(loc=0.0,scale=0.3,size=[n_train,1]) #繪制x,y波形 plt.figure() plt.plot(train_x,train_y,'ro',label='y=2x') #o使用圓點標記一個點 plt.legend() plt.show() tf.reset_default_graph() ''' 二 搭建模型 ''' ''' 前向反饋 ''' #創建占位符 input_x = tf.placeholder(dtype=tf.float32) input_y = tf.placeholder(dtype=tf.float32) #模型參數 w = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='w') #設置正太分布參數 初始化權重 b = tf.Variable(tf.truncated_normal(shape=[1],mean=0.0,stddev=1),name='b') #設置正太分布參數 初始化偏置 #前向結構 pred = tf.multiply(w,input_x) + b ''' 反向傳播bp ''' #定義代價函數 選取二次代價函數 cost = tf.reduce_mean(tf.square(input_y - pred)) #設置求解器 采用梯度下降法 學習了設置為0.001 train = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost) ''' 三 迭代模型 ''' #設置迭代次數 training_epochs = 200 display_step = 20 #生成Saver對象 saver = tf.train.Saver(max_to_keep = 1) #生成模型的路徑 savedir = './LinearRegression' #模型文件 savefile = 'linearmodel.cpkt' #路徑不存在創建目錄 if not os.path.isdir(savedir): os.mkdir(savedir) with tf.Session() as sess: #初始化所有張量 sess.run(tf.global_variables_initializer()) #恢復模型 if os.path.isfile(os.path.join(savedir, savefile)+'.meta'): saver.restore(sess,os.path.join(savedir,savefile)) #存放批次值和代價值 plotdata = {'batch_size':[],'loss':[]} #開始迭代 for epoch in range(training_epochs): for (x,y) in zip(train_x,train_y): #開始執行圖 sess.run(train,feed_dict={input_x:x,input_y:y}) #一輪訓練完成后 打印輸出信息 if epoch % display_step == 0: #計算代價值 loss = sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}) print('Epoch {0} cost {1} w {2} b{3}'.format(epoch,loss,sess.run(w),sess.run(b))) #保存每display_step輪訓練后的代價值以及當前迭代輪數 if not loss == np.nan: plotdata['batch_size'].append(epoch) plotdata['loss'].append(loss) #每隔display_step輪后保存一次檢查點 saver.save(sess,os.path.join(savedir,savefile),global_step = epoch) #輸出最終結果 print('Finished!') print('cost {0} w {1} b {2}'.format(sess.run(cost,feed_dict={input_x:train_x,input_y:train_y}),sess.run(w),sess.run(b))) #預測 test_x = [2,4,5,7] test_y = sess.run(pred,feed_dict={input_x:test_x}) print('prediction ',test_y) ''' 四 可視化顯示 ''' #繪制原數據點,和估計曲線 plt.figure(figsize=(4.2*2,3.2*1)) plt.subplot(121) plt.plot(train_x,train_y,'ro',label='Original data') plt.plot(train_x,sess.run(w)*train_x + sess.run(b),label ='Estimate data') plt.legend() #繪制代價曲線 plt.subplot(122) plt.plot(plotdata['batch_size'],plotdata['loss'],'b--') plt.xlabel('batch_size') plt.ylabel('loss') plt.title('Minibatch run vs. Training loss') plt.show() ''' 重啟一個session,載入檢查點 方法一 ''' load_epoch = 180 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.restore(sess,os.path.join(savedir,savefile+'-'+str(load_epoch))) test_x = [2,4,5,7] test_y = sess.run(pred,feed_dict={input_x:test_x}) print('prediction ',test_y) ''' 由於恢復模型,需要指定迭代次數,比較麻煩,我們可以直接載入最近保存的檢查點文件 方法二 ''' with tf.Session() as sess: #需要指定檢查點文件所在目錄 ckpt = tf.train.get_checkpoint_state(savedir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess,ckpt.model_checkpoint_path) ''' 或者 方法三 ''' with tf.Session() as sess: ckpt = tf.train.latest_checkpoint(savedir) if ckpt != None: #恢復模型 saver.restore(sess,ckpt) #使用默認圖,即我們定義的線性回歸模型 並獲取模型中的tensor graph = tf.get_default_graph() weight = graph.get_tensor_by_name('w:0') bias = graph.get_tensor_by_name('b:0') print(sess.run([w,b])) #在加載的模型后繼續加載新的網絡層 add_on_op = tf.multiply(w,2) print(sess.run(add_on_op)) ''' 或者 直接把網絡結構加載進來(.meta),不可以重寫網絡結構,不然會出現變量重命名沖突問題。 方法四 ''' #清空默認圖的內容 tf.reset_default_graph() with tf.Session() as sess: #加載以前保存的網絡 將保存在.meta文件中的圖添加到當前的圖中 new_saver = tf.train.import_meta_graph(os.path.join(savedir,savefile)+'.meta') #從指定目錄下獲取最近一次檢查點 new_saver.restore(sess,tf.train.latest_checkpoint(savedir)) #使用加載的模型 並獲取模型中的tensor graph = tf.get_default_graph() weight = graph.get_tensor_by_name('w:0') bias = graph.get_tensor_by_name('b:0') print(sess.run([weight,bias])) #在加載的模型后繼續加載新的網絡層 add_on_op = tf.multiply(weight,2) print(sess.run(add_on_op)) ''' (2) 使用tf.train.MonitoredTrainingSession按時間來保存檢查點 ''' #清空默認圖的內容 tf.reset_default_graph() #設置檢查點路徑 savedir = './LinearRegression/checkpoints' global_step = tf.train.get_or_create_global_step() #通過向 "ref" 添加 "value" 來更新 "ref"。此操作在更新完成后輸出 "ref"。 step = tf.assign_add(global_step,1) with tf.train.MonitoredTrainingSession(checkpoint_dir = savedir,save_checkpoint_secs = 2) as sess: print(sess.run([global_step])) #啟用死循環,當sess不結束時就不停止 while not sess.should_stop(): #運行自加1操作 i =sess.run(step) print(i)
