【问题标题】:Bad argument to theano function, Wrong number of dimensionstheano 函数的参数错误,维数错误
【发布时间】:2016-03-26 07:34:10
【问题描述】:

我正在使用 lasagne 和 theano 预测来自 VGG 的回归任务的 20 个数字。对于我编写的示例脚本,图像数量为 100。我认为我在做一些愚蠢的事情,但被卡住了。

网上看,用nolearn的人,可以通过指定regression=True修复,但我只是用千层面

所以:

('X.shape', (100, 3, 224, 224))
('y.shape', (100, 20))

这是确切的错误消息

Traceback (most recent call last):
  File "script_1.py", line 167, in <module>
    loss = train_batch()
  File "script_1.py", line 90, in train_batch
    return train_fn(X_tr[ix], y_tr[ix])
  File "/usr/local/lib/python2.7/dist-packages/Theano-0.8.0rc1-py2.7.egg/theano/compile/function_module.py", line 786, in __call__
    allow_downcast=s.allow_downcast)
  File "/usr/local/lib/python2.7/dist-packages/Theano-0.8.0rc1-py2.7.egg/theano/tensor/type.py", line 177, in filter
    data.shape))
TypeError: ('Bad input argument to theano function with name "script_1.py:159"  at index 1(0-based)', 'Wrong number of dimensions: expected 1, got 2 with shape (16, 20).')

这是模型

def build_model():
    net = {}
    net['input'] = InputLayer((None, 3, 224, 224))
    net['conv1'] = ConvLayer(net['input'], num_filters=96, filter_size=7, stride=2, flip_filters=False)
     ...............
    net['drop7'] = DropoutLayer(net['fc7'], p=0.5)
    net['fc8'] = DenseLayer(net['drop7'], num_units=20, nonlinearity=None)
    return net

发电机:

def batches(iterable, N):
    chunk = []
    for item in iterable:
        chunk.append(item)
        if len(chunk) == N:
            yield chunk
            chunk = []
    if chunk:
        yield chunk
def train_batch():
    ix = range(len(y_tr))
    np.random.shuffle(ix)
    ix = ix[:BATCH_SIZE]
    return train_fn(X_tr[ix], y_tr[ix])

相关训练sn-p

X_sym = T.tensor4()
y_sym = T.ivector()
output_layer = net['fc8']
prediction = lasagne.layers.get_output(output_layer, X_sym)
loss = lasagne.objectives.squared_error(prediction, y_sym)
loss = loss.mean()
acc = T.mean(T.eq(T.argmax(prediction, axis=1), y_sym), dtype=theano.config.floatX)
params = lasagne.layers.get_all_params(output_layer, trainable=True)
updates = lasagne.updates.nesterov_momentum(loss, params, learning_rate=0.0001, momentum=0.9)

train_fn = theano.function([X_sym, y_sym], loss, updates=updates)
val_fn = theano.function([X_sym, y_sym], [loss, acc])
pred_fn = theano.function([X_sym], prediction)

for epoch in range(5):
    for batch in range(25):
       loss = train_batch()
.....

【问题讨论】:

    标签: shape theano mismatch lasagne


    【解决方案1】:

    您的预测输出具有形状 (batchsize, 20) 但您的 y_sym 变量是 ivector 类型,因此它可能是长度为 batchsize 的向量。我不确定这是否是导致错误的原因,但我认为您无法计算这两个量的平方误差项。一个是矩阵,另一个是向量,它们的形状似乎没有对齐?

    您的回归目标是什么?如果您为每个数据点预测 20 个数字,您的 y_sym 可能应该是一个矩阵,那么您可以计算平方误差项。

    另一种可能性是将最后一层更改为 sigmoid 非线性。通过这种方式,您可以将卷积神经网络解释为产生多标签概率。然后,您可以为回归综合生成多标签概率目标变量。一个例子是,假设一个数据点 x 有多个标签 0、1、10。您可以创建一个长度为 20 的向量,其中 0、1、10 就像一些小的 a 的 1-a,而其他条目是小的正数.

    您还可以将目标函数切换为二元交叉熵。在这种情况下,我们不执行回归。然而,我们的网络仍然输出一个类分数矩阵,而不是一个向量。这通常是在检测图像中是否存在 K 个不同对象(例如猫、狗、人、汽车、自行车等)时使用的损失函数,例如多标签分类。如果你想试试这条路线,我们将最后一层改成如下:

    net['fc8'] = DenseLayer(net['drop7'], num_units=20, nonlinearity=sigmoid)
    

    现在我将我的网络解释为输出概率;每个概率将代表关于我们的网络是否相信该对象类在图像中的置信度分数。

    我们现在将有以下损失函数:

    X_sym = T.tensor4()
    y_sym = T.imatrix() 
    output_layer = net['fc8']
    probabilities = lasagne.layers.get_output(output_layer, X_sym)
    loss = lasagne.objectives.binary_crossentropy(probabilities, y_sym)
    loss = loss.mean()
    ... the rest of the update stuff...
    train_fn = theano.function([X_sym, y_sym], loss, updates=updates)
    

    这里的关键区别在于我们的目标变量 y_sym 现在是一个矩阵。这必须是一个 {0,1} 值 (batchsize,K) 大小的矩阵,其中 0 表示图像中不存在对象,1 表示图像中存在对象。

    为了计算多标签预测的准确性,通常使用 F1 分数。 Here 是关于如何使用 scikit-learn 计算 F1 分数的参考。在这种情况下,我们的验证函数会有所不同,它可能看起来像这样:

     from sklearn.metrics import f1_score
     probabilities_fn = theano.function([X_sym], probabilities)
     confidence_threshold = .5 
     predictions = np.where(probabilities_fn(X_sym) > confidence_threshold, 1, 0)  
     f1_score(y_true, predictions, average='micro')
    

    上面的代码 sn-p 返回来自我们网络的概率/置信度分数,以及超过我们的 confidence_threshold 参数的任何概率,这里我选择 0.5,我们将其解释为存在类标签。

    【讨论】:

    • 谢谢!我昨晚意识到并改为矢量,但现在似乎我搞砸了准确性。
    • 无法修复。您能否帮助正确表达准确性(它是snipper中的分类acc,这是错误的)?我想我把轴弄乱了..
    • 你用什么转换成矢量了?如果您尝试对可能具有多个对象的图像进行分类,例如 K 个总类(猫、狗、人、自行车、汽车等),对于每个数据点,您需要输出 K 个类别分数,因此您的模型的输出应该是一个矩阵。如果您想跟踪准确性,我认为 argmax 不再合适,因为这将限制您对每张图像仅预测 1 个类别。您可能想要使用 F1 分数之类的东西,它通常用于多标签图像分类。
    • 糟糕。我的意思是一个矩阵,也就是我把 y_sym 改成了一个矩阵。感谢您更新答案。我正在尝试预测 10 个关键点的 x 和 y 坐标。因此我需要回归。我不确定多类范式是否是正确的方法。我需要解决的是我的代码 sn-p 中回归输出的准确性。您认为在这种情况下应该采取什么措施?也许我也应该缩放我的标签? (在这里完成danielnouri.org/notes/2014/12/17/…)。
    • 或许你是对的。还记得我问题开头的“regression=True”+ nolearn 评论吗? stackoverflow.com/questions/32654026/… 建议在回归 = True 的情况下,nolearn 网络输出每个类的概率,并使用输出向量上的平方误差计算损失。 "ctrl+f" 这里回归github.com/dnouri/nolearn/blob/master/nolearn/lasagne/base.py
    猜你喜欢
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    相关资源
    最近更新 更多