Регрессия TFLearn, несовместимость форм при расчете потерь

Я работаю с последовательностями белка. Моя цель - создать сверточную сеть, которая будет предсказывать три угла для каждой аминокислоты в белке. У меня проблемы с отладкой модели DNF TFLearn, которая требует операции изменения формы.

Входные данные описывают (в настоящее время) 25 белков различной длины. Чтобы использовать Tensors, мне нужно иметь одинаковые размеры, поэтому я дополняю пустые ячейки ввода нулями. Каждая аминокислота представлена ​​4-мерным кодом. Детали этого, вероятно, не важны, кроме того, чтобы помочь вам понять формы Тензорных.

Выходные данные DNN представляют собой шесть чисел, представляющих синусы и косинусы трех углов. Чтобы создать упорядоченные пары, граф DNN преобразует тензор [..., 6] в [..., 3, 2]. Мои целевые данные кодируются так же. Я вычисляю потери, используя косинусное расстояние.

Я построил не сверточный DNN, который показал хорошее начальное поведение при обучении, которое очень похоже на код, который я опубликую здесь. Но эта модель рассматривала три смежные аминокислоты в изоляции. Я хочу рассматривать каждый белок как единое целое - сначала с раздвижными окнами шириной 3 аминокислоты, а в конце концов и больше.

Теперь, когда я перехожу на сверточную модель, я не могу подобрать формы, которые бы соответствовали. Вот рабочие части моего кода:

import tensorflow as tf
import tflearn as tfl

from protein import ProteinDatabase   # don't worry about its details

def backbone_angle_distance(predict, actual):
    with tf.name_scope("BackboneAngleDistance"):
        actual = tfl.reshape(actual, [-1,3,2])
        # Supply the -1 argument for axis that TFLearn can't pass
        loss = tf.losses.cosine_distance(predict, actual, -1, 
               reduction=tf.losses.Reduction.MEAN)
        return loss

# Training data
database = ProteinDatabase("./data")
inp, tgt = database.training_arrays()

# DNN model, convolution only in topmost layer for now
net = tfl.input_data(shape=[None, None, 4]) 
net = tfl.conv_1d(net, 24, 3)
net = tfl.conv_1d(net, 12, 1)
net = tfl.conv_1d(net, 6, 1)
net = tfl.reshape(net, [-1,3,2]) 
net = tf.nn.l2_normalize(net, dim=2)
net = tfl.regression(net, optimizer="sgd", learning_rate=0.1, \
                     loss=backbone_angle_distance)
model = tfl.DNN(net)

# Generate a prediction.  Compare shapes for compatibility.
out = model.predict(inp)
print("\ninp : {}, shape = {}".format(type(inp), inp.shape))
print("out : {}, shape = {}".format(type(out), out.shape))
print("tgt : {}, shape = {}".format(type(tgt), tgt.shape))
print("tgt shape, if flattened by one dimension = {}\n".\
      format(tgt.reshape([-1,3,2]).shape))

Выход в этот момент:

inp : <class 'numpy.ndarray'>, shape = (25, 543, 4)
out : <class 'numpy.ndarray'>, shape = (13575, 3, 2)
tgt : <class 'numpy.ndarray'>, shape = (25, 543, 3, 2)
tgt shape, if flattened by one dimension = (13575, 3, 2)

Поэтому, если я изменю форму 4D Tensor tgt, сглажив крайнее измерение, out и tgt должны совпадать. Поскольку код TFLearn создает пакеты, я пытаюсь перехватить и изменить форму фактического значения Tensor в первой строке backbone_angle_distance(), моей пользовательской функции потерь.

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

e, b = 1, 5
model.fit(inp, tgt, n_epoch=e, batch_size=b, validation_set=0.2, show_metric=True)

Я получаю следующий дополнительный вывод и ошибку:

