Skip to content

Instantly share code, notes, and snippets.

@PCJohn
Created July 20, 2017 05:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PCJohn/93d9cf6a4238cdea3924a32fa7f72af2 to your computer and use it in GitHub Desktop.
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
"""
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