训练过程——使用命令行参数

时间:2022-12-20 14:31:35

   大多数神经网络训练过程都是比较漫长的,为了避免过程中发生意外导致训练结果丢失,我们需要采用保存训练过程的方法。另外,物品们无法预知多少次训练才能达到合适的准确率,所以往往要在一次程序训练结束后先保存当时的训练结果,再根据当时的误差率来决定是否继续训练,那么,再次训练的时候就需要载入保存的训练结果再往下训练。

   当然,如果训练结果不佳,也要可能调整网络结构后重新开始训练,本节,将介绍保存和载入训练过程的方法。

一、保存训练过程

   以下代码以身份证问题作为案例,进行保存训练过程.

以下执行程序命名为:idcard4.py

import tensorflow as tf
import random
random.seed()

#定义输入层张量x的变量结构式
x = tf.placeholder(dtype=tf.float32)
#定义输出层张量yYrain的标量结构式
yTrain = tf.placeholder(dtype=tf.float32)
#定义w1:第一层权重可变参数的值,输入层有4个节点,隐藏层有8个节点,那么w1就是[4,8]矩阵,服众正态分布
w1 = tf.Variable(tf.random_normal([4,8],mean = 0.5,stddev = 0.1),dtype=tf.float32)
#定义b1偏移量,与向量或矩阵进行相加减等操作,会对每一个向量或矩阵中的每一个元素都进行相同的操作
b1 = tf.Variable(0,dtype=tf.float32)
#定义xr:将输入数据x从一个思维向量转换为一个[1,4]的矩阵,保存在xr变量中,后面进行矩阵乘法运算。
xr = tf.reshape(x,[1,4])
#n1:隐藏层1的结构,tf.matmul函数为矩阵乘法运算,tf.nn.tanh为激活函数tanh,去线性化的作用。
n1 = tf.nn.tanh(tf.matmul(xr,w1) + b1)
#定义w2:第二层权重可变参数的值,第一个隐藏层有8个节点,第二个隐藏层有2个节点,那么w1就是[8,2]矩阵,服众正态分布
#定义第二个隐藏层为2个,是为了让输出到输出层的节点数为2,便于应用sorftmax函数
w2 = tf.Variable(tf.random_normal([8,2],mean = 0.5,stddev = 0.1),dtype=tf.float32)
#定义b2偏移量
b2 = tf.Variable(0,dtype=tf.float32)
#隐藏层2的结构
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变量,调用会话对象
sess = tf.Session()

#定义一个init变量,他返回的是一个专门用于初始化可变参数的对象,
init = tf.global_variables_initializer()

#调用会话对象sess的run函数run()
sess.run(init)



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})
    #print(result)
    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)

慢慢看完了代码,可以发现,保存训练过程的代码就是:

trainResultPath = './save/idcard2'
print('saving...')
tf.train.Saver().save(sess,save_path=trainResultPath)

  使用一个标量trainResultPath来指定保存训练过程数据的记录,‘./save/idcard2’:保存的位置是执行程序idcard4.py时当下目录的save子目录以idcard2为基本名称的文本。

  调用了tensorflow下train包下的Saver函数返回的Saver对象的save成员函数来进行保存,传入的第一个参数当前的会话对象,第二个参数是传入保存的路径位置。

 

二、载入保存的训练过程并继续训练

  一下代码为:idcard4.py

#载入保存的训练过程并继续训练
import tensorflow as tf 
import random
import os

