卷积神经网络8bit量化

在卷积神经网络的模型压缩中,量化是非常重要的一个方法,本人曾在FPGA上进行过16bit的定点量化,其最后的精度损失可以忽略不计,为了更进一步的节省FPGA的资源,又尝试了int8量化,量化方式比较粗糙,采用训练后量化(Post training quantization),当然,更高级的量化方式为训练时量化(quantization aware training),虽然量化方式粗糙,但是还是取得了不错的效果,代码如下

import tensorflow as tf
import time
from keras.utils import to_categorical
import numpy as np

path="F:\mnist.npz"
f = np.load(path)
train_X, train_y = f['x_train'], f['y_train']
test_X, test_y = f['x_test'], f['y_test']
f.close()

train_X = train_X.reshape(-1, 784)
train_X = train_X.astype('float32')
train_X /= 255
train_y = to_categorical(train_y, 10)
test_X = test_X.reshape(-1,784)
test_X = test_X.astype('float32')
test_X /= 255
test_y = to_categorical(test_y,10)


def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.05)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='VALID')

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

sess = tf.InteractiveSession()

# 声明输入图片数据、类别
x = tf.placeholder('float', [None, 784])
y_ = tf.placeholder('float', [None, 10])
# 输入图片数据化
x_image = tf.reshape(x, [-1, 28, 28, 1])

W_conv1 = weight_variable([3, 3, 1, 4])
b_conv1 = bias_variable([4])
h_conv1 = tf.nn.relu(tf.nn.conv2d(x_image, W_conv1,strides=[1,1,1,1],padding="SAME") + b_conv1)   #(28,28,4)

W_conv2 = weight_variable([5, 5, 4, 32])
b_conv2 = bias_variable([32])
h_conv2 = tf.nn.relu(tf.nn.conv2d(h_conv1, W_conv2,strides=[1,1,1,1],padding="SAME") + b_conv2)   #(28,28,32)

W_conv3 = weight_variable([5,5,32,32])
b_conv3 = bias_variable([32])
h_conv3 =tf.nn.relu(tf.nn.conv2d(h_conv2,W_conv3,strides=[1,1,1,1],padding="SAME")+b_conv3)       #(28,28,32)

h_pool1=tf.nn.max_pool(h_conv3,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")                  #(14,14,32)

W_conv4 = weight_variable([5,5,32,64])
b_conv4 = bias_variable([64])
h_conv4=tf.nn.relu(tf.nn.conv2d(h_pool1,W_conv4,strides=[1,1,1,1],padding="SAME")+b_conv4)        #(14,14,64)

W_conv5 = weight_variable([5,5,64,64])                                                            #(14,14,64)
b_conv5 = bias_variable([64])
h_conv5 = tf.nn.relu(tf.nn.conv2d(h_conv4,W_conv5,strides=[1,1,1,1],padding="SAME")+b_conv5)

h_pool2 =tf.nn.max_pool(h_conv5,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")                 #(7,7,64)

h_fc1=tf.reshape(h_pool2,[-1,7*7*64])

W_fc1 = weight_variable([7*7*64, 10])
b_fc1 = bias_variable([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1,W_fc1)+b_fc1)

# 代价函数
cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv))
train_step = tf.train.GradientDescentOptimizer(0.0001).minimize(cross_entropy)
# 测试正确率
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float32"))

# 变量初始化
epoch=5
sess.run(tf.initialize_all_variables())
for k in range(epoch):
    for i in range(600):
        # 获取训练数据
        batch_xs, batch_ys =train_X[i*100:i*100+100],train_y[i*100:i*100+100]
        # 每迭代10个batch,对当前训练数据进行测试,输出当前预测准确率
        if i % 10 == 0:
            train_accuracy = accuracy.eval(feed_dict={
    
    x: batch_xs, y_: batch_ys})
            print("step %d , training accuracy %g" % (i, train_accuracy))
        # 训练数据
        train_step.run(feed_dict={
    
    x: batch_xs, y_: batch_ys})




F=16

Wc1=W_conv1.eval()
bc1=b_conv1.eval()
Wc2=W_conv2.eval()
bc2=b_conv2.eval()
Wc3=W_conv3.eval()
bc3=b_conv3.eval()
Wc4=W_conv4.eval()
bc4=b_conv4.eval()
Wc5=W_conv5.eval()
bc5=b_conv5.eval()
Wf1=W_fc1.eval()
bf1=b_fc1.eval()

sess.close()


def float_to_int8(In,F):
    In=In*F
    In=np.round(In)
    In=np.maximum(-128,In)
    In=np.minimum(127,In)
    Out=In.astype(np.int8)
    return Out

