tf.train.batch 和 tf.train.batch_join的区别

2024-08-31 18:38
文章标签 区别 tf join train batch

本文主要是介绍tf.train.batch 和 tf.train.batch_join的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先看两个函数的官方文档说明

tf.train.batch官方文档地址:

https://www.tensorflow.org/api_docs/python/tf/train/batch

tf.train.batch_join官方文档地址:

https://www.tensorflow.org/api_docs/python/tf/train/batch_join

tf.train.batch

batch(
    tensors,
    batch_size,
    num_threads=
1,
    capacity=
32,
    enqueue_many=
False,
    shapes=
None,
    dynamic_pad=
False,
    allow_smaller_final_batch=
False,
    shared_name=
None,
    name=
None
)

创建在参数tensors里的张量的batch

参数tensors可以是一个张量的列表或者字典。函数的返回值将会和参数tensors的类型一致。

这个函数使用队列来实现。一个用于队列的QueueRunner对象被添加当前图的QUEUE_RUNNER的集合中。

如果enqueue_many设置为Falsetensors被认为代表单个样本。那么输入维度(shape)[x,y,z]的张量,将会输出一个维度为[batch_size,x,y,z]的张量。

 

如果enqueue_many设置为True,参数tensors被认为是一批次的样本,其中第一维是按样本编索引的(where the first dimension is indexed by example,这里翻译出来意思有点奇怪),并且tensors中所有成员都应该在第一维上有相同的大小。如果输入的张量的维度是[*,x,y,z],那么输出的张量的维度将会是[batch_size,x,y,z]。参数capacity控制着增长队列时,预先分配的队列长度。

 

返回的操作是一个出队操作,如果输入的队列被耗尽,那么这个操作会抛出tf.errors.OutOfRangeError的异常。如果这个操作供给了另一个输入队列,那么它的队列运行器(queue runner)会捕捉这个异常,但是如果这个操作在你的主线程中使用,你需要自己捕捉这个异常。

 

