如何使用 MNIST 在 tensorflow 中减少权重位或更改为较低位的类型?

Posted

技术标签:

【中文标题】如何使用 MNIST 在 tensorflow 中减少权重位或更改为较低位的类型?【英文标题】:How to reduce weight's bit or change to lower bit's type in tensorflow by using MNIST? 【发布时间】:2018-06-08 05:47:33 【问题描述】:

我正在做 CNN 模型压缩,并试图减少权重的位以获得位的长度和准确性之间的关系。但是当我使用Tensorflow网站的方法改变CNN的权重类型时,出现了错误:

“类型错误:传递给参数‘a’的值的 DataType int8 不在允许值列表中:float16、float32、float64、int32、complex64、complex128”。

似乎重量不能是其他Dtype。但我读了一些类似https://arxiv.org/pdf/1502.02551.pdf 的论文。可以将权重的位数减少到 6bits , 4bits ,甚至更低的位。

我的代码在这里(忽略导入的东西):

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)
x = tf.placeholder(tf.int8,[None,784])
W = tf.Variable(tf.zeros([784,10]),tf.int8)
b = tf.Variable(tf.zeros([10]),tf.int8)

y = tf.nn.softmax(tf.matmul(x,W)+b)
#the error come out with "y = tf.nn.softmax(tf.matmul(x,W)+b)"

这只是一个标准的tensorflow官方代码,只是改变了变量的Dtype。我也尝试过 tf.cast ,但它仍然出现错误。

tf.cast(W,tf.int8)
tf.cast(b,tf.int8)

谁能告诉我如何克服这种情况?非常感谢!!

【问题讨论】:

请添加您的代码示例以及您的预期输出。 【参考方案1】:

Tensorflow 不允许小于 16 位的数字。无论如何,少于 16 位是不切实际的,因为假设您使用 8 位(整数 4 位,十进制 4 位),可能的最低十进制数为 0.0625(1/16 -> 4 位只有 16 个不同的数字)。

您引用的论文使用 16 位数字,16 位分为 8-8、10-6 和 14-2 位(第一个是十进制位)。它还会对变量进行四舍五入,然后将它们转换为上述位分布,而不是在不四舍五入的情况下直接截断变量。


更新:我做了一点挖掘,如果您使用 float16 或 14-2 固定位分布,它实际上并没有太大区别:

最低float16十进制数:0.0000610352 1 或 14-2 固定位分布的最小十进制数:0.00006103515625

所以我建议,您只需使用 float16 instad of fixed 位分布,只使用随机舍入算法, 论文中描述的。


更新 2: 我使用 float32float16 训练了 MNIST 数据集。 float16 网络的性能与float32 网络几乎相同。该网络有两个隐藏层,每个隐藏层有 1000 个神经元,tf.nn.relu 作为激活函数。我使用了标准的 tensorflow tf.train.GradientDescentOptimizer 优化器,学习率为 0.1。作为成本函数,我使用了tf.nn.softmax_cross_entropy_with_logits。该网络训练了 120 多个 epoch,每 600 步,batch-size 为 100。float16 网络的测试准确度为 98.189997673,而float32test 准确度为 98.1599986553

一些有趣的链接:

GTC talk on mixed precision training NVIDIA fork of caffe

更新 3: 我认为在 tensorflow 中实现混合精度会很困难,因为您必须为反向传播编写自定义处理。 tensorflow 团队已经在努力实现 nativ 半精度。同时,我认为实现这一点的最佳方法是使用 caffe,其中已经实现了原生混合精度(至少在 nvidia branch 中)。见this ticket。

【讨论】:

这不是答案。您可以将其添加为问题中的评论吗? 抱歉,我无法对问题发表评论。 我撤消了反对票,并在问题下方发表了评论。 嗨! Markus Schwer 感谢您的回答 =) 我也尝试过,但仍然有同样的错误 =( 是的,float16 可以工作!但我想知道是否可以通过使用低位来完成。也许我需要修改 tensorflow 的文件以使用自定义功能?毕竟,谢谢你的回答=)【参考方案2】:

由于 OP 关注的是降低权重的精度,但不倾向于在实现级别上做同样的事情,我认为这可能会有所帮助:

您可以通过在 Keras 中编写自己的自定义层来降低权重的精度(通过近似高精度值):https://keras.io/layers/writing-your-own-keras-layers/

您可以在此处找到二进制权重模型的示例:https://github.com/DingKe/nn_playground/blob/master/binarynet/binary_layers.py

您必须编辑层的call() 方法并将权重近似为所需的位数。见下文:

```
def call(self, inputs):
    low_precision_kernel = reduce_precision_by_round_off(self.kernel)
    <--- Use the low precision kernel get the outputs --->
    return outputs

```

self.kernel 在自定义层的build() 调用中定义。

【讨论】:

以上是关于如何使用 MNIST 在 tensorflow 中减少权重位或更改为较低位的类型?的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow:如果我有一个训练有素的 MNIST 模型,我如何检测图像中的手写数字?

如何在 tensorflow mnist_softmax.py 中打印张量的值

使用tensorflow操作MNIST数据

教程 | 使用MNIST数据集,在TensorFlow上实现基础LSTM网络

TensorFlow学习笔记MNIST手写数字识别

在 TensorFlow 中使用 LSTM-CGAN 生成 MNIST 数字