7000字精华总结,PandasSklearn进行机器学习之特征筛选,有效提升模型性能
编辑:广州人工智能解决方案_APP开发公司_小程序开发公司_歌莫信息 来源: 日期:2024-6-26 12:02:36 人气: 标签:

作者 | 俊欣来源 | 关于数据分析与可视化今天小编来说说如何通过pandas以及sklearn这两个模块来对数据集进行特征筛选,毕竟有时候我们拿到手的数据集是非常庞大的,有着非常多的特征,减少这些特征的数量会带来许多的好处,例如

  • 提高预测的精准度
  • 降低过拟合的风险
  • 加快模型的训练速度
  • 增加模型的可解释性
事实上,很多时候也并非是特征数量越多训练出来的模型越好,当添加的特征多到一定程度的时候,模型的性能就会下降,从下图中我们可以看出,

因此我们需要找到哪些特征是最佳的使用特征,当然我们这里分连续型的变量以及离散型的变量来讨论,毕竟不同数据类型的变量处理的方式不同,我们先来看一下对于连续型的变量而言,特征选择到底是怎么来进行的。

计算一下各个变量之间的相关性

我们先导入所需要用到的模块以及导入数据集,并且用pandas模块来读取from?sklearn.datasets?import?load_boston
import?pandas?as?pd
import?numpy?as?np
import?matplotlib
import?matplotlib.pyplot?as?plt
import?seaborn?as?sns
import?statsmodels.api?as?sm
%matplotlib?inline
from?sklearn.model_selection?import?train_test_split
from?sklearn.linear_model?import?LinearRegression
from?sklearn.feature_selection?import?RFE
from?sklearn.linear_model?import?RidgeCV,?LassoCV,?Ridge,?Lasso
这次用到的数据集是机器学习中尤其是初学者经常碰到的,波士顿房价的数据集,其中我们要预测的这个对象是MEDV这一列x?=?load_boston()
df?=?pd.DataFrame(x.data,?columns?=?x.feature_names)
df["MEDV"]?=?x.target
X?=?df.drop("MEDV",1)???#将模型当中要用到的特征变量保留下来
y?=?df["MEDV"]??????????#最后要预测的对象
df.head()
output??????CRIM????ZN??INDUS??CHAS????NOX??...????TAX??PTRATIO???????B??LSTAT??MEDV
0??0.00632??18.0???2.31???0.0??0.538??...??296.0?????15.3??396.90???4.98??24.0
1??0.02731???0.0???7.07???0.0??0.469??...??242.0?????17.8??396.90???9.14??21.6
2??0.02729???0.0???7.07???0.0??0.469??...??242.0?????17.8??392.83???4.03??34.7
3??0.03237???0.0???2.18???0.0??0.458??...??222.0?????18.7??394.63???2.94??33.4
4??0.06905???0.0???2.18???0.0??0.458??...??222.0?????18.7??396.90???5.33??36.2
我们可以来看一下特征变量的数据类型df.dtypes
outputCRIM???????float64
ZN?????????float64
INDUS??????float64
CHAS???????float64
NOX????????float64
RM?????????float64
AGE????????float64
DIS????????float64
RAD????????float64
TAX????????float64
PTRATIO????float64
B??????????float64
LSTAT??????float64
MEDV???????float64
dtype:?object
我们看到都是清一色的连续型的变量,我们来计算一下自变量和因变量之间的相关性,通过seaborn模块当中的热力图来展示,代码如下plt.figure(figsize=(10,8))
cor?=?df.corr()
sns.heatmap(cor,?annot=True,?cmap=plt.cm.Reds)
plt.show()

相关系数的值一般是在-1到1这个区间内波动的
  • 相关系数要是接近于0意味着变量之间的相关性并不强
  • 接近于-1意味着变量之间呈负相关的关系
  • 接近于1意味着变量之间呈正相关的关系
我们来看一下对于因变量而言,相关性比较高的自变量有哪些#?筛选出于因变量之间的相关性
cor_target?=?abs(cor["MEDV"])
#?挑选于大于0.5的相关性系数
relevant_features?=?cor_target[cor_target>0.5]
relevant_features
outputRM?????????0.695360
PTRATIO????0.507787
LSTAT??????0.737663
MEDV???????1.000000
Name:?MEDV,?dtype:?float64
筛选出3个相关性比较大的自变量来,然后我们来看一下自变量之间的相关性如何,要是自变量之间的相关性非常强的话,我们也只需要保留其中的一个就行,print(df[["LSTAT","PTRATIO"]].corr())
print("="?*?50)
print(df[["RM","LSTAT"]].corr())
print("="?*?50)
print(df[["PTRATIO","RM"]].corr())
output????????????LSTAT???PTRATIO
LSTAT????1.000000??0.374044
PTRATIO??0.374044??1.000000
==================================================
?????????????RM?????LSTAT
RM?????1.000000?-0.613808
LSTAT?-0.613808??1.000000
==================================================
??????????PTRATIO????????RM
PTRATIO??1.000000?-0.355501
RM??????-0.355501??1.000000
从上面的结果中我们可以看到,RM变量和LSTAT这个变量是相关性是比较高的,我们只需要保留其中一个就可以了,我们选择保留LSTAT这个变量,因为它与因变量之间的相关性更加高一些

