Проблема

OpenAI недавно опубликовал несколько открытых исследовательских вопросов. Как новичок в ИИ, я решил заняться «Разминкой» для начинающих, которую они предложили. Вы можете просмотреть их сообщение в блоге здесь: https://blog.openai.com/requests-for-research-2/:

Обучите LSTM решать проблему XOR: то есть, учитывая последовательность битов, определить ее четность. LSTM должен потреблять последовательность по одному биту за раз, а затем выводить правильный ответ в конце последовательности. Протестируйте два подхода ниже:

  • Создайте набор данных из 100 000 случайных двоичных строк длиной 50. Обучите LSTM; какую производительность вы получаете?
  • Создайте набор данных из 100 000 случайных двоичных строк, где длина каждой строки выбирается независимо и случайным образом в диапазоне от 1 до 50. Обучите LSTM. Удается ли это? Чем объясняется разница?

Функция XOR

| Вход | Вход 2 | Вывод |
| — — — — — — — |: — — — — — — —:| — — —:|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |

Задача 1: 100 000 двоичных строк длины 50

Код для решения этой проблемы благодаря [christopher5106](https://github.com/christopher5106/grid-1D-LSTM-theano/blob/master/main.py)

Настраивать

python
‘’’
Trains a 1D Grid LSTM network to learn XOR answers.
‘’’
from __future__ import print_function
import numpy as np
import theano
import theano.tensor as T
import lasagne
#Lasagne Seed for Reproducibility
lasagne.random.set_rng(np.random.RandomState(1))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(‘ — iterations’, type=int, default=100000, help=’Number of iterations’)
parser.add_argument(‘ — bits’, type=int, default=50, help=’Number of bits in the input strings’)
parser.add_argument(‘ — hidden’, type=int, default=2, help=’Number of units in the two hidden (LSTM) layers’)
parser.add_argument(‘ — learning_rate’, type=float, default=0.5, help=’Optimization learning rate’)
#parser.add_argument(‘ — grad_clip’, type=int, default=100, help=’All gradients above this will be clipped’)
parser.add_argument(‘ — print_freq’, type=int, default=500, help=’How often should we check the output?’)
parser.add_argument(‘ — batch_size’, type=int, default=1, help=’Batch size’)
parser.add_argument(‘ — layers’, type=int, default=2, help=’Number of layers’)
args = parser.parse_args()
print(“Parameters:”)
print(args)
args.print_batch_freq = args.print_freq / args.batch_size + 1

Генератор случайных строк

python
def gen_data(bits=args.bits, batch_size = args.batch_size):
 x = np.random.randint(2, size=(batch_size,bits))
 y = x.sum(axis=1) % 2
 return x, y
```
# Network
```python
print(“Building network …”)
l_in = lasagne.layers.InputLayer(shape=(None,1))
l_in_zero = lasagne.layers.InputLayer(shape=(None, args.layers, 1))
l_lin = lasagne.layers.DenseLayer(l_in, num_units = args.hidden, nonlinearity = None)
l_forward = lasagne.layers.LSTMLayer(
 l_in_zero, args.hidden,
 nonlinearity=lasagne.nonlinearities.tanh, hid_init = l_lin, only_return_final=True)
l_lin_out = lasagne.layers.DenseLayer(l_forward, num_units = 2, nonlinearity = None)
l_out = lasagne.layers.DenseLayer(l_lin_out, num_units=2, nonlinearity=lasagne.nonlinearities.softmax)
target_values = T.ivector(‘target_output’)
network_output = lasagne.layers.get_output(l_out)
cost = T.nnet.categorical_crossentropy(network_output,target_values).mean()
accuracy = lasagne.objectives.categorical_accuracy(network_output,target_values).mean()
all_params = lasagne.layers.get_all_params(l_out,trainable=True)
all_params2 = lasagne.layers.get_all_params(l_out,trainable=False)

Теано Функции

python
print(“Computing updates …”)
updates = lasagne.updates.adadelta(cost, all_params, args.learning_rate)
updates2 = lasagne.updates.adagrad(cost, all_params2, args.learning_rate)
print(“Compiling functions …”)
train = theano.function([l_in.input_var, l_in_zero.input_var, target_values], cost, updates=updates, allow_input_downcast=True)
train2 = theano.function([l_in.input_var, l_in_zero.input_var, target_values], cost, updates=updates2, allow_input_downcast=True)
compute_cost = theano.function([l_in.input_var, l_in_zero.input_var, target_values], cost, allow_input_downcast=True)
compute_accuracy = theano.function([l_in.input_var, l_in_zero.input_var, target_values],
 accuracy, allow_input_downcast=True)
probs = theano.function([l_in.input_var, l_in_zero.input_var],network_output,allow_input_downcast=True)

Обучение

python
print(“Training …”)
print(“The average loss and accuracy will be printed every {} iterations”.format(args.print_batch_freq*args.batch_size))
num_batch_print_iter = args.iterations / args.batch_size / args.print_batch_freq + 1
act_num_batches = int(num_batch_print_iter * args.print_batch_freq)
all_cost = np.zeros((act_num_batches))
all_accuracy = np.zeros((act_num_batches))
for it_out in range(int(num_batch_print_iter)):
 for it_in in range(int(args.print_batch_freq)):
 x,y = gen_data()
 stoplen = (len(x[0])-1)
 for i in range(0,stoplen):
 x_zero = np.zeros((args.batch_size,args.layers,1),dtype=’int32')
 batch_cost = train2(np.reshape(x[0][i], newshape=(1,1)), x_zero, y)
 x_zero = np.zeros((args.batch_size, args.layers, 1), dtype=’int32')
 batch_iter = int(it_out * args.print_batch_freq + it_in + 1)
 batch_cost = train(np.reshape(x[0][len(x[0])-1], newshape=(1,1)), x_zero, y)
 batch_accuracy = compute_accuracy(np.reshape(x[0][len(x[0])-1], newshape=(1,1)), x_zero, y)
all_cost[batch_iter — 1] = batch_cost
 all_accuracy[batch_iter — 1] = batch_accuracy
 start_index = int(it_out * args.print_batch_freq)
 end_index = int((it_out + 1) * args.print_batch_freq)
 av_cost = all_cost[start_index:end_index].mean()
 av_accuracy = all_accuracy[start_index:end_index].mean()
 np.savetxt(‘cost.txt’, all_cost[:end_index], delimiter=’,’) #average in batch
 np.savetxt(‘accuracy.txt’, all_accuracy[:end_index], delimiter=’,’)
print(“Iteration {} average loss = {} average accuracy = {}”.format(batch_iter*args.batch_size,
av_cost,av_accuracy))

Задача 2. 100 000 двоичных строк произвольной длины 1:50

Различия кодов

```python
parser.add_argument(‘ — hidden’, type=int, default=100, help=’Number of units in the two hidden (LSTM) layers’)
parser.add_argument(‘ — layers’, type=int, default=2, help=’Number of layers’)
args = parser.parse_args()
```
```python
def gen_data(bits=args.bits, batch_size = args.batch_size):
 bitsran = np.random.randint(1, bits)
 x = np.random.randint(2, size=(batch_size,bitsran))
 y = x.sum(axis=1) % 2
 return x, y
```

Вывод