Package

This package includes an example Recurrent Neural Network. The package is loaded using:

library(rnn)

Code

We can view the code of the main rnn() function by calling it without the parathesis.

rnn
## function(Y, X1, X2, binary_dim, alpha, input_dim, hidden_dim, output_dim, silent = FALSE) {
##   
##   # check what largest possible number is
##   largest_number = 2^binary_dim
##   
##   # initialize neural network weights
##   synapse_0 = matrix(stats::runif(n = input_dim*hidden_dim, min=-1, max=1), nrow=input_dim)
##   synapse_1 = matrix(stats::runif(n = hidden_dim*output_dim, min=-1, max=1), nrow=hidden_dim)
##   synapse_h = matrix(stats::runif(n = hidden_dim*hidden_dim, min=-1, max=1), nrow=hidden_dim)
##   
##   synapse_0_update = matrix(0, nrow = input_dim, ncol = hidden_dim)
##   synapse_1_update = matrix(0, nrow = hidden_dim, ncol = output_dim)
##   synapse_h_update = matrix(0, nrow = hidden_dim, ncol = hidden_dim)
##   
##   # training logic
##   for (j in 1:length(Y)) {
##     
##     # generate a simple addition problem (a + b = c)
##     a_int = X1[j] # int version
##     a = int2binary(a_int, binary_dim) # binary encoding
##     
##     b_int = X2[j] # int version
##     b = int2binary(b_int, binary_dim)
##     
##     # true answer
##     c_int = Y[j]
##     c = int2binary(c_int, binary_dim)
##     
##     # where we'll store our best guesss (binary encoded)
##     d = matrix(0, nrow = 1, ncol = binary_dim)
##     
##     overallError = 0
##     
##     layer_2_deltas = matrix(0)
##     layer_1_values = matrix(0, nrow=1, ncol = hidden_dim)
##     # layer_1_values = rbind(layer_1_values, matrix(0, nrow=1, ncol=hidden_dim))
##     
##     # moving along the positions in the binary encoding
##     for (position in 0:(binary_dim-1)) {
##       
##       # generate input and output
##       X = cbind(a[binary_dim - position],b[binary_dim - position])
##       y = c[binary_dim - position]
##       
##       # hidden layer (input ~+ prev_hidden)
##       layer_1 = sigmoid((X%*%synapse_0) + (layer_1_values[dim(layer_1_values)[1],] %*% synapse_h))
##       
##       # output layer (new binary representation)
##       layer_2 = sigmoid(layer_1 %*% synapse_1)
##       
##       # did we miss?... if so, by how much?
##       layer_2_error = y - layer_2
##       layer_2_deltas = rbind(layer_2_deltas, layer_2_error * sigmoid_output_to_derivative(layer_2))
##       overallError = overallError + abs(layer_2_error)
##       
##       # decode estimate so we can print it out
##       d[binary_dim - position] = round(layer_2)
##       
##       # store hidden layer so we can print it out
##       layer_1_values = rbind(layer_1_values, layer_1)
##     }
##     
##     future_layer_1_delta = matrix(0, nrow = 1, ncol = hidden_dim)
##     
##     for (position in 0:(binary_dim-1)) {
##       
##       X = cbind(a[position+1], b[position+1])
##       layer_1 = layer_1_values[dim(layer_1_values)[1]-position,]
##       prev_layer_1 = layer_1_values[dim(layer_1_values)[1]-(position+1),]
##       
##       # error at output layer
##       layer_2_delta = layer_2_deltas[dim(layer_2_deltas)[1]-position,]
##       # error at hidden layer
##       layer_1_delta = (future_layer_1_delta %*% t(synapse_h) + layer_2_delta %*% t(synapse_1)) *
##         sigmoid_output_to_derivative(layer_1)
##       
##       # let's update all our weights so we can try again
##       synapse_1_update = synapse_1_update + matrix(layer_1) %*% layer_2_delta
##       synapse_h_update = synapse_h_update + matrix(prev_layer_1) %*% layer_1_delta
##       synapse_0_update = synapse_0_update + t(X) %*% layer_1_delta
##       
##       future_layer_1_delta = layer_1_delta
##     }
##     
##     synapse_0 = synapse_0 + ( synapse_0_update * alpha )
##     synapse_1 = synapse_1 + ( synapse_1_update * alpha )
##     synapse_h = synapse_h + ( synapse_h_update * alpha )
##     
##     synapse_0_update = synapse_0_update * 0
##     synapse_1_update = synapse_1_update * 0
##     synapse_h_update = synapse_h_update * 0
##     
##     # print out progress
##     if(!silent && j %% 500 ==0) {
##       print(paste('Iteration:', j))
##       print(paste('Error:', overallError))
##       print(paste('X1:', paste(a, collapse = ' '), ' ', '(', a_int, ')'))
##       print(paste('X2:', paste(b, collapse = ' '), '+', '(', b_int, ')'))
##       print('-----------------------------')
##       print(paste('Y: ', paste(c, collapse = ' '), ' ', '(', c_int, ')'))
##       out = 0
##       for (x in 1:length(d)) {
##         out[x] = rev(d)[x]*2^(x-1) }
##       print(paste('Y^:',   paste(d, collapse = ' '), ' ', '(', sum(out), ')'))
##       print('=============================')
##     }             
##   }
## }
## <environment: namespace:rnn>

