【问题标题】:Tensorflow error : Dimensions must be equal张量流错误:尺寸必须相等
【发布时间】:2019-03-29 05:50:42
【问题描述】:

我有一个包含 25000 张彩色图片 100*100(*3) 的数据集,我正在尝试构建一个带有一个卷积层的简单神经网络。它的细胞图片是否被疟疾感染,所以我的输出是 2。 但似乎我的尺寸不匹配,我不知道我的错误来自哪里。

我的神经网络:

def simple_nn(X_training, Y_training, X_test, Y_test):
    input = 100*100*3
    batch_size = 25

    X = tf.placeholder(tf.float32, [batch_size, 100, 100, 3])
    #Was:
    # W = tf.Variable(tf.zeros([input, 2]))
    # b = tf.Variable(tf.zeros([2]))
    #Now:
    W = tf.Variable(tf.truncated_normal([4, 4, 3, 3], stddev=0.1))
    B = tf.Variable(tf.ones([3])/10) # What should I put here ??

    init = tf.global_variables_initializer()

    # model
    #Was:
    # Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, input]), W) + b)
    #Now:
    stride = 1  # output is still 28x28
    Ycnv = tf.nn.conv2d(X, W, strides=[1, stride, stride, 1], padding='SAME')
    Y = tf.nn.relu(Ycnv + B)

    # placeholder for correct labels
    Y_ = tf.placeholder(tf.float32, [None, 2])


    # loss function
    cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y))

    # % of correct answers found in batch
    is_correct = tf.equal(tf.argmax(Y,1), tf.argmax(Y_,1))
    accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))

    learning_rate = 0.00001

    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    train_step = optimizer.minimize(cross_entropy)
    sess = tf.Session()
    sess.run(init)
    #Training here...

我的错误:

Traceback (most recent call last):
  File "neural_net.py", line 135, in <module>
    simple_nn(X_training, Y_training, X_test, Y_test)
  File "neural_net.py", line 69, in simple_nn
    cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y))
...
ValueError: Dimensions must be equal, but are 2 and 3 for 'mul' (op: 'Mul') with input shapes: [?,2], [25,100,100,3].