递归消除法

我们可以尝试这么一种策略,我们选择一个基准模型,起初将所有的特征变量传进去,我们再确认模型性能的同时通过对特征变量的重要性进行排序,去掉不重要的特征变量,然后不断地重复上面的过程直到达到所需数量的要选择的特征变量。LR=?LinearRegression()
#?挑选出7个相关的变量
rfe_model?=?RFE(model,?7)
#?交给模型去进行拟合
X_rfe?=?rfe_model.fit_transform(X,y)??
LR.fit(X_rfe,y)
#?输出各个变量是否是相关的,并且对其进行排序
print(rfe_model.support_)
print(rfe_model.ranking_)
output[False?False?False??True??True??True?False??True??True?False??True?False
??True]
[2?4?3?1?1?1?7?1?1?5?1?6?1]
第一行的输出包含TrueFalse,其中True代表的是相关的变量对应下一行的输出中的1,而False包含的是不相关的变量,然后我们需要所需要多少个特征变量,才能够使得模型的性能达到最优#将13个特征变量都依次遍历一遍
feature_num_list=np.arange(1,13)
#?定义一个准确率
high_score=0
#?最优需要多少个特征变量
num_of_features=0???????????
score_list?=[]
for?n?in?range(len(feature_num_list)):
????X_train,?X_test,?y_train,?y_test?=?train_test_split(X,y,?test_size?=?0.3,?random_state?=?0)
????model?=?LinearRegression()
????rfe_model?=?RFE(model,feature_num_list[n])
????X_train_rfe_model?=?rfe_model.fit_transform(X_train,y_train)
????X_test_rfe_model?=?rfe_model.transform(X_test)
????model.fit(X_train_rfe_model,y_train)
????score?=?model.score(X_test_rfe_model,y_test)
????score_list.append(score)
????if(score>high_score):
????????high_score?=?score
????????num_of_features?=?feature_num_list[n]
print("最优的变量是:?%d个"?%num_of_features)
print("%d个变量的准确率为:?%f"?%?(num_of_features,?high_score))
output最优的变量是:?10个
10个变量的准确率为:?0.663581
从上面的结果可以看出10个变量对于整个模型来说是最优的,然后我们来看一下到底是哪10个特征变量cols?=?list(X.columns)
model?=?LinearRegression()
#?初始化RFE模型,筛选出10个变量
rfe_model?=?RFE(model,?10)?????????????
X_rfe?=?rfe.fit_transform(X,y)??
#?拟合训练模型
model.fit(X_rfe,y)??????????????
df?=?pd.Series(rfe.support_,index?=?cols)
selected_features?=?df[df==True].index
print(selected_features)
outputIndex(['CRIM',?'ZN',?'INDUS',?'CHAS',?'NOX',?'RM',?'DIS',?'RAD',?'PTRATIO',
???????'LSTAT'],
??????dtype='object')

正则化

例如对于Lasso的正则化而言,对于不相关的特征而言,该算法会让其相关系数变为0,因此不相关的特征变量很快就会被排除掉了,只剩下相关的特征变量lasso?=?LassoCV()
lasso.fit(X,?y)
coef?=?pd.Series(lasso.coef_,?index?=?X.columns)
然后我们看一下哪些变量的相关系数是0print("Lasso算法挑选了?"? ?str(sum(coef?!=?0))? ?"?个变量,然后去除掉了"? ??str(sum(coef?==?0))? ?"个变量")
outputLasso算法挑选了10个变量,然后去除掉了3个变量
我们来对计算出来的相关性系数排个序并且做一个可视化imp_coef?=?coef.sort_values()
matplotlib.rcParams['figure.figsize']?=?(8,?6)
imp_coef.plot(kind?=?"barh")
plt.title("Lasso?Model?Feature?Importance")
output可以看到当中有3个特征,‘NOX’、'CHAS'、'INDUS'的相关性为0

根据缺失值来进行判断

