特征选择和特征降维

1 目录结构


特征选择

特征降维

sklearn中的特征选择和降维方法的使用

针对于titanic数据集做特征选择与降维



2. 特征选择 https://scikit-learn.org/stable/modules/feature_selection.html#feature-selection

何时开始做特征选择呢?

当数据预处理完成后,我们需要选择有意义的特征输入机器学习的算法和模型进行训练。通常来说,从两个方面考虑来选择特征:

特征是否发散:如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用。

特征与目标的相关性:这点比较显见,与目标相关性高的特征,应当优选选择。除方差法外,接下来我要介绍的都是从相关性来考虑的。

分为三种:

1、过滤法: 不用考虑后续学习器,按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。

2、包装法:需考虑后续学习器,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。

3、嵌入法:是过滤法与包装法方法的结合。先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。

过滤法(filter)

方差选择法

使用方差选择法,先要计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征。使用feature_selection库的VarianceThreshold类来选择特征的代码如下:

from sklearn.datasets import load_iris
iris = load_iris()##数据
from sklearn.feature_selection import VarianceThreshold#导入方差阈值
#方差选择法,返回值为特征选择后的数据
#参数threshold为方差的阈值
x1 = VarianceThreshold(threshold=3).fit_transform(iris.data)
x1.shape

单变量做特征

单变量特征选择能够对每一个特征进行测试,衡量该特征和目标变量之间的关系,根据得分扔掉不好的特征。对于回归和分类问题可以采用卡方检验等方式对特征进行测试。

方法简单,易于运行,易于理解,通常对于理解数据有较好的效果(但对特征优化、提高泛化能力来说不一定有效);这种方法有许多改进的版本、变种。

1708277760920.png

卡方检验适用于分类问题
检验特征对标签的相关性,选择其中K个与标签最相关的特征。使用feature_selection库SelectKBest类结合卡方检验来选择特征的代码如下:(这个就是自变量与因变量的相关性的取值,注意k的取值)

from sklearn.feature_selection import SelectKBest##选择最好的几个特征
from sklearn.feature_selection import chi2#卡方检验

#选择K个最好的特征,返回选择特征后的数据
x2 = SelectKBest(chi2, k=1).fit_transform(iris.data,iris.target)

除此之外针对于过滤法还有皮尔狲系数、距离相关系数

包装法(wrapper)

包装法主要思想是:根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征

递归特征消除法

递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练。使用feature_selection库的RFE类来选择特征的代码如下:

from sklearn.feature_selection import RFE#递归特征消除法
from sklearn.linear_model import LogisticRegression

#递归特征消除法,返回特征选择后的数据
#参数estimator为基模型
#参数n_features_to_select为选择的特征个数
x3 = RFE(estimator=LogisticRegression(), n_features_to_select=3).fit_transform(iris.data,iris.target)

Embedded

嵌入法主要思想是:使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。其实是讲在确定模型的过程中,挑选出那些对模型的训练有重要意义的属性。

基于惩罚项的特征选择法

使用带惩罚项的基模型,除了筛选出特征外,同时也进行了降维。使用feature_selection库的SelectFromModel类结合带L1惩罚项的逻辑回归模型,来选择特征的代码如下:

from sklearn.feature_selection import SelectFromModel##基模型选择器
from sklearn.linear_model import LogisticRegression

#带L1惩罚项的逻辑回归作为基模型的特征选择
x4 = SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data,iris.target)
# x4
from sklearn.svm import LinearSVC
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
X.shape
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X,y)#先训练好,然后再来选特征
model = SelectFromModel(lsvc, prefit=True)
X_new = model.transform(X)
X_new.shape

L1惩罚项降维的原理在于保留多个对目标值具有同等相关性的特征中的一个,所以没选到的特征不代表不重要。故可结合L2惩罚项来优化

基于树模型的特征选择法

树模型中GBDT可用来作为基模型进行特征选择,使用feature_selection库的SelectFromModel类结合GBDT模型,来选择特征的代码如下:

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier#导入GBDT算法

#GBDT作为基模型的特征选择
x5 = SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)
# x5
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
clf = RandomForestClassifier()
clf = clf.fit(X, y)
clf.feature_importances_ # 显示每一个特征的重要性指标,越大说明越重要,可以看出,第三第四两个特
# 征比较重要
# SelectFromModel(RandomForestClassifier()).fit_transform(X,y)###和特征重要性一样的

针对于boston房价画一个基于随机森林算法的特征重要性图

