This tutorial will help you go through the procedures of training a one-layer XNorNet as a perceptron on mnist dataset, and how to deploy trained weights and images into magma. This tutorial has borrowed some codes from https://github.com/BenBBear/MNIST-XNORNet.
In [1]:
import numpy as np
import tensorflow as tf
from tensorflow.python.framework import ops
from tf_func import *
from mnist import read_data_sets
mnist = read_data_sets('MNIST_data')
Here we train a xnor network following description(https://arxiv.org/abs/1603.05279). Considering the limit amount of resources on ice40, we resize the image from 28x28 to 16x16. We use only one fully-connected layer to conduct classification. Feel free to add conv layers if you have a larger resource.
In [2]:
# Build Computational Graph
sess = tf.InteractiveSession()
# Initialize placeholders for data & labels
x = tf.placeholder(tf.float32, shape=[None, 256])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
keep_prob = tf.placeholder(tf.float32)
# reshape to make image volumes
x_image = tf.reshape(x, [-1,1,1,256])
x_image_drop = tf.nn.dropout(x_image, keep_prob)
W_fc = weight_variable([1, 1, 256, 10])
BW_fc = binarize_weights(W_fc)
y_conv = tf.reshape(conv2d(x_image, BW_fc), [-1, 10])
# create train ops
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# initialize all variables
sess.run(tf.global_variables_initializer())
# train loop
for i in range(10000):
batch = mnist.train.next_batch(50)
if i % 1000 == 0:
print("test accuracy %g"%accuracy.eval(feed_dict={
x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
if i % 100 == 0:
train_accuracy = accuracy.eval(feed_dict={
x:batch[0], y_: batch[1], keep_prob: 1.0})
print("step %d,r training accuracy %g"%(i, train_accuracy))
train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
In [80]:
import pickle
# trained binary weights
res = BW_fc.eval()
alpha = np.abs(res).sum(0).sum(0).sum(0) / res[:,:,:,0].size
BW = np.sign(res)
BW = np.squeeze(BW, axis=(0, 1))
BW = BW.T
BW[BW==-1] = 0
# mnist samples ranging from label 0 to 9
imgs = [mnist.test.images[3], mnist.test.images[2], mnist.test.images[208], mnist.test.images[811], mnist.test.images[1140],
mnist.test.images[102], mnist.test.images[814], mnist.test.images[223],mnist.test.images[128], mnist.test.images[214]]
imgs = np.vstack(imgs)
imgs[imgs==-1]=0
weights_int16 = np.zeros((10, 16), dtype=np.uint16)
for index in range(10):
for i in range(16):
for j in range(15):
weights_int16[index, i] += BW[index, 16 * i + j]
weights_int16[index, i] = np.left_shift(weights_int16[index, i], 1)
weights_int16[index, i] += BW[index, 16 * i + 15]
imgs_int16 = np.zeros((10, 16), dtype=np.uint16)
for index in range(10):
for i in range(16):
for j in range(15):
imgs_int16[index, 15-i] += imgs[index, 16 * (15 - j) + i]
imgs_int16[index, 15-i] = np.left_shift(imgs_int16[index, 15-i], 1)
imgs_int16[index, 15-i] += imgs[index, 16 * 0 + i]
pickle.dump({'imgs':imgs, 'weights': BW, 'alpha':alpha,
'imgs_int16':imgs_int16, 'weights_int16':weights_int16}, open( "BNN.pkl", "wb" ))
In [27]:
import matplotlib.pyplot as plt
%matplotlib inline
def dis_img(imgs, index):
img = imgs[index, :]
img = np.reshape(img, [16, 16])
plt.imshow(img, cmap='gray')
plt.show()
In [81]:
for img_index in range(10):
res = []
for i in range(10):
kk = np.logical_not(np.logical_xor(imgs[img_index, :], BW[i, :].T))
pop_count = np.sum(kk)
res.append(pop_count)
plt.subplot(2, 5, img_index + 1)
img = np.reshape(imgs[img_index, :], [16, 16])
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.title("Pred: " + str(np.argmax(res, axis=0)))
plt.show()
In [ ]: