为scikit-learn准备scipy.io.loadarff的结果
我正在尝试使用 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
现在返回的是一个包含 ndarray
和 MetaData
的元组。
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'>
这种类型没有文档说明,并且在使用 asarray
和 astype
时表现得相当奇怪,不过把它转换成列表的列表再转回数组就能解决问题:
>>> 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)