我正在用9100张图像(每张图像大小为256 x 64)训练一个变分自编码器(VAE)模型。我使用Nvidia RTX 3080进行训练。首先,我将所有图像加载到一个大小为9100 x 256 x 64的numpy数组中,称为traindata
。然后,为了形成训练数据集,我使用以下代码:
train_dataset = (tf.data.Dataset.from_tensor_slices(traindata).shuffle(len(traindata)).batch(batch_size))
这里我使用了batch_size
为65。我在训练过程中主要有两个问题:
问题1:
根据文档,整个数据集在每个epoch中都会被重新洗牌。然而,这种方式下的训练速度非常慢(每个epoch大约50秒)。我做了一个对比,没有调用.shuffle(len(traindata))
来创建数据集时的训练速度要快得多(每个epoch大约20秒)。我想知道为什么.shuffle()
操作这么慢,以及是否有任何方法可以使其更快?根据这个StatsSE讨论,洗牌对训练非常重要,这就是我包含洗牌操作的原因。
问题2:
当我在创建数据集时调用.shuffle()
时,Tensorflow总是给出以下消息:
I tensorflow/core/platform/windows/subprocess.cc:308] SubProcess ended with return code: 4294967295
我在网上搜索过,但仍然无法理解这背后的含义。这是否意味着有某种错误,还是只是一个我可以忽略的警告?
回答:
这是因为在缓冲区中保存数据集的所有元素是昂贵的。除非你绝对需要完美的随机性,否则你应该使用较小的buffer_size
。所有元素最终都会被取出,但以一种更确定性的方式进行。
使用较小的buffer_size
,例如3时,会发生以下情况。缓冲区用括号表示,Tensorflow在这个括号中随机抽取一个值。被随机选中的值用^
表示:
1) [1 2 3]4 5 6 7 8 9 ^2) [1 3 4]5 6 7 8 ^3) [1 3 5]6 7 8 ^4) [1 3 6]7 8 ^5) [3 6 7]8
等等
因此,较早的值会在epoch的早期被取出,但你仍然会进行一些洗牌操作,并且最终所有样本都会被取出。
简而言之 大幅减少buffer_size