Tensorflow 保存和載入訓練過程


本節涉及點:

  1. 保存訓練過程
  2. 載入保存的訓練過程並繼續訓練
  3. 通過命令行參數控制是否強制重新開始訓練
  4. 訓練過程中的手動保存
  5. 保存訓練過程前,程序征得同意

一、保存訓練過程

以下方代碼為例:

import tensorflow as tf
import random

random.seed()
x = tf.placeholder(tf.float32)
yTrain = tf.placeholder(tf.float32)
w1 = tf.Variable(tf.random_normal([4, 8], mean=0.5, stddev=0.1), dtype=tf.float32)
b1 = tf.Variable(0, dtype=tf.float32)
xr = tf.reshape(x, [1, 4])
n1 = tf.nn.tanh(tf.matmul(xr, w1)  + b1)
w2 = tf.Variable(tf.random_normal([8, 2], mean=0.5, stddev=0.1), dtype=tf.float32)
b2 = tf.Variable(0, dtype=tf.float32)
n2 = tf.matmul(n1, w2) + b2
y = tf.nn.softmax(tf.reshape(n2, [2]))
loss = tf.reduce_mean(tf.square(y - yTrain))
optimizer = tf.train.RMSPropOptimizer(0.01)
train = optimizer.minimize(loss)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
lossSum = 0.0

for i in range(5):
    xDataRandom = [int(random.random() * 10), int(random.random() * 10), int(random.random() * 10), int(random.random() * 10)]
    if xDataRandom[2] % 2 == 0:
        yTrainDataRandom = [0, 1]
    else:
        yTrainDataRandom = [1, 0]
    result = sess.run([train, x, yTrain, y, loss], feed_dict={x: xDataRandom, yTrain: yTrainDataRandom})
    lossSum = lossSum + float(result[len(result) - 1])
    print("i: %d, loss: %10.10f, avgLoss: %10.10f" % (i, float(result[len(result) - 1]), lossSum / (i + 1)))
trainResultPath = "./save/idcard2" print("saving...") tf.train.Saver().save(sess, save_path=trainResultPath)
i: 0, loss: 0.2790884972, avgLoss: 0.2790884972
i: 1, loss: 0.2675500214, avgLoss: 0.2733192593
i: 2, loss: 0.2441657931, avgLoss: 0.2636014372
i: 3, loss: 0.2675784826, avgLoss: 0.2645956986
i: 4, loss: 0.2452606559, avgLoss: 0.2607286900
saving...
'./save/idcard2'

解析:

首先用一個變量 trainResultPath 來指定保存訓練過程數據的目錄

這是一個字符串類型的變量,其中的小數點 “ . ” 表示 Python 程序執行的當前目錄, “ / ” 用於分隔目錄和子目錄(windows 中一般用反斜杠 " \ " 來分隔 ),一般采用Linux 目錄中的寫法,兼容性更好

 ./save/idcard2 表示 保存的位置是 執行程序 idcard2.py 的目錄的 save 的子目錄下以 idcard2 為基本名稱的一系列文件

 

下方圖片中,以 idcard2 開頭的文件分別保存了 模型和可變參數的信息,checkpoint 文件保存了一些基礎信息

  • “.meta”文件:包含圖形結構。
  • “.data”文件:包含變量的值。
  • “.index”文件:標識檢查點。
  • “checkpoint”文件:具有最近檢查點列表的協議緩沖區。

 

tf.train.Saver().save(sess, save_path=trainResultPath) 

調用 tensorflow 下的train 包中的 saver 對象的 save 成員函數進行保存,第一個參數 純如當前的會話對象(本程序中 是 sess),第二個參數 save_path 傳入保存位置

 

 

 

二、載入保存的訓練過程並繼續訓練

如果已經保存了訓練數據,就可以用下面的代碼 載入訓練數據並繼續訓練

注意:如果使用的是 jupyter ,請再運行完畢 上方的代碼 並保存結果到 ./save/idcard2 之后

 

 重啟服務再運行下方的代碼,以免報錯 NotFoundError: Key Variable_10 not found in checkpoint

 

import tensorflow as tf
import random
import os

trainResultPath = "./save/idcard2"

random.seed()

x = tf.placeholder(tf.float32)
yTrain = tf.placeholder(tf.float32)

w1 = tf.Variable(tf.random_normal([4, 8], mean=0.5, stddev=0.1), dtype=tf.float32)
b1 = tf.Variable(0, dtype=tf.float32)

xr = tf.reshape(x, [1, 4])

n1 = tf.nn.tanh(tf.matmul(xr, w1)  + b1)

w2 = tf.Variable(tf.random_normal([8, 2], mean=0.5, stddev=0.1), dtype=tf.float32)
b2 = tf.Variable(0, dtype=tf.float32)

