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

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

Входные данные описывают (в настоящее время) 25 белков различной длины. Чтобы использовать тензоры, мне нужно иметь одинаковые размеры, поэтому я заполняю пустые входные ячейки нулями. Каждая аминокислота представлена ​​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-тензора tgt, сгладив самое внешнее измерение, out и tgt должны совпадать. Так как код TFLearn создает пакеты, я пытаюсь перехватить и изменить Tensor actual в первой строке 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().

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


person John Ladasky    schedule 17.08.2017    source источник
comment
Следуя за мной: эти два сообщения, возможно, связаны: регрессия с помощью tflearn"> stackoverflow.com/questions/44763935/ stackoverflow.com/questions/42317586/   -  person John Ladasky    schedule 17.08.2017


Ответы (2)


Вам нужно изменить форму tgt следующим образом: tgt = tgt.reshape([-1,3,2])

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

person GeertH    schedule 17.08.2017
comment
Привет Герт, спасибо за ваш ответ. У меня также была идея сгладить tgt по одному измерению. Но тогда как будет работать model.fit() в TFLearn? Эта функция создает пакеты для обучения и проверки. Ему необходимо получить целые белки и выбрать соответствующие части как inp, так и tgt. Я указываю, что validation_set=0,2, и я ожидаю, что это означает, что пять белков должны быть отложены для проверки. Также: я думал, что прогноз — это результат работы сети, а фактический — это часть tgt. Я немного смущен. - person John Ladasky; 24.08.2017
comment
Привет, Джон, ты прав насчет того, что на самом деле являешься частью tgt, конечно. Я обновлю свой ответ. Остальная часть ответа по-прежнему верна, я думаю. Размеры аргументов inpt и tgt функции model.fit() должны соответствовать форме вывода вашей сети. В настоящее время выход вашей сети имеет форму [-1,3,2], а форма tgt[25, 543, 3, 2]. - person GeertH; 24.08.2017

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

Я пробовал различные перестановки того, что предлагал Герт, и у меня ничего не получалось. Когда я строил несверточную сеть, которая предшествовала той, которую я здесь обсуждаю, попытка изменить обучающие данные на [-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 многоточие? Это может быть полезно.

person John Ladasky    schedule 30.08.2017