【问题标题】:Image classifier “ValueError: Found array with dim 3. Estimator expected <= 2.”图像分类器“ValueError:找到暗淡为 3 的数组。预计估计器 <= 2。”
【发布时间】:2020-04-14 20:47:09
【问题描述】:

当我尝试使用 3 个数据集文件夹运行此代码时,我遇到了这个问题。以前,此代码在数据集文件夹内只有 2 个文件夹即可完美运行,一个名为 normal,另一个名为 covid。但在这种情况下,我添加了另一个名为 pneumonia 的分类器,使其成为 3 类图像分类器。我是机器学习的新手,所以我对如何解决这个问题进行了很多研究,但每个解决方案都不同,代码也不同。我尝试了它们,但它们不起作用,这就是我寻求您帮助的原因。

此代码不属于我,它是 Adrian Rosebrock 代码,所有功劳归于他。它是关于在 COVID 或正常情况下对 X 射线图像进行分类,但改进此代码的想法添加了一个新类别来对具有正常(非 COVID)肺炎的图像进行分类。这就是我在数据集中添加一个新文件夹的原因。希望您能帮帮我,谢谢!

# USAGE
python train.py --dataset dataset
# import the necessary packages

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 numpy as np
import argparse
import cv2
import os

# construct the argument parser and parse the arguments

ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
    help="path to input dataset")
ap.add_argument("-p", "--plot", type=str, default="plot.png",
    help="path to output loss/accuracy plot")
ap.add_argument("-m", "--model", type=str, default="covid19.model",
    help="path to output loss/accuracy plot")
args = vars(ap.parse_args())

# initialize the initial learning rate, number of epochs to train for,
# and batch size

INIT_LR = 1e-3
EPOCHS = 1
BS = 8

# 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(args["dataset"]))
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)

这是错误信息:

[INFO] loading images...
Traceback (most recent call last):
  File "train_covid19.py", line 77, in <module>
    test_size=0.20, stratify=labels, random_state=42)
  File "C:\Users\KQ\anaconda3\lib\site-packages\sklearn\model_selection\_split.py", line 2143, in train_test_split
    train, test = next(cv.split(X=arrays[0], y=stratify))
  File "C:\Users\KQ\anaconda3\lib\site-packages\sklearn\model_selection\_split.py", line 1737, in split
    y = check_array(y, ensure_2d=False, dtype=None)
  File "C:\Users\KQ\anaconda3\lib\site-packages\sklearn\utils\validation.py", line 574, in check_array
    % (array.ndim, estimator_name))
ValueError: Found array with dim 3. Estimator expected <= 2.

【问题讨论】:

  • 在错误之后出现的代码与问题无关(从未执行)并且应该包含在此处,因为它只会造成不必要的混乱。此处发布的代码应该最少且仅与错误相关 - 请查看原因a wall of code isn't helpful

标签: machine-learning keras neural-network conv-neural-network


【解决方案1】:

我认为您不需要LabelBinarizerto_categorical。他们做同样的事情,所以你只需要一个或另一个。尝试删除对to_categorical 的调用。

lb = LabelBinarizer()
labels = lb.fit_transform(labels)
labels = to_categorical(labels)  # Remove this line.

您还需要更新模型中的类别数量。

# Change the size from 2 to 3.
headModel = Dense(3, activation="softmax")(headModel)

为避免每次添加或删除类别时都需要更改此设置,您可以计算唯一标签。

n_labels = len(set(labels))
headModel = Dense(n_labels, activation="softmax")(headModel)

更新

另请注意,to_categorical 仅适用于整数标签。这使它更像OneHotEncoder 而不是LabelBinarizer

这就是所谓的一切。

labels = [0, 1, 0, 2]                                                                                                                                                                                                               

lb = LabelBinarizer() 
binarized = lb.fit_transform(labels)                                                                                                                                                                                                
binarized                                                                                                                                                                                                                           
# array([[1, 0, 0],
#        [0, 1, 0],
#        [1, 0, 0],
#        [0, 0, 1]])

to_categorical(labels)                                                                                                                                                                                                              
# array([[1., 0., 0.],
#        [0., 1., 0.],
#        [1., 0., 0.],
#        [0., 0., 1.]], dtype=float32)

to_categorical(binarized)                                                                                                                                                                                                           
# array([[[0., 1.],
#         [1., 0.],
#         [1., 0.]],
# 
#        [[1., 0.],
#         [0., 1.],
#         [1., 0.]],
# 
#        [[0., 1.],
#         [1., 0.],
#         [1., 0.]],
# 
#        [[1., 0.],
#         [1., 0.],
#         [0., 1.]]], dtype=float32)

请注意标签的 3 维输出,因为它尝试对已单热编码数据的 3 个部分中的每一个进行单热编码,添加了一个 train_test_split 不知道如何处理的额外维度。

这就是你得到ValueError: Found array with dim 3.的原因

【讨论】:

  • 非常感谢,它运行良好,我可以运行代码,我按照您的说明更改了设置,但是避免更改类别的 n_labels 不起作用。我手动输入了 3,但后来我遇到了 UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predict ed samples. Use zero_division 参数来控制这种行为的问题。在我的前两个类别中获得 0 的预测值,我读它是因为 y_test 和 x_test 是空的其他类别,但文件夹有图像,你知道吗?
  • 这是我的错误。您需要在编码之前计算n_labels,或更改为n_labels = labels.shape[1]。至于新警告,这是因为,正如您所说,您的某些标签在测试集中没有任何示例。每个班级没有足够的样本来进行训练测试拆分。也许您的新 pneumonia 数据集只有 1 个或很少的示例?添加更多应该可以解决问题。
  • 我试过了,一开始covid和normal文件夹里面有25张图片,pneumonia文件夹里面有68张图片,EPOCHS=1,这些是变量,然后我尝试减少图片数量肺炎文件夹到 28 张图像并获得 covid 类别的 acc 编号(现在 2 个类别具有 acc 值)。我再次尝试将 EPOCHS 的数量增加到 10,最后获得 3 个类别的 acc 值,一个具有 1.00 的精度,第二个具有 0.2,最后一个是 0.5。我想这是一个时代和图像数量的问题,是真的吗?再次感谢您的帮助
  • 我相信如果您的模型无法预测某个标签,也可能会发生这种情况。这就是为什么改变模型训练细节很重要,因为它也会改变预测,从而改变这种情况是否发生。
猜你喜欢
  • 2016-11-28
  • 2019-06-01
  • 2020-07-10
  • 2021-04-16
  • 2019-07-19
  • 2018-12-15
  • 2018-01-16
  • 1970-01-01
  • 2020-10-08
相关资源
最近更新 更多