python - 在 CPU 上使用卷积层时出错
问题描述
我可以在没有 gpu 支持的情况下使用 keras 的卷积层吗?当我在运行时为 None 的 Colab 上使用它时出现错误。我的代码如下所示:
model = tf.keras.Sequential()
model.add(layers.Conv1D(1,5, name='conv1', padding="same", activation='relu',data_format="channels_first", input_shape=(1,2048)))
# model.add(layers.LSTM(5, activation='tanh'))
model.add(layers.Flatten())
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))
#model.summary()
model.compile(loss=tf.keras.losses.categorical_crossentropy,
optimizer=tf.keras.optimizers.SGD(lr=0.001, momentum=0.9),
metrics=['accuracy'])
x_train = train_value
y_train = train_label
x_test = test_value
y_test = test_label
print(np.shape(x_train)) #shape of x train is (4459, 1, 2048)
print(np.shape(x_test)) #shape of test is (1340,1,2048)
history = model.fit(x_train, y_train,
batch_size=100,
epochs=30,
verbose=1,
validation_data=(x_test, y_test)
)
它在 GPU 上运行良好,但在 CPU 上出现以下错误:
InvalidArgumentError:Conv2DCustomBackpropFilterOp 仅支持 NHWC。[[{{节点训练/SGD/gradients/gradients/conv1/conv1d_grad/Conv2DBackpropFilter}}]]
UnimplementedError:Conv2D 运算目前仅支持 CPU 上的 NHWC 张量格式。该操作的格式为:NCHW [[{{node conv1_1/conv1d}}]]
我发现问题出在输入数据的格式上。我的输入数据是大小为 (1,2048) 的向量。您能否指导我如何将这些向量转换为 NHWC 格式?如果有人可以为我解决这个问题,我将不胜感激。提前致谢。
解决方案
根据Keras 文档
data_format:一个字符串,“channels_last”(默认)或“channels_first”之一。输入中维度的排序。“channels_last”对应于形状为(batch、steps、channels)的输入(Keras 中时间数据的默认格式),而“channels_first”对应于形状为(batch、channels、steps)的输入
现在 TensorFlow 中的 Keras 似乎是Conv1D
根据Conv2D
操作符来实现的——基本上形成一个“图像”,其中包含 1 行、W
列,然后是C
“通道”。这就是当您没有图像数据时会收到有关图像形状的错误消息的原因。
在上面的文档中,“通道”是每个时间步长的数据项数(例如,您可能在每个时间步长有 5 个传感器读数,因此您有 5 个通道)。从您上面的答案中,我相信您传递的张量形状(n, 1, 2048)
是n
您的批量大小。因此,channels_last
TensorFlow 认为这意味着您n
的批次中有示例,每个示例的序列长度1
和2048
每个时间步的数据项 - 这只是一个时间步,每次观察有 2048 个数据项(例如,在每个时间步获取 2048 个传感器读数)在这种情况下,卷积不会进行卷积 - 它相当于将所有 2048 个数字作为输入的单个密集层。
我认为实际上每个时间步只有一个数据项,并且有 2048 个时间步。这就解释了为什么传递channels_first
可以提高您的准确性 - 现在 TensorFlow 了解您的数据代表 1 个数据项样本 2048 次,并且它可以对该数据进行卷积。
要修复,您可以tf.reshape(t, (1, 2048, 1))
- 并删除channels_first
(该代码假设您正在执行大小为 1 的批次,并且您的张量名为t
)。现在它的格式(n, s, 1)
是n
批量大小(1
此处),s
时间步数(2048),并1
表示每个时间步一个数据点。您现在可以在 GPU 或 CPU 上运行相同的模型。
推荐阅读
- android - 如何在 react-native 中解决此错误?
- php - 如何将数据库结果序列化为 FCM/推送通知数据?
- assembly - 如何使8086清屏然后将光标移动到换行符以打印出下一个功能
- docker - 使用 docker secret 登录到容器内的 docker 注册表
- c++ - 在 Eclipse (C/C++) 中链接文件夹时出现问题
- sql - 如何重写 SQL 查询,使其更像左外连接
- css - 为什么我的溢出:隐藏不能使用 div+img?
- swift - 如何根据标签动态设置 UICollectionView Header 的高度?
- haskell - 了解将 Maybe a 列表转换为 Maybe [a] 的函数中的递归
- javascript - 如何导入 js 模块,而不是 require()?