Несоответствие представления формы NNPY и тензорного потока RNN - PullRequest
0 голосов
/ 27 декабря 2018

Я строю свой первый RNN в тензорном потоке.После понимания всех концепций, касающихся формы 3D-ввода, я столкнулся с этой проблемой.

В моей простой версии (1.15.4) представление формы для 3D-массивов выглядит следующим образом: (panel, row, column).Я сделаю каждое измерение различным, чтобы оно было более понятным:

In [1]: import numpy as np                                                                                                                  

In [2]: arr = np.arange(30).reshape((2,3,5))                                                                                                

In [3]: arr                                                                                                                                 
Out[3]: 
array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14]],

       [[15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29]]])

In [4]: arr.shape                                                                                                                           
Out[4]: (2, 3, 5)

In [5]: np.__version__                                                                                                                      
Out[5]: '1.15.4'

Здесь я понимаю следующее: У меня есть два временных шага с каждым временным шагом, имеющим 3 наблюдения с 5 особенностями в каждом наблюдении.

Тем не менее, в «теории» тензорного потока (которая, как я полагаю, она сильно основана на NumPy) клетки RNN ожидают тензоры (т. Е. Просто n-мерные матрицы) формы [batch_size, timesteps, features], которые можно перевести на: (row, panel, column)в числовом «жаргоне».

Как видно, представление не совпадает, что приводит к ошибкам при подаче пустых данных в заполнитель, который в большинстве примеров и теории определяется следующим образом:

x = tf.placeholder(tf.float32, shape=[None, N_TIMESTEPS_X, N_FEATURES], name='XPlaceholder')

  • np.reshape() не решает проблему, потому что она просто переставляет размеры, но портит данные.

  • Я впервые использую API набора данных , но я сталкиваюсь с проблемами один раз в сеансе, а не в операциях API набора данных.

  • Я использую метод static_rnn, и все работает хорошо, пока мне не придется подавать данные в заполнитель, что, очевидно, приводит к ошибке формы.

  • Я попытался изменить форму заполнителя на shape=[N_TIMESTEPS_X, None, N_FEATURES].ОДНАКО, я использую API набора данных и получаю ошибки при создании инициализатора, если я изменяю Xplaceholder на shape=[N_TIMESTEPS_X, None, N_FEATURES].

Итак, чтобы подвести итог:

  • Первая проблема: Ошибки формы с различными представлениями формы.
  • Вторая проблема: Ошибка набора данных при выравнивании представлений формы (я думаю, что static_rnn илиdynamic_rnn будет работать, если это будет решено).

Мой вопрос:

¿Есть ли что-то, что я упускаю в связи с этой другой логикой представления, котораяэто сбивает с толку практику?

ould Может ли быть достигнуто решение о переходе на dynamic_rnn?(хотя проблемы с формой, с которыми я сталкиваюсь, связаны с тем, что инициализатор API набора данных получает форму [N_TIMESTEPS_X, None, N_FEATURES], а не с самой ячейкой RNN.

Большое спасибо за ваше время.

Полный код:

'''The idea is to create xt, yt, xval and yval. My numpy arrays to 
be fed are of the following shapes: 

The 3D xt array has a shape of: (11, 69579, 74)
The 3D xval array has a shape of: (11, 7732, 74)

The yt array has a shape of: (69579, 3)
The yval array has a shape of: (7732, 3)

'''

N_TIMESTEPS_X = xt.shape[0] ## The stack number
BATCH_SIZE = 256
#N_OBSERVATIONS = xt.shape[1]
N_FEATURES = xt.shape[2]
N_OUTPUTS = yt.shape[1]
N_NEURONS_LSTM = 128 ## Number of units in the LSTMCell 
N_NEURONS_DENSE = 64 ## Number of units in the Dense layer
N_EPOCHS = 600
LEARNING_RATE = 0.1

### Define the placeholders anda gather the data.
train_data = (xt, yt)
validation_data = (xval, yval)

## We define the placeholders as a trick so that we do not break into memory problems, associated with feeding the data directly.
'''As an alternative, you can define the Dataset in terms of tf.placeholder() tensors, and feed the NumPy arrays when you initialize an Iterator over the dataset.'''
batch_size = tf.placeholder(tf.int64)
x = tf.placeholder(tf.float32, shape=[None, N_TIMESTEPS_X, N_FEATURES], name='XPlaceholder')
y = tf.placeholder(tf.float32, shape=[None, N_OUTPUTS], name='YPlaceholder')

# Creating the two different dataset objects.
train_dataset = tf.data.Dataset.from_tensor_slices((x,y)).batch(BATCH_SIZE).repeat()
val_dataset = tf.data.Dataset.from_tensor_slices((x,y)).batch(BATCH_SIZE)

# Creating the Iterator type that permits to switch between datasets.
itr = tf.data.Iterator.from_structure(train_dataset.output_types, train_dataset.output_shapes)
train_init_op = itr.make_initializer(train_dataset)
validation_init_op = itr.make_initializer(val_dataset)

next_features, next_labels = itr.get_next()

### Create the graph 
cellType = tf.nn.rnn_cell.LSTMCell(num_units=N_NEURONS_LSTM, name='LSTMCell')
inputs = tf.unstack(next_features, N_TIMESTEPS_X, axis=0)
'''inputs: A length T list of inputs, each a Tensor of shape [batch_size, input_size]'''
RNNOutputs, _ = tf.nn.static_rnn(cell=cellType, inputs=inputs, dtype=tf.float32)
predictionsLayer = tf.layers.dense(inputs=tf.layers.batch_normalization(RNNOutputs[-1]), units=N_NEURONS_DENSE, activation=None, name='Dense_Layer')

### Define the cost function, that will be optimized by the optimizer. 
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=predictionsLayer, labels=next_labels, name='Softmax_plus_Cross_Entropy'))
optimizer_type = tf.train.AdamOptimizer(learning_rate=LEARNING_RATE, name='AdamOptimizer')
optimizer = optimizer_type.minimize(cost)