n2 = tf.matmul(n1, w2) + b2

y = tf.nn.softmax(tf.reshape(n2, [2]))

loss = tf.reduce_mean(tf.square(y - yTrain))

optimizer = tf.train.RMSPropOptimizer(0.01)

train = optimizer.minimize(loss)

sess = tf.Session()
# 因為數據文件不只一個,所以隨便挑選一個文件判斷數據是否存在
# 但是不要挑選 checkpoint ,因為這個文件不隨我們指定的前綴名而變化
if os.path.exists(trainResultPath + ".index"): print("loading: %s" % trainResultPath) tf.train.Saver().restore(sess, save_path=trainResultPath) else: print("train result path not exists: %s" % trainResultPath) sess.run(tf.global_variables_initializer()) lossSum = 0.0 for i in range(5): xDataRandom = [int(random.random() * 10), int(random.random() * 10), int(random.random() * 10), int(random.random() * 10)] if xDataRandom[2] % 2 == 0: yTrainDataRandom = [0, 1] else: yTrainDataRandom = [1, 0] result = sess.run([train, x, yTrain, y, loss], feed_dict={x: xDataRandom, yTrain: yTrainDataRandom}) lossSum = lossSum + float(result[len(result) - 1]) print("i: %d, loss: %10.10f, avgLoss: %10.10f" % (i, float(result[len(result) - 1]), lossSum / (i + 1))) print("saving...") tf.train.Saver().save(sess, save_path=trainResultPath)
loading: ./save/idcard2
INFO:tensorflow:Restoring parameters from ./save/idcard2
i: 0, loss: 0.2710282207, avgLoss: 0.2710282207
i: 1, loss: 0.2567882836, avgLoss: 0.2639082521
i: 2, loss: 0.2574761510, avgLoss: 0.2617642184
i: 3, loss: 0.2574799955, avgLoss: 0.2606931627
i: 4, loss: 0.2419599444, avgLoss: 0.2569465190
saving...
'./save/idcard2'

原因詳情見博客:

https://blog.csdn.net/haiqingonly/article/details/80921802

摘要如下:

 

問題1:TensorFlow:Unsuccessful TensorSliceReader constructor: Failed to find any matching files
問題2:NotFoundError: Key Variable_10 not found in checkpoint山重水復疑無路,柳暗花明又一村。
問題1:多次遇到訓練模型save之后,重新restore提示Failed to find any matching files。            
分析原因:因為自定義的絕對路徑報錯,我的自定義路徑(D:\\test\\pictures\\faces),這個問題算是tensorflow的bug。          
修改方法:所有路徑全部用當前運行路徑上一級路徑形式(.\\faces):            
保存訓練模型:
saver = tf.train.Saver()                                     
sess = tf.Session()                                   
save_path=saver.save(sess, '.\\save_net.ckpt')            
恢復訓練模型:
saver=tf.train.Saver()                                   
sess = tf.Session()                                   saver.restore(sess,tf.train.latest_checkpoint('.'))           

至於我自定義的絕對路徑為什么不能追蹤找到,下一步再探索。


問題2:保存后模型恢復出來用於測試:NotFoundError: Key Variable_10 not found in checkpoint             
分析原因:如果模型訓練完保存后直接加載,相當於變量在前后定義了兩次,第一次創建的變量name="weight",測試時              
創建的變量雖然name="weight",但是實際上name會變成"weight_1"(weight_n-1),我們在保存的checkpoint中搜索的就是            
 weight_n-1,因為搜索不到所以會報錯。          

網上各種查找后有兩種解決方法:        
(1)在加載過程中,定義 name 相同的變量前面加 tf.reset_default_graph() 清除默認圖的堆棧,並設置全局圖為默認圖 ;        
(2)保存模型后,不馬上加載,或 restart kernel后,再加載測試,又不會出錯。  

  我自己嘗試了第二種方法,因為第二種方法簡單,確實可行。   希望能夠幫到遇到和我一樣問題的朋友。
Tensorflow save&restore遇到問題及解決

 

代碼解讀:

  • 載入訓練數據的時候需要用到數據文件保存位置的信息,所以把 定義 trainResultPath 語句提前
  • 定義完會話變量 sess 后,不是像以前馬上調用 sess.run(tf.global_variables_initializer()) 來對可變參數進行初始化,因為要載入訓練數據,就不能做初始化操作,否則所有的可變參數又被復原成初始值了。
  • 之后,加了一個代碼判斷該目錄下是否存有保存了的訓練過程文件,有就載入,沒有就初始化變量。
  • 使用 tf.train.Saver().restore(sess,save_path = trainResultPath)  載入訓練數據,與保存時的 save 函數一樣,都是傳入 會話變量和保存路徑兩個參數。save 是保存,restore 是載入訓練過程
  • 判斷是否存在已保存的訓練過程數據文件,使用 os 包中的 os.path.exists 函數。

 

