我正在尝试在 Databricks 中对 Tensorflow 模型执行稍微复杂的超参数调整操作(尽管复杂性来自于我们试图让多少种不同的工具一起工作,而不是具体涉及模型训练本身)。问题出现在我们正在使用的库 hyperopt 和数据集(即 TFRecordDataset)之间。具体来说,如果我们想使用 SparkTrials 在集群中的不同工作节点上分配单独的调优运行,hyperopt 需要 pickle 模型、数据集、超参数以及目标函数闭包中定义的任何其他内容。所有这些都在驱动程序节点上进行了pickle,然后在工作节点上进行了unpickle,然后进行了训练,等等。所以,一切都很好,除了数据集之外,pickle 都很好,因为 Tensorflow 数据集是不可 picklable 的,在至少据我所知。它给出的错误始终是无法将 dtype 变量的张量转换为 numpy 数组。
我想我想弄清楚是否有任何我可以设置的解决方法。该数据集大约有 8,000 张图像(但解决方案需要扩展,因为数量可能会增长),每个图像加上目标变量还有一些额外的相应数据字段。
这是我一直在思考的一些事情。我已经尝试了这些路径中的每一条,但没有取得太大的成功(和/或只是发现解决方案可能会在某种程度上涉及每条路径,所以我想在深入研究可能不会的事情之前获得建议平移出来。
将所有内容转换为 numpy 数组。我不知道我该怎么做,因为 np 数组存在于内存中,这么大的数据集不一定适合(即使这个数据集适合,也无法保证可扩展性)。
修改 fmin 函数和/或 hyperopt 库中的任何相关类,以忽略目标函数中不可挑选的项目,然后当需要在工作节点上取消挑选这些项目时,实例化它们。我不知道这是否可行,但如果可行,我认为这将比我的工资高出几个档次。
放弃分布式超参数调整,转而只进行串行超参数运行的分布式模型训练。实际上,我已经使用 Tensorflow 的镜像分布策略尝试过此操作,并且它给出了关于变量张量未转换为 numpy 数组的相同错误。不过,我认为 Databricks 中也内置了一个名为 Horovod 的库,但我还没有尝试过。但我并不一定对此抱有希望;我不知道会有什么不同。我尝试在 Spark 上下文中广播数据集,这也给出了相同的错误,所以我怀疑该数据集确实不想用于分布式任何内容。
想法?考虑因素?我还没有尝试过的事情?我似乎有很大的误解?
只是想说,我最终确实想出了一个解决方案,以防有人偶然发现这个线程有同样的问题。我不确定数据集的不可腌制性是否适用于所有 TF 数据集,但由于在这种情况下它是相关的,所以这就是需要解决(或解决)的问题。
我所做的是将 TFRecord 文件放在分布式存储上(在本例中为 UC Volume),然后在目标函数内实例化 TF 数据集对象。我想在某些情况下可能会产生一些开销,但即使使用大约 8k 图像的图像数据集,也只需要不到一秒的时间,所以这很好。对于任何其他不会腌制的对象来说,这也往往是一种方法(在对数据集进行排序后,最终确实出现了这种情况);只需将其构建在目标函数内即可。这可以是分布式存储上对象的数据集,可以是模型本身,也可以是任何东西。
对于知情人士来说,这可能是一个完全基本的“废话”答案,但这是我第一次尝试真正利用 Spark 集群的力量,所以我绝对不知所措,并且可以利用这种洞察力。也许其他人也会有同样的情况,并且也会从这个答案中受益。干杯!