• 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 documentsxxxxxx.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 程序的运行,避免低效率的训练

  • 相关阅读:
    Kafka文件存储机制那些事(转发)
    Kafka文件存储机制那些事(转发)
    消息队列设计精要(转发)
    RocketMQ原理解析-Broker(转发)
    Apache Kafka:下一代分布式消息系统(转发)
    新浪技术分享:我们如何扛下32亿条实时日志的分析处理(转发)
    消息队列技术介绍(转发)
    confluent kafka for .net
    kafka参考资料
    kafka架构(转发)
  • 原文地址:https://www.cnblogs.com/expedition/p/11639627.html
Copyright © 2020-2023  润新知