这是我的代码,代码可以很好地处理两类图像的分类,它根据目录名称获取标签,但每当我添加一个新目录时,它就停止工作了,有人能帮帮我吗?这是我用于两个目录和两个标签的图像分类代码,但当我将其转换为三个标签/目录时,我得到了一个错误,错误信息如下,有人能帮我解决这个问题吗?这是用于图像分类的代码。我尝试过删除NumPy数组,我在某处看到只需要通过CNN传递它,但我没能做到。我正在尝试使用前胸X光片制作一个由冠状病毒引起的肺炎和其他疾病的分类器
from tensorflow.keras.preprocessing.image import ImageDataGeneratorfrom from tensorflow.keras.applications import VGG16from tensorflow.keras.layers import AveragePooling2Dfrom tensorflow.keras.layers import Dropoutfrom tensorflow.keras.layers import Flattenfrom tensorflow.keras.layers import Densefrom tensorflow.keras.layers import Inputfrom tensorflow.keras.models import Modelfrom tensorflow.keras.optimizers import Adamfrom tensorflow.keras.utils import to_categoricalfrom sklearn.preprocessing import LabelBinarizerfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import classification_reportfrom sklearn.metrics import confusion_matrixfrom imutils import pathsimport matplotlib.pyplot as pltimport numpy as npimport argparseimport cv2import os# 构建参数解析器并解析参数# 初始化初始学习率、训练轮数和批量大小INIT_LR = 1e-3EPOCHS = 40BS = 66# 获取数据集目录中的图像列表,然后初始化数据(即图像)和类别图像列表print("[INFO] 正在加载图像...")imagePaths = list(paths.list_images('/content/drive/My Drive/testset/'))data = []labels = []# 遍历图像路径for imagePath in imagePaths: # 从文件名中提取类别标签 label = imagePath.split(os.path.sep)[-2] # 加载图像,交换颜色通道,并调整大小为固定的224x224像素,同时忽略纵横比 image = cv2.imread(imagePath) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = cv2.resize(image, (224, 224)) # 分别更新数据和标签列表 data.append(image) labels.append(label)# 将数据和标签转换为NumPy数组,同时将像素强度缩放到[0, 255]范围内data = np.array(data) / 255.0labels = np.array(labels)# 对标签进行独热编码lb = LabelBinarizer()labels = lb.fit_transform(labels)labels = to_categorical(labels)# 使用80%的数据进行训练,剩余20%用于测试,将数据分割为训练和测试集(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.20, stratify=labels, random_state=42)# 初始化训练数据增强对象trainAug = ImageDataGenerator( rotation_range=15, fill_mode="nearest")# 加载VGG16网络,确保头部全连接层被移除baseModel = VGG16(weights="imagenet", include_top=False, input_tensor=Input(shape=(224, 224, 3)))# 构建将放置在基础模型顶部的模型头部headModel = baseModel.outputheadModel = 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)# 将头部全连接模型放置在基础模型的顶部(这将成为我们实际训练的模型)model = Model(inputs=baseModel.input, outputs=headModel)# 遍历基础模型中的所有层并冻结它们,以便在第一次训练过程中不会更新它们for layer in baseModel.layers: layer.trainable = False# 编译模型print("[INFO] 正在编译模型...")opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"])# 训练网络头部print("[INFO] 正在训练头部...")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)# 在测试集上进行预测print("[INFO] 正在评估网络...")predIdxs = model.predict(testX, batch_size=BS)# 对于测试集中的每张图像,我们需要找到对应最大预测概率的标签索引predIdxs = np.argmax(predIdxs, axis=1)# 显示格式良好的分类报告print(classification_report(testY.argmax(axis=1), predIdxs, target_names=lb.classes_))# 计算混淆矩阵并使用它来推导原始准确率、灵敏度和特异度cm = confusion_matrix(testY.argmax(axis=1), predIdxs)total = sum(sum(cm))acc = (cm[0, 0] + cm[1, 1]) / totalsensitivity = cm[0, 0] / (cm[0, 0] + cm[0, 1])specificity = cm[1, 1] / (cm[1, 0] + cm[1, 1])# 显示混淆矩阵、准确率、灵敏度和特异度print(cm)print("acc: {:.4f}".format(acc))print("sensitivity: {:.4f}".format(sensitivity))print("specificity: {:.4f}".format(specificity))# 绘制训练损失和准确率N = EPOCHSplt.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("在COVID-19数据集上的训练损失和准确率")plt.xlabel("轮数")plt.ylabel("损失/准确率")plt.legend(loc="lower left")plt.savefig("plot.png")# 将模型序列化到磁盘print("[INFO] 正在保存COVID-19检测器模型...")model.save('/content/drive/My Drive/setcovid/model.h5', )
回答:
你需要做一些更改才能使其工作。你得到的错误是因为独热编码。你对标签进行了两次独热编码。
lb = LabelBinarizer()labels = lb.fit_transform(labels)labels = to_categorical(labels)
请从你的代码中删除最后一行的’to_categorical’。你将获得正确的独热编码格式。这将修复你现在得到的错误。
还有另一个问题我必须提到。你的模型输出层只有2个神经元,但你想对3个类别进行分类。请将输出层的神经元设置为3个。
headModel = Dense(3, activation="softmax")(headModel)
现在你用3个类别进行训练,这不再是二分类。你必须使用另一个损失函数。我建议你使用分类交叉熵损失函数。
model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])
你还忘记导入以下内容。请添加这些导入。
from tensorflow.keras.preprocessing.image import ImageDataGeneratorfrom tensorflow.keras.applications.vgg16 import VGG16from tensorflow.keras.layers import *
然后你就可以开始了。
顺便说一句,我对你使用的批量大小(66)感到非常担心。我不知道你使用的是哪种GPU,但我建议你减小批量大小。