Я работаю с белковыми последовательностями. Моя цель — создать свёрточную сеть, которая будет предсказывать три угла для каждой аминокислоты в белке. У меня возникли проблемы с отладкой модели 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().
Любые советы приветствуются, спасибо!