TFLearn回归,损失计算中的形状不相容

时间:2017-08-17 10:10:52

标签: python tensorflow tflearn

我正在研究蛋白质序列。我的目标是建立一个卷积网络,预测蛋白质中每个氨基酸的三个角度。我在调试需要重塑操作的TFLearn DNN模型时遇到了问题。

输入数据描述(当前)25种不同长度的蛋白质。要使用张量,我需要有统一的尺寸,所以我用零填充空输入单元格。每个氨基酸由4维代码表示。除了帮助您了解张量的形状之外,其中的细节可能并不重要。

DNN的输出是六个数字,代表三个角度的正弦和余弦。为了创建有序对,DNN图将[...,6] Tensor重新整形为[...,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的代码生成批次,我尝试拦截并重塑我的自定义丢失函数backbone_angle_distance()的第一行中的Tensor 实际

如果我添加几行来尝试模型拟合,如下所示:

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 个答案:

答案 0 :(得分:0)

您需要像tgt

那样重塑tgt = tgt.reshape([-1,3,2])

目标的维度应与此行定义的网络输出维度相同: net = tfl.reshape(net, [-1,3,2])

答案 1 :(得分:0)

好吧,看起来我正在回答我自己的问题。

我尝试了Geert所建议的各种排列,但我无法做任何事情。当我在构建我在此讨论的网络之前的非卷积网络时,尝试将训练数据重新整形为[-1,3,2]是合适的。最后,我得出结论,TFLearn不会让我在损失函数中压缩CNN需要的4D Tensor。我需要像以前一样添加一个维度。但不是保留一个维度(这是-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输入Tensor的维度:

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)

我之前遇到的与形状有关的错误现在已经消失了。但如果有人仍在关注此事,我还有其他问题。

a)我做了吗?#34;对&#34;?这个算法可能永远不会在分布式系统上进行训练,因为我所拥有的数据集太小而不能打扰。但是,据我所知,TensorFlow图使用的任何东西本身都不是TensorFlow对象,有可能破坏可执行的任何并行化优化。 shp 是否是正确的TensorFlow对象?它通过切片操作得到的元素怎么样?

b)如果我在Numpy工作,这看起来像Python的省略号运算符。我甚至无意识地使用省略号在本讨论的顶部写下了我对Tensor形状的初步描述。 TensorFlow是否理解省略号?它可能很有用。