## 删除低方差的特征

`sklearn` 提供 `VarianceThreshold` 去除低方差特征。同时， `threshold` 允许我们控制方差阈值。

```import sklearn.feature_selection as fs
# X is you feature matrix
var = fs.VarianceThreshold(threshold=0.2)
var.fit(X)
X_trans = var.transform(X)```

```import sklearn.feature_selection as fs
import numpy as np
X = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1,
1]])
var = fs.VarianceThreshold(threshold=0.2)
var.fit(X)
X_trans = var.transform(X)
print("The original data")
print(X)
print("The processed data by variance threshold")
print(X_trans)```

`line 3` 创建一个大小为六行三列的矩阵。
`line 6` 使用 `VarianceThreshold` 参数创建一个方差阈值对象 `threshold=0.2` ，这意味着方差小于 0.2 的列将被删除。

## 选择 K-best 特征

`sklearn` 提供了一个通用功能 `SelectKBest` ，可以 `k` 根据某些指标选择最佳特征，只需要提供一个评分函数来定义指标即可。幸运的是， `sklearn` 提供了一些预定义的评分函数。以下是一些预定义的可调用评分函数。

```f_classif
mutual_info_classif
chi2
f_regression
mutual_info_regression
SelectFpr```

#### 这里的核心思想是计算目标和每个特征之间的一些度量，对它们进行排序，然后选择K最好的特征。

```import sklearn.datasets as datasets
X, y = datasets.make_classification(n_samples=300, n_features=10, n_informative=4)
# choose the f_classif as the metric and K is 3
bk = fs.SelectKBest(fs.f_classif, 3)
bk.fit(X, y)
X_trans = bk.transform(X)```

```import sklearn.feature_selection as fs
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
import sklearn.metrics as metrics
import matplotlib.pyplot as plt
X, y = datasets.make_classification(n_samples=500,
n_features=20,
n_informative=8,
random_state=42)
f1_list = []
for k in range(1, 15):
bk = fs.SelectKBest(fs.f_classif, k)
bk.fit(X, y)
X_trans = bk.transform(X)
train_x, test_x, train_y, test_y = train_test_split(X_trans,
y,
test_size=0.2,
random_state=42)
lr = LogisticRegression()
lr.fit(train_x, train_y)
y_pred = lr.predict(test_x)
f1 = metrics.f1_score(test_y, y_pred)
f1_list.append(f1)
fig, axe = plt.subplots(dpi = 300)
axe.plot(range(1, 15), f1_list)
axe.set_xlabel("best k features")
axe.set_ylabel("F1-score")
fig.savefig("output/img.png")
plt.close(fig)```

`line 14``line 26` 是一个循环 `for k in range(1, 15)` 。在此循环的每次迭代中， `K` 都会将不同的值传递给 `SelectKBest` . 我们想看看不同的值如何 `K` 影响模型的性能。使用所选特征在循环的每次迭代（从 `line 22``line 25` ）中构建、拟合和评估逻辑回归模型。 `K` 该指标存储在一个列表中， `f1_list` 。在这个演示中，使用 `f1-score` 作为指标。
`line 28``line 33` ，绘制那些 `K` 和它们对应的 f1 分数。

## 按其他模型选择特征

`SelectFromModel` 是一个元转换器，可以与任何在拟合后具有 `coef_``feature_importances_` 属性的估计器一起使用。但是，这里只想关注基于树的模型。 可能还记得，树是由单个特征上的某个度量分割的。根据这个指标，就可能知道不同特征的重要性 。这是树模型的一个属性；所以通过树模型，能够知道不同特征对模型的不同贡献。

`sklearn` 提供 `SelectFromModel` 进行特征选择。从下面的代码中，可能会注意到第一个参数 `gb` 。它是一个 `GBDT` 模型，用于通过使用来选择特征 `feature_importances_` 。树模型非常适合特征选择。

```import sklearn.feature_selection as fs
model = fs.SelectFromModel(gb, prefit=True)
# X is your feature matrix, X_trans is the new feature matrix.
X_trans = model.transform(X)```

```import sklearn.feature_selection as fs
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
import sklearn.metrics as metrics
X, y = datasets.make_classification(n_samples=500,
n_features=20,
n_informative=6,
random_state=21)
gb.fit(X, y)
print("The feature importances of GBDT")
print(gb.feature_importances_)
model = fs.SelectFromModel(gb, prefit=True)
X_trans = model.transform(X)
print("The shape of original data is {}".format(X.shape))
print("The shape of transformed data is {}".format(X_trans.shape))```

```The feature importances of GBDT
[0.00000000e+00 4.35611629e-03 0.00000000e+00 2.37301143e-02
0.00000000e+00 1.35731571e-01 1.93024194e-01 0.00000000e+00
0.00000000e+00 4.83477430e-02 3.84429422e-02 6.80747372e-02
2.11790637e-02 0.00000000e+00 1.60274532e-02 2.79721758e-04
4.50188188e-01 0.00000000e+00 0.00000000e+00 6.18155685e-04]
The shape of original data is (500, 20)
The shape of transformed data is (500, 4)```

`line 15` 输出显示了不同特征的重要性；数字越大，重要性越高。
`line 17` 显示如何使用另一个模型来选择一个特征 `SelectFromModel` 。所要做的就是传递 `GBDT` 对象。这 `prefit=True` 意味着该模型已经拟合完毕。

hands on machine learning with scikit learn
https://scikit-learn.org/stable/modules/classes.html#module-sklearn.feature_selection