Created
July 20, 2017 05:06
-
-
Save PCJohn/93d9cf6a4238cdea3924a32fa7f72af2 to your computer and use it in GitHub Desktop.
This script tries to overfit a small convolutional network, to perform integer division
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Attempt to perform integer division by overfitting convolution layers | |
Input: 2 numbers A and C | |
Output: Integer B such that A.B = C | |
Author: Prithvijit Chakrabarty (prithvichakra@gmail.com) | |
""" | |
import random | |
import numpy as np | |
import tensorflow as tf | |
from matplotlib import pyplot as plt | |
N_EPOCH = 5000 | |
LRATE = 1 | |
EPSILON = 0 | |
#Start a TensorFlow session | |
def start_sess(): | |
config = tf.ConfigProto() | |
config.gpu_options.allocator_type = 'BFC' | |
sess = tf.Session(config=config) | |
return sess | |
#Convert number to vector of digits (with padding) | |
def num2vec(n): | |
return np.array([map(float,str(n))]) | |
def vec2num(v): | |
ndig = v.size | |
d = map(int,np.round(v)) | |
return np.dot(d,pow_wt(ndig)) | |
def pad(v): | |
ndig = v.size | |
pv = np.zeros((1,3*ndig-2)) | |
pv[0,ndig-1:2*ndig-1] = v[0,:] | |
return pv | |
#Create the weight matrix for combining the partial products | |
def pow_wt(n): | |
return np.array([[10**(n-i-1) for i in range(n)]]).astype(np.float32).T | |
def build_net(sess,A): | |
#Number of digits | |
ndig = len(str(A)) | |
#Add padding | |
vA = pad(num2vec(A)) | |
#Placeholder: Number to be factorized | |
x_hold = tf.placeholder(tf.float32,vA.shape) | |
y_hold = tf.placeholder(tf.float32) | |
#Convolutions: For integer multiplication | |
n1 = tf.reshape(x_hold,[1,vA.size,1]) | |
n2 = tf.Variable(tf.random_uniform([ndig,1,1],minval=0,maxval=10)) | |
cout = tf.nn.conv1d(n1,n2,1,'VALID') | |
out = tf.reshape(cout,[1,2*ndig-1]) | |
#Weight with powers of 10 | |
print pow_wt(2*ndig-1) | |
wt = tf.constant(pow_wt(2*ndig-1)) | |
out = tf.matmul(out,wt) | |
#Error term | |
out = tf.reduce_sum(out) | |
loss = tf.sqrt(tf.reduce_mean(tf.squared_difference(out,y_hold))) | |
train_step = tf.train.AdamOptimizer(learning_rate=LRATE,epsilon=EPSILON).minimize(loss) | |
#Initialize variable | |
sess.run(tf.global_variables_initializer()) | |
return out,x_hold,y_hold,n1,n2,train_step,loss,cout,wt | |
def divide(A,C): | |
sess = start_sess() | |
out,x_hold,y_hold,n1,n2,train_step,loss,cout,wt = build_net(sess,A) | |
sess.run(tf.global_variables_initializer()) | |
#Overfit the network | |
avec = pad(num2vec(A)) | |
for epoch in range(N_EPOCH): | |
_,loss_v = sess.run([train_step,loss],feed_dict={x_hold:avec,y_hold:C}) | |
print 'Loss '+str(epoch)+': '+str(loss_v) | |
n1,n2,out,cout,wt = sess.run([n1,n2,out,cout,wt],feed_dict={x_hold:avec}) | |
print 'N1',n1 | |
print 'N2',n2 | |
print 'Out',out | |
print 'Cout',cout | |
print 'Wt',wt | |
sess.close() | |
print n2[::-1,:,:] | |
print 'Predicted B:',vec2num(n2[::-1,:,:]) | |
if __name__ == '__main__': | |
print 'A.B = C' | |
print 'This will find B = C/A' | |
print '(Assumes A and B have the same number of digits)' | |
while True: | |
A = int(raw_input('Enter A: ')) | |
C = int(raw_input('Enter C: ')) | |
print 'Dividing C with A:' | |
divide(A,C) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment