Tensorflow使用笔记(2): 如何构建TFRecords并进行Mini Batch训练

引言

  1. 前段时间在做一门课程的期末大作业的时候,用到了TensorFlow,构建了含有两层卷积层的神经网络去做 交通标志的识别,一开始使用 24x24 的图像作为输入(把数据集的图像都resize为24x24)后来感觉应该设计大一点会可靠一点,那就想把输入的图像都改为 64x64 的大小,相应修改了网络一些参数后,run的时候发现出问题了,我还以为是代码没有改好,仔细看一下提示信息:run out of memory 。原来是是内存不足

  2. 那在了解到情况后,就上网找方法,于是乎,找到了个普遍的解决方法:使用mini_batch方法训练,好,那下面就是一些整理网上的资料了

什么是Mini_Batch方法

点这里可以看比较简略的介绍。

先简单介绍一下这三个常见的名词:batch_size ,iteration,epoch

  1. batchsize:批大小。在深度学习中,一般采用SGD训练,即每次训练在训练集中取batchsize个样本训练;
  2. iteration:1个iteration等于使用batchsize个样本训练一次;
  3. epoch:1个epoch等于使用训练集中的全部样本训练一次

总体来说Mini_Batch就是介于SGD(随机梯度下降)和BGD(批梯度下降)之间的一种比较不错的方法,batch_size选择合适了,既能提高训练速度,又能求得一个逼近全局最优解的结果(但是在实际运用中应该要多次修改才能获得合适的size),点这里可以看一些关于怎么选择好batch_size的建议


怎么实现?

那问题来了,怎么在tensorflow中实现Mini_batch训练呢?一开始我的数据集是使用pickle存在硬盘上的

with open( 'images.pkl') as f:
    # training_images 就是存储了很多的使用opencv读取的图像,它们的类型都是np.array
    training_images = pickle.load(f)

那如果是按照顺序读取,每次从取training_images的一部分,然后再取它的下一部分,似乎很容易实现,但是如果每次喂进去的样本没有随机性的话,那似乎便失去了Mini Batch的意义,如果想实现随机取的话,似乎不太容易,那我们可以利用tensorflow,制作适合Tensorflow的数据集TFRecords


简单制作TFRecords

使用TFRecord有什么好处,能把它转成二进制,tensorflow对它会加速。处理起来更快;可以配合tensorflow里的函数,配合使用起来更方便
直接上代码(参考网上)

with open('Training_images64x64.pkl') as f1,open('Training_labels.pkl') as f2:
    print "loading...,please waitting for few seconds"  
    images = pickle.load(f1)  # 数据
    labels = pickle.load(f2)  # 样本标签

# 构建一个writer,待会用来把TFRecords写入硬盘的
writer = tf.python_io.TFRecordWriter("train.tfrecords")  

num = len(labels)
print "the total account of the samples:",num

for i in range(num):
    # build tf record
    label = eval(labels[i])  # 写入的标签是要数字
    img = images[i]
    img_raw = img.tobytes()  # TFRecord 要把它转化成字节
    # 重点,开始映射了
    example = tf.train.Example(features=tf.train.Features(feature={
            "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
            'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw]))
        }))
    # 写入到硬盘
    writer.write(example.SerializeToString())  # Serialize To String
print "all Done"
# 结束,close。跟文件操作挺类似的
writer.close()

读取并使用TFRecords

首先先定义一个读取 TFRecords的函数吧

# 使用队列读取数据,这个队列在tensorflow里面有特别的含义
# 把数据放在队列里有很多好处,可以完成训练数据和测试数据的解耦
def read_and_decode(filename):
    # 根据文件名生成一个队列
    filename_queue = tf.train.string_input_producer([filename])
    # 定义reader,跟之前定义writer是对应的
    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)   #返回文件名和文件
    features = tf.parse_single_example(serialized_example,
                                       features={
                                           'label': tf.FixedLenFeature([], tf.int64),
                                           'img_raw' : tf.FixedLenFeature([], tf.string),
                                       })

    img = tf.decode_raw(features['img_raw'], tf.uint8)
    # 下面这个reshape 可以根据自己的需要来决定要不要重新定义大小
    # img = tf.reshape(img, [224, 224, 3])
    
    # 转化为tensorflow 的 float32,
    img = tf.cast(img, tf.float32) * (1. / 255) - 0.5
    label = tf.cast(features['label'], tf.int32)

    return img, label

接下来是怎么使用的问题了。假设已经定义好计算图了

假设计算图是已经定义好的 为 graph

# 先度硬盘上读取出来,利用上面定义好的函数
img, label = read_and_decode("train.tfrecords") 
sess = tf.Session(graph=graph)  # 定义回话
init.run(session=sess)  # 初始化
# 启动队列线程
threads = tf.train.start_queue_runners(sess=sess) 
sess.run(fetches=init,feed_dict={images_ph:training_images, labels_ph:training_labels})

# !!!划重点了!!!
# 使用shuffle_batch,tensorflow可以有效地帮我们随机从训练数据中随机抽出batch_size个数据样本
image_batch ,label_batch = tf.train.shuffle_batch([img, label] ,batch_size=30) 
# 上面这个函数,还有capacity等其他参数,作用还未明白
# image_train ,label_train = tf.train.shuffle_batch([img, label] ,batch_size=30, capacity=2000,min_after_dequeue=1000)

iteration_times = 2000 # 假定迭代次数为200

# 开始训练

for i in range(0,iteration_times):
    
    # 每次都要run一次,否则取不到说好的batch的数据哟
    sess.run([image_train,label_train])  
    
    # 接下来就可以把image_train,label_train
    # 喂给你的训练节点了
    _, loss_value =sess.run( 
        [train_op,loss],
        feed_dict={images_ph: image_train, labels_ph:label_train}
    )
    # 其他代码
    

训练完之后别忘记保存模型参数哟,具体的介绍可以看我的另一篇文章

关于队列的详细介绍,可以看这里,还挺复杂的
参考代码


小结一下

我在自己的问题上,在实际训练的时候,使用实验室的带GPU的服务器,训练的结果有些慢,损失loss震荡比较厉害,一直没有收敛,可能还是网络设计的有问题吧。
后来在提交作业的时候,选择了32x32的输入图像(梯度下降法,没有使用分批训练),反而在测试集上的准确率比较高,对于Mini_batch的训练方法。batch_size的选择还是缺少指导方针呀。大过小都不好,实践是检验真理的唯一标准呀,此次作业收获良多。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容