我是机器学习的新手。我正在准备使用Scikit Learn SVM进行分类的数据。为了选择最好的功能,我使用了以下方法:
SelectKBest(chi2, k=10).fit_transform(A1, A2)
由于我的数据集由负值组成,我得到以下错误:
ValueError Traceback (most recent call last)
/media/5804B87404B856AA/TFM_UC3M/test2_v.py in <module>()
----> 1
2
3
4
5
/usr/local/lib/python2.6/dist-packages/sklearn/base.pyc in fit_transform(self, X, y, **fit_params)
427 else:
428 # fit method of arity 2 (supervised transformation)
--> 429 return self.fit(X, y, **fit_params).transform(X)
430
431
/usr/local/lib/python2.6/dist-packages/sklearn/feature_selection/univariate_selection.pyc in fit(self, X, y)
300 self._check_params(X, y)
301
--> 302 self.scores_, self.pvalues_ = self.score_func(X, y)
303 self.scores_ = np.asarray(self.scores_)
304 self.pvalues_ = np.asarray(self.pvalues_)
/usr/local/lib/python2.6/dist- packages/sklearn/feature_selection/univariate_selection.pyc in chi2(X, y)
190 X = atleast2d_or_csr(X)
191 if np.any((X.data if issparse(X) else X) < 0):
--> 192 raise ValueError("Input X must be non-negative.")
193
194 Y = LabelBinarizer().fit_transform(y)
ValueError: Input X must be non-negative.
有人能告诉我如何转换数据吗?
错误消息Input X must be non-negative
说明了一切:Pearson卡方检验(拟合优度)不适用于负值。这是合乎逻辑的,因为卡方检验假设频率分布,频率不可能是负数。因此,sklearn.feature_selection.chi2
断言输入是非负的。
你说你的特征是"加速度计信号的最小值、最大值、平均值、中值和FFT"。在许多情况下,简单地移动每个特征以使其全部为正,或者甚至如EdChum所建议的标准化为[0, 1]
区间,可能是非常安全的。
如果由于某些原因无法进行数据转换(例如负值是一个重要因素),您应该选择另一个统计数据来对您的功能进行评分:
sklearn.feature_selection.f_classif
计算方差分析f值sklearn.feature_selection.mutual_info_classif
计算互信息
由于这个过程的全部目的是为另一种方法准备功能,所以挑选任何人都没什么大不了的,最终结果通常相同或非常接近。
正如其他人提到的那样,为了避免错误,您可以将数据缩放到0到1之间,从缩放的数据中选择特征,并使用它来训练模型。
import numpy as np
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.preprocessing import MinMaxScaler
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
X, y = make_classification(random_state=0)
topk = 5
# scale the data to be between 0 and 1
sc = MinMaxScaler()
X_sc = sc.fit_transform(X)
# select from the scaled data
skb = SelectKBest(chi2, k=topk)
X_sc_selected = skb.fit_transform(X_sc, y)
# build model using (X_sc_selected, y)
lr = LogisticRegression(random_state=0)
lr.fit(X_sc_selected, y)
lr.score(X_sc_selected, y) # 0.87
如果原始数据非常重要(您希望保留负值),您也可以使用SelectKBest
中的前k个分数来选择数据,即不使用transform
对数据进行切片。
# fit feature selector with the scaled data
skb = SelectKBest(chi2, k=topk)
skb.fit(X_sc, y)
# column index of top-k features
cols = np.sort(skb.scores_.argsort()[-topk:])
# index the top-k features from X
X_selected = X[:, cols]
# build model using (X_selected, y)
lr = LogisticRegression(random_state=0)
lr.fit(X_selected, y)
lr.score(X_selected, y) # 0.92
请注意,skb.transform()
实际上也类似于对列进行索引。例如,(X_sc[:, cols] == X_sc_selected).all()
返回True。