注意:如果dynamic_pad参数为False,你应该确保(1shapes参数被传递进来,(2)所有在tensors参数中的张量必须有完整定义的形状。如果上述任意一个条件没有满足,那么会抛出ValueError的异常。

 

如果dynamic_pad参数设置为True,那么知道tensors的秩就足够了,但是tensors的个别维度的形状可能为空(None)。这种情况下,每个有维度值为空的队列可能有一个可变的长度;在出队的时候,输出的张量将在左边填充当前最小批次中的张量的最大形状。对于数字,填充的是数值0.对于字符串,填充的是空字符串。参见PaddingFIFOQueue获得更多信息。

 

如果allow_smaller_final_batch参数为True,当队列被关闭并且没有足够的元素来填满一批次的数据的情况下,操作将会返回一个数量小于batch_size个数的批次数据,否则待处理的数据将被丢弃。除此之外,通过get_shape方法访问的所有输出的张量的静态形状的第一维将为空,依赖于固定为batch_size大小的操作将会失败。

 

参数:

  • tensors: 入队张量的列表或字典。
  • batch_size: 整数。一个从队列中出队新的批次的大小。
  • num_threads:入队tensors的线程的个数。如果num_threads大于1,那么批次的数据是不确定的。
  • capacity: 整数。在队列中的最大元素个数。
  • enqueue_many: tensor_list_list中的每个张量是否是单个样本。
  • shapes:(可选)每个样本的形状。默认的为tensors推断的形状。
  • dynamic_pad: 布尔变量。允许输入形状的可变维度。出队时被填充到指定维度,使得一批次的张量具有相同的形状。
  • allow_smaller_final_batch: (可选)布尔型变量。如果为True,允许在没有足够的元素留在队列中时,最后一批次的元素的个数比batch_size小。
  • shared_name:(可选)如果被设置的话,这个队列将在多个会话中以给定的名字被共享。
  • name: (可选)操作的名字。

 

返回:

有着与tensors参数相同类型的张量的列表或字典(除了如果输入的是一个元素的列表,那么返回的是一个张量,而不是列表)

 

抛出:

  • ValueError: 如果形状没有被指定,并且不能从tensors的元素中推断出来。

 

tf.train.batch_join

batch_join(
    
tensors_list,
    
batch_size,
    
capacity=32,
   
enqueue_many=False,
    
shapes=None,
    
dynamic_pad=False,
    
allow_smaller_final_batch=False,
    
shared_name=None,
    
name=None
)

运行张量列表来填充队列,以创建样本的批次。

 

tensors_list参数是一个张量元组的列表,或者张量字典的列表。在列表中的每个元素被类似于tf.train.batch()函数中的tensors一样对待。

 

警告:这个函数是非确定性的,因为它为每个张量启动了独立的线程。

 

在不同的线程中入队不同的张量列表。用队列实现——队列的QueueRunner被添加到当前图的QUEUE_RUNNER集合中。

 

len(tensors_list)个线程被启动,第i个线程入队来自tensors_list[i]中的张量。tensors_list[i1][j]比如在类型和形状上与tensors_list[i2][j]相匹配,除了当enqueue_many参数为True的时候的第一维。

 

如果enqueue_many设置为False,那么每个tensors_list[i]被认为是单个样本。一个输入的张量x将被输出为形状为[batch_size] + x.shape的张量。

 

如果dequeue_many设置为True,那么tensors_list[i]被认为代表一个批次的样本,其中第一维是按样本编索引的,并且tensors_list[i]的所有成员都应该在第一维上有相同的大小。任何输入的张量x的切片都被当做样本,并且输出的张量的形状将是[batch_size]+x.shape[1:]

 

capacity参数控制着当增长队列的时候,预分配队列的长度。

 

函数返回的操作是一个出队操作,并且会再输入的队列耗尽的情况下,抛出tf.errors.OutOfRangeError的异常。如果这个操作供给给其他输入队列,那么那个队列的队列运行器会捕捉这个异常,但是如果这个操作在你的主线程中操作,你需要自己负责捕捉这个异常。

 

注意:如果dynamic_pad参数为False,你应该确保(1shapes参数被传递进来,(2)所有在tensors参数中的张量必须有完整定义的形状。如果上述任意一个条件没有满足,那么会抛出ValueError的异常。

 

如果dynamic_pad参数设置为True,那么知道tensors的秩就足够了,但是tensors的个别维度的形状可能为空(None)。这种情况下,每个有维度值为空的队列可能有一个可变的长度;在出队的时候,输出的张量将在左边填充当前最小批次中的张量的最大形状。对于数字,填充的是数值0.对于字符串,填充的是空字符串。参见PaddingFIFOQueue获得更多信息。

 

如果allow_smaller_final_batch参数为True,当队列被关闭并且没有足够的元素来填满一批次的数据的情况下,操作将会返回一个数量小于batch_size个数的批次数据,否则待处理的数据将被丢弃。除此之外,通过get_shape方法访问的所有输出的张量的静态形状的第一维将为空,依赖于固定为batch_size大小的操作将会失败。

 

参数:

 

返回:

tensors_list[i]有着相同数量和类型的张量的列表或者字典。

 

抛出:

  • ValueError: 如果形状没有被指定,并且不能从tensor_list_list中的元素推断出来。

 

看完上述官方文档的说明,其实还是挺蒙的,下面给一段例子,就很容易理解这两个函数了,例子的代码如下:

# -*- coding: utf-8 -*-

import tensorflow as tf

 

tensor_list = [[1,2,3,4], [5,6,7,8],[9,10,11,12],[13,14,15,16],[17,18,19,20]]

tensor_list2 = [[[1,2,3,4]], [[5,6,7,8]],[[9,10,11,12]],[[13,14,15,16]],[[17,18,19,20]]]

with tf.Session() as sess:

    x1 = tf.train.batch(tensor_list, batch_size=4, enqueue_many=False)

    x2 = tf.train.batch(tensor_list, batch_size=4, enqueue_many=True)

 

    y1 = tf.train.batch_join(tensor_list, batch_size=4, enqueue_many=False)

    y2 = tf.train.batch_join(tensor_list2, batch_size=4, enqueue_many=True)

 

    coord = tf.train.Coordinator()

    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    print("x1 batch:"+"-"*10)

    print(sess.run(x1))

    print("x2 batch:"+"-"*10)

    print(sess.run(x2))

    print("y1 batch:"+"-"*10)

    print(sess.run(y1))

    print("y2 batch:"+"-"*10)

    print(sess.run(y2))

    print("-"*10)

    coord.request_stop()

    coord.join(threads)

上述例子的输出类似如下这样:

x1 batch:----------

[array([[1, 2, 3, 4],

       [1, 2, 3, 4],

       [1, 2, 3, 4],

       [1, 2, 3, 4]]), array([[5, 6, 7, 8],

       [5, 6, 7, 8],

       [5, 6, 7, 8],

       [5, 6, 7, 8]]), array([[ 9, 10, 11, 12],

       [ 9, 10, 11, 12],

       [ 9, 10, 11, 12],

       [ 9, 10, 11, 12]]), array([[13, 14, 15, 16],

       [13, 14, 15, 16],

       [13, 14, 15, 16],

       [13, 14, 15, 16]]), array([[17, 18, 19, 20],

       [17, 18, 19, 20],

       [17, 18, 19, 20],

       [17, 18, 19, 20]])]

x2 batch:----------

[array([1, 2, 3, 4]), array([5, 6, 7, 8]), array([ 9, 10, 11, 12]), array([13, 1

4, 15, 16]), array([17, 18, 19, 20])]

y1 batch:----------

[array([ 1,  9, 17,  9]), array([ 2, 10, 18, 10]), array([ 3, 11, 19, 11]), arra

y([ 4, 12, 20, 12])]

y2 batch:----------

[5 6 7 8]

----------

enqueue_many参数设置为False(默认值)的时候,tf.train.batch的输出,是batch_size*tensor.shape,其含义就是将tensors参数看做一个样本,那么batch_size个样本,只是单一样本的复制。在其实际应用中,tensors参数一般对应的是一个文件,那么这样操作意味着从文件中读取batch_size次, 以获得一个batch的样本。

而在enqueu_many参数设置为True的时候,tf.train.batchtensors参数看做一个batch的样本,那么batch_size只是调整一个batch中样本的维度的,因为输出的维度是batch_size*tensor.shape[1:](可以尝试将代码例子中batch_size改成3,再看结果)。

最后需要注意的tf.train.batchnum_threads参数,指定的是进行入队操作的线程数量,可以进行多线程对于同一个文件进行操作,这样会比单一线程读取文件快。

tf.train.batch_join一般就对应于多个文件的多线程读取,可以看到当enqueue_many参数设置为False(默认值)的时候,tensor_list中每个tensor被看做单个样本,这个时候组成batch_size的一个batch的样本,是从各个单一样本中凑成一个batch_size的样本。可以看到由于是多线程,每次取值不同,也就是类似,每个tensor对应一个文件,也对应一个线程,那么组成batch的时候,该线程读取到文件(例子中是tensor的哪个值)是不确定,这样就形成了打乱的形成样本的时候。

而在enqueue_many参数设置为True的时候,取一个batch的数据,是在tensor_list中随机取一个,因为每一个就是一个batch的数据,batch_size只是觉得截断或填充这个batch的大小。

这样就很容易明白了tf.train.batchtf.train.batch_join的区别,一般来说,单一文件多线程,那么选用tf.train.batch(需要打乱样本,有对应的tf.train.shuffle_batch);而对于多线程多文件的情况,一般选用tf.train.batch_join来获取样本(打乱样本同样也有对应的tf.train.shuffle_batch_join使用)。

这篇关于tf.train.batch 和 tf.train.batch_join的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124690

相关文章

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

javascript中break与continue的区别

在javascript中,break是结束整个循环,break下面的语句不再执行了 for(let i=1;i<=5;i++){if(i===3){break}document.write(i) } 上面的代码中,当i=1时,执行打印输出语句,当i=2时,执行打印输出语句,当i=3时,遇到break了,整个循环就结束了。 执行结果是12 continue语句是停止当前循环,返回从头开始。

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令 在日常的工作中由于各种原因,会出现这样一种情况,某些项目并没有打包至mvnrepository。如果采用原始直接打包放到lib目录的方式进行处理,便对项目的管理带来一些不必要的麻烦。例如版本升级后需要重新打包并,替换原有jar包等等一些额外的工作量和麻烦。为了避免这些不必要的麻烦,通常我们

ActiveMQ—Queue与Topic区别

Queue与Topic区别 转自:http://blog.csdn.net/qq_21033663/article/details/52458305 队列(Queue)和主题(Topic)是JMS支持的两种消息传递模型:         1、点对点(point-to-point,简称PTP)Queue消息传递模型:         通过该消息传递模型,一个应用程序(即消息生产者)可以

深入探讨:ECMAScript与JavaScript的区别

在前端开发的世界中,JavaScript无疑是最受欢迎的编程语言之一。然而,很多开发者在使用JavaScript时,可能并不清楚ECMAScript与JavaScript之间的关系和区别。本文将深入探讨这两者的不同之处,并通过案例帮助大家更好地理解。 一、什么是ECMAScript? ECMAScript(简称ES)是一种脚本语言的标准,由ECMA国际组织制定。它定义了语言的语法、类型、语句、

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

msys2 minggw-w64 cygwin wsl区别

1 mingw-w64,这是gcc一直win平台下产生的,所以是win版的gcc,既支持32也支持64bit 2cygwin专注于原样在windows上构建unix软件, 3msys让Linux开发者在windows上运行软件,msys2专注于构建针对windows api构建的本机软件 4 wsl  windows subsystem for linux 是一个在windows 10 上能

【Java中的位运算和逻辑运算详解及其区别】

Java中的位运算和逻辑运算详解及其区别 在 Java 编程中,位运算和逻辑运算是常见的两种操作类型。位运算用于操作整数的二进制位,而逻辑运算则是处理布尔值 (boolean) 的运算。本文将详细讲解这两种运算及其主要区别,并给出相应示例。 应用场景了解 位运算和逻辑运算的设计初衷源自计算机底层硬件和逻辑运算的需求,它们分别针对不同的处理对象和场景。以下是它们设计的初始目的简介: