TensorFlow rnn analog binary subtracter

Keywords: network Lambda Session

Convert two numbers to binary arrays

Also convert the result to a binary array

Two input and one output subtracters simulated by rnn

Where i is the binary array of two numbers, j is the array after subtraction, and k is the simulation result

i: [[0. 0. 1. 0. 0. 1. 0. 1.]
 [0. 0. 1. 0. 0. 0. 0. 0.]]
j [0. 0. 0. 0. 0. 1. 0. 1.]
k [0. 0. 0. 0. 0. 1. 0. 1.]

Of course, you can also simulate addition, pay attention to not exceed the limit of digits when generating array, of course, you can also take truncation

i: [[0. 1. 0. 1. 0. 1. 1. 0.]
 [0. 1. 0. 1. 0. 0. 0. 1.]]
j [1. 0. 1. 0. 0. 1. 1. 1.]
k [1. 0. 1. 0. 0. 1. 1. 1.]

 

Tune in

Building a simple network

rnn -- full -- output

Output the rnn output sequence after a layer of full connection

The relu function is used to prevent negative numbers in the result

The loss function uses simple sum of squares

Finally, np is used to round the result to the final prediction sequence

import tensorflow as tf
import numpy as np
import random


#  Turning numbers into binary np arrays
def int2bin(x, num_len):
    x = bin(x)[2:].zfill(num_len)
    return np.array(
        list(map(lambda i: float(i), x))
    ).reshape((1, 1, num_len))


#  Get data, number of data groups and maximum number of digits
def get_data(batch_size, num_len):
    # Maximum number of subtraction
    max_num = (1 << num_len) - 1
    # Maximum number of addition
    # max_num = (1 << num_len - 1) - 1
    x_data = []
    y_data = []
    for i in range(batch_size):
        a, b = random.randint(0, max_num), random.randint(0, max_num)
        a, b = max(a, b), min(a, b)
        # print(a, b)

        c = np.concatenate([int2bin(a, num_len), int2bin(b, num_len)], axis=1)
        x_data.append(c)
        y_data.append(int2bin(a - b, num_len))
    x_data = np.concatenate(x_data)
    y_data = np.concatenate(y_data).reshape(batch_size, -1)
    return x_data, y_data


# x, y = get_data(10, 8)
# print(x.shape, y.shape) # (10, 2, 8) (10, 8)

input_n = 8
output_n = 8
train_steps = 40000
show_steps = 500
batch_size = 32
hidden_size = 128
full_size = 64
time_step = 2
learning_rate = .01

x_in = tf.placeholder(tf.float32, (None, time_step, input_n))
y_in = tf.placeholder(tf.float32, (None, output_n))
print(x_in.shape, y_in.shape)  # (?, 2, 8) (?, 8)
weight = tf.Variable(tf.truncated_normal([full_size, output_n], stddev=.1))
biase = tf.Variable(tf.constant(.1, shape=[output_n]))

# Building network lstm -- full -- relu
# cell = tf.contrib.rnn.BasicLSTMCell(hidden_size)
# outputs, final_state = tf.nn.dynamic_rnn(cell, x_in, dtype=tf.float32)
# print(final_state[1].shape)  # (?, 128)
# full = tf.layers.dense(final_state[1], full_size)
# print(full.shape)  # (?, 64)
# result = tf.matmul(full, weight) + biase
# result = tf.nn.relu(result)
# print(result.shape)  # (?, 8)


# Simple network, after rnn output, directly connected to a full connection output, relu prevents negative numbers
cell = tf.contrib.rnn.BasicLSTMCell(hidden_size)
outputs, final_state = tf.nn.dynamic_rnn(cell, x_in, dtype=tf.float32)
print(final_state[1].shape)  # (?, 128)
result = tf.contrib.slim.fully_connected(final_state[1],
                                         input_n,
                                         activation_fn=tf.nn.relu)