### Model evaluation 
correctPrediction = tf.equal(tf.argmax(predictionsLayer,1), tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correctPrediction,tf.float32))
#confusionMatrix = tf.confusion_matrix(next_labels, predictionsLayer, num_classes=3, name='ConfMatrix')
N_BATCHES = train_data[0].shape[0] // BATCH_SIZE

## Saving variables so that we can restore them afterwards.
saver = tf.train.Saver()
save_dir = '/home/zmlaptop/Desktop/tfModels/{}_{}'.format(cellType.__class__.__name__, datetime.now().strftime("%Y%m%d%H%M%S"))
os.mkdir(save_dir)
varDict = {'nTimeSteps':N_TIMESTEPS_X, 'BatchSize': BATCH_SIZE, 'nFeatures':N_FEATURES,
           'nNeuronsLSTM':N_NEURONS_LSTM, 'nNeuronsDense':N_NEURONS_DENSE, 'nEpochs':N_EPOCHS,
           'learningRate':LEARNING_RATE, 'optimizerType': optimizer_type.__class__.__name__}
varDicSavingTxt = save_dir + '/varDict.txt'
modelFilesDir = save_dir + '/modelFiles'
os.mkdir(modelFilesDir)

logDir = save_dir + '/TBoardLogs'
os.mkdir(logDir)

acc_summary = tf.summary.scalar('Accuracy', accuracy)
loss_summary = tf.summary.scalar('Cost_CrossEntropy', cost)
summary_merged = tf.summary.merge_all()

with open(varDicSavingTxt, 'w') as outfile:
    outfile.write(repr(varDict))

with tf.Session() as sess:

    tf.set_random_seed(2)
    sess.run(tf.global_variables_initializer())
    train_writer = tf.summary.FileWriter(logDir + '/train', sess.graph)
    validation_writer = tf.summary.FileWriter(logDir + '/validation')

    # initialise iterator with train data
    sess.run(train_init_op, feed_dict = {x : train_data[0], y: train_data[1], batch_size: BATCH_SIZE})

    print('¡Training starts!')
    for epoch in range(N_EPOCHS):

        batchAccList = []
        tot_loss = 0

        for batch in range(N_BATCHES):

            optimizer_output, loss_value, summary = sess.run([optimizer, cost, summary_merged])
            accBatch = sess.run(accuracy)
            tot_loss += loss_value
            batchAccList.append(accBatch)

            if batch % 10 == 0:

                train_writer.add_summary(summary, batch)

        epochAcc = tf.reduce_mean(batchAccList)

        if epoch%10 == 0:

            print("Epoch: {}, Loss: {:.4f}, Accuracy: {}".format(epoch, tot_loss / N_BATCHES, epochAcc))

    #confM = sess.run(confusionMatrix)
    #confDic = {'confMatrix': confM}
    #confTxt = save_dir + '/confMDict.txt'
    #with open(confTxt, 'w') as outfile:
    #    outfile.write(repr(confDic))
    #print(confM)

    # initialise iterator with validation data
    sess.run(validation_init_op, feed_dict = {x : validation_data[0], y: validation_data[1], batch_size:len(validation_data[0])})
    print('Validation Loss: {:4f}, Validation Accuracy: {}'.format(sess.run(cost), sess.run(accuracy)))
    summary_val = sess.run(summary_merged)
    validation_writer.add_summary(summary_val)

    saver.save(sess, modelFilesDir)

1 Ответ

0 голосов
/ 27 декабря 2018

Есть ли что-то, что я упускаю в связи с этой другой логикой представления, которая делает практику запутывающей?

На самом деле, вы допустили ошибку относительно форм ввода static_rnnи dynamic_rnn.Форма ввода static_rnn - [timesteps,batch_size, features] ( link ), представляющая собой список 2D-тензоров формы [batch_size, features].Но форма ввода dynamic_rnn может быть [timesteps,batch_size, features] или [batch_size,timesteps, features], в зависимости от того, time_major является True или False ( link ).

Возможно ли решение достигнутопереключиться на dynamic_rnn?

Ключ не в том, что вы используете static_rnn или dynamic_rnn, а в том, что ваша форма данных соответствует требуемой форме.Общий формат заполнителя похож на ваш код [None, N_TIMESTEPS_X, N_FEATURES].Вам также удобно использовать API набора данных.Вы можете использовать transpose() ( link ) вместо reshape(). transpose() будет переставлять размеры массива и не будет путаться с данными.

Итак, ваш коднеобходимо изменить.

# permute the dimensions
xt = xt.transpose([1,0,2])
xval = xval.transpose([1,0,2])

# adjust shape,axis=1 represents timesteps
inputs = tf.unstack(next_features,  axis=1)

Другие ошибки не должны иметь ничего общего с формой rnn.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...