As can be seen from the above, the model relies on three other functions that are included with the package.

The first one is int2binary, which stands for integer to binary, and converts an integer number to its binary representation:

int2binary(146, length=8)
## [1] 1 0 0 1 0 0 1 0

The code for this function is:

int2binary
## function(x, length) {
##   utils::tail(rev(as.integer(intToBits(x))), length) }
## <environment: namespace:rnn>

The second function is sigmoid(), which converts an integer to its sigmoid value.

(a <- sigmoid(3))
## [1] 0.9525741

The code for the sigmoid() function is:

sigmoid
## function(x) {
##   output = 1 / (1+exp(-x))
##   return(output)            }
## <environment: namespace:rnn>

The final function converts the sigmoid value of a number to its derivative.

sigmoid_output_to_derivative(a) # a was created above using sigmoid()
## [1] 0.04517666

Finally, we can inspect this code using:

sigmoid_output_to_derivative
## function(output) {
##   return( output*(1-output) )                      }
## <environment: namespace:rnn>

Application

By setting a seed for the random number generator, we ensure replicability.

set.seed(123)

An example is included in the help file.

help('rnn')

First we generate the data:

# create sample inputs
X1 = sample(0:127, 5000, replace=TRUE)
X2 = sample(0:127, 5000, replace=TRUE)

# create sample output
Y <- X1 + X2

This example is:

rnn(Y,
    X1,
    X2,
    binary_dim =  8,
    alpha      =  0.1,
    input_dim  =  2,
    hidden_dim = 10,
    output_dim =  1)
## [1] "Iteration: 500"
## [1] "Error: 3.94449836190173"
## [1] "X1: 0 1 1 0 0 1 0 0   ( 100 )"
## [1] "X2: 0 1 0 0 1 0 1 0 + ( 74 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 1 1 1 0   ( 174 )"
## [1] "Y^: 1 0 1 1 0 1 0 0   ( 180 )"
## [1] "============================="
## [1] "Iteration: 1000"
## [1] "Error: 3.79861131785405"
## [1] "X1: 0 0 0 0 1 1 0 1   ( 13 )"
## [1] "X2: 0 1 1 1 0 0 1 1 + ( 115 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 0 0 0 0 0   ( 128 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 1500"
## [1] "Error: 3.84284094669253"
## [1] "X1: 0 0 1 1 1 0 0 0   ( 56 )"
## [1] "X2: 0 0 0 0 0 0 1 0 + ( 2 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 1 1 1 0 1 0   ( 58 )"
## [1] "Y^: 1 1 1 1 1 1 1 1   ( 255 )"
## [1] "============================="
## [1] "Iteration: 2000"
## [1] "Error: 4.35601700739721"
## [1] "X1: 0 0 1 1 1 0 0 1   ( 57 )"
## [1] "X2: 0 1 0 1 0 1 1 1 + ( 87 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 1 0 0 0 0   ( 144 )"
## [1] "Y^: 1 1 1 1 1 1 1 1   ( 255 )"
## [1] "============================="
## [1] "Iteration: 2500"
## [1] "Error: 3.60470935009456"
## [1] "X1: 0 0 0 1 0 0 1 0   ( 18 )"
## [1] "X2: 0 1 1 1 0 0 1 0 + ( 114 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 0 0 1 0 0   ( 132 )"
## [1] "Y^: 0 0 1 0 0 1 0 0   ( 36 )"
## [1] "============================="
## [1] "Iteration: 3000"
## [1] "Error: 4.23322205952535"
## [1] "X1: 0 1 0 1 0 1 1 1   ( 87 )"
## [1] "X2: 0 0 1 0 1 1 1 1 + ( 47 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 0 0 1 1 0   ( 134 )"
## [1] "Y^: 1 1 1 1 1 1 1 0   ( 254 )"
## [1] "============================="
## [1] "Iteration: 3500"
## [1] "Error: 3.91551740500765"
## [1] "X1: 0 0 0 0 1 0 0 0   ( 8 )"
## [1] "X2: 0 1 0 1 1 1 1 0 + ( 94 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 0 0 1 1 0   ( 102 )"
## [1] "Y^: 0 0 0 1 0 1 0 0   ( 20 )"
## [1] "============================="
## [1] "Iteration: 4000"
## [1] "Error: 3.94852213025003"
## [1] "X1: 0 0 1 1 0 1 1 0   ( 54 )"
## [1] "X2: 0 1 1 0 0 1 0 0 + ( 100 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 1 1 0 1 0   ( 154 )"
## [1] "Y^: 0 1 0 0 1 0 0 0   ( 72 )"
## [1] "============================="
## [1] "Iteration: 4500"
## [1] "Error: 3.83796814080785"
## [1] "X1: 0 0 1 1 0 1 0 0   ( 52 )"
## [1] "X2: 0 1 1 1 1 0 1 0 + ( 122 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 1 1 1 0   ( 174 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 5000"
## [1] "Error: 2.88197887989984"
## [1] "X1: 0 0 0 0 0 0 0 1   ( 1 )"
## [1] "X2: 0 1 1 1 0 0 1 1 + ( 115 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 1 0 1 0 0   ( 116 )"
## [1] "Y^: 0 1 1 1 0 1 1 0   ( 118 )"
## [1] "============================="

