python - sklearn 管道中用于分类的图像数组 - ValueError : setting an array element with a sequence

标签 python pandas numpy scikit-learn

我想将图像分类为 A 或 B。为此,我加载它们并将其大小调整为 160x160,然后将 2D 数组转换为 1D 并将它们添加到 pandas 数据帧中:

from pandas import DataFrame
from scipy.misc import imread, imresize
rows = []
for product in products:
    try:
        relevant = product.categoryrelevant.all()[0].relevant
    except IndexError:
        relevant = False
    if relevant:
        relevant = "A"
    else:
        relevant = "B"
    # this exists for all pictures
    image_array = imread("{}/{}".format(MEDIA_ROOT, product.picture_file.url))
    image_array = imresize(image_array, (160, 160))
    image_array = image_array.reshape(-1)
    print(image_array)
    # [254 254 252 ..., 255 255 253]
    print(image_array.shape)
    # (76800,)
    rows.append({"id": product.pk, "image": image_array, "class": relevant})
    index.append(product)
df = DataFrame(rows, index=index)

我想要的不仅仅是稍后用于分类的图像(例如,产品描述),因此我使用带有FeatureUnion的管道(即使它现在只有图像)。 ItemSelector 取自此处:

http://scikit-learn.org/stable/auto_examples/hetero_feature_union.html

它采用“图像”列中的值。或者,可以执行 train_X = df.iloc[train_indices]["image"].values,但我想稍后添加其他列。

def randomforest_image_pipeline():
    """Returns a RandomForest pipeline."""
    return Pipeline([
        ("union", FeatureUnion(
            transformer_list=[
                ("image", Pipeline([
                    ("selector", ItemSelector(key="image")),
                ]))
            ],
            transformer_weights={
                "image": 1.0
            },
        )),
        ("classifier", RandomForestClassifier()),
    ])

然后用KFold分类:

from sklearn.model_selection import KFold
kfold(tested_pipeline=randomforest_image_pipeline(), df=df)
def kfold(tested_pipeline=None, df=None, splits=6):
    k_fold = KFold(n_splits=splits)
    for train_indices, test_indices in k_fold.split(df):
        # training set
        train_X = df.iloc[train_indices]
        train_y = df.iloc[train_indices]['class'].values
        # test set
        test_X = df.iloc[test_indices]
        test_y = df.iloc[test_indices]['class'].values
        for val in train_X["image"]:
            print(len(val), val.dtype, val.shape)
            # 76800 uint8 (76800,) for all
        tested_pipeline.fit(train_X, train_y) # crashes in this call
        pipeline_predictions = tested_pipeline.predict(test_X)
        ...

但是对于 .fit 我收到以下错误:

Traceback (most recent call last):
  File "<path>/project/classifier/classify.py", line 362, in <module>
    best = best_pipeline(dataframe=data, f1_scores=f1_dict, get_fp=True)
  File "<path>/project/classifier/classify.py", line 351, in best_pipeline
    confusion_list=confusion_list, get_fp=get_fp)
  File "<path>/project/classifier/classify.py", line 65, in kfold
    tested_pipeline.fit(train_X, train_y)
  File "/usr/local/lib/python3.5/dist-packages/sklearn/pipeline.py", line 270, in fit
    self._final_estimator.fit(Xt, y, **fit_params)
  File "/usr/local/lib/python3.5/dist-packages/sklearn/ensemble/forest.py", line 247, in fit
    X = check_array(X, accept_sparse="csc", dtype=DTYPE)
  File "/usr/local/lib/python3.5/dist-packages/sklearn/utils/validation.py", line 382, in check_array
    array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: setting an array element with a sequence.

我发现其他人也有同样的问题,对他们来说问题是他们的行长度不一样。对我来说情况似乎并非如此,因为所有行都是一维的,长度为 76800:

    for val in train_X["image"]:
        print(len(val), val.dtype, val.shape)
        # 76800 uint8 (76800,) for all
崩溃的行中的

array 看起来像这样(从调试器复制):

[array([ 255.,  255.,  255., ...,  255.,  255.,  255.])
 array([ 255.,  255.,  255., ...,  255.,  255.,  255.])
 array([ 255.,  255.,  255., ...,  255.,  255.,  255.]) ...,
 array([ 255.,  255.,  255., ...,  255.,  255.,  255.])
 array([ 255.,  255.,  255.

我可以做什么来解决这个问题?

最佳答案

该错误是因为您将图像的所有数据(即 76800 个要素)保存在列表中,并且该列表被保存到数据帧的单个列中。

因此,当您使用 ItemSelector 选择该列时,其输出将是形状为 (Train_len, ) 的一维数组。 76800 的内部尺寸对于FeatureUnion 或后续估计器不可见。

更改 ItemSelector 的 transform() 函数以返回形状为 (Train_len, 76800) 的正确二维数据数组。只有这样它才会起作用。

更改为:

def transform(self, data_dict):
    return np.array([np.array(x) for x in data_dict[self.key]])

如有不懂的地方,请随时提问。

关于python - sklearn 管道中用于分类的图像数组 - ValueError : setting an array element with a sequence,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45858798/

相关文章:

python - 将Python REST API身份验证脚本转换为curl命令

python - 使用 python 登录 SAML/Shibboleth 认证服务器

python - 将 .DAT 文件导入 Pandas 数据框

python - 在 Python 中使用正则表达式删除数据框的部分列名

python - NumPy:有没有办法在 ndarray 上执行 'shifting' ?

Python numpy/f2py 链接库

Python:解码由unicode代码点和unicode文本组成的字符串

python - 多个文件中的 PyQt 小部件

python - 如何在python中获得证据权重(WOE)和信息值(value)(IV)?

numpy - 如何规范化 3D 数组的特定维度