【问题标题】:Remove a specific feature in scikit learn删除 scikit learn 中的特定功能
【发布时间】:2018-10-04 21:31:57
【问题描述】:

有没有办法从scikit.learn 数据集中删除特定特征?例如,我知道可以使用sklearn.feature_selection 删除功能,但这些都是自动删除功能的过程,他们 认为这些功能是无用的。有什么方法可以在不进入数据内部的情况下实现自定义特征删除算法?例如,假设我有一个对特征进行评分的函数,这里提供了一个玩具示例:

def score(feature_index):
    return 0 if feature_index == 1 else 1

现在假设我想删除 iris 数据集中得分低于0.5 的所有特征。我想做这样的事情:

from sklearn import datasets
iris = datasets.load_iris()
#this is the function I want:
iris.filter_features(score, threshold=0.5)

之后,我希望 iris 数据集少一个特征。现在,我可以这样做:

from sklearn import datasets
iris = datasets.load_iris()
for feature_index in range(len(iris.feature_names)):
    if score(feature_index) < 0.5:
        iris.feature_names.pop(feature_index)
        iris.data = np.delete(iris.data, feature_index, 1)

但这看起来……很脏。

【问题讨论】:

  • 查看相关:stackoverflow.com/questions/23405739/… 这使用 pandas 来存储数据但原理是一样的,您只需定义一些列表作为您的特征选择或排除,然后再次训练,没有错您目前的方法 IMO。在 pandas 中,很容易进行列选择/排除
  • @EdChum 我认为我的方法没有问题,只要小心操作,但如果有人忘记删除相应的功能名称以及data 数组的列。

标签: python scikit-learn


【解决方案1】:

没有像 scikit-learn 数据集这样的想法。 scikit-learn 使用的常见数据结构只是 numpy 数组(或 scipy 稀疏矩阵):

>>> from sklearn.datasets import load_iris
>>> iris = load_iris
>>> type(iris.data)
<class 'numpy.ndarray'>

您可以使用常规的 numpy 数组索引来生成新版本的数据。例如用布尔掩码删除第二个特征:

>>> import numpy as np
>>> X = iris.data
>>> mask = np.array([True, False, True, True])
>>> X_masked = X[:, mask]

注意,第一个位置的: 符号表示“所有行”。

要检查,您可以打印每个数组的前 5 行:

>>> print(X[:5])
[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 [ 4.6  3.1  1.5  0.2]
 [ 5.   3.6  1.4  0.2]]
>>> print(X_masked[:5])
[[ 5.1  1.4  0.2]
 [ 4.9  1.4  0.2]
 [ 4.7  1.3  0.2]
 [ 4.6  1.5  0.2]
 [ 5.   1.4  0.2]]

您还可以使用基于整数的精美索引来获得相同的结果:

>>> index = np.array([0, 2, 3])
>>> X_indexed = X[:, index]
>>> print(X_indexed[:5])
[[ 5.1  1.4  0.2]
 [ 4.9  1.4  0.2]
 [ 4.7  1.3  0.2]
 [ 4.6  1.5  0.2]
 [ 5.   1.4  0.2]]

要了解有关基本 numpy 操作的更多信息,请查看以下教程:

http://scipy-lectures.github.io/

【讨论】:

  • 感谢您的回答,我对 scipy 和 numpy 都很熟悉,因此找到解决方案(使用numpy.delete,相当于您的解决方案)并不难。我只是希望找到一个很好的工具,用它来自动化(对我而言)有问题的部分(确保删除功能名称以及功能)。
  • 您必须自己更新feature_names 数组的副本。为避免引入错误,请不要修改原始数组,而是显式处理副本。
【解决方案2】:

虽然 sklearn 中没有内置类来执行此操作,但您可以使用标准的 fit 和 transform 方法轻松创建一个:

from sklearn.base import TransformerMixin

class ManualFeatureSelector(TransformerMixin):
    """
    Transformer for manual selection of features using sklearn style 
    transform 
    method.  
    """

    def __init__(self, features):
        self.features = features
        pass

    def fit(self, X, y=None):
        return self

    def transform(self, X):
        return X[:,self.features]

通常最好在 sklearn 框架之外进行这样的手动特征选择,但我遇到过将手动特征选择作为流水线一部分的情况很有帮助。

例如,如果一个对象将一个数组同时传递给分类器和其他对象(如显示函数),您可能只想将某些字段传递给分类器。这很容易通过将分类器更改为包含上述转换和原始分类器的管道来完成。

希望有帮助!

【讨论】:

    猜你喜欢
    • 2019-06-29
    • 2015-08-13
    • 2014-08-09
    • 2014-05-01
    • 2018-09-22
    • 2018-02-22
    • 2018-10-27
    • 2014-04-16
    • 1970-01-01
    相关资源
    最近更新 更多