Wc1=float_to_int8(Wc1,F)
bc1=float_to_int8(bc1,F)
Wc2=float_to_int8(Wc2,F)
bc2=float_to_int8(bc2,F)
Wc3=float_to_int8(Wc3,F)
bc3=float_to_int8(bc3,F)
Wc4=float_to_int8(Wc4,F)
bc4=float_to_int8(bc4,F)
Wc5=float_to_int8(Wc5,F)
bc5=float_to_int8(bc5,F)
Wf1=float_to_int8(Wf1,F)
bf1=float_to_int8(bf1,F)

def conv(In,W,b):
    H=In.shape[0]
    K=W.shape[0]
    N=W.shape[3]
    P=(K-1)//2
    O=np.zeros(shape=(H,H,N),dtype=np.int8)
    I=np.pad(In,((P,P),(P,P),(0,0)),mode='constant')
    for i in range(O.shape[0]):
        for j in range(O.shape[1]):
            for m in range(N):
                O[i,j,m]=np.sum(I[i:i+K,j:j+K,:]*W[:,:,:,m])/F+b[m]
    return O

def maxpool(In):
    H,W,C=In.shape
    O=np.zeros((H//2,W//2,C))
    for i in range(H//2):
        for j in range(W//2):
            for n in range(C):
                O[i,j,n]=np.max(In[2*i:2*i+2,2*j:2*j+2,n])
    return O

def relu(In):
    return np.maximum(In,0)

def predict(In):
    x=conv(In,Wc1,bc1)
    x=relu(x)
    x=conv(x,Wc2,bc2)
    x=relu(x)
    x=conv(x,Wc3,bc3)
    x=relu(x)
    x=maxpool(x)

    x=conv(x,Wc4,bc4)
    x=relu(x)
    x=conv(x,Wc5,bc5)
    x=relu(x)
    x=maxpool(x)

    x=x.reshape(-1,7*7*64)

    x=np.dot(x,Wf1)/F+bf1.reshape(-1,10)
    label=np.argmax(x)
    return label

a=0

for i in range(100):
    x=test_X[i].reshape(28,28,1)
    x=float_to_int8(x,F)
    c=predict(x)
    if c==np.argmax(test_y[i]):
        print("right")
        a+=1
    else:
        print("error")

print(a/100.0)


训练5轮,量化后(8bit,4bit小数位)预测100张图片,得到准确率为
在这里插入图片描述
修改1

import tensorflow as tf
import time
from keras.utils import to_categorical
import numpy as np

path="F:\mnist.npz"
f = np.load(path)
train_X, train_y = f['x_train'], f['y_train']
test_X, test_y = f['x_test'], f['y_test']
f.close()

train_X = train_X.reshape(-1, 784)
train_X = train_X.astype('float32')
train_X /= 255
train_y = to_categorical(train_y, 10)
test_X = test_X.reshape(-1,784)
test_X = test_X.astype('float32')
test_X /= 255
test_y = to_categorical(test_y,10)


def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.05)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='VALID')

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

sess = tf.InteractiveSession()

# 声明输入图片数据、类别
x = tf.placeholder('float', [None, 784])
y_ = tf.placeholder('float', [None, 10])
# 输入图片数据化
x_image = tf.reshape(x, [-1, 28, 28, 1])

W_conv1 = weight_variable([3, 3, 1, 4])
b_conv1 = bias_variable([4])
h_conv1 = tf.nn.relu(tf.nn.conv2d(x_image, W_conv1,strides=[1,1,1,1],padding="SAME") + b_conv1)   #(28,28,4)

W_conv2 = weight_variable([5, 5, 4, 32])
b_conv2 = bias_variable([32])
h_conv2 = tf.nn.relu(tf.nn.conv2d(h_conv1, W_conv2,strides=[1,1,1,1],padding="SAME") + b_conv2)   #(28,28,32)

W_conv3 = weight_variable([5,5,32,32])
b_conv3 = bias_variable([32])
h_conv3 =tf.nn.relu(tf.nn.conv2d(h_conv2,W_conv3,strides=[1,1,1,1],padding="SAME")+b_conv3)       #(28,28,32)

h_pool1=tf.nn.max_pool(h_conv3,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")                  #(14,14,32)

W_conv4 = weight_variable([5,5,32,64])
b_conv4 = bias_variable([64])
h_conv4=tf.nn.relu(tf.nn.conv2d(h_pool1,W_conv4,strides=[1,1,1,1],padding="SAME")+b_conv4)        #(14,14,64)

W_conv5 = weight_variable([5,5,64,64])                                                            #(14,14,64)
b_conv5 = bias_variable([64])
h_conv5 = tf.nn.relu(tf.nn.conv2d(h_conv4,W_conv5,strides=[1,1,1,1],padding="SAME")+b_conv5)

h_pool2 =tf.nn.max_pool(h_conv5,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")                 #(7,7,64)

h_fc1=tf.reshape(h_pool2,[-1,7*7*64])

W_fc1 = weight_variable([7*7*64, 10])
b_fc1 = bias_variable([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1,W_fc1)+b_fc1)

# 代价函数
cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv))
train_step = tf.train.GradientDescentOptimizer(0.0001).minimize(cross_entropy)
# 测试正确率
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float32"))

# 变量初始化
epoch=1
sess.run(tf.initialize_all_variables())
for k in range(epoch):
    for i in range(600):
        # 获取训练数据
        batch_xs, batch_ys =train_X[i*100:i*100+100],train_y[i*100:i*100+100]
        # 每迭代10个batch,对当前训练数据进行测试,输出当前预测准确率
        if i % 10 == 0:
            train_accuracy = accuracy.eval(feed_dict={
    
    x: batch_xs, y_: batch_ys})
            print("step %d , training accuracy %g" % (i, train_accuracy))
        # 训练数据
        train_step.run(feed_dict={
    
    x: batch_xs, y_: batch_ys})




F=16

Wc1=W_conv1.eval()
bc1=b_conv1.eval()
Wc2=W_conv2.eval()
bc2=b_conv2.eval()
Wc3=W_conv3.eval()
bc3=b_conv3.eval()
Wc4=W_conv4.eval()
bc4=b_conv4.eval()
Wc5=W_conv5.eval()
bc5=b_conv5.eval()
Wf1=W_fc1.eval()
bf1=b_fc1.eval()

sess.close()


def float_to_int8(In,F):
    In=In*F
    In=np.round(In)
    In=np.maximum(-128,In)
    In=np.minimum(127,In)
    Out=In.astype(np.int8)
    return Out

Wc1=float_to_int8(Wc1,F)
bc1=float_to_int8(bc1,F)
Wc2=float_to_int8(Wc2,F)
bc2=float_to_int8(bc2,F)
Wc3=float_to_int8(Wc3,F)
bc3=float_to_int8(bc3,F)
Wc4=float_to_int8(Wc4,F)
bc4=float_to_int8(bc4,F)
Wc5=float_to_int8(Wc5,F)
bc5=float_to_int8(bc5,F)
Wf1=float_to_int8(Wf1,F)
bf1=float_to_int8(bf1,F)

def conv(In,W,b):
    H=In.shape[0]
    K=W.shape[0]
    N=W.shape[3]
    P=(K-1)//2
    O=np.zeros(shape=(H,H,N),dtype=np.int16)
    I=np.pad(In,((P,P),(P,P),(0,0)),mode='constant')
    for i in range(O.shape[0]):
        for j in range(O.shape[1]):
            for m in range(N):
                O[i,j,m]=np.sum(I[i:i+K,j:j+K,:]*W[:,:,:,m])/F+b[m]
    return np.minimum(127,O)

def maxpool(In):
    H,W,C=In.shape
    O=np.zeros((H//2,W//2,C))
    for i in range(H//2):
        for j in range(W//2):
            for n in range(C):
                O[i,j,n]=np.max(In[2*i:2*i+2,2*j:2*j+2,n])
    return O

def relu(In):
    return np.maximum(In,0)

def predict(In):
    x=conv(In,Wc1,bc1)
    x=relu(x)
    x=conv(x,Wc2,bc2)
    x=relu(x)
    x=conv(x,Wc3,bc3)
    x=relu(x)
    x=maxpool(x)

    x=conv(x,Wc4,bc4)
    x=relu(x)
    x=conv(x,Wc5,bc5)
    x=relu(x)
    x=maxpool(x)

    x=x.reshape(-1,7*7*64)

    x=np.minimum(127,np.dot(x,Wf1)/F)+bf1.reshape(-1,10)
    label=np.argmax(x)
    return label

a=0

for i in range(100):
    x=test_X[i].reshape(28,28,1)
    x=float_to_int8(x,F)
    c=predict(x)
    if c==np.argmax(test_y[i]):
        print("right")
        a+=1
    else:
        print("error")

print(a/100.0)


训练1轮,准确率为89%

猜你喜欢

转载自blog.csdn.net/qq_40268672/article/details/105586360