【问题标题】:Multiclass classification using Categorical cross entropy - ValueError: Shapes (3, 1) and (1, 3) are incompatible使用分类交叉熵的多类分类 - ValueError:形状 (3, 1) 和 (1, 3) 不兼容
【发布时间】:2020-09-16 22:22:19
【问题描述】:

我正在对 22500 张图像构建多类分类器。

标签有 3 个类别 - 0,1,2

我对 y 标签进行了如下热编码:

y_train = tf.one_hot(y_train,3)
y_test = tf.one_hot(y_test,3)
y_val = tf.one_hot(y_val,3)

由于数据量很大,我使用 tf.data.Dataset 对象来预处理数据。 我已经使用 dataset.zip 压缩了数据和标签

#creating zipped tuples ofdata and label
data_set_train = tf.data.Dataset.zip((X_train , y_train))
data_set_test = tf.data.Dataset.zip((X_test , y_test))
data_set_val = tf.data.Dataset.zip((X_val , y_val))

并应用了预处理功能


def pre_process(x,y):
     x_norm = (x - mean_Rot_MIP) / Var_Rot_MIP
     # Stacking along the last dimension to avoid having to move channel axis
     x_norm_3ch = tf.stack((x_norm, x_norm, x_norm), axis=-1)
     x_norm_3ch = tf.reshape(x_norm_3ch, [1,224,224,3])
     return x_norm_3ch , y


#creating dataset iterable with all transaformations
X_train1 = data_set_train.map(pre_process)
X_test1 = data_set_test.map(pre_process)
X_val1 = data_set_val.map(pre_process)

数据集对象包含一个数据张量和 y 标签张量的元组,如:

(<tf.Tensor: shape=(1, 224, 224, 3), dtype=float64, numpy=
array([[[[-1.02143877, -1.02143877, -1.02143877],
         [-1.02143877, -1.02143877, -1.02143877],
         [-1.02143877, -1.02143877, -1.02143877],
...,
         [-1.02143877, -1.02143877, -1.02143877],
         [-1.02143877, -1.02143877, -1.02143877],
         [-1.02143877, -1.02143877, -1.02143877]]]])>,
 <tf.Tensor: shape=(3,), dtype=float32, numpy=array([1., 0., 0.], dtype=float32)>)

每个输入的形状是:(1,224,224,3) y标签的形状是:(3,)

我正在使用带有少量附加头层的 RESNET50 来执行分类

baseModel = ResNet50(weights=None, include_top=False, input_tensor=Input(shape=(224, 224, 3)))
headModel = baseModel.output
headModel = AveragePooling2D(pool_size=(7, 7))(headModel)
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(256, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(3, activation="softmax")(headModel)
model = Model(inputs=baseModel.input, outputs=headModel)

并使用 categorical_cross 熵作为损失函数。

# compile the model
INIT_LR = 1e-4
BS = 16
NUM_EPOCHS = 20

opt = Adam(lr=INIT_LR, decay=INIT_LR / NUM_EPOCHS)
model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])

# train the model
H = model.fit(X_train1, batch_size = BS, validation_data=(X_val1), epochs = NUM_EPOCHS, shuffle =False)

当我拟合模型时,我得到以下错误:

Traceback (most recent call last):

  File "<ipython-input-81-eda0da51ce9e>", line 1, in <module>
    H = model.fit(X_train1, batch_size = BS, validation_data=(X_val1), epochs = NUM_EPOCHS, shuffle =False)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\training.py", line 108, in _method_wrapper
    return method(self, *args, **kwargs)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1098, in fit
    tmp_logs = train_function(iterator)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\eager\def_function.py", line 780, in __call__
    result = self._call(*args, **kwds)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\eager\def_function.py", line 814, in _call
    results = self._stateful_fn(*args, **kwds)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\eager\function.py", line 2828, in __call__
    graph_function, args, kwargs = self._maybe_define_function(args, kwargs)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\eager\function.py", line 3210, in _maybe_define_function
    return self._define_function_with_shape_relaxation(args, kwargs)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\eager\function.py", line 3142, in _define_function_with_shape_relaxation
    args, kwargs, override_flat_arg_shapes=relaxed_arg_shapes)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\eager\function.py", line 3075, in _create_graph_function
    capture_by_value=self._capture_by_value),

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\framework\func_graph.py", line 986, in func_graph_from_py_func
    func_outputs = python_func(*func_args, **func_kwargs)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\eager\def_function.py", line 600, in wrapped_fn
    return weak_wrapped_fn().__wrapped__(*args, **kwds)

  File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\framework\func_graph.py", line 973, in wrapper
    raise e.ag_error_metadata.to_exception(e)

