为scikit-learn准备scipy.io.loadarff的结果

3 投票
2 回答
5160 浏览
提问于 2025-04-18 01:25

我正在尝试使用 scikit-learn 处理 .arff 文件。看看下面的代码:

from sklearn.ensemble import RandomForestClassifier
from scipy.io.arff import loadarff

import scipy as sp
import numpy as np

dataset = loadarff(open('iris.arff','r'))
target = np.array(dataset[0]['class'])
train = np.array(dataset[0][['sepallength', 'sepalwidth', 'petallength', 'petalwidth']])
rf = RandomForestClassifier(n_estimators = 20, n_jobs = 8)
rf.fit(train, target)

运行后出现了以下错误:

ValueError: need more than 1 value to unpack

我猜这个问题可能是因为 train 是一个元组的数组,而不是列表(或者说数组?);查看 sklearn.datasets.load_iris() 的结果,发现它是一个列表(数组?)的数组,这个格式可以成功地与 RandomForestClassifier 一起使用。

2 个回答

3

自从四月份以来,似乎发生了一些变化,loadarff 现在返回的是一个包含 ndarrayMetaData 的元组。

with open('training_set.arff','r') as f:
    data, meta = loadarff(f)

print(type(data)) # <class 'numpy.ndarray'> 
print(type(meta)) # <class 'scipy.io.arff.arffread.MetaData'>

更具体来说,data 似乎是一个记录数组。要把它转换成普通的 numpy 数组,可以使用下面的代码片段。

train_data = data[meta.names()[:-1]] #everything but the last column
train_data = train_data.view(np.float).reshape(data.shape + (-1,)) #converts the record array to a normal numpy array
6

关于 RandomForestClassifier 的文档会告诉你,fit 方法需要一个形状为 (n_samples, n_features) 的二维数组作为 X 参数,但你现在手上的是一个一维数组:

>>> target.shape
(150,)
>>> train.shape
(150,)

让人惊讶的是,这个数组里的内容不是元组,而是一种我之前从未见过的类型:

>>> train[0]
(5.1, 3.5, 1.4, 0.2)
>>> type(train[0])
<type 'numpy.void'>

这种类型没有文档说明,并且在使用 asarrayastype 时表现得相当奇怪,不过把它转换成列表的列表再转回数组就能解决问题:

>>> X = np.asarray(train.tolist(), dtype=np.float32)
>>> X.shape
(150, 4)
>>> rf.fit(X, target)
RandomForestClassifier(bootstrap=True, compute_importances=None,
            criterion='gini', max_depth=None, max_features='auto',
            max_leaf_nodes=None, min_density=None, min_samples_leaf=1,
            min_samples_split=2, n_estimators=20, n_jobs=8,
            oob_score=False, random_state=None, verbose=0)

撰写回答