代碼的執行結果如上,可見已成功載入了指定位置的訓練過程數據,並且接下來的誤差值逐漸變小,可見,載入成功

 

 

 

 

三、通過命令行參數控制是否強制重新開始訓練

如何強制重新開始訓練?

  1. 可以把保存的數據和文件都刪除
  2. 命令行參數控制

命令行參數:

 

python xxx.py

 

對於整個命令,"python" 就是 命令體,后面的程序名稱就是它的命令行參數

命令體與命令行參數用空格隔開,命令行參數可有多個,其中也是用空格隔開

如果命令行參數自身就帶空格

python "c:\my documents\xxx\xxx.py"

 

 

導入 sys包 --->   sys.argv  獲得命令行參數,返回一個 一維數組

 

載入訓練過程前,通過判斷命令行參數決定是否強制重新訓練:

 

import tensorflow as tf
import random
import os
import sys

ifRestartT = False

argt = sys.argv[1:] # [1:] 切片,返回從數組下標1開始到數組最后一項的子數組
for v in argt:
    if v == "-restart":
        ifRestartT = True
# 用一個循環判斷 命令行參數數組是否有“-restart” ,有就是 ifRestartT = true 
# 來控制之后 強制執行初始化可變參數

trainResultPath = "./save/idcard2"

random.seed()

x = tf.placeholder(tf.float32)
yTrain = tf.placeholder(tf.float32)

w1 = tf.Variable(tf.random_normal([4, 8], mean=0.5, stddev=0.1), dtype=tf.float32)
b1 = tf.Variable(0, dtype=tf.float32)

xr = tf.reshape(x, [1, 4])

n1 = tf.nn.tanh(tf.matmul(xr, w1)  + b1)

w2 = tf.Variable(tf.random_normal([8, 2], mean=0.5, stddev=0.1), dtype=tf.float32)
b2 = tf.Variable(0, dtype=tf.float32)

n2 = tf.matmul(n1, w2) + b2

y = tf.nn.softmax(tf.reshape(n2, [2]))

loss = tf.reduce_mean(tf.square(y - yTrain))

optimizer = tf.train.RMSPropOptimizer(0.01)

train = optimizer.minimize(loss)

sess = tf.Session()

if ifRestartT == True:
    print("force restart...")
    sess.run(tf.global_variables_initializer()) #可變參數強制初始化,重新開始訓練 elif os.path.exists(trainResultPath + ".index"):
    print("loading: %s" % trainResultPath)
    tf.train.Saver().restore(sess, save_path=trainResultPath)
else:
    print("train result path not exists: %s" % trainResultPath)
    sess.run(tf.global_variables_initializer())


lossSum = 0.0

for i in range(5):

    xDataRandom = [int(random.random() * 10), int(random.random() * 10), int(random.random() * 10), int(random.random() * 10)]
    if xDataRandom[2] % 2 == 0:
        yTrainDataRandom = [0, 1]
    else:
        yTrainDataRandom = [1, 0]

    result = sess.run([train, x, yTrain, y, loss], feed_dict={x: xDataRandom, yTrain: yTrainDataRandom})

    lossSum = lossSum + float(result[len(result) - 1])

    print("i: %d, loss: %10.10f, avgLoss: %10.10f" % (i, float(result[len(result) - 1]), lossSum / (i + 1)))

print("saving...")
tf.train.Saver().save(sess, save_path=trainResultPath)

 

 

 

四、訓練過程中的手動保存

在訓練中,隨時隨地的保存訓練數據:

 

import tensorflow as tf
import random
import os
import sys

ifRestartT = False

argt = sys.argv[1:]

for v in argt:
    if v == "-restart":
        ifRestartT = True


trainResultPath = "./save/idcard2"

random.seed()

x = tf.placeholder(tf.float32)
yTrain = tf.placeholder(tf.float32)

w1 = tf.Variable(tf.random_normal([4, 8], mean=0.5, stddev=0.1), dtype=tf.float32)
b1 = tf.Variable(0, dtype=tf.float32)

xr = tf.reshape(x, [1, 4])

n1 = tf.nn.tanh(tf.matmul(xr, w1)  + b1)

w2 = tf.Variable(tf.random_normal([8, 2], mean=0.5, stddev=0.1), dtype=tf.float32)
b2 = tf.Variable(0, dtype=tf.float32)

n2 = tf.matmul(n1, w2) + b2

y = tf.nn.softmax(tf.reshape(n2, [2]))

