密集层二元分类不能设置为2

我刚开始接触Keras和TensorFlow。我在尝试弄清楚为什么我的代码在使用密集层设置为2时会报错,而设置为1时则不会。这是我的基于目录结构分配类别的方式:

res_scans = np.array([process_scan(path) for path in res_scan_paths])non_res_scans = np.array([process_scan(path) for path in non_res_scan_paths])# 对有病毒性肺炎的CT扫描赋值1,普通的赋值0res_labels = np.array([1 for _ in range(len(res_scans))])non_res_labels = np.array([0 for _ in range(len(non_res_scans))])# 按70-30的比例分割数据spl = 0.7resF = round(spl * len(res_scan_paths) )non_resF = round(spl * len(non_res_scan_paths))# 分割数据为训练和验证集x_train = np.concatenate((res_scans[:resF], non_res_scans[:non_resF]), axis=0)y_train = np.concatenate((res_labels[:resF], non_res_labels[:non_resF]), axis=0)x_test = np.concatenate((res_scans[resF:], non_res_scans[non_resF:]), axis=0)y_test = np.concatenate((res_labels[resF:], non_res_labels[non_resF:]), axis=0)

这是我使用的带有卷积层之间批量归一化的VGG16 CNN模型

# VGG16模型lr = 0.001activ='relu'Model = Sequential()Model.add(Conv3D(64, (3,3,3), strides=(1, 1, 1), input_shape = (91, 109, 91, 30), activation =activ, padding="same"))Model.add(Conv3D(64, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(MaxPool3D((2,2,2), strides = (2,2,2)))  Model.add(Conv3D(128, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(Conv3D(128, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(MaxPool3D((2,2,2), strides = (1,1,1)))Model.add(Conv3D(256, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(Conv3D(256, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization())Model.add(Conv3D(256, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(MaxPool3D((2,2,2), strides = (2,2,2)))Model.add(Conv3D(512, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(Conv3D(512, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization())Model.add(Conv3D(512, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(MaxPool3D((2,2,2), strides = (2,2,2)))Model.add(Conv3D(512, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(Conv3D(512, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization())Model.add(Conv3D(512, (3,3,3), strides=(1, 1, 1), activation =activ, padding="same"))Model.add(BatchNormalization()) Model.add(MaxPool3D((2,2,2), strides = (1,1,1)))Model.add(Flatten())Model.add(Dense(units=4096,activation="relu"))Model.add(Dense(units=4096,activation="relu"))Model.add(Dense(units=2, activation="softmax"))Model.summary()

然后进行编译和运行如下

Model.compile(loss='mse' , optimizer=tf.keras.optimizers.Adam(lr=lr), metrics=["acc"])history = Model.fit(x_train, y_train, epochs=30, batch_size=12, verbose=1,validation_data=(x_test, y_test))

我得到了以下让我困惑的错误:

ValueError: A target array with shape (18, 1) was passed for output of shape (None, 2) while using as loss `mean_squared_error`. This loss expects targets to have the same shape as the output.

我在另一台仅使用CPU的电脑上可以正常运行。然而在配有两张2080ti显卡的电脑上,它会报上述错误。当我将设置改为1时,在第一个epoch后内核就死掉了。我知道根据之前的帖子,dense=2是正确的方式。请帮助我解决这个问题。

kevin


回答:

从你下面的陈述来看,你似乎是在尝试构建一个二元分类模型。

# 对有病毒性肺炎的CT扫描赋值1,普通的赋值0

因此,正确的设置应如下所示:

...# (1)# 模型的最后一层应该有一个输出单元,并使用sigmoid激活函数Model.add(Dense(units=1, activation="sigmoid"))# (2)# 损失函数应设置为如下Model.compile(loss='binary_crossentropy' ,               optimizer=tf.keras.optimizers.Adam(lr=lr),               metrics=["acc"])

现在,你可以训练你的模型,问题应该会得到解决。


更多信息供你参考

你选择了mse作为units=2, activation="softmax"的损失函数,这是错误的。通常,对于mse,激活函数应该设置为None,即线性激活函数。

...Model.add(Dense(units=1, activation=None))Model.compile(loss='mse' ,               optimizer=tf.keras.optimizers.Adam(lr=lr),               metrics=["acc"])

另外,选择softmax作为激活函数时,你的损失函数应该设置为categorical_crossentropy。但请注意,在你的案例中,目标不是2D的。对于你的案例,目标是二元的[0, 1, 0],而不是这种形状:[[0, 1], [1,0], [0,1]]。如果你将目标从[0, 1, 0]转换为[[0, 1], [1,0], [0,1]],那么你需要进行如下设置。但请注意,这没有意义,因为你的目标已经是一元编码的了。

...Model.add(Dense(units=2, activation='softmax'))Model.compile(loss='categorical_crossentropy' ,               optimizer=tf.keras.optimizers.Adam(lr=lr),               metrics=["acc"])

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注