数据不给力,再高级的算法都没有用
数据挖掘的五大流程:
1.获取数据
2.数据预处理
数据预处理是从数据中检测,纠正或者删除损坏,不准确或者不适用于模型的记录和过程
可能面对的问题有:
数据类型不同,比如有的是文字,有的是数字,有的含时间序列,有的连续有的是离散的,数据质量不行,有噪声,有异常,有缺失,数据出错,量纲不一,有重复等
数据预处理的目的:
让数据适应模型,匹配模型的需求
3.特征工程
特征工程是将原始数据转换为更代表预测模型的潜在问题的特征的过程 ,可以通过挑选最相关的特征,提取特征以及创造特征来实现。
其中创造特征又经常以降维算法的方式实现
可能面对的问题有:
特征之间的相关性,特征与标签无关,特征太多或太少,或者干脆就无法表现出应有的数据现象或无法展示数据的真实面貌
特征工程的目的:
1)降低计算成本
2)提升模型上限
4.建模,测试模型并预测出结果
5.上线,验证模型效果
模块preprocessing:几乎包含了数据预处理的所有内容
模块impute:用来填补缺失值专用
模块feature_selection:包含特征选择的各种方法和实践
模块decomposition:包含降维算法
定义:将不同规格的数据转换到同一规格,或者不同分布的数据转换到某个特定的分布的需求,此需求就是无量纲化
线性的无量纲包括中心化(Zero-centered或者Mean-subtraction)处理和放缩处理(Scale)。
中心化的本质是让所有记录的减去一个固定值,即让数据样本数据平移到某个位置。
缩放的本质是通过除以一个固定值,将数据固定在某个范围中,取对数也算是一种缩放处理。
当数据(X)按照最小值中心化后,再按极差(最大值-最小值)缩放,数据移动了最小值个单位,并且会被收敛到[0,1]之间,不是正则化,真正的正则化是regularization,不是数据预处理的一种手段的一种手段。归一化之后的数据服从正态分布,公式如下:
在sklearn当中,我们使用preprocessing.MinMaxScaler来实现这个功能。MinMaxScaler有一个重要参数,feature_range,控制我们希望把数据压缩到的范围,默认是[0,1]。
实现归一化
from sklearn.preprocessing import MinMaxScaler
data = [[-1,2],[-0.5,6],[0,10],[1,18]]
#不太熟悉numpy的小伙伴,能够判断data的结构?
#如果换成表什么样子?
import pandas as pd
pd.DataFrame(data)
#实现归一化
scaler = MinMaxScaler()#实例化
scaler = scaler.fit(data)#fit 在这里本质是生成min(x)和max(x)
result = scaler.transform(data)#通过接口导出结果
result
#训练和导出结果一步达到
result_ = scaler.fit_transform(data)
result_
#将归一化后的结果逆转
scaler.inverse_transform(result)
data = [[-1,2],[-0.5,6],[0,10],[1,18]]
scaler = MinMaxScaler(feature_range=[5,10])#依然实例化
result = scaler.fit_transform(data)#fit_transform一步导出结果
result
BONUS:使用numpy来实现归一化
import numpy as np
X = np.array([[-1,2],[-0.5,6],[0,10],[1,18]])
#归一化
#axis = 0 求每一行的最大/最小
X_nor = (X-X.min(axis=0))/(X.max(axis=0) - X.min(axis=0))
X_nor
#逆转归一化
X_returnd = X_nor * (X.max(axis=0) - X.min(axis=0))+X.min(axis=0)
X_returnd
当数据按均值中心化后,再按照标准差缩放,数据就会服从均值为0,方差为1的正态分布,而这个过程就是数据标准化(Standardization,又称Z-score normalization)
from sklearn.preprocessing import StandardScaler
data = [[-1,2],[-0.5,6],[0,10],[1,18]]
scaler = StandardScaler()
scaler.fit(data)
scaler.mean_#查看属性mean
scaler.var_#查看属性var_
x_std = scaler.transform(data)
x_std
scaler.fit_transform(data)#一步达成
scaler.inverse_transform(x_std)#一步逆转
看情况!
大多数机器学习算法中,会选择StandardScaler来进行特征的缩放。在PCA、聚类、逻辑回归、支持向量机、神经网络这些算法中,StandardScaler往往是最好的
MinMaxScaler在不涉及距离、梯度、协方差计算以及数据需要压缩到特定区域时使用广泛。在量化像素强度,会使用MinMaxScaler将数据压缩到[0,1]区间之中
在希望压缩数据却不影响数据的稀疏性是(不影响矩阵中取值为0的个数时),我们会使用MaxAbsScaler
在异常值多,噪声非常大的时候,我们可能会选择用分位数来无量纲化,使用RobustScaler
Age = data.loc[:,"Age"].values.reshape(-1,1)
#sklearn当中特征矩阵必须是二维
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer()
imp_median = SimpleImputer(strategy=“median”)#使用中位数填补
imp_0 = SimpleImputer(strategy=“constant”,fill_value=0)#使用0填补
imp_mean = imp_mean.fit_transform(Age)
imp_median = imp_median.fit_transform(Age)
imp_0 = imp_0.fit_transform(Age)
使用中位数填补Age
data.loc[:,"Age"] = imp_median
data,info()
使用众数填补Embarked
Embarked = data.loc[:,"Embarked"].values.reshape(-1,1)
imp_mode = SimpleImputer(strategy="most_frequent")
data.loc[:,"Embarked"] = imp_mode.fit_transform(Embarked)
data,info()
BONUS:用Pandas和Numpy进行填补更加简单
data.loc[:,"Age"] = data.loc[:,"Age"].fillna(data.loc[:,"Age".median()])
data_.dropna(axis=0,inplace = True)
#.dropna(axis=0)删除所有有缺失值的行
#.dropna(axis=1)删除所有有缺失值的列
#参数inplace 为True表示在原数据上修改
在机器学习中吗,大多数算法,如逻辑回归,支持向量机SVM,K近邻算法都只能够处理数值型不能处理文字
在sklearn中除了专用来处理文字的算法,fit时候都需要导入矩阵(数值数据)
现实中我们需要将文字型数据转换成数值型
from sklearn.preprocessingn import LabelEncoder
y = data.iloc[:,-1] #要输入的是标签,不是特征矩阵
le = LabelEncoder()
le = le.fit(y)
label = le.transform(y)
le.classes_#属性classes_查看标签究竟有多少类别
label#查看获取的结果label
#一步到位
le.fit_transform(y)
le.inverse_transform(label)
#让标签等于我们运行出来的结果
data.iloc[:,-1] = label
data.head()
#一下子写好
from sklearn.preprocessing import LabelEncoder
data.iloc[:,1] = LabelEncoder().fit_transform(data.iloc[:,-1])
data.head()
from sklearn.preprocessing import OrdinalEncode
#接口categories对应LabekEncoder的接口classes_,一模一样的功能
data_ = data.copy()
data_.head()
OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_#相当与.classes_
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data.iloc[:,1:-1])
data_.head()
data.head()
from sklearn.preprocessing import OneHotEncoder
X = data.iloc[:,1:-1]
#categories表示有几个类别
enc = OneHotEncoder(categories='auto').fit(X)
result = enc.transform(X).toarray()
result
#一步到位
OneHotEncoder(categories=‘auto’).fit_transform(X).toarray()
pd.DataFrame(enc.inverse_transform(result))
enc.get_feature_names()
result
#axit=1,表示跨行进行合并,也就是将量表示左右相连
#如果axis = 0 就是将表上下相连
newdata = pd.concat(["sex","Embarked"],axit = 1,inplace=True)
newdata.columns = ["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
根据阈值将数据二值化(将特征值设置为0或1),用于处理连续变量。大于阈值的映射为1,小于阈值的映射为0
#将年龄二值化
data_2 = data.copy()
from sklearn.preprocessing import Binarizer
X = data_2.lioc[:,0].values.reshape(-1,1)#要升维
transformer = Binarizer(threshold=30).fit_transform(X)
transformrs
data_2.iloc[:,0] = transformer
这是将连续型变量划分为分类变量的类,能够连续型变量排序后按顺序分箱后编码。
from sklearn.preprocessing import KBinsDiscretizer
X = data.iloc[:,0].values.reshape(-1,1)
est = KBinsDiscretizer(n_bins=3,encode='ordinal',strategy='uniform')
est = fit_transform(X)
set(est.fit_transform(X).ravel())#降维
est = KBinsDiscretizer(n_bins=3,encoder=‘onehot’,strategy=‘uniform’)
est.fit_transform(X).toarray()
特征工程:特征提取、特征创造、特征选择
特征工程的第一步:理解业务
四种选择特征的方法:过滤法、嵌入法、包装法和降维算法
所以无论接下来的特征工程做什么,都要优先消除方差为0 的特征
过滤方差为零的特征
from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold()
X_var0 = selector.fit_transform(X)
过滤方差为中位数的特征
import numpy as np
X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)
X_fsvar.shape
#若特征是伯努利随机变量,假设p = 0.8 即二分类特征中某种分类占到80%以上的时候删除特征
x_bnvar = VarianceThreshold(.8*(1-.8)).fit_transform(X)
这里对比了KNN算法和随机森林
为什么随机森林如此之快?为什么方差过滤对随机森林没有很大影响?
是因为两种算法原理中涉及到的计算量不同
KNN,单棵决策树,支持向量机SVM,神经网络,回归算法都需要遍历特征或者升维来进行运算
随机森林则是随机选择特征进行分枝
因此过滤法的只要对象:
需要遍历特征或升维的算法
卡方过滤是专门针对离散型标签(分类问题)的相关性过滤。
卡方检验类feature_selection.chi2计算每个非负特征和标签之间的卡方统计量,并依照卡方统计量由高到低为特征排名。
再结合feature_selection.Selection.SelectKBest这个可以输入“评分标准”来选出前K个分数最高的特征的类,我们可以借此去最可能独立于标签,与我们分类目的无关特征。
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score
from sklearn.feature_selecion 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()
F检验,又称ANOVA,方差齐性检验,是用来捕捉每个特征与标签与标签之间的线性关系的过滤方法。
feature_selection.f_classif(F检验分类)
F检验分类用于标签是离线型变量的数据
feature_selection.f_regression(F检验回归)
F检验回归用于标签是连续变量的数据
和卡方检验一样,这两个类需要和类SelectKBest连用,
和卡方顾虑一样,我们希望选取p值小于0.05或0.01的特征,这些特征与标签时显著线性相关的,而p值大于0.0-5或0.01的特征则被我们认为是和标签没有显著线性关系的特征,应该被删除。
以F检测的分类为例,我们继续在数字数据集上来进行特征选择:
from sklearn.feature_selection import f_classif
F,pvalues_f = f_classif(x_fsvar,y)
k = F.shape[0]-(pvalues_f>0.05).sum()
互信息法是用来捕捉每个特征与标签之间的任意关系(包含线性和非线性关系)的过滤方法。
feature_selection.mutual_info_classif(互信息分类)
feature_selection.mutual_info_regression(互信息回归)
from sklearn.feature_selecion import mutual_info_classif as MIS
result = MIC(X_fsvar,y)
k = result.shape[0] - sum(result<=0)
嵌入法是一种让自己决定使用哪些特征的方法(特征选择和算法训练同时进行)
####feature_selection_SelectFromModet
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)
通过学习曲线来寻找最佳阈值
import numpy as np
import matplotlib.pyplot as plt
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()
进一步细化
score2 = []
for i in np.linspace(0,0.00134,20):
X_embedded = SelectFromModel(RFC_,threshold=i).fit_transform(X,y)
once = cross_val_score(RFC_,X_embedded,y,cv=5).mean()
score2.append(once)
plt.figure(figsize=[20,5])
plt.plot(np.linspace(0,0.00134,20))
plt.xticks(np,linspace(0,0.00134,20))
plt.show()
包装法也是一种特征选择和算法训练同时进行的方法,与嵌入法十分相似
参数:
estimator是需要填写的实例化后的评估器
n_feature_to_select是想要选择的特征个数
step表示每次迭代中希望移除的特征个数
属性:
.support_:返回所有的特征的是否最后被选中的布尔矩阵
.ranking_:返回特征的按次数迭代中综合重要性的排名。
from sklearn.feature_selection import RFE
RFC_ = RFC(n_etimators = 10,random_state=0)
selector = RFE(RFC_,n_features_to_select=340,step=50).fit(X,y)
selector.support_.sum()
selector.ranking_
X_wrapper = selector.transform(X)
cross_val_score(RFC_,X_wrapper,cv=5).mean()
通过学习曲线来寻找最佳阈值
score = []
for i in range(1,751,50):
X_wrapper = RFE(RFC_,n_features_to_select = i,step=50),fit_transform(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.xtices(range(1,751,50))
plt.show()
经验上来讲,过滤法更加快速但是粗糙,包装法和嵌入法更加精确,比较适合具体到算法上去调整,但是计算量比较大,运行时间长
当数据量很大的时候,优先使用方差过滤和互信息法调账,再上其他的特征选择方法。
在逻辑回归时候优先使用嵌入法
使用支持向量机时,优先使用包装法