第六節,TensorFlow編程基礎案例-保存和恢復模型(中)


在我們使用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)
View Code
# -*- 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)
    

        
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM