学习数据预处理的内容
数据无量纲化:包括中心化和缩放处理
数据归一化,使用sklearn的preprocessing.MinMaxScaler实现该功能。
#coding:utf-8
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
data = [[-1,2],[-0.5,6],[0,10],[1,18]]
print(pd.DataFrame(data))#查看数据的结构
#调用接口实现归一化
scaler = MinMaxScaler() #实例化
scaler = scaler.fit(data)#居然是生成min和max?但我觉得应该是先放数据,然后里面是内置属性
result = scaler.transform(data)#计算结果
print(result)
result = scaler.fit_transform(data)#训练和导出结果一步生成
print(result)
result_1 = scaler.inverse_transform(result)
print(result_1)
scaler = MinMaxScaler(feature_range=[5,10])#归一化到[0,1]以外的范围
data.dropna(axis=0,inplace=True)
#.dropnan=0删除所有缺失值的行,axis=1则删除所有缺失值的列
#参数为inplace,为True表示在原数据集做修改,为False表示生成一个复制对象,不修改原数据,默认False
print(data.info())
print(data.head(4))
y = data.iloc[:,-1]#读所有行,但只取最后一列的值,输入为标签,允许一维所以可以放进fit()接口
#print(y)
le = LabelEncoder() #实例化
le = le.fit(y)#装载数据
label = le.transform(y)#逆转标签的意思
#print(label)
#lable = le.fit_transform(y)#可以直接fit_transform一步到位
#print(le.inverse_transform(label)) 逆转标签的意思
data.iloc[:,-1] = label #替换标签成刚刚生成的数值
print(data.head(4))
#python一切皆对象,全部都有地址,都可以通过特定的写法然后允许被调用,最常用的就是"."点符号调用
#像上面展示的结果,可以一行代码
data.iloc[:,-1] = LabelEncoder().fit_transform(data.iloc[:,-1])#此时inplace应是False,生成新的data对象
print(data.head(4))#结果一样
#coding:utf-8
import pandas as pd
from sklearn.preprocessing import OrdinalEncoder
#index_col=0是想告诉计算机第一列的值是索引
data = pd.read_csv(r"D:\PycharmPro\Dataengineer\Narrativedata.csv",index_col=0)
data_ = data.copy()
print(data_.head(4))
print(OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_) #内置属性,查看数值的值和类型
#data_.iloc[:,1:-1]是指数据中所有行,第二列到倒数第一列的数值,包头不包尾
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
#一样的功能,只是没有实例化OrdinalEncoder()
print(data_.head(4))
#coding:utf-8
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
#index_col=0是想告诉计算机第一列的值是索引
data = pd.read_csv(r"D:\PycharmPro\Dataengineer\Narrativedata.csv",index_col=0)
X = data.iloc[:,1:-1]
print(X)
enc = OneHotEncoder(categories='auto').fit(X)
result = enc.transform(X).toarray()
print(result)
#print("*"*100)
#print(OneHotEncoder(categories='auto').fit_transform(X).toarray())#一步到位,直接得结果
'''
fit和transform必不可少
'''
'''print(enc.get_feature_names())
print(result.shape)
newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
'''
'''
axis=1,将表左右相连
axsi=0,将表上下相连
'''
'''
print(newdata.head(4))
#newdata.drop(["Sex","Embarked"],axis=1,inplace=True)#inplace=True,原表上做修改
#newdata.columns = ["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
#print(data.head(4))
'''
3.1filter过滤法
方差过滤:VarianceThreshold类,消除方差为0的特征值
#python中的魔法命令,可以直接使用%%timeit来计算运行这个cell中的代码所需的时间
#为了计算所需的时间,需要将这个cell中的代码运行很多次(通常是7次)后求平均值,因此运行%%timeit的时间会远远超过cell中的代码单独运行的时间
方差过滤对随机森林的影响:
为什么随机森林运行如此之快?为什么方差过滤对随机森林没很大的有影响?这是由于两种算法的原理中涉及到的计算量不同。最近邻算法KNN,单棵决策树,支持向量机SVM,神经网络,回归算法,都需要遍历特征或升维来进行运算,所以他们本身的运算量就很大,需要的时间就很长,因此方差过滤这样的特征选择对他们来说就尤为重要。但对于不需要遍历特征的算法,比如随机森林,它随机选取特征进行分枝,本身运算就非常快速,因此特征选择对它来说效果平平。这其实很容易理解,无论过滤法如何降低特征的数量,随机森林也只会选取固定数量的特征来建模;而最近邻算法就不同了,特征越少,距离计算的维度就越少,模型明显会随着特征的减少变得轻量。因此,过滤法的主要对象是:需要遍历特征或升维的算法们,而过滤法的主要目的是:在维持算法表现的前提下,帮助算法们降低计算成本。
过滤法对随机森林有效,却对树模型有效?
为什么:从算法原理上来说,传统决策树需要遍历所有特征,计算不纯度后进行分枝,而随机森林却是随机选择特征进行计算和分枝,因此随机森林的运算更快,过滤法对随机森林无用,对决策树却有用
在sklearn中,决策树和随机森林都是随机选择特征进行分枝(参数random_state),但决策树在建模过程中随机抽取的特征数目却远远超过随机森林当中每棵树随机抽取的特征数目(比如说对于这个780维的数据,随机森林每棵树只会抽10~20个特征,而决策树可能会抽取300~400个特征),因此,过滤法对随机森林无用,却对决策树有用
也因此,在sklearn中,随机森林中的每棵树都比单独的一棵决策树简单得多,高维数据下的随机森林的计算比决策树快很多。
3.1.2在方差挑选完毕后,筛选出与标签相关的特征。
有三种常用的方法来评判特征与标签之间的相关性:
1.卡方;2.F检验;3.互信息
卡方过滤是专门针对离散型标签(即分类问题)的 相关性过滤
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#假设在这里我一直我需要300个特征
X_fschi = SelectKBest(chi2, k=300).fit_transform(X_fsvar, y)
X_fschi.shape
cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()
Ts
可以根据经验设置for循环选择分数最高的k;更好的方法是看p值选k
卡方检验的本质是推测两组数据之间的差异,其检验的原假设是”两组数据是相互独立的”。卡方检验返回卡方值和P值两个统计量,其中卡方值很难界定有效的范围,而p值,我们一般使用0.01或0.05作为显著性水平,即p值判断的边界,具体我们可以这样来看:
从特征工程的角度,我们希望选取卡方值很大,p值小于0.05的特征,即和标签是相关联的特征。而调用SelectKBest之前,我们可以直接从chi2实例化后的模型中获得各个特征所对应的卡方值和P值
3.1.2.3F检验
F检验,又称ANOVA,方差齐性检验,是用来捕捉每个特征与标签之间的线性关系的过滤方法。它即可以做回归也可以做分类,因此包含feature_selection.f_classif(F检验分类)和feature_selection.f_regression(F检验回归)两个类。其中F检验分类用于标签是离散型变量的数据,而F检验回归用于标签是连续型变量的数据。
卡方检验一样,这两个类需要和类SelectKBest连用,并且我们也可以直接通过输出的统计量来判断我们到底要设置一个什么样的K。需要注意的是,F检验在数据服从正态分布时效果会非常稳定,因此如果使用F检验过滤,我们会先将数据转换成服从正态分布的方式
3.1.2.4互信息法
互信息法是用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)的过滤方法。和F检验相似,它既可以做回归也可以做分类,并且包含两个类feature_selection.mutual_info_classif(互信息分类)和feature_selection.mutual_info_regression(互信息回归)。这两个类的用法和参数都和F检验一模一样,不过互信息法比F检验更加强大,F检验只能够找出线性关系,而互信息法可以找出任意关系。
互信息法不返回p值或F值类似的统计量,它返回“每个特征与目标之间的互信息量的估计”,这个估计量在[0,1]之间取值,为0则表示两个变量独立,为1则表示两个变量完全相关。
3.2 Embedded嵌入法
嵌入法是一种让算法自己决定使用哪些特征的方法,即特征选择和算法训练同时进行。根据权重由大到小选择特征,比如决策树和树的集成模型中的feature_importances_属性,可以列出各个特征对树的建立的贡献,我们就可以基于这种贡献的评估,找出对模型建立最有用的特征
3.3Wrapper包装法
包装法也是一个特征选择和算法训练同时进行的方法,与嵌入法十分相似,它也是依赖于算法自身的选择,比如coef_属性或feature_importances_属性来完成特征选择。但不同的是,我们往往使用一个目标函数作为黑盒来帮助我们选取特征,而不是自己输入某个评估指标或统计量的阈值。包装法在初始特征集上训练评估器,并且通过coef_属性或通过feature_importances_属性获得每个特征的重要性。然后,从当前的一组特征中修剪最不重要的特征。在修剪的集合上递归地重复该过程,直到最终到达所需数量的要选择的特征。区别于过滤法和嵌入法的一次训练解决所有问题,包装法要使用特征子集进行多次训练,因此它所需要的计算成本是最高的。
4.总结
过滤法是手动选择参数一步步挑选特征,先是设定方差阈值,筛选方差为0的特征,因为方差为0的特征表示样本在这个特征上没有差异,因此该特征对于区分样本没有什么作用。设定方差阈值筛选为特征后,考虑与标签意义相关的特征,若无关会浪费时间和给模型带来噪音,有三种方法选择与标签相关性强的特征:1.卡方过滤,针对离散标签的相关性过滤。;2.F检验,方差齐性检验,用来捕捉每个特征与标签之间的线性关系的过滤方法,可以做回归也可以做分类。注意是两组数据的线性关系,选择相关性强的特征;3.互信息法,捕捉每个特征与标签的任意关系(包括线性和非线性),可以做回归和分类,返回每个特征与目标之间的互信息量的统计。
Emdedded嵌入法和Wrapper包装法都是让算法自己决定选择使用哪些特征的方法,与过滤法手动设置参数阈值不同。Emdedded嵌入法是先进行训练,考虑特征对模型的贡献,得到各特征的权重系数,在排序进行选择;Wrapper包装法使=使用目标函数选取特征,通过coef_属性或通过feature_importances_属性获得特征重要性,然后排序,修剪最不重要的特征,得到特征子集重复上述过程。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)