我正在尝试使用UCI机器学习库中的CRX数据集。这个特定的数据集包含一些非连续变量的特征。因此,我需要在将它们传递给SVM之前将它们转换为数值。
我最初考虑使用独热编码器,它可以将整数值转换为矩阵(例如,如果一个特征有三种可能的值,’red’ ‘blue’ 和 ‘green’,这将被转换为三个二进制特征:’red’ 为 1,0,0,’blue’ 为 0,1,0,’green’ 为 0,0,1)。这对于我的需求来说是理想的,除了它只能处理整数特征这一事实之外。
def get_crx_data(debug=False): with open("/Volumes/LocalDataHD/jt306/crx.data", "rU") as infile: features_array = [] reader = csv.reader(infile,dialect=csv.excel_tab) for row in reader: features_array.append(str(row).translate(None,"[]'").split(",")) features_array = np.array(features_array) print features_array.shape print features_array[0] labels_array = features_array[:,15] features_array = features_array[:,:15] print features_array.shape print labels_array.shape print("FeatureHasher on frequency dicts") hasher = FeatureHasher(n_features=44) X = hasher.fit_transform(line for line in features_array) print X.shapeget_crx_data()
这返回了
Reading CRX data from diskTraceback (most recent call last): File"/Volumes/LocalDataHD/PycharmProjects/FeatureSelectionPython278/Crx2.py", line 38, in <module>get_crx_data() File "/Volumes/LocalDataHD/PycharmProjects/FeatureSelectionPython278/Crx2.py", line 32, in get_crx_dataX = hasher.fit_transform(line for line in features_array)File "/Volumes/LocalDataHD/anaconda/lib/python2.7/site-packages/sklearn/base.py", line 426, in fit_transform return self.fit(X, **fit_params).transform(X)File "/Volumes/LocalDataHD/anaconda/lib/python2.7/site-packages/sklearn/feature_extraction/hashing.py", line 129, in transform _hashing.transform(raw_X, self.n_features, self.dtype)File "_hashing.pyx", line 44, in sklearn.feature_extraction._hashing.transform (sklearn/feature_extraction/_hashing.c:1649)File "/Volumes/LocalDataHD/anaconda/lib/python2.7/site-packages/sklearn/feature_extraction/hashing.py", line 125, in <genexpr> raw_X = (_iteritems(d) for d in raw_X)File "/Volumes/LocalDataHD/anaconda/lib/python2.7/site-packages/sklearn/feature_extraction/hashing.py", line 15, in _iteritems return d.iteritems() if hasattr(d, "iteritems") else d.items()AttributeError: 'numpy.ndarray' object has no attribute 'items'(690, 16)['0' ' 30.83' ' 0' ' u' ' g' ' w' ' v' ' 1.25' ' 1' ' 1' ' 1' ' 0' ' g' ' 202' ' 0' ' +'](690, 15)(690,)FeatureHasher on frequency dictsProcess finished with exit code 1如何使用特征哈希(或其他方法)将这些数据从类别(其中一些是字符串,其他的是离散数值)转换为SVM可以处理的数据?我也考虑过使用独热编码,但它只能接受整数作为输入。
回答:
问题在于FeatureHasher
对象期望每行输入具有特定的结构——或者更准确地说,是三种不同的可能的结构之一。第一种可能性是feature_name:value
对的字典。第二种是(feature_name, value)
元组的列表。第三种是feature_name
的平面列表。在前两种情况下,特征名称被映射到矩阵中的列,并在每行中存储给定的值。在最后一种情况下,列表中特征的存在或不存在被隐式理解为True
或False
值。以下是一些简单具体的例子:
>>> hasher = sklearn.feature_extraction.FeatureHasher(n_features=10,... non_negative=True,... input_type='dict')>>> X_new = hasher.fit_transform([{'a':1, 'b':2}, {'a':0, 'c':5}])>>> X_new.toarray()array([[ 1., 2., 0., 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0., 5., 0., 0.]])
这展示了默认模式——如果您没有传递input_type
,如您原始代码中那样,FeatureHasher
将期望的输入是每个输入样本或数据行的字典列表。每个字典包含任意数量的特征名称,映射到该行的值。
输出X_new
包含数组的稀疏表示;调用toarray()
返回一个新的普通numpy
数组副本。
如果您想传递元组对,请传递input_type='pairs'
。然后您可以这样做:
>>> hasher = sklearn.feature_extraction.FeatureHasher(n_features=10,... non_negative=True,... input_type='pair')>>> X_new = hasher.fit_transform([[('a', 1), ('b', 2)], [('a', 0), ('c', 5)]])>>> X_new.toarray()array([[ 1., 2., 0., 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0., 5., 0., 0.]])
最后,如果您只有布尔值,您根本不需要显式传递值——FeatureHasher
将简单地假设如果特征名称存在,则其值为True
(这里表示为浮点值1.0
)。
>>> hasher = sklearn.feature_extraction.FeatureHasher(n_features=10,... non_negative=True,... input_type='string')>>> X_new = hasher.fit_transform([['a', 'b'], ['a', 'c']])>>> X_new.toarray()array([[ 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [ 1., 0., 0., 0., 0., 0., 0., 1., 0., 0.]])
不幸的是,您的数据似乎并不一致地符合这些格式中的任何一种。然而,将您现有的数据修改为适应'dict'
或'pair'
格式应该不会太难。如果您需要帮助,请告诉我;在这种情况下,请详细说明您尝试转换的数据格式。