下面我们来看一下如何针对离散型的特征变量来做处理,首先我们可以根据缺失值的比重来进行判断,要是对于一个离散型的特征变量而言,绝大部分的值都是缺失的,那这个特征变量也就没有存在的必要了,我们可以针对这个思路在进行判断。首先导入所需要用到的数据集train?=?pd.read_csv("credit_example.csv")
train_labels?=?train['TARGET']
train?=?train.drop(columns?=?['TARGET'])
我们可以先来计算一下数据集当中每个特征变量缺失值的比重missing_series?=?train.isnull().sum()?/?train.shape[0]
df?=?pd.DataFrame(missing_series).rename(columns?=?{'index':?'特征变量',?0:?'缺失值比重'})
df.sort_values("缺失值比重",?ascending?=?False).head()
output???????????????????????????缺失值比重
COMMONAREA_AVG????????????0.6953
COMMONAREA_MODE???????????0.6953
COMMONAREA_MEDI???????????0.6953
NONLIVINGAPARTMENTS_AVG???0.6945
NONLIVINGAPARTMENTS_MODE??0.6945
我们可以看到缺失值最高的比重将近有70%,我们也可以用可视化的根据来绘制一下缺失值比重的分布图plt.rcParams['font.sans-serif']=['SimHei']?#用来正常显示中文标签
plt.figure(figsize?=?(7,?5))
plt.hist(df['缺失值比重'],?bins?=?np.linspace(0,?1,?11),?edgecolor?=?'k',?color?=?'blue',?linewidth?=?2)
plt.xticks(np.linspace(0,?1,?11));
plt.xlabel('缺失值的比重',?size?=?14);?
plt.ylabel('特征变量的数量',?size?=?14);?
plt.title("缺失值分布图",?size?=?14);
output我们可以看到有一部分特征变量,它们缺失值的比重在50%以上,有一些还在60%以上,我们可以去除掉当中的部分特征变量

计算特征的重要性

在基于树的众多模型当中,会去计算每个特征变量的重要性,也就是feature_importances_属性,得出各个特征变量的重要性程度之后再进行特征的筛选from?sklearn.ensemble?import?RandomForestClassifier
clf?=?RandomForestClassifier()
#?模型拟合数据
clf.fit(X,Y)
feat_importances?=?pd.Series(clf.feature_importances_,?index=X.columns)
#?筛选出特征的重要性程度最大的10个特征
feat_importances.nlargest(10)
我们同时也可以对特征的重要性程度进行可视化,feat_importances.nlargest(10).plot(kind='barh',?figsize?=?(8,?6))
output除了随机森林之外,基于树的算法模型还有很多,如LightGBMXGBoost等等,大家也都可以通过对特征重要性的计算来进行特征的筛选

Select_K_Best算法

Sklearn模块当中还提供了SelectKBest的API,针对回归问题或者是分类问题,我们挑选合适的模型评估指标,然后设定K值也就是既定的特征变量的数量,进行特征的筛选。假定我们要处理的是分类问题的特征筛选,我们用到的是iris数据集iris_data?=?load_iris()
x?=?iris_data.data
y?=?iris_data.target
?
print("数据集的行与列的数量:?",?x.shape)?
output数据集的行与列的数量:??(150,?4)
对于分类问题,我们采用的评估指标是卡方,假设我们要挑选出3个对于模型最佳性能而言的特征变量,因此我们将K设置成3select?=?SelectKBest(score_func=chi2,?k=3)
#?拟合数据
z?=?select.fit_transform(x,y)
filter_1?=?select.get_support()
features?=?array(iris.feature_names)
print("所有的特征:?",?features)
print("筛选出来最优的特征是:?",?features[filter_1])
output所有的特征:??['sepal?length?(cm)'?'sepal?width?(cm)'?'petal?length?(cm)'
?'petal?width?(cm)']
筛选出来最优的特征是:??['sepal?length?(cm)'?'petal?length?(cm)'?'petal?width?(cm)']
那么对于回归的问题而言,我们可以选择上面波士顿房价的例子,同理我们想要筛选出对于模型最佳的性能而言的7个特征变量,同时对于回归问题的评估指标用的是f_regressionboston_data?=?load_boston()
x?=?boston_data.data
y?=?boston_data.target
然后我们将拟合数据,并且进行特征变量的筛选select_regression?=?SelectKBest(score_func=f_regression,?k=7)
z?=?select_regression.fit_transform(x,?y)

filter_2?=?select_regression.get_support()
features_regression?=?array(boston_data.feature_names)
?
print("所有的特征变量有:")
print(features_regression)
?
print("筛选出来的7个特征变量则是:")
print(features_regression[filter_2])
output
所有的特征变量有:['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT']筛选出来的7个特征变量则是:['CRIM' 'INDUS' 'NOX' 'RM' 'TAX' 'PTRATIO' 'LSTAT']

直播TeaTalk 线上直播倒计时

资讯
人工智能监考VS传统方式监考

资讯
Meta研发触觉手套助力元宇宙

资讯自动驾驶图书馆,热爱阅读的er


分享

点收藏

点点赞

点在看

相关新闻