It is interesting to vary the number of hidden units and iterations.

# create sample inputs
X1 = sample(0:127, 20000, replace=TRUE)
X2 = sample(0:127, 20000, replace=TRUE)

# create sample output
Y <- X1 + X2

rnn(Y,
    X1,
    X2,
    binary_dim = 8,
    alpha      = 0.1,
    input_dim  = 2,
    hidden_dim = 3,
    output_dim = 1)
## [1] "Iteration: 500"
## [1] "Error: 4.05003768856707"
## [1] "X1: 0 1 1 1 1 1 0 0   ( 124 )"
## [1] "X2: 0 1 1 1 1 1 1 0 + ( 126 )"
## [1] "-----------------------------"
## [1] "Y:  1 1 1 1 1 0 1 0   ( 250 )"
## [1] "Y^: 1 0 0 0 0 0 0 1   ( 129 )"
## [1] "============================="
## [1] "Iteration: 1000"
## [1] "Error: 4.00581060883197"
## [1] "X1: 0 0 0 1 0 0 1 1   ( 19 )"
## [1] "X2: 0 0 1 1 1 1 1 0 + ( 62 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 1 0 0 0 1   ( 81 )"
## [1] "Y^: 1 1 1 1 1 1 1 1   ( 255 )"
## [1] "============================="
## [1] "Iteration: 1500"
## [1] "Error: 3.99519377955615"
## [1] "X1: 0 1 1 1 1 0 1 1   ( 123 )"
## [1] "X2: 0 1 0 0 1 1 1 0 + ( 78 )"
## [1] "-----------------------------"
## [1] "Y:  1 1 0 0 1 0 0 1   ( 201 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 2000"
## [1] "Error: 4.05519613296592"
## [1] "X1: 0 0 1 1 1 0 1 0   ( 58 )"
## [1] "X2: 0 0 1 1 1 1 1 1 + ( 63 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 1 1 0 0 1   ( 121 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 2500"
## [1] "Error: 3.91489043806127"
## [1] "X1: 0 0 1 1 0 1 0 1   ( 53 )"
## [1] "X2: 0 0 1 0 0 0 1 1 + ( 35 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 1 1 0 0 0   ( 88 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 3000"
## [1] "Error: 4.00309087882978"
## [1] "X1: 0 1 1 0 1 0 1 1   ( 107 )"
## [1] "X2: 0 1 0 0 0 1 0 0 + ( 68 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 1 1 1 1   ( 175 )"
## [1] "Y^: 0 0 0 0 1 0 0 0   ( 8 )"
## [1] "============================="
## [1] "Iteration: 3500"
## [1] "Error: 4.03456518452721"
## [1] "X1: 0 1 1 0 0 0 0 1   ( 97 )"
## [1] "X2: 0 0 0 1 0 0 1 0 + ( 18 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 1 0 0 1 1   ( 115 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 4000"
## [1] "Error: 3.9979157964333"
## [1] "X1: 0 0 0 1 0 1 1 1   ( 23 )"
## [1] "X2: 0 1 0 0 1 0 1 0 + ( 74 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 0 0 0 0 1   ( 97 )"
## [1] "Y^: 1 0 0 1 0 1 0 0   ( 148 )"
## [1] "============================="
## [1] "Iteration: 4500"
## [1] "Error: 3.9764908147916"
## [1] "X1: 0 1 0 1 0 0 1 0   ( 82 )"
## [1] "X2: 0 0 0 1 1 1 1 1 + ( 31 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 1 0 0 0 1   ( 113 )"
## [1] "Y^: 1 1 1 1 1 1 1 1   ( 255 )"
## [1] "============================="
## [1] "Iteration: 5000"
## [1] "Error: 4.02559985626535"
## [1] "X1: 0 0 0 1 0 0 0 0   ( 16 )"
## [1] "X2: 0 0 1 0 0 0 1 1 + ( 35 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 1 1 0 0 1 1   ( 51 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 5500"
## [1] "Error: 4.01779534811687"
## [1] "X1: 0 0 1 1 1 0 0 0   ( 56 )"
## [1] "X2: 0 0 0 0 0 0 1 0 + ( 2 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 1 1 1 0 1 0   ( 58 )"
## [1] "Y^: 0 0 0 0 0 1 0 0   ( 4 )"
## [1] "============================="
## [1] "Iteration: 6000"
## [1] "Error: 3.98188869279542"
## [1] "X1: 0 0 0 1 1 0 1 1   ( 27 )"
## [1] "X2: 0 0 0 0 1 1 1 0 + ( 14 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 1 0 1 0 0 1   ( 41 )"
## [1] "Y^: 0 0 0 0 1 0 0 0   ( 8 )"
## [1] "============================="
## [1] "Iteration: 6500"
## [1] "Error: 4.02683730670772"
## [1] "X1: 0 1 0 1 1 0 1 0   ( 90 )"
## [1] "X2: 0 1 0 0 1 1 0 1 + ( 77 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 0 1 1 1   ( 167 )"
## [1] "Y^: 1 0 0 1 1 0 1 0   ( 154 )"
## [1] "============================="
## [1] "Iteration: 7000"
## [1] "Error: 3.97125001336543"
## [1] "X1: 0 0 0 1 0 0 1 0   ( 18 )"
## [1] "X2: 0 0 1 1 0 1 0 0 + ( 52 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 0 0 1 1 0   ( 70 )"
## [1] "Y^: 0 0 0 0 1 0 0 0   ( 8 )"
## [1] "============================="
## [1] "Iteration: 7500"
## [1] "Error: 4.00404074101843"
## [1] "X1: 0 0 1 1 1 0 0 0   ( 56 )"
## [1] "X2: 0 1 1 1 0 0 1 0 + ( 114 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 1 0 1 0   ( 170 )"
## [1] "Y^: 1 1 1 1 1 1 1 1   ( 255 )"
## [1] "============================="
## [1] "Iteration: 8000"
## [1] "Error: 3.95976138728772"
## [1] "X1: 0 1 0 0 1 1 1 1   ( 79 )"
## [1] "X2: 0 1 0 0 1 0 1 1 + ( 75 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 1 1 0 1 0   ( 154 )"
## [1] "Y^: 1 0 0 1 0 1 1 0   ( 150 )"
## [1] "============================="
## [1] "Iteration: 8500"
## [1] "Error: 3.89468295812157"
## [1] "X1: 0 0 0 0 1 0 1 1   ( 11 )"
## [1] "X2: 0 0 1 1 0 0 0 0 + ( 48 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 1 1 1 0 1 1   ( 59 )"
## [1] "Y^: 0 1 1 1 1 0 1 1   ( 123 )"
## [1] "============================="
## [1] "Iteration: 9000"
## [1] "Error: 3.9000311712921"
## [1] "X1: 0 1 0 1 1 0 0 1   ( 89 )"
## [1] "X2: 0 0 0 0 0 1 1 0 + ( 6 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 1 1 1 1 1   ( 95 )"
## [1] "Y^: 0 0 0 0 1 1 0 1   ( 13 )"
## [1] "============================="
## [1] "Iteration: 9500"
## [1] "Error: 3.94842400076739"
## [1] "X1: 0 1 0 0 1 0 0 0   ( 72 )"
## [1] "X2: 0 0 0 1 0 0 1 0 + ( 18 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 1 1 0 1 0   ( 90 )"
## [1] "Y^: 0 0 0 0 0 0 0 0   ( 0 )"
## [1] "============================="
## [1] "Iteration: 10000"
## [1] "Error: 3.77216128486592"
## [1] "X1: 0 0 0 1 1 1 1 1   ( 31 )"
## [1] "X2: 0 0 0 1 0 1 1 0 + ( 22 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 1 1 0 1 0 1   ( 53 )"
## [1] "Y^: 0 0 0 0 1 1 1 1   ( 15 )"
## [1] "============================="
## [1] "Iteration: 10500"
## [1] "Error: 3.60145199253427"
## [1] "X1: 0 1 0 1 0 0 0 0   ( 80 )"
## [1] "X2: 0 1 0 0 1 1 1 0 + ( 78 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 1 1 1 1 0   ( 158 )"
## [1] "Y^: 1 0 0 1 1 1 0 0   ( 156 )"
## [1] "============================="
## [1] "Iteration: 11000"
## [1] "Error: 3.53622411158228"
## [1] "X1: 0 0 0 1 1 0 0 0   ( 24 )"
## [1] "X2: 0 1 1 1 0 1 0 0 + ( 116 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 0 1 1 0 0   ( 140 )"
## [1] "Y^: 1 1 1 0 1 0 0 0   ( 232 )"
## [1] "============================="
## [1] "Iteration: 11500"
## [1] "Error: 3.91947382648576"
## [1] "X1: 0 0 0 1 1 1 0 0   ( 28 )"
## [1] "X2: 0 1 0 0 0 0 0 1 + ( 65 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 1 1 1 0 1   ( 93 )"
## [1] "Y^: 1 0 0 1 1 1 1 0   ( 158 )"
## [1] "============================="
## [1] "Iteration: 12000"
## [1] "Error: 3.63749232770687"
## [1] "X1: 0 0 0 0 1 1 0 1   ( 13 )"
## [1] "X2: 0 0 1 1 1 0 0 1 + ( 57 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 0 0 1 1 0   ( 70 )"
## [1] "Y^: 0 0 1 1 0 1 1 0   ( 54 )"
## [1] "============================="
## [1] "Iteration: 12500"
## [1] "Error: 3.67750496280662"
## [1] "X1: 0 0 1 1 0 1 0 0   ( 52 )"
## [1] "X2: 0 1 0 0 0 1 0 1 + ( 69 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 1 1 0 0 1   ( 121 )"
## [1] "Y^: 1 1 1 1 1 0 1 1   ( 251 )"
## [1] "============================="
## [1] "Iteration: 13000"
## [1] "Error: 3.53987923342722"
## [1] "X1: 0 1 0 1 0 1 0 0   ( 84 )"
## [1] "X2: 0 1 0 0 0 0 0 1 + ( 65 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 1 0 1 0 1   ( 149 )"
## [1] "Y^: 1 0 0 1 0 1 1 1   ( 151 )"
## [1] "============================="
## [1] "Iteration: 13500"
## [1] "Error: 3.18696622262771"
## [1] "X1: 0 0 1 0 0 0 1 0   ( 34 )"
## [1] "X2: 0 1 1 1 0 0 0 1 + ( 113 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 1 0 0 1 1   ( 147 )"
## [1] "Y^: 1 1 0 1 0 1 1 1   ( 215 )"
## [1] "============================="
## [1] "Iteration: 14000"
## [1] "Error: 3.06002694096972"
## [1] "X1: 0 1 0 1 0 1 1 0   ( 86 )"
## [1] "X2: 0 1 0 1 0 1 1 0 + ( 86 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 1 1 0 0   ( 172 )"
## [1] "Y^: 1 0 1 0 1 0 0 0   ( 168 )"
## [1] "============================="
## [1] "Iteration: 14500"
## [1] "Error: 3.0721497221066"
## [1] "X1: 0 0 1 0 1 0 0 1   ( 41 )"
## [1] "X2: 0 0 0 1 1 1 0 1 + ( 29 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 0 0 0 1 1 0   ( 70 )"
## [1] "Y^: 0 1 1 1 0 1 1 0   ( 118 )"
## [1] "============================="
## [1] "Iteration: 15000"
## [1] "Error: 3.59314580597317"
## [1] "X1: 0 1 0 0 1 0 1 1   ( 75 )"
## [1] "X2: 0 1 0 1 1 1 1 1 + ( 95 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 1 0 1 0   ( 170 )"
## [1] "Y^: 1 0 1 0 0 0 0 0   ( 160 )"
## [1] "============================="
## [1] "Iteration: 15500"
## [1] "Error: 3.50807592457865"
## [1] "X1: 0 1 1 0 1 1 0 1   ( 109 )"
## [1] "X2: 0 1 1 0 1 1 1 0 + ( 110 )"
## [1] "-----------------------------"
## [1] "Y:  1 1 0 1 1 0 1 1   ( 219 )"
## [1] "Y^: 1 0 0 1 0 0 1 1   ( 147 )"
## [1] "============================="
## [1] "Iteration: 16000"
## [1] "Error: 3.52772271488862"
## [1] "X1: 0 0 0 1 0 0 1 1   ( 19 )"
## [1] "X2: 0 1 1 1 1 1 0 0 + ( 124 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 0 1 1 1 1   ( 143 )"
## [1] "Y^: 1 1 0 0 1 1 1 1   ( 207 )"
## [1] "============================="
## [1] "Iteration: 16500"
## [1] "Error: 3.01368792446641"
## [1] "X1: 0 0 1 1 1 0 1 0   ( 58 )"
## [1] "X2: 0 0 1 0 1 0 1 1 + ( 43 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 0 0 1 0 1   ( 101 )"
## [1] "Y^: 0 1 0 1 0 1 0 1   ( 85 )"
## [1] "============================="
## [1] "Iteration: 17000"
## [1] "Error: 1.01627141527645"
## [1] "X1: 0 1 0 1 0 0 0 0   ( 80 )"
## [1] "X2: 0 0 1 0 0 1 0 0 + ( 36 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 1 0 1 0 0   ( 116 )"
## [1] "Y^: 0 1 1 1 0 1 0 0   ( 116 )"
## [1] "============================="
## [1] "Iteration: 17500"
## [1] "Error: 2.17915966115816"
## [1] "X1: 0 0 0 1 1 0 1 0   ( 26 )"
## [1] "X2: 0 0 0 0 0 0 1 1 + ( 3 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 0 1 1 1 0 1   ( 29 )"
## [1] "Y^: 0 0 0 1 1 1 0 0   ( 28 )"
## [1] "============================="
## [1] "Iteration: 18000"
## [1] "Error: 3.12585151531538"
## [1] "X1: 0 1 0 1 0 1 1 1   ( 87 )"
## [1] "X2: 0 1 0 1 1 0 0 0 + ( 88 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 1 0 1 1 1 1   ( 175 )"
## [1] "Y^: 1 0 1 0 1 1 1 0   ( 174 )"
## [1] "============================="
## [1] "Iteration: 18500"
## [1] "Error: 2.29357945379783"
## [1] "X1: 0 0 0 0 1 1 1 1   ( 15 )"
## [1] "X2: 0 0 1 0 0 1 0 0 + ( 36 )"
## [1] "-----------------------------"
## [1] "Y:  0 0 1 1 0 0 1 1   ( 51 )"
## [1] "Y^: 0 0 1 1 0 0 1 1   ( 51 )"
## [1] "============================="
## [1] "Iteration: 19000"
## [1] "Error: 3.76283074446683"
## [1] "X1: 0 1 1 1 0 1 1 1   ( 119 )"
## [1] "X2: 0 0 0 1 0 0 0 0 + ( 16 )"
## [1] "-----------------------------"
## [1] "Y:  1 0 0 0 0 1 1 1   ( 135 )"
## [1] "Y^: 1 1 0 0 1 1 1 1   ( 207 )"
## [1] "============================="
## [1] "Iteration: 19500"
## [1] "Error: 2.88900711490157"
## [1] "X1: 0 1 0 0 1 1 1 1   ( 79 )"
## [1] "X2: 0 0 0 1 1 0 1 0 + ( 26 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 0 1 0 0 1   ( 105 )"
## [1] "Y^: 0 1 1 0 0 0 0 1   ( 97 )"
## [1] "============================="
## [1] "Iteration: 20000"
## [1] "Error: 2.73563618581195"
## [1] "X1: 0 1 0 1 1 1 0 0   ( 92 )"
## [1] "X2: 0 0 0 1 1 1 1 0 + ( 30 )"
## [1] "-----------------------------"
## [1] "Y:  0 1 1 1 1 0 1 0   ( 122 )"
## [1] "Y^: 0 1 1 0 0 0 1 0   ( 98 )"
## [1] "============================="