当训练卷积神经网络用于图像分类任务时,我们通常希望我们的算法学习将给定图像转换为其正确标签的滤波器(和偏差)。我有一些模型,我试图在模型大小,操作数量,准确性等方面进行比较。但是,模型的大小从tensorflow输出,具体是 model.ckpt.data 存储图中所有变量值的文件不是我期望的那个。事实上,它似乎要大三倍。
要直接解决这个问题,我将在this 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 文件(我通过计算模型学习的浮点元素的数量得到了这个然后将该值转换为MegaBytes)。但!保存的 .data 文件为39.3Mb。这是为什么?
我使用更复杂的网络(ResNet的变体)采用相同的方法,我预期的model.data大小也比实际的 .data 文件小~3倍。< / p>
所有这些变量的数据类型是float32。
答案 0 :(得分:2)
添加所有这些变量,我们希望得到一个大小为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
,但Adam优化器还有2个副本。这些变量由the Adam optimizer创建,它们被称为广告位,并为所有可训练变量保留m
和v
累加器 。现在总的大小是有道理的。
您可以运行以下代码来计算图变量的总大小 - 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')
所以开销实际上很小。额外的大小是由优化器决定的。