Python 密集层二进制分类不能设置为2

Python 密集层二进制分类不能设置为2,python,tensorflow,machine-learning,keras,deep-learning,Python,Tensorflow,Machine Learning,Keras,Deep Learning,我对keras和tensorflow还比较陌生。我试图弄明白为什么在使用稠密层=2而非稠密层=1时运行代码会出现错误。这是我如何根据dir结构分配类的: 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]) # For the CT scans havin

我对keras和tensorflow还比较陌生。我试图弄明白为什么在使用稠密层=2而非稠密层=1时运行代码会出现错误。这是我如何根据dir结构分配类的:

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])

# For the CT scans having presence of viral pneumonia
# assign 1, for the normal ones assign 0.
res_labels = np.array([1 for _ in range(len(res_scans))])
non_res_labels = np.array([0 for _ in range(len(non_res_scans))])

#Split data 
spl = 0.7
resF = round(spl * len(res_scan_paths) )
non_resF = round(spl * len(non_res_scan_paths))


# Split data in the ratio 70-30 for training and validation.
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)
这是CNN模型,使用VGG16在conv层之间进行批量标准化

#VGG16 Model
lr = 0.001
activ='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的计算机上很好地运行它。然而,在装有2桥2080ti的计算机上,它给了我这个错误。当我把它改为1时,它在第一个纪元之后给了我死内核。 我从以前的帖子中知道,密度=2是正确的方法。请帮忙


凯文

根据你下面的陈述,你似乎在试图建立一个二元分类模型

# For the CT scans had the presence of viral pneumonia
# assign 1, for the normal ones assign 0.
这就是为什么正确的设置如下所示:

...
# (1)
# last layer of your model should have 1 output unit and
# with sigmoid activation
Model.add(Dense(units=1, activation="sigmoid"))

# (2)
# and your loss function should be as follows
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"])
另外,选择activation to
softmax
,您的损失函数应该是
Category\u 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"])

神经网络的输出应该适合数据集中的y标签大小。看起来你的y标签是一个18个元素的向量,所以你应该在输出层有18个神经元。或者,如果您认为数据集y标签不应由18个元素组成,则应该更改它。 在MAE中:


因此,神经网络y_pred的输出应该与数据集y-label的大小相同(即y_true)

在这种情况下,也可以使用二进制交叉熵,但也可以使用它。
loss = mean(abs(y_true - y_pred), axis=-1)