【问题标题】:ValueError: logits and labels must have the same shape ((32, 1) vs (32, 2))ValueError:logits 和标签必须具有相同的形状 ((32, 1) vs (32, 2))
【发布时间】:2021-04-13 09:05:01
【问题描述】:

我已经更改了来自 here 的代码,用于具有 1 个输出神经元的二进制分类

import os
from keras.models import Sequential
from sklearn.model_selection import train_test_split
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import optimizers
from skimage import io
from skimage.transform import resize
from keras.utils import to_categorical
import numpy as np
import tensorflow as tf
import random
import glob

n_category_samples = 4000
batch_size = 32
num_classes = 2
epochs = 10

n_image_rows = 106
n_image_cols = 106
n_channels = 3


def train_selfie_model():
    random_seed = 1
    tf.random.set_seed(random_seed)
    np.random.seed(random_seed)

    x_train, y_train = prepare_train_set()

    x_train, x_test, y_train, y_test = train_test_split(x_train, y_train, test_size=0.30, random_state=42)

    mean = np.array([0.5, 0.5, 0.5])
    std = np.array([1, 1, 1])
    x_train = x_train.astype('float')
    x_test = x_test.astype('float')
    for i in range(3):
        x_train[:, :, :, i] = (x_train[:, :, :, i] - mean[i]) / std[i]
        x_test[:, :, :, i] = (x_test[:, :, :, i] - mean[i]) / std[i]

    y_train = to_categorical(y_train, num_classes)
    y_test = to_categorical(y_test, num_classes)

    model = compile_model()

    print(model.summary())

    print(y)
    model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test))

    score = model.evaluate(x_test, y_test, verbose=0)

    print('Test loss: ', score[0])
    print('Test accuracy: ', score[1])

    model_path = os.getcwd() + "/models/saved/selfie-model/"
    model.save(model_path)


def prepare_train_set():
    positive_samples = glob.glob('datasets/drunk_resize_frontal_faces/pos/*')[0:n_category_samples]
    negative_samples = glob.glob('datasets/drunk_resize_frontal_faces/neg/*')[0:n_category_samples]
    negative_samples = random.sample(negative_samples, len(positive_samples))
    x_train = []
    y_train = []
    for i in range(len(positive_samples)):
        x_train.append(resize(io.imread(positive_samples[i]), (n_image_rows, n_image_cols)))
        y_train.append(1)
        if i % 1000 == 0:
            print('Reading positive image number ', i)
    for i in range(len(negative_samples)):
        x_train.append(resize(io.imread(negative_samples[i]), (n_image_rows, n_image_cols)))
        y_train.append(0)
        if i % 1000 == 0:
            print('Reading negative image number ', i)
    x_train = np.array(x_train)
    y_train = np.array(y_train)
    return x_train, y_train


def compile_model():
    model_input_shape = (n_image_rows, n_image_cols, n_channels)
    model = Sequential()
    model.add(
        Conv2D(8, kernel_size=(3, 3), activation='relu', strides=(1, 1), padding='same', input_shape=model_input_shape))
    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'))
    model.add(Dropout(0.25))
    model.add(Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'))
    model.add(Dropout(0.25))
    model.add(Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'))
    model.add(Conv2D(8, kernel_size=(3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'))
    model.add(Flatten())
    model.add(Dense(10, activation='relu'))
    # single output neuron
    model.add(Dense(1, activation='sigmoid'))
    sgd = optimizers.SGD(lr=.001, momentum=0.9, decay=0.000005, nesterov=False)
    model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
    return model

但是运行train_selfie_model()时出现以下错误

ValueError: logits and labels must have the same shape ((32, 1) vs (32, 2))

model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test))

我是 TF 和 Keras 的新手。似乎这是一个数组维度不匹配。但是我该如何解决这个问题?

【问题讨论】:

    标签: python tensorflow keras tensorflow2.0


    【解决方案1】:

    问题是

    def train_selfie_model():
        ...
        y_train = to_categorical(y_train, num_classes)
        y_test = to_categorical(y_test, num_classes)
        ...
    

    您将y_trainy_test 设置为 one-hot 编码(形状为 (2,) 的向量。但在

    def compile_model():
        ...
        model.add(Dense(1, activation='sigmoid'))
        ...
    

    你只有一个输出神经元(形状为 (1,) 的输出)。

    所以注释掉/删除以下行将解决您的问题。

    y_train = to_categorical(y_train, num_classes)
    y_test = to_categorical(y_test, num_classes)
    

    【讨论】:

    • 你如何建议在不改变单个输出神经元的情况下改变 train_selfie_model?
    • @user158 如果您将其视为二元分类任务而不是多类分类问题,将会很有帮助。因此,您可以使用 0 和 1 而不是 [1, 0][0, 1]y_trainy_test 进行编码。
    • 如果您不介意,我可以看看代码中的必要更改吗?您是否建议删除 to_categorical(...)
    • 我不知道y_trainy_test 长什么样。也许删除to_categorical 再试一次。
    • 另外,在您发布的 github 链接中,在第 87 行,作者使用了 2 个输出神经元。
    【解决方案2】:

    要使(32, 1) 数组显示为(32, 2),您可以构造一个视图:

    arr = np.lib.stride_tricks.as_strided(arr, shape=(arr.shape[0], 2), strides=(arr.strides[0], 0))
    

    您可以采取更加手动的方法:

    arr = np.ndarray(shape=(arr.shape[0], 2), strides=(arr.strides[0], 0), dtype=arr.dtype, buffer=arr)
    

    两者都可以两次查看相同的内存,因此您通常应该将它们视为只读的。要复制数据,请使用以下任一方法:

    arr = np.concatenate((arr,) * 2, axis=-1)
    arr = np.repeat(arr, 2, axis=-1)
    arr = np.tile(arr, [1, 2])
    

    【讨论】:

    • 你能说一下如何在我发布的代码的上下文中应用它吗?
    • 将这些行中的任何一行与适当调整的变量名称放在错误上方的一行
    • 感谢您迄今为止的支持。在拟合模型之前,我已经用你的 sn-p 修改了`x_train,y_train,x_test,y_test`,现在我在model.fit(...) 收到一个新错误ValueError: Input 0 of layer sequential is incompatible with the layer: : expected min_ndim=4, found ndim=2. Full shape received: (32, 2)
    • 听起来是个不同的问题
    猜你喜欢
    • 2020-10-23
    • 1970-01-01
    • 2021-07-27
    • 2021-10-28
    • 2021-07-28
    • 2020-12-02
    • 1970-01-01
    • 2021-09-19
    • 2021-03-23
    相关资源
    最近更新 更多