Python Tensorflow数据集API评估输出形状需要10分钟以上

Python Tensorflow数据集API评估输出形状需要10分钟以上,python,tensorflow,tensorflow-datasets,Python,Tensorflow,Tensorflow Datasets,我正在使用Python 3.5、低镜头MicroSoft Celeb1M数据集、Tensorflow 1.4,我想在图像分类任务中使用新的数据集API 我需要构建一个具有以下形式的数据集(一个插曲),它包含(N*k+1)图像,其中N包含不同类别的数量,k包含每个类别的样本数量。目标是在N类中对正确类中的最后一幅图像进行分类,每个类由k样本表示 为此,我在硬盘上有16000条TF记录,每条大约20MB。每个TFRecord包含一个类的图像,大约50-100个图像 我想随机选择N文件,然后从每个文件

我正在使用Python 3.5、低镜头MicroSoft Celeb1M数据集、Tensorflow 1.4,我想在图像分类任务中使用新的数据集API

我需要构建一个具有以下形式的数据集(一个插曲),它包含
(N*k+1)
图像,其中
N
包含不同类别的数量,
k
包含每个类别的样本数量。目标是在
N
类中对正确类中的最后一幅图像进行分类,每个类由
k
样本表示

为此,我在硬盘上有16000条TF记录,每条大约20MB。每个TFRecord包含一个类的图像,大约50-100个图像

我想随机选择
N
文件,然后从每个文件中随机选择
k
图像,混合它们,然后选择一个最终图像在
N
类中进行分类,与样本不同。为此,我混合了“本机”Python代码和Tensorflow数据集API方法

问题是我写的解决方案需要很长时间才能完成。 下面是我为创建这样一个数据集而编写的工作代码。对于这个例子,我只从硬盘上取了20个文件

将tensorflow导入为tf
导入操作系统
导入时间
将numpy.random作为rng导入
#创建一些变量
data_dir='/fastdata/Celeb1M/'
test_data=[data_dir+'test/'+elt for elt for elt in os.listdir(data_dir+'/test/')]
#用于解码TFR记录的函数
def读取和解码(示例proto):
features=tf.parse_单个_示例(
例如(proto),,
特征={
“image”:tf.FixedLenFeature([],tf.string),
“标签”:tf.FixedLenFeature([],tf.int64),
“高度”:tf.FixedLenFeature([],tf.int64),
“宽度”:tf.FixedLenFeature([],tf.int64),
“通道”:tf.FixedLenFeature([],tf.int64)
})
image=tf.decode_raw(特征['image'],tf.uint8)
image=tf.cast(image,tf.float32)*(1./255)
高度=tf.cast(特征['height'],tf.int32)
宽度=tf.cast(特征['width'],tf.int32)
channels=tf.cast(特性['channels'],tf.int32)
image=tf.重塑(图像[高度、宽度、通道])
label=tf.cast(特性['label'],tf.int32)
返回图像、标签
def get_插曲(每个集合的类、每个类的样本、列表文件):
"""
:参数数据包:列车、val或测试
:参数类每个集合:N向分类
:参数样本每类:k-shot分类
:param list_files:每个包含示例的文件集的长度类列表
:return:一集包含类/集合*samples\u/集合+1个图像以在N*k个其他图像中分类
"""
断言类每集合=len(列出文件)
dataset=tf.data.TFRecordDataset(列表文件[-1]).map(读取和解码)\
.洗牌(100)
elt_to_classify=dataset.take(1)
随机播放(列出文件)
事件=tf.data.TFRecordDataset([list_files[-1]])\
.map(读取和解码)\
.洗牌(100)\
.采取(1)
_=list_files.pop()
对于列表文件中的类文件:
element=tf.data.TFRecordDataset([class\u文件])\
.map(读取和解码)\
.洗牌(150)\
.采取(1)
插曲=插曲.连接(元素)
插曲=插曲。连接(elt_至_分类)
返回集
#测试代码
事件=获取事件(20,1,测试数据)
开始=时间。时间()
迭代器=情节。制作一个镜头迭代器()
end=time.time()
打印(“经过的时间:”,结束-开始)
"""
结果:
开始构建单镜头迭代器
时间:188.75095319747925
"""
需要花费太长时间的步骤是迭代器初始化。在我的完整代码中,包括批处理,大约需要15分钟。我注意到问题最有可能是由于评估
插曲.输出形状
:仅在结尾执行
打印(插曲.输出形状)
也需要很长时间(但比初始化迭代器要短)

此外,我在Docker中工作,当迭代器初始化时,我可以看到CPU在整个步骤中处于
100%

我想知道是不是本地Python代码和Tensorflow操作的混合导致了这种情况,这可能会在CPU上造成瓶颈

我认为处理Dataset API包括在Tensorflow图上创建操作节点,并且只有在执行
tf.Session().run()
时才对数据集进行评估

要了解更多信息,我尝试:

<代码>集=数据集。获取集(50,1,测试数据[:50]) 迭代器=情节。制作一个镜头迭代器() 3个小时后,它甚至没有结束。我停止了代码,这是回溯(我编辑了一些重复的块,例如
返回self.\u as\u variant\u tensor()

键盘中断回溯(最近一次调用)
在()
2打印(“那里”)
3开始=时间。时间()
---->4迭代器=插曲。制作一个镜头迭代器()
5结束=时间。时间()
6打印(“经过的时间:”,结束-开始)
~/miniconda2/envs/dljupyter/lib/python3.5/site-packages/tensorflow/python/data/ops/dataset\u ops.py在make\u one\u shot\u迭代器(self)中
110返回self._as_variant_tensor()
111
-->112 \u生成\u数据集。将\u添加到\u图(ops.get\u default\u graph())
113
114返回迭代器_ops.iterator(
添加到图中的~/miniconda2/envs/dljupyter/lib/python3.5/site-packages/tensorflow/python/framework/function.py(self,g)
484 def添加到图中(self,g):
485“将此函数添加到图形g中。”
-->486自我。如果需要,创建定义()
487
488#将此函数添加到“g”中。
~/miniconda2/envs/dljupyter/lib/python3.5/site-packages/tensorflow/python/framew
def get_episode(classes_per_set, samples_per_class, list_files):
    """
    :param data_pack : train, val or test
    :param classes_per_set : N-way classification
    :param samples_per_class : k-shot classification
    :param list_files : list of length classes_per_set of files containing examples
    :return : an episode containing classes_per_set * samples_per_class + 1 image to classify among the N*k other
    """
    assert classes_per_set == len(list_files)

    elt_to_classify = tf.data.TFRecordDataset(list_files[-1]).map(read_and_decode) \
                      .shuffle(100) \
                      .take(1)

    rng.shuffle(list_files)

    # Special handling for the first file (smaller shuffle buffer).
    first_file = tf.data.TFRecordDataset([list_files[-1]]) \
                 .map(read_and_decode) \
                 .shuffle(100) \
                 .take(1)

    _ = list_files.pop()

    # Creates a nested dataset for each file in `list_files`, and 
    # concatenates them together.
    other_files = tf.data.Dataset.from_tensor_slices(list_files).flat_map(
        lambda filename: tf.data.TFRecordDataset(filename)
                         .map(read_and_decode)
                         .shuffle(150)
                         .take(1))

    episode = first_file.concatenate(other_files).concatenate(elt_to_classify)
    return episode