---------------------------------
Run id: EEG6JW
Log directory: /tmp/tflearn_logs/
---------------------------------
Training samples: 20
Validation samples: 5
--
--
Traceback (most recent call last):
  File "exp54.py", line 252, in <module>
    model.fit(inp, tgt, n_epoch=e, batch_size=b, validation_set=0.2, show_metric=True)
  File "/usr/local/lib/python3.5/dist-packages/tflearn/models/dnn.py", line 216, in fit
    callbacks=callbacks)
  File "/usr/local/lib/python3.5/dist-packages/tflearn/helpers/trainer.py", line 339, in fit
    show_metric)
  File "/usr/local/lib/python3.5/dist-packages/tflearn/helpers/trainer.py", line 818, in _train
    feed_batch)
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 789, in run
    run_metadata_ptr)
  File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 975, in _run
    % (np_val.shape, subfeed_t.name, str(subfeed_t.get_shape())))
ValueError: Cannot feed value of shape (5, 543, 3, 2) for Tensor 'TargetsData/Y:0', which has shape '(?, 3, 2)'

Где в моем коде я УКАЗЫВАЮ, что TargetsData/Y:0 имеет форму (?, 3, 2)? Я знаю, что не будет. Согласно трассировке, я никогда не достигал своей операции изменения формы в backbone_angle_distance().

Любой совет приветствуется, спасибо!

2 ответа

Решение

Ну, похоже, я отвечаю на свой вопрос.

Я попробовал различные варианты того, что предлагал Герт, и я не мог заставить что-либо работать. Когда я строил не сверточную сеть, которая предшествовала той, которую я здесь обсуждаю, попытка изменить форму тренировочных данных в [-1,3,2] была уместной. В конце концов, я пришел к выводу, что TFLearn не позволит мне сгладить тензор 4D, который мне нужен для CNN в функции потерь. Мне нужно добавить одно измерение, как и раньше. Но вместо сохранения одного измерения (что и делает -1), теперь я должен сохранить ДВА.

Вот мое решение.

1) Устранить изменение формы из функции потерь:

def backbone_angle_distance(predict, actual):
    with tf.name_scope("BackboneAngleDistance"):
        # Supply the -1 argument for axis that TFLearn can't pass
        loss = tf.losses.cosine_distance(predict, actual, -1, 
               reduction=tf.losses.Reduction.MEAN)
        return loss

2) Введите переменную shp, которая явно хранит размеры входного тензора 4D:

net = tfl.input_data(shape=[None, None, 4])
shp = tf.shape(net)  # <--- (new)
net = tfl.conv_1d(net, 24, window) 
net = tfl.conv_1d(net, 12, 1)
net = tfl.conv_1d(net, 6, 1)
net = tfl.reshape(net, [shp[0], shp[1], 3, 2])  # <--- (new)
net = tf.nn.l2_normalize(net, dim=2)
net = tfl.regression(net, optimizer="sgd", learning_rate=0.1, \
                     loss=backbone_angle_distance_1)
model = tfl.DNN(net)

Ошибки, связанные с формой, которые у меня были раньше, теперь исчезли. Но если кто-то все еще следит за этим, у меня есть дополнительные вопросы.

а) Я сделал это "правильно"? Этот алгоритм, вероятно, никогда не будет обучен в распределенной системе, так как мой набор данных слишком мал, чтобы беспокоиться. Тем не менее, я понимаю, что все, что использует график TensorFlow, но не является объектом TensorFlow, потенциально может сломать любые параллелизующие оптимизации, которые могут быть выполнены. Является ли shp правильным объектом TensorFlow? Как насчет его элементов, которые я получаю с помощью операций нарезки?

б) Если бы я работал в Numpy, это похоже на работу для оператора многоточия Python. Я даже неосознанно написал свое первоначальное описание тензорных фигур в верхней части этого обсуждения, используя эллипсы. TensorFlow понимает многоточие? Это может быть полезно.

Вам нужно изменить tgt как это: tgt = tgt.reshape([-1,3,2])

Измерение target должно быть таким же, как измерение вывода вашей сети, которое определяется этой строкой:net = tfl.reshape(net, [-1,3,2]),

Другие вопросы по тегам