我正在做CNN模型压缩,并试图减少重量的位,以得到位的长度和精度之间的关系。但当我使用Tensorflow网站的方法来改变CNN的权重类型时,却出现了一个错误:
“TypeError:传递给参数‘a’的值的数据类型int8不在允许值的列表中:float16、float32、float64、int32、complex64、complex128。”。
重量似乎不能是其他类型的。但我读过一些像这样的论文。可以将权重的位减少到6位、4位,甚至更低的位。
我的代码在这里(忽略导入某些内容):

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官方代码,只是改变了变量的数据类型。我也试过tf.cast,但还是出了问题。
tf.cast(W,tf.int8)
tf.cast(b,tf.int8)

有人能告诉我如何克服这种情况吗?谢谢!!

最佳答案

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
a或14-2固定位分配的最低十进制数:0.00006103515625
所以我建议你用
位分布,使用随机舍入算法,
文中描述。
更新2:我用float16float32训练MNIST数据集。float16网络的性能与float16网络几乎相同。该网络有两个隐藏层,每层1000个神经元,并以float32为激活函数。我使用标准的tensorflowtf.nn.relu优化器,学习率为0.1。作为成本函数,我使用了tf.train.GradientDescentOptimizer。该网络被训练了120多个阶段,每个阶段600个步骤,批量大小为100。tf.nn.softmax_cross_entropy_with_logits网络的测试精度为98.189997673,float16网络的测试精度为98.1599986553。
一些有趣的链接:
GTC talk on mixed precision training
NVIDIA fork of caffe
更新3:我认为在tensorflow中实现混合精度会很困难,因为您必须为反向传播编写自定义处理。tensorflow团队已经在致力于实现nativ半精度。同时,我认为实现这一点的最佳方法是使用caffe,其中已经实现了本机混合精度(至少在nvidia branch中)。见this ticket

08-24 14:04