# loss and train
loss = tf.reduce_mean((result - y_in) ** 2)
train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(train_steps):
        x_data, y_data = get_data(batch_size, input_n)
        sess.run(train_op, feed_dict={
            x_in: x_data,
            y_in: y_data,
        })

        if not (epoch + 1) % show_steps:
            x_data, y_data = get_data(batch_size, input_n)
            loss__val, res = sess.run([loss, result], feed_dict={
                x_in: x_data,
                y_in: y_data,
            })
            print('epoch:', epoch + 1, 'loss:', loss__val)
            for i, j, k in zip(x_data[:4], y_data[:4], res[:4]):
                print('i:', i)
                print('j', j)
                print('k', np.rint(k))
                print('k', k)

 

After seeing that the loss is small, the prediction result is still very accurate

epoch: 39500 loss: 0.00060202624
i: [[1. 1. 0. 1. 0. 0. 1. 1.]
 [1. 1. 0. 1. 0. 0. 0. 1.]]
j [0. 0. 0. 0. 0. 0. 1. 0.]
k [0. 0. 0. 0. 0. 0. 1. 0.]
k [0.        0.        0.        0.        0.        0.        1.0148226
 0.       ]
i: [[1. 1. 1. 1. 1. 1. 1. 0.]
 [1. 1. 0. 1. 0. 0. 0. 1.]]
j [0. 0. 1. 0. 1. 1. 0. 1.]
k [0. 0. 1. 0. 1. 1. 0. 1.]
k [0.        0.        1.0292125 0.        1.0081979 1.0195892 0.
 1.0046306]
i: [[1. 1. 0. 0. 1. 0. 0. 1.]
 [1. 0. 1. 0. 0. 0. 1. 1.]]
j [0. 0. 1. 0. 0. 1. 1. 0.]
k [0. 0. 1. 0. 0. 1. 1. 0.]
k [0.         0.         1.0501771  0.         0.         1.0002633
 0.98572767 0.        ]
i: [[1. 0. 1. 0. 1. 1. 0. 0.]
 [0. 1. 1. 0. 0. 0. 1. 0.]]
j [0. 1. 0. 0. 1. 0. 1. 0.]
k [0. 1. 0. 0. 1. 0. 1. 0.]
k [0.         1.0481278  0.         0.         0.99072963 0.
 0.99771726 0.        ]
epoch: 40000 loss: 0.00059128506
i: [[1. 1. 1. 1. 1. 0. 1. 0.]
 [0. 1. 1. 0. 0. 1. 0. 1.]]
j [1. 0. 0. 1. 0. 1. 0. 1.]
k [1. 0. 0. 1. 0. 1. 0. 1.]
k [0.999081  0.        0.        1.0134556 0.        0.996073  0.
 1.0186146]
i: [[1. 0. 0. 1. 0. 1. 0. 1.]
 [0. 1. 1. 1. 0. 0. 1. 1.]]
j [0. 0. 1. 0. 0. 0. 1. 0.]
k [0. 0. 1. 0. 0. 0. 1. 0.]
k [0.        0.        1.0294001 0.        0.        0.        1.0243944
 0.       ]
i: [[1. 1. 1. 0. 0. 0. 1. 0.]
 [1. 1. 0. 1. 0. 1. 1. 0.]]
j [0. 0. 0. 0. 1. 1. 0. 0.]
k [0. 0. 0. 0. 1. 1. 0. 0.]
k [0.         0.         0.         0.         0.99334943 1.0034381
 0.         0.        ]
i: [[1. 0. 1. 0. 0. 0. 0. 0.]
 [1. 0. 0. 1. 1. 0. 1. 1.]]
j [0. 0. 0. 0. 0. 1. 0. 1.]
k [0. 0. 0. 0. 0. 1. 0. 1.]
k [0.         0.         0.         0.         0.         0.98055166
 0.         0.99823564]

Posted by something on Sat, 04 Jan 2020 05:40:31 -0800