如何正确提取 Keras ConvNet 权重矩阵以在 Excel 中使用?

Posted

技术标签:

【中文标题】如何正确提取 Keras ConvNet 权重矩阵以在 Excel 中使用?【英文标题】:How do I correctly extract Keras ConvNet weights matrices for use in Excel? 【发布时间】:2020-10-20 15:50:24 【问题描述】:

我正在尝试在 Excel 中构建一个非常简单的卷积神经网络。该模型是一个图像分类器,试图识别手写的 I、O 和 X;并使用 Keras 对 EMNIST 字母数据集的一个子集进行了训练。 Excel 电子表格只是前向传播阶段(即所有实际训练都在 Keras 中进行),我主要将其用于说明和理解目的。

模型架构非常简单:输入 > 卷积层(5 个 3x3 滤波器)> maxpool > 密集输出层(3 类)。

该模型在测试集上的准确率为 99.33%,所以我知道它运行良好。使用model.predict 对单个样本进行了正确分类,但是当我在 Excel 版本中尝试相同的样本时,预测通常不同(并且不正确)。

在我看来,可能存在两个问题:首先,我从训练模型中提取的权重(并复制粘贴到 Excel 中)的顺序/形状可能有误。其次,Excel模型设置不正确。我相当确定 Excel 模型很好,所以我认为权重是问题所在。

所以我的问题如下:如何使用get_weights 从 Keras 中提取权重,以便我可以在 Excel 中排列它们?特别是在 15x3 网格中,即卷积层的 5 个 3x3 过滤器权重的垂直堆叠和密集层的 980x3 网格。

这是我一直在做的 - 但它似乎不正确:

raw_conv1_weights = iox_model.get_weights()[0]
raw_conv1_biases = iox_model.get_weights()[1]
raw_dense_weights = iox_model.get_weights()[2]
raw_dense_biases = iox_model.get_weights()[3]

conv1_weights = pd.DataFrame(raw_conv1_weights.swapaxes(0,2).swapaxes(1,3).reshape(15,3))
conv1_biases = pd.DataFrame(raw_conv1_biases)
dense_weights = pd.DataFrame(raw_dense_weights)
dense_biases = pd.DataFrame(raw_dense_biases)

然后将数据框保存为 .xlsx 格式,并将网格复制粘贴到 Excel 模型中。

在 Keras 中构建的模型本身如下所示,以防相关。

# defining the model architecture
n_classes = 3

iox_model = models.Sequential()

# first convolutional layer (with padding to preserve output dimensions)
iox_model.add(layers.Conv2D(5,(3,3), activation='relu', input_shape=img_shape, padding='same'))

# max pooling layer
iox_model.add(layers.MaxPooling2D((2,2)))

# fully connected output layer
iox_model.add(layers.Flatten())
iox_model.add(layers.Dense(n_classes, activation='softmax'))

非常感谢!

编辑:

我正在添加一些关于 Excel 电子表格如何工作的详细信息,以防万一。

输入图像是一个 28x28 网格,其值范围为 0-255(单通道图像)。 标准化图像是通过将每个单元格的值除以 255 创建的,然后填充为 0。 使用 SUMPRODUCT 在归一化图像上依次使用每个过滤器执行卷积,从而为 5 个过滤器中的每一个创建一个 28x28 网格(特征图),并将相关过滤器的偏置项添加到每个单元格在新的网格中。 使用 MAX(0,cell) 对卷积特征图中的每个单元执行 ReLU 激活,为 5 个过滤器中的每一个创建另一个 28x28 网格。 - 对激活图中的每个 2x2 细胞批次使用 MAX(2x2 细胞批次)执行最大池化。 然后将输出按顺序展平为单列(最大池映射 1,第 1 行;映射 1,第 2 行;...;映射 2,第 1 行;依此类推)。 logit 输出分数是通过在扁平化的最大池输出和 3 个密集层权重列中的每一个上依次使用 SUMPRODUCT 获得的,并在每个列中添加相关的偏置项。然后使用 EXP 等对 logit 输出进行 softmax 处理。

【问题讨论】:

【参考方案1】:

很高兴报告我已经解决了这个问题。我想我只是在这里发布一个答案,以防有人需要它。

事实证明,问题既不是权重也不是前向传播电子表格。我多次尝试为权重重新塑造和交换轴,但无济于事,我还从 Keras 中提取了正在调查的实际样本的激活,并将它们与 Excel 中的激活进行了比较,如下所示:

layer_outputs = [layer.output for layer in iox_model.layers] 
activation_model = models.Model(inputs=iox_model.input, outputs=layer_outputs)
activations = activation_model.predict(np.expand_dims(sample, axis=0)) 

以这种方式提取的所有激活都与 Excel 版本中的激活匹配。问题在于Flatten() 层。在 Keras 中扁平化产生的数组按如下方式排序:

过滤器 1,第 1 列,第 1 行;过滤器 2,第 1 列,第 1 行;过滤器 3,第 1 列,第 1 行; ... 过滤器 5,第 14 列,第 14 行;

而不是:

过滤器 1,第 1 列,第 1 行;过滤器 1,第 2 列,第 1 行;过滤器 1,第 3 列,第 1 行; ... 过滤器 5,第 14 列,第 14 行;

如我所料。

我这样做的方式意味着代表全连接输出层的 SUMPRODUCT 设置不正确。我修复了 Excel 版本的展平层,使其生成的列遵循与 Keras 中相同的顺序,现在它可以正常工作了。

【讨论】:

以上是关于如何正确提取 Keras ConvNet 权重矩阵以在 Excel 中使用?的主要内容,如果未能解决你的问题,请参考以下文章

如何准备图像以使用 Python/Keras 训练 ConvNet?

了解每一层的 Keras 权重矩阵

如何正确从 keras 中的 Conv2D 获取层权重?

在不使用 Keras API 的情况下,提取 Keras 层的权重对于进行前向传递有啥意义

keras 如何保存训练集与验证集正确率的差最小那次epoch的网络及权重

将 Convnet.js 神经网络模型转换为 Keras Tensorflow