ValueError: in user code:

    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\training.py:806 train_function  *
        return step_function(self, iterator)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\training.py:796 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\distribute\distribute_lib.py:1211 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\distribute\distribute_lib.py:2585 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\distribute\distribute_lib.py:2945 _call_for_each_replica
        return fn(*args, **kwargs)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\training.py:789 run_step  **
        outputs = model.train_step(data)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\training.py:749 train_step
        y, y_pred, sample_weight, regularization_losses=self.losses)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\compile_utils.py:204 __call__
        loss_value = loss_obj(y_t, y_p, sample_weight=sw)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\losses.py:149 __call__
        losses = ag_call(y_true, y_pred)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\losses.py:253 call  **
        return ag_fn(y_true, y_pred, **self._fn_kwargs)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\util\dispatch.py:201 wrapper
        return target(*args, **kwargs)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\losses.py:1535 categorical_crossentropy
        return K.categorical_crossentropy(y_true, y_pred, from_logits=from_logits)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\util\dispatch.py:201 wrapper
        return target(*args, **kwargs)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\keras\backend.py:4687 categorical_crossentropy
        target.shape.assert_is_compatible_with(output.shape)
    C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\framework\tensor_shape.py:1134 assert_is_compatible_with
        raise ValueError("Shapes %s and %s are incompatible" % (self, other))

    ValueError: Shapes (3, 1) and (1, 3) are incompatible


我做错了什么,我该如何解决?

【问题讨论】:

    标签: python tensorflow keras categorical-data multiclass-classification


    【解决方案1】:

    我认为使用zip() 是一种奇怪的方式来解决这个问题。为什么不使用from_tensor_slices 和批处理:

    data_set_train = tf.data.Dataset.from_tensor_slices((X_train , y_train)).batch(4)
    

    这应该可行。您的输出标签形状应为(4, 3)

    更正的例子:

    import tensorflow as tf
    
    x = tf.random.uniform(minval=0, maxval=1, shape=(100, 224, 224, 3), dtype=tf.float32)
    y = tf.random.uniform(minval=0, maxval=3, shape=(100,), dtype=tf.int32)
    
    y = tf.keras.utils.to_categorical(y, num_classes=3)
    
    BS = 16
    ds = tf.data.Dataset.from_tensor_slices((x, y)).batch(BS)
    
    baseModel = tf.keras.applications.ResNet50(weights=None, include_top=False,
                                      input_tensor=tf.keras.Input(shape=(224, 224, 3)))
    headModel = baseModel.output
    headModel = tf.keras.layers.AveragePooling2D(pool_size=(7, 7))(headModel)
    headModel = tf.keras.layers.Flatten(name="flatten")(headModel)
    headModel = tf.keras.layers.Dense(256, activation="relu")(headModel)
    headModel = tf.keras.layers.Dropout(0.5)(headModel)
    headModel = tf.keras.layers.Dense(3, activation="softmax")(headModel)
    model = tf.keras.Model(inputs=baseModel.input, outputs=headModel)
    
    INIT_LR = 1e-4
    NUM_EPOCHS = 1
    
    opt = tf.keras.optimizers.Adam(lr=INIT_LR, decay=INIT_LR / NUM_EPOCHS)
    model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])
    
    H = model.fit(ds, epochs = NUM_EPOCHS, shuffle=False)
    

    【讨论】:

    • 我们为什么要添加 'batch' ?我最终使用了 zip,因为我必须将 x 和 y 作为元组传递。事实上,我之前的一个问题导致我使用 zip stackoverflow.com/questions/63456492/…
    • 另外,我尝试了您提到的解决方案,但现在我收到以下错误:ValueError: Unbatching a dataset is only supported for rank &gt;= 1
    • 这里真的没有理由使用zip。您所指的答案不一定正确。您还添加了一个批次维度,它是必需的。所以在我的回答中,我做了一个更正的例子,你可以从中工作。我唯一没有实现的是我不理解的预处理。
    【解决方案2】:

    问题在于 y 标签的形状。我通过使用tf.reshape(y,[1,3]) 重塑它来修复它 我所做的唯一更改是在 pre_process 函数中。

    def pre_process(x,y):
         x_norm = (x - mean_Rot_MIP) / Var_Rot_MIP
         # Stacking along the last dimension to avoid having to move channel axis
         x_norm_3ch = tf.stack((x_norm, x_norm, x_norm), axis=-1)
         x_norm_3ch = tf.reshape(x_norm_3ch, [1,224,224,3])
         y_s = tf.reshape(y,[1,3])
         return x_norm_3ch , y_s
    

    我确信可能还有其他方法可以实现我的目标,这个方法只需很少的改动。

    【讨论】:

      猜你喜欢
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 2021-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多