##导入相应的包
from sklearn.ensemble import RandomForestRegressor
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
boston = load_boston()##
##数据的划分
x, y = boston.data, boston.target
feature_name = np.array(["%d %s"%(b,a) for a,b in zip(boston.feature_names,range(len(boston.feature_names)))])
##模型的训练
rf = RandomForestRegressor(n_estimators=100, random_state=101).fit(x,y)
importance = np.mean([tree.feature_importances_ for tree in rf.estimators_], axis=0)
std = np.std([ tree.feature_importances_ for tree in rf.estimators_],axis=0)

indices = np.argsort(importance)#返回由小到大的数据之前的索引
range_ = range(len(importance))
##画图
plt.figure()
plt.title("random forset importance")
plt.barh(range_, importance[indices],color='r',xerr=std[indices],alpha=1,align='center')
plt.yticks(range(len(importance)),feature_name[indices])
plt.ylim([-1,len(importance)])
plt.xlim([0.0,0.65])
plt.show()
image.png

降维 https://scikit-learn.org/stable/modules/decomposition.html#pca

PCA

LDA

当特征选择完成后,可以直接训练模型了,但是可能由于特征矩阵过大,导致计算量大,训练时间长的问题,因此降低特征矩阵维度也是必不可少的。常见的降维方法除了以上提到的基于L1惩罚项的模型以外,另外还有主成分分析法(PCA)和线性判别分析(LDA),线性判别分析本身也是一个分类模型。PCA和LDA有很多的相似点,其本质是要将原始的样本映射到维度更低的样本空间中,但是PCA和LDA的映射目标不一样:PCA是为了让映射后的样本具有最大的发散性;而LDA是为了让映射后的样本有最好的分类性能。所以说PCA是一种无监督的降维方法,而LDA是一种有监督的降维方法。

PCA的理解
设有m条n维数据。

1)将原始数据按列组成n行m列矩阵X

2)将X的每一行(代表一个属性字段)进行零均值化,即减去这一行的均值

3)求出协方差矩阵

4)求出协方差矩阵的特征值及对应的特征向量

5)将特征向量按对应特征值大小从上到下按行排列成矩阵,取前k行组成矩阵P

6)即为降维到k维后的数据</font>

使用decomposition库的PCA类选择特征的代码如下:

from sklearn.decomposition import PCA
#主成分分析法,返回降维后的数据
#参数n_components为主成分数目,你要保留的维度
PCA(n_components=3).fit_transform(iris.data)
from sklearn.decomposition import PCA,KernelPCA
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
iris_data = load_iris()
category = pd.Categorical(iris_data.target) # 将标签进行量化,就是说本来都是字符串啊,但是最后计算的
# 时候都需要量化成1,2,3类等
pca_2c = PCA(n_components=2) # 使用PCA降到2维
#pca_2c = KernelPCA(n_components=2)
x_pca_2c = pca_2c.fit_transform(iris_data.data)
print(x_pca_2c.shape)
plt.scatter(x_pca_2c[:,0],x_pca_2c[:,1],c=category.codes)##x,y,类别不一致的颜色
plt.show()
image.png

线性判别分析(LDA)有监督的降维方法

1708625466045.png
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
#线性判别分析法,返回降维后的数据
#参数n_components为降维后的维数
LDA(n_components=2).fit_transform(iris.data, iris.target)##最大的不同
##LDA相较于pca是有监督的,但不能用于回归分析
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
iris_data = load_iris()
category = pd.Categorical(iris_data.target) # 将标签进行量化,就是说本来都是字符串啊,但是最后计算的
##时候都需要量化成1,2,3类等
lda_2c = LDA(n_components=2)
x_pca_2c = lda_2c.fit_transform(iris_data.data,iris_data.target)
x_pca_2c.shape
plt.scatter(x_pca_2c[:,0],x_pca_2c[:,1],c=category.codes)
plt.show()
image.png

针对于titanic数据集做特征选择与降维

import pandas as pd
import numpy as np

def read_dataset(fname):
#     指定第一列作为行索引
    data = pd.read_csv(fname, index_col=0)
#     丢弃无用数据
    data.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)
#     处理性别数据
    lables = data['Sex'].unique().tolist()#变成列表的意思
    data['Sex'] = [*map(lambda x: lables.index(x) , data['Sex'])]
#     处理登船港口数据## sklearn里面的labelencoder
    lables = data['Embarked'].unique().tolist()
    data['Embarked'] = data['Embarked'].apply(lambda n: lables.index(n))
#     处理缺失数据填充0
    data = data.fillna(0)
    return data
train = read_dataset("data/train.csv")
import warnings
warnings.filterwarnings("ignore")#过滤掉警告的意思

先划分数据集 特征和标签

1708625647002.png
1708625696895.jpg
1708625732470.png
1708625788683.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容