loss = tf.reduce_mean(tf.square(y - yTrain))

optimizer = tf.train.RMSPropOptimizer(0.01)

train = optimizer.minimize(loss)

sess = tf.Session()

if ifRestartT == True:
    print("force restart...")
    sess.run(tf.global_variables_initializer())
elif os.path.exists(trainResultPath + ".index"):
    print("loading: %s" % trainResultPath)
    tf.train.Saver().restore(sess, save_path=trainResultPath)
else:
    print("train result path not exists: %s" % trainResultPath)
    sess.run(tf.global_variables_initializer())


lossSum = 0.0

for i in range(500000):

    xDataRandom = [int(random.random() * 10), int(random.random() * 10), int(random.random() * 10), int(random.random() * 10)]
    if xDataRandom[2] % 2 == 0:
        yTrainDataRandom = [0, 1]
    else:
        yTrainDataRandom = [1, 0]

    result = sess.run([train, x, yTrain, y, loss], feed_dict={x: xDataRandom, yTrain: yTrainDataRandom})

    lossSum = lossSum + float(result[len(result) - 1])

    print("i: %d, loss: %10.10f, avgLoss: %10.10f" % (i, float(result[len(result) - 1]), lossSum / (i + 1)))

    if os.path.exists("save.txt"): os.remove("save.txt") print("saving...") tf.train.Saver().save(sess, save_path=trainResultPath) print("saving...")
tf.train.Saver().save(sess, save_path=trainResultPath)

 

 可以隨時保存代碼的核心: 

通過 os.path.exists("save.txt") 判斷是否存在一個文件 save.txt ,如果存在,將該文件刪除【防止一直保存】,保存訓練數據。

 

 

五、保存訓練過程前,程序征得同意

實現每次訓練完畢后,如果結果不滿意,希望可以不要保存這一回訓練的結果,實現程序可以在保存前詢問一下,再執行是否保存訓練結果

import tensorflow as tf
import random
import os
import sys

ifRestartT = False

argt = sys.argv[1:]

for v in argt:
    if v == "-restart":
        ifRestartT = True


trainResultPath = "./save/idcard2"

random.seed()

x = tf.placeholder(tf.float32)
yTrain = tf.placeholder(tf.float32)

w1 = tf.Variable(tf.random_normal([4, 8], mean=0.5, stddev=0.1), dtype=tf.float32)
b1 = tf.Variable(0, dtype=tf.float32)

xr = tf.reshape(x, [1, 4])

n1 = tf.nn.tanh(tf.matmul(xr, w1)  + b1)

w2 = tf.Variable(tf.random_normal([8, 2], mean=0.5, stddev=0.1), dtype=tf.float32)
b2 = tf.Variable(0, dtype=tf.float32)

n2 = tf.matmul(n1, w2) + b2

y = tf.nn.softmax(tf.reshape(n2, [2]))

loss = tf.reduce_mean(tf.square(y - yTrain))

optimizer = tf.train.RMSPropOptimizer(0.01)

train = optimizer.minimize(loss)

sess = tf.Session()

if ifRestartT == True:
    print("force restart...")
    sess.run(tf.global_variables_initializer())
elif os.path.exists(trainResultPath + ".index"):
    print("loading: %s" % trainResultPath)
    tf.train.Saver().restore(sess, save_path=trainResultPath)
else:
    print("train result path not exists: %s" % trainResultPath)
    sess.run(tf.global_variables_initializer())


lossSum = 0.0

for i in range(5):

    xDataRandom = [int(random.random() * 10), int(random.random() * 10), int(random.random() * 10), int(random.random() * 10)]
    if xDataRandom[2] % 2 == 0:
        yTrainDataRandom = [0, 1]
    else:
        yTrainDataRandom = [1, 0]

    result = sess.run([train, x, yTrain, y, loss], feed_dict={x: xDataRandom, yTrain: yTrainDataRandom})

    lossSum = lossSum + float(result[len(result) - 1])

    print("i: %d, loss: %10.10f, avgLoss: %10.10f" % (i, float(result[len(result) - 1]), lossSum / (i + 1)))

    if os.path.exists("save.txt"):
        os.remove("save.txt")
        print("saving...")
        tf.train.Saver().save(sess, save_path=trainResultPath)

resultT = input('Would you like to save? (y/n)') # 提示語句,輸出: Would you like to save? (y/n) 並將輸入保存至 resultT if resultT == "y": print("saving...") tf.train.Saver().save(sess, save_path=trainResultPath)

運行結果如下:

 

 

 

 

 

 

也可以配合 Ctrl + C 終止 Python 程序的運行,避免低效率的訓練

 


免責聲明!

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



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