如何使用对 GPU 来说太大的 NN 架构?

数据挖掘 神经网络 深度学习 喀拉斯 张量流 显卡
2021-09-30 13:09:37

最初发布在Stack Overflow 上

我想实现一个实际上是 2 个神经网络堆叠在一起的模型。然而,这两种架构的尺寸太大,无法同时容纳在 GPU 中。

我的想法如下:

  • 加载第一个模型并运行 1 批
  • 从 GPU 卸载第一个模型,加载第二个模型
  • 从第一个模型的输出运行第二个模型
  • 从 GPU 中卸载第二个模型
  • 对每批重复

我实际上不需要训练第一个模型,因为它是预先训练的。但我需要训练第二个模型。

有可能做这样的事情吗?我的方法正确吗?我应该注意哪些陷阱?性能怎么样?

编辑

我已经尝试过首先为整个数据集计算第一个模型的输出,然后将其用作第二个数据集的输入。但是第一个数据集的输出非常大,我没有可用空间来存储整个预处理数据集。这就是为什么我想每批都做。

编辑 2

在@Gal Avineri 给出非常好的回答之后,再提高一个精度:我想只使用一个 GPU 来实现我的架构。

2个回答

我建议一种类似于@ignatius 提供的方法。

由于您不需要训练第一个模型而只需要训练第二个模型,您可以执行以下操作:

  1. 在整个数据集上使用第一个模型并将提取的结果保存在内存中。
  2. 使用上一步的结果训练第二个模型。

这样,您只需在给定时间加载一个模型。
此外,这将使第二个模型的训练更快。

编辑 1

(操作人员已指定他没有足够的内存用于推理结果)
在这种情况下,我可以建议在第一个模型的推理和第二个模型的训练之间并行化。
这可以通过prefacking来实现。

让我们将原始数据集表示为data1,将第一个模型的相应推理结果表示为data2
我们也将第一个模型表示为M1,将第二个模型表示为M2
因此,您可以执行以下操作:

  1. 将M1加载到 cpu,将M2加载到 gpu。
  2. 从data1中绘制一批并使用M1M2准备一批data2
  3. 使用 gpu在上一步收到的批次上训练M2
  4. 在执行步骤 3 的同时,通过执行步骤 2准备下一批数据2 。

这样,当M2在一个批次上训练时,下一个批次正在准备中。这称为预取下一批。这将使M2
的训练和data2的制作并行化

我上面描述的方法有一个非常简单的方法来使用 tensorflow“数据”api 来实现。

这是一个代码示例:

import numpy as np
from tensorflow.keras import backend as K
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.data import Dataset

with K.device('cpu0'):
    input = Input((10,))
    x = Dense(100)(input)
    m1 = Model(input_shape=input, outputs=x)

with K.device('gpu0'):
    input = Input((100,))
    x = Dense(5)(input)
    m2 = Model(input_shape=input, outputs=x)


features = np.random.rand(10, 2000)
labels = np.random.randint(2, size=2000)
dataset = Dataset.from_tensor_slices((features, labels))


def preprocess_sample(features, label):
    inference = m2.predict(features, batch_size=1)
    return inference, label


dataset = dataset.shuffle(2000).repeat().map(preprocess_sample).batch(32)
dataset = dataset.prefetch(1)

m2.fit(dataset, epochs=100, steps_per_epoch=2000//32)

我以前在大型 CNN 架构中看到过这个问题。如果第一个网络不会改变,则使用该网络对所有数据进行预测,并将输出用作第二个网络的训练数据。您可以将其保存为单独的数据集并重复使用。

编辑-我刚刚注意到 Gal Avineri 发布了相同的答案。