trainResultPath = './save/idcard2'
random.seed()
#定义输入层张量x的变量结构式
x = tf.placeholder(dtype=tf.float32)
#定义输出层张量yYrain的标量结构式
yTrain = tf.placeholder(dtype=tf.float32)
#定义w1:第一层权重可变参数的值,输入层有4个节点,隐藏层有8个节点,那么w1就是[4,8]矩阵,服众正态分布
w1 = tf.Variable(tf.random_normal([4,8],mean = 0.5,stddev = 0.1),dtype=tf.float32)
#定义b1偏移量,与向量或矩阵进行相加减等操作,会对每一个向量或矩阵中的每一个元素都进行相同的操作
b1 = tf.Variable(0,dtype=tf.float32)
#定义xr:将输入数据x从一个思维向量转换为一个[1,4]的矩阵,保存在xr变量中,后面进行矩阵乘法运算。
xr = tf.reshape(x,[1,4])
#n1:隐藏层1的结构,tf.matmul函数为矩阵乘法运算,tf.nn.tanh为激活函数tanh,去线性化的作用。
n1 = tf.nn.tanh(tf.matmul(xr,w1) + b1)
#定义w2:第二层权重可变参数的值,第一个隐藏层有8个节点,第二个隐藏层有2个节点,那么w1就是[8,2]矩阵,服众正态分布
#定义第二个隐藏层为2个,是为了让输出到输出层的节点数为2,便于应用sorftmax函数
w2 = tf.Variable(tf.random_normal([8,2],mean = 0.5,stddev = 0.1),dtype=tf.float32)
#定义b2偏移量
b2 = tf.Variable(0,dtype=tf.float32)
#隐藏层2的结构
n2 = tf.matmul(n1,w2) + b2
#先对第二个隐藏层的矩阵形态[1,2]转换为一个向量,[2]就是转换为二维向量

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变量,调用会话对象
sess = tf.Session()

#定义一个init变量,他返回的是一个专门用于初始化可变参数的对象,
#init = tf.global_variables_initializer()

#调用会话对象sess的run函数run()
#sess.run(init)

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})
    #print(result)
    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)

  看完了上方的代码,可以看到有两处与保存训练过程不一样的地方:

1、定义的trainResultPath变量的语句在程序开头部分,因为载入训练数据时也需要用到数据文件保存位置的信息。

2、在定义好sess会话变量后,不想以前一样马上调用sess.run(tf.global_variables_initializer())来对可变参数进行初始化,因为如果要载入训练数据,就不能做初始化操作,否则所有的可变参数又被复原为初始值。加上一个条件判断,如果目录下指定位置保存了训练过程文件,就载入相应文件中保存的训练过程信息;否则才去进行初始化可变参数的操作。

 

三、通过命令行参数控制是否强制重新开始训练

  所谓命令行参数:在cmd这种操作文件的窗口中操作,给出某个参数运行在某个运行程序中。

  举个例子吧:

  自编一个text.py程序:

import sys
argt = sys.arge
print(arge)
print('打印的是:%s'%arge[1])

在该python程序路径位置下,输入python  text.py abc

输出的是:

['text.py', 'abc']
Parameter 1:abc

所以,可以利用命令行参数来执行保存好的训练过程文件。

 代码命名为:incard6.py 

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)))

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

在cmd窗口下,用python incard6.py -restart 这个命令行来执行程序,运行的结果如下:

  

force restart...
i:0,loss:0.2178457528,avgLoss:0.3178457528
i:1,loss:0.1825756580,avgLoss:0.2002107054
i:2,loss:0.3673197329,avgLoss:0.2559137146
i:3,loss:0.1935390979,avgLoss:0.2403200604
i:4,loss:0.1634049714,avgLoss:0.2249370426
saving......

四、从命令行参数读取需要预测的数据
训练神经网络是让神经网络具有可用性,而真正使用神经网络时需要输入数据进行预测。这些输入数据不想训练数据一样又目标值,而是确实通过神经网络计算来获得预测结果的。
下面,介绍通过命令行参数来输入数据的方法进行预测目标值。
import tensorflow as tf
import numpy as np
import random
import os
import sys

ifRestartT = False

predictData = None

argt = sys.argv[1:]

for v in argt:
    if v == "-restart":
        ifRestartT = True
    if v.startswith("-predict="):
        tmpStr = v[len("-predict="):]
        predictData = np.fromstring(tmpStr, dtype=np.float32, sep=",")

print("predictData: %s" % predictData)

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:
    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())

if predictData is not None:
    result = sess.run([x, y], feed_dict={x: predictData})
    print(result[1])
    print(y.eval(session=sess, feed_dict={x: predictData})) sys.exit(0) 
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)')

if resultT == "y":
    print("saving...")
    tf.train.Saver().save(sess, save_path=trainResultPath)
predictData:[1,2,3,4]
loading:./save.idcard2 [0.32765886 0.67232467]
[0.32765886  0.67232467]