我之前使用了一个简单的图层,它正在工作。我改变了我的体重和偏见,老实说,我不知道为什么我的偏见是这样设置的,我遵循了一个教程(https://codelabs.developers.google.com/codelabs/cloud-tensorflow-mnist/#11)但没有解释。 我还将我的 Y 替换为 conv2D。 如果我想得到一个大小为 2*1 的向量,我不知道我的输出应该是什么。

【问题讨论】:

  • 错误到底发生在哪里?请花时间创建一个 minimal reproducible example 来演示您的问题,删除所有不需要重现它的代码。 (我还建议将您的模型更改为仅具有范围从 0 到 1 的单个输出,其中 0 代表健康,1 代表受感染的细胞,然后可以将其解释为概率。)
  • 对不起,我忘了复制我的错误,我删除了一些代码
  • 我也不知道怎么机会输出,恐怕我不明白如何使用过滤器
  • 代码还是很多的。我建议你尽量删除和简化。从外观上看,我相信Y 的形状为(None, 3),但您的Y_ 的形状为(None, 2)。如果您刚开始使用 CNN,发现自己在所有维度之间有点迷失,我的建议是研究 Keras(tf.keras 或标准 keras),它作为高级 API 可以让您从很多方面解脱这些考虑因素。

标签: python-3.x tensorflow conv-neural-network


【解决方案1】:

您已将标签正确定义为

Y_ = tf.placeholder(tf.float32, [None, 2])

所以最后一个维度是 2。但是,卷积步骤的输出并不直接适合将其与标签进行比较。我的意思是:如果你这样做了

Ycnv = tf.nn.conv2d(X, W, strides=[1, stride, stride, 1], padding='SAME')
Y = tf.nn.relu(Ycnv + B)

正如错误所说,它的维度将是四:

ValueError: Dimensions must be equal, but are 2 and 3 for 'mul' (op: 'Mul') with input shapes: [?,2], [25,100,100,3].

因此不可能将卷积的输出与标签直接相乘(或运算)。我建议将卷积的输出展平(将其重塑为一维)并将其传递给 2 个单元的全连接层(与您拥有的类一样多)。像这样:

Y = tf.reshape(Y, [1,-1])
logits = tf.layers.dense(Y, units= 2)

你可以把它传递给损失。

另外我建议您将损失更改为更合适的版本。例如,tf.losses.sigmoid_cross_entropy

另外,你使用卷积的方式很奇怪。为什么要在卷积中放入手工过滤器?除此之外,您还应该在将它们放入集合之前进行初始化。总之,我建议您删除以下所有代码:

    W = tf.Variable(tf.truncated_normal([4, 4, 3, 3], stddev=0.1))
    B = tf.Variable(tf.ones([3])/10) # What should I put here ??

    init = tf.global_variables_initializer()

    # model
    #Was:
    # Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, input]), W) + b)
    #Now:
    stride = 1  # output is still 28x28
    Ycnv = tf.nn.conv2d(X, W, strides=[1, stride, stride, 1], padding='SAME')
    Y = tf.nn.relu(Ycnv + B)

并替换为:

conv1 = tf.layers.conv2d(X, filters=64, kernel_size=3,
                         strides=1, padding='SAME',
                         activation=tf.nn.relu, name="conv1")

init = tf.global_variable_initializer() 也应该在图构造的末尾,因为如果没有,就会有它无法捕获的变量。

我的最终工作代码是:

def simple_nn():
    inp = 100*100*3
    batch_size = 2

    X = tf.placeholder(tf.float32, [batch_size, 100, 100, 3])
    Y_ = tf.placeholder(tf.float32, [None, 2])
    #Was:
    # W = tf.Variable(tf.zeros([input, 2]))
    # b = tf.Variable(tf.zeros([2]))
    #Now:



    # model
    #Was:
    # Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, input]), W) + b)
    #Now:
    stride = 1  # output is still 28x28

    conv1 = tf.layers.conv2d(X, filters=64, kernel_size=3,
                         strides=1, padding='SAME',
                         activation=tf.nn.relu, name="conv1")
    Y = tf.reshape(conv1, [1,-1])
    logits = tf.layers.dense(Y, units=2, activation=tf.nn.relu)
    # placeholder for correct labels



    # loss function
      cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=Y_, logits=logits)
    loss = tf.reduce_mean(cross_entropy)

    # % of correct answers found in batch
    is_correct = tf.equal(tf.argmax(Y,1), tf.argmax(Y_,1))
    accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))

    learning_rate = 0.00001

    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    train_step = optimizer.minimize(cross_entropy)

    init = tf.global_variables_initializer()

    with  tf.Session() as sess:
        sess.run(init)
            ...

【讨论】:

  • 我为这篇长文道歉。希望解决方案有所帮助
  • 感谢您的评论,真的很有用。我尝试使用 sigmoid_cross_entropy 更改我的损失函数,但是当我这样做时,我会为每个批次获得一个恒定值,并且我的准确度为 0%。我试图理解为什么会这样
  • 我将修改代码以包含此内容。选择的选项是:tf.nn.softmax_cross_entropy_with_logits_v2()。你可以在这里看到一个解释:stackoverflow.com/questions/35277898/…
  • 当我用你的改变我丢失的功能时出现这个错误:Inputs to operation gradients/dense/Relu_grad/ReluGrad of type ReluGrad must have the same size and shape. Input 0: [2,2] != input 1: [1,2] 所以还是形状不匹配?我检查了每个参数,但看不到不匹配的来源
  • 我将Y = tf.reshape(conv1, [1,-1]) 替换为Y = tf.reshape(conv1, [batch_size,-1]) 并且不再不匹配。但我仍然有 0% 的准确率(我有 65% 的简单层,而不是卷积层)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-18
  • 2021-11-08
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 2019-10-11
  • 1970-01-01
相关资源
最近更新 更多