【问题标题】:TFLearn regression, shape incompatibility in loss calculationTFLearn回归,损失计算中的形状不兼容
【发布时间】:2017-08-31 03:10:51
【问题描述】:

我正在处理蛋白质序列。我的目标是创建一个卷积网络,它将预测蛋白质中每个氨基酸的三个角度。我在调试需要重塑操作的 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,展平最外层维度,outtgt 应该匹配。由于 TFLearn 的代码进行了批处理,因此我尝试在我的自定义损失函数骨干角距离()的第一行中截取并重塑 Tensor actual

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

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)?我知道不会。根据回溯,我实际上似乎从未在骨干角距离()中完成我的重塑操作。

感谢任何建议,谢谢!

【问题讨论】:

标签: python tensorflow tflearn


【解决方案1】:

你需要像这样重塑tgttgt = tgt.reshape([-1,3,2])

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

【讨论】:

  • 嗨 Geert,感谢您的回复。我也有将 tgt 扁平化一维的想法。但是,TFLearn 的 model.fit() 将如何工作?该功能正在创建训练和验证批次。它需要获得完整的蛋白质,并且需要选择inptgt的对应部分。我指定validation_set=0.2,我希望这意味着应该留出五种蛋白质进行验证。另外:我认为predict是网络的输出,而actualtgt的一部分。我有点困惑。
  • 嗨,约翰,你是对的,当然,你是tgt 的一员。我会更新我的答案。我认为其余的答案仍然是正确的。 model.fit()inpttgt 参数的尺寸应与网络输出的形状相对应。目前你的网络输出的形状是[-1,3,2],但tgt的形状是[25, 543, 3, 2]
【解决方案2】:

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

我尝试了 Geert 所建议的各种排列方式,但我无法让任何事情发挥作用。当我在此处讨论之前构建非卷积网络时,尝试将训练数据重塑为 [-1,3,2] 是合适的。最终,我得出结论,TFLearn 不会让我在损失函数中压平 CNN 所需的 4D 张量。我需要像以前一样添加一个维度。但是现在我必须保留两个,而不是保留一个维度(这是 -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) 我做的“正确”吗?该算法可能永远不会在分布式系统上进行训练,因为我拥有的数据集太小而无法打扰。但是,据我了解,TensorFlow 图使用的任何本身不是 TensorFlow 对象的东西都有可能破坏任何可以执行的并行优化。 shp 是正确的 TensorFlow 对象吗?它的元素呢,我是通过切片操作得到的?

b) 如果我在 Numpy 中工作,这看起来像是 Python 省略号运算符的工作。我什至不自觉地使用椭圆在讨论的顶部写了我对张量形状的初始描述。 TensorFlow 是否理解省略号?它可能很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    • 2021-02-06
    • 2018-04-24
    • 2022-01-03
    • 2018-01-10
    • 1970-01-01
    相关资源
    最近更新 更多