day 7 特征选择

import pandas as pd
import numpy as np

data = pd.read_csv("digit recognizor.csv")
# print(data.head())
x = data.iloc[:, 1:]
y = data.iloc[:, 0]
# print(x.shape)  ##(42000, 784)
"""
数据量相对夸张,如果使用支持向量机和神经网络,可能会直接跑不出来。使用KNN跑一次需要半个小时
用这个数据,能更体现特征工程的重要性
方差过滤
"""
# todo:  Filter 过滤法
from sklearn.feature_selection import VarianceThreshold  # 方差过滤

# todo::::::::::::::::::::::::::方差过滤 # 不论接下来特征工程要做什么,都要优先消除方差为(默认阈值0)的特征
selector = VarianceThreshold()  # 实例化,不填默认方差为0
x_var0 = selector.fit_transform(x)  # 删除不合格特征,生成新矩阵
# # print(x.var().values) # 获取所有方差
# # print(np.median(x.var().values))  # 方差中位数
# # 如果想把特征删掉一半
x_fsvar = VarianceThreshold(np.median(x.var().values)).fit_transform(x)
# print(x_fsvar.shape)
#
# # 若特征是伯努利随机变量,假设p=0.8,即二分类特征中某种分类占到80%以上删除这种特征
# x_bvar=VarianceThreshold(0.8*(1-0.8)).fit_transform(x)
# print(x_bvar.shape)

# todo::::::::::::::::::::::::::相关过滤
"""
1.卡方过滤: 专门针对离散型标签(即分类问题)的相关性过滤
不能计算负数
"""
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectKBest  # 选择k个
from sklearn.feature_selection import chi2  # 卡方检验

#### 假设在这里我已经我需要300个特征
# x_fschi = SelectKBest(chi2,k=300).fit_transform(x_fsvar,y)
# print(x_fschi.shape)
#
#### 交叉验证查看效果
## print(cross_val_score(RFC(n_estimators=10, random_state=0), x_fschi,y,cv=5).mean())

#### 使用学习曲线查看最优的特征k数量,大概需要跑5分钟
## 发现结果是单调递增的,所以得特征都是有用的,卡方值很难界定有效的范围
# import matplotlib.pyplot as plt
# score=[]
# for i in range(390,200,-10):
#     x_fschi=SelectKBest(chi2,k=i).fit_transform(x_fsvar,y)
#     once=cross_val_score(RFC(n_estimators=10,random_state=0),x_fschi,y,cv=5).mean()
#     score.append(once)
# plt.plot(range(390,200,10),score)
# plt.show()
######更好的办法,通过p值
### p值作用

chivalue, pvalues_chi = chi2(x_fsvar, y)
# print(chivalue)  # 卡方值
# print(pvalues_chi)  # p值
# k取多少,我们先要消除所以p值大于设定值,比如0.05或0.01的特征
k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()  # 特征总数-大于0.05的特征数总和
print(k)

 

"""
2. F检验   ANOVA 方差齐性检验,用来捕捉每个特征与标签之间的线性关系的过滤方法
"""
# todo: F检验:  寻找俩组数据之间的线性关系
# F 类似卡方,很难界定
# frature_selection.f_classif  (F检验分类)
# frature_selection.f_regression  (F检验回归)
from sklearn.feature_selection import f_classif

# F, pvalues_f = f_classif(x_fsvar, y)
# print(F)
# 找出合理的k值
# k = F.shape[0] - (pvalues_f > 0.05).sum()
# print(k)
# X_fsF = SelectKBest(f_classif, k=k).fit_transform(x_fsvar, y)
# cross_val_score(RFC(n_estimators=10, random_state=0), X_fsF, y, cv=5).mean()

# todo: 互信息法
"""
3.互信息法: 
"""
# 互信息分类
from sklearn.feature_selection import mutual_info_classif as MIC
# 互信息回归
from sklearn.feature_selection import mutual_info_regression

# result = MIC(x_fsvar, y)
# k = result.shape[0] - sum(result <= 0)

#####
# todo::::::::::::::::::::::::::嵌入法

# 重要参数
# estimator  使用的模型评估器
# threshold  特征重要性的阈值
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier as RFC

# RFC_ = RFC(n_estimators=10, random_state=0)
# X_embedded = SelectFromModel(RFC_, threshold=0.005).fit_transform(x, y)
#  在这里我只想取出来有限的特征。0.005这个阈值对于有780个特征的数据来说,是非常高的
# 只能分到大概0.001的feature_importances_
# print(X_embedded.shape)
# 阈值取多少合适?
# 学习曲线 (少说起码要跑十分钟)
import numpy as np

# RFC_.fit(x,y).feature_importances_
# threshold = np.linspace(0,(RFC_.fit(x,y).feature_importances_).max(),20)
# score = []
# for i in threshold:
#     x_embedded = SelectFromModel(RFC_,threshold=i).fit_transform(x,y)
#     once=cross_val_score(RFC_,x_embedded,y,cv=5).mean()
#     score.append(once)
# plt.plot(threshold,score)
# plt.show()
# x_embedd = SelectFromModel(RFC_, threshold=0.00067).fit_transform(x, y)
# print(cross_val_score(RFC_, x_embedd, y, cv=5).mean())   ##0.939905083368037
# 根据上面的图可以看到,目前最好的范围可能是在0-0.00134之间,再画图具体找到最好的值
# 十几分钟跑完
# score2=[]
# for i in np.linspace(0,0.00134,20):
#     x_embedd = SelectFromModel(RFC_,threshold=i).fit_transform(x,y)
#     once = cross_val_score(RFC_, x_embedd, y, cv=5).mean()
#     score2.append(once)
# plt.figure(figsize=[20,5])
# plt.plot(np.linspace(0,0.00134,20),score2)
# plt.show()
###结论,最高点是0.000564
# 跑一下模型
# x_embedd = SelectFromModel(RFC_, threshold=0.000564).fit_transform(x, y)
# cross_val_score(RFC_, x_embedd, y, cv=5).mean()
# 结果 0.94083354150556387
# 然后调一下别的,rfc模型的n_estimators
# RFC_ = RFC(n_estimators=100, random_state=0)
# x_embedd = SelectFromModel(RFC_, threshold=0.000564).fit_transform(x, y)
# cross_val_score(RFC_, x_embedd, y, cv=5).mean()
# 结果 0.9639525817795566


# todo::::::::::::::::::::::::::包装法
"""
计算成本位于过滤法和嵌入法之间
也是一个特质选择和算法训练同时进行的方法
"""
# 目标函数是递归特征消除法
# feature_selection.RFE
# 参数      estimator                 评估器
#           n_features_to_select    想要选择的特征个数
#           step                    希望移出的特征个数
from sklearn.feature_selection import RFE

RFC_ = RFC(n_estimators=10, random_state=0)
# selector = RFE(RFC_, n_features_to_select=340, step=50).fit(x, y)
# print(selector.support_)  # 返回所有特征最后是否被选中的布尔矩阵
# print(selector.support_.sum())  # 最后被选中的特征加和
# print(selector.ranking_)        # 返回特征的按次数迭代中的综合重要性的排名
# X_weapper = selector.transform(x)  # 使用包装法得到的特征矩阵
# print(cross_val_score(RFC_, X_weapper, y, cv=5).mean()) # 0.9389522459432109

# 对包装法画学习曲线 # 这玩意也要画好久,大概10分钟
# score = []
# for i in range(1, 751, 50):
#     x_wrapper = RFE(RFC_, n_features_to_select=i, step=50).fit(x, y)
#     once = cross_val_score(RFC_, x_wrapper, y, cv=5).mean()
#     score.append(once)
# plt.figure(figsize=[20, 5])
# plt.plot(range(1, 751, 50), score)
# plt.xticks(range(1, 751, 50))
# plt.show()
##结果,应用50个特征时,模型的表现就已经达到了90%以上

### 然后就去调吧,调的头皮发麻

# todo:::::总结
# 数据量大的时候,优先使用方差过滤和互信息法,在上其他的特征选择方法
# 逻辑回归时,优先使用嵌入法
# 使用向量机时,优先使用包装法
# 迷茫的时候,过滤法走起
# 崩溃时,建议该行送外卖或者手机贴膜
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值