将二元分类转换为多标签?



我正在尝试将我的二进制图像分类模型转换为多标签,但 NumPy 数组一直出错 期望值二维值,任何人都可以帮我编辑 法典。

我尝试使用多标签Binazier,但我没有运气,这里有人可以帮助我吗?

错误# 用法

# python train.py --dataset dataset
# import the necessary packages
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import AveragePooling2D
from tensorflow.keras.layers import Dropout
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import to_categorical
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import argparse
import cv2
import os
# construct the argument parser and parse the arguments
# initialize the initial learning rate, number of epochs to train for,
# and batch size
INIT_LR = 1e-3
EPOCHS = 40
BS = 66
# grab the list of images in our dataset directory, then initialize
# the list of data (i.e., images) and class images
print("[INFO] loading images...")
imagePaths = list(paths.list_images('/content/drive/My Drive/testset/'))
data = []
labels = []
# loop over the image paths
for imagePath in imagePaths:
# extract the class label from the filename
label = imagePath.split(os.path.sep)[-2]
# load the image, swap color channels, and resize it to be a fixed
# 224x224 pixels while ignoring aspect ratio
image = cv2.imread(imagePath)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (224, 224))
# update the data and labels lists, respectively
data.append(image)
labels.append(label)
# convert the data and labels to NumPy arrays while scaling the pixel
# intensities to the range [0, 255]
data = np.array(data) / 255.0
labels = np.array(labels)
# perform one-hot encoding on the labels
lb = LabelBinarizer()
labels = lb.fit_transform(labels)
labels = to_categorical(labels)
# partition the data into training and testing splits using 80% of
# the data for training and the remaining 20% for testing
(trainX, testX, trainY, testY) = train_test_split(data, labels,
test_size=0.20, stratify=labels, random_state=42)
# initialize the training data augmentation object
trainAug = ImageDataGenerator(
rotation_range=15,
fill_mode="nearest")
# load the VGG16 network, ensuring the head FC layer sets are left
# off
baseModel = VGG16(weights="imagenet", include_top=False,
input_tensor=Input(shape=(224, 224, 3)))
# construct the head of the model that will be placed on top of the
# the base model
headModel = baseModel.output
headModel = AveragePooling2D(pool_size=(4, 4))(headModel)
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(64, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(2, activation="softmax")(headModel)
# place the head FC model on top of the base model (this will become
# the actual model we will train)
model = Model(inputs=baseModel.input, outputs=headModel)
# loop over all layers in the base model and freeze them so they will
# *not* be updated during the first training process
for layer in baseModel.layers:
layer.trainable = False
# compile our model
print("[INFO] compiling model...")
opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"])
# train the head of the network
print("[INFO] training head...")
H = model.fit(
trainAug.flow(trainX, trainY, batch_size=BS),
steps_per_epoch=len(trainX) // BS,
validation_data=(testX, testY),
validation_steps=len(testX) // BS,
epochs=EPOCHS)
# make predictions on the testing set
print("[INFO] evaluating network...")
predIdxs = model.predict(testX, batch_size=BS)
# for each image in the testing set we need to find the index of the
# label with corresponding largest predicted probability
predIdxs = np.argmax(predIdxs, axis=1)
# show a nicely formatted classification report
print(classification_report(testY.argmax(axis=1), predIdxs,
target_names=lb.classes_))
# compute the confusion matrix and and use it to derive the raw
# accuracy, sensitivity, and specificity
cm = confusion_matrix(testY.argmax(axis=1), predIdxs)
total = sum(sum(cm))
acc = (cm[0, 0] + cm[1, 1]) / total
sensitivity = cm[0, 0] / (cm[0, 0] + cm[0, 1])
specificity = cm[1, 1] / (cm[1, 0] + cm[1, 1])
# show the confusion matrix, accuracy, sensitivity, and specificity
print(cm)
print("acc: {:.4f}".format(acc))
print("sensitivity: {:.4f}".format(sensitivity))
print("specificity: {:.4f}".format(specificity))
# plot the training loss and accuracy
N = EPOCHS
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, N), H.history["accuracy"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_accuracy"], label="val_acc")
plt.title("Training Loss and Accuracy on COVID-19 Dataset")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="lower left")
plt.savefig("plot.png")
# serialize the model to disk
print("[INFO] saving COVID-19 detector model...")
model.save('/content/drive/My Drive/setcovid/model.h5', )

取决于您如何预处理标签

有三点

1.第一个:标签形状

观察你的标签形状。从您的代码中,我猜测您的标签形状必须是一维的,就像您可以使用labels.shape看到它(5000,)一样。 要使其二维使用这个

labels = np.expand_dims(labels,axis=1)


2.第二个:最后一个密集层中的单位

您在最后dense层 2 中使用了单元数,因此基本上它是一个多类分类,其行为类似于二元分类。我建议如果你正在进行二元分类,那么最后dense层使用 1 个单位,然后激活softmax以外的 .如果您的数据集具有 3 个或超过 3 个类,请使用具有输出类数和激活softmaxdense图层。但是对于这种情况,标签应该是one hot encoded.

3.第三个:更改损失函数

如果您仍然打算将 2 个单位的输出用于最后一个密集层。将损失函数从binary_crossentropy更改为categorical_crossentropy

取决于您的 TF 版本,但如果您的输入是生成器,也许您应该使用 fit_generator (https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit_generator( 方法而不是 model.fit。

还要检查之前提到的答案

我认为你错了

将 numpy 数组
  1. 列表转换为单个 numpy 数组,您可以使用

    data = np.stack( data, axis=0 )/255

    data = np.concatenate( data, axis=0 )# 它将返回形状(bath_size,dim_height * dim_width,通道(,然后重塑数据

    data.reshape(bath_size, dim_height, dim_width, channel)

    data = np.vstack(data)/255.0

    另一个答案

  2. 使用lb.fit_transform(标签(后,无需使用to_categorical(标签(

  3. 不清楚你想要什么,多标签还是多类? 这是不同的。 如果要更改为多标签案例,则binary_crossentropy是解决方案之一。 但是您会将准确性(默认(混淆为度量,在多标签中是错误的,您可以使用精度计算进行多标签分类。 并且不要在最终激活输出中使用 softmax, 请使用乙状结肠。或者,如果它的多类将损失更改为categorical_crossentropy,如果它的标签是一个热编码,或者如果它的标签是数字而不是一个热编码,则损失更改为sparse_categorical_crossentropy。

  4. 如果其二进制图像分类之前,则输出模型必须是 1(1 或 0(而不是 2

希望这个答案成为你的解决方案

最新更新