来自学习变量的预期张量流模型大小


问题内容

在训练卷积神经网络进行图像分类任务时,我们通常希望我们的算法学习将给定图像转换为其正确标签的过滤器(和偏差)。我正在尝试比较一些模型,包括模型大小,操作数量,准确性等。但是,从tensorflow输出的模型大小,
具体来说 就是存储所有值的 model.ckpt.data 文件图中的变量不是我期望的。实际上,它似乎要大三倍。

为了直接解决这个问题,我要在这款Jupyter笔记本上提出问题。以下是定义变量(权重和偏差)的部分:

# Store layers weight & bias
weights = {
# 5x5 conv, 1 input, 32 outputs
'wc1': tf.Variable(tf.random_normal([5, 5, 1, 32]),dtype=tf.float32),
# 5x5 conv, 32 inputs, 64 outputs
'wc2': tf.Variable(tf.random_normal([5, 5, 32, 64]),dtype=tf.float32),
# fully connected, 7*7*64 inputs, 1024 outputs
'wd1': tf.Variable(tf.random_normal([7*7*64, 1024]),dtype=tf.float32),
# 1024 inputs, 10 outputs (class prediction)
'out': tf.Variable(tf.random_normal([1024, num_classes]),dtype=tf.float32)
}

biases = {
'bc1': tf.Variable(tf.random_normal([32]),dtype=tf.float32),
'bc2': tf.Variable(tf.random_normal([64]),dtype=tf.float32),
'bd1': tf.Variable(tf.random_normal([1024]),dtype=tf.float32),
'out': tf.Variable(tf.random_normal([num_classes]),dtype=tf.float32)
}

我添加了几行代码,以便在训练过程结束时保存模型:

# Save the model
save_path = saver.save(sess, logdir+"model.ckpt")
print("Model saved in file: %s" % save_path)

将所有这些变量 加起来, 我们期望得到一个大小为12.45Mb的 model.ckpt.data
文件(我已经通过计算模型学习的float元素的数量并将其转换为MegaBytes来获得此文件)。但!保存的 .data
文件为39.3Mb。为什么是这样?

我对更复杂的网络(ResNet的一个变体)采用了相同的方法,并且我期望的模型。数据大小也比实际 .data 文件小约3倍。

所有这些变量的数据类型为float32。


问题答案:

将所有这些变量加起来,我们希望得到一个大小为12.45Mb的model.ckpt.data文件

传统上,在这种情况下,大多数模型参数位于第一个完全连接的层中wd1。仅计算其大小会得出:

7*7*128 * 1024 * 4 = 25690112

…或25.6Mb。注意4系数,因为变量dtype=tf.float32,即4每个参数的字节数。其他层也影响模型的大小,但并不是很大。

如您所见,您的估算12.45Mb有些偏离
(您是否为每个参数使用16位?)。该检查点还存储一些常规信息,因此开销大约为25%,这仍然很大,但不是300%。

[更新]

[7*7*64, 1024]正如所阐明的,所讨论的模型实际上具有FC1形状的图层。因此,计算出的上述尺寸应该12.5Mb确实是。这使我更加仔细地查看了保存的检查点。

检查之后,我注意到我最初错过的其他大变量:

...
Variable_2 (DT_FLOAT) [3136,1024]
Variable_2/Adam (DT_FLOAT) [3136,1024]
Variable_2/Adam_1 (DT_FLOAT) [3136,1024]
...

Variable_2是完全wd1,但也有亚当优化2个拷贝。这些变量由创建亚当优化,他们是所谓的
插槽 并保持mv蓄能器 对所有训练的变量 。现在总大小有意义。

您可以运行以下代码来计算图形变量的总大小- 37.47Mb

var_sizes = [np.product(list(map(int, v.shape))) * v.dtype.size
             for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)]
print(sum(var_sizes) / (1024 ** 2), 'MB')

因此,开销实际上很小。额外的大小取决于优化程序。