数据预处理方法
-
特征编码
- 数字编码
- 简单的数字编码:从0开始赋予特征的每一个取值一个整数
- 收入水平={贫困,低收入,小康,中等收入,富有} → 收入水平={0,1,2,3,4}
- 但这样的数字编码后的数据,引入了本不存在的次序关系,会导致后续错误的建模分析结果,故为了避免上述误导性的结果,对于离散型特征(特别是名义型特征),使用One-Hot编码
- One-Hot编码
- 将包含K个取值的离散型特征转换成K个二元特征(0/1)
- 优点:不会人为地引入次序关系,不同的原始特征取值之间拥有相同的距离,线性回归模型中,对名义型特征进行One-Hot编码的效果通常比数字编码的效果好,对包含离散型特征的分类模型的效果有很好的提升。
- 缺点:使特征维度显著增多,增加特征之间的相关性【特征之间存在线性关系,会影响线性回归等模型的效果】
- 优化:对于一个包含K个取值的离散型特征,将其转换成K-1个二元特征【哑变量编码】(第K个特征取值全为0)
- 数字编码
-
缺失值处理
- 在数据采集、传输和处理等过程中,由于某种原因导致数据不完整
- 删除法
- 删除样本
- 某些样本有多个特征存在缺失值,且存在缺失值的样本数量较少,总样本量足够多,某则将影响数据的客观性,进而影响到数据分析结果的正确性
- 删除特征
- 当某个特征缺失值过多,且改特征对数据分析的目标影响不大时,可将该特征删除
- 简单易操作,但也有很大的局限性,以减少数据来换取信息的完整,丢失了被删除数据中的信息
- 删除样本
- 均值填补
- 使用非缺失值的平均值或众数来代替缺失值
- 连续型-平均值;离散型-众数
- 使数据过分集中在平均值或众数,导致特征的方差被低估;由于完全忽略特征之间的相关性,大大弱化特征之间的相关性——可将数据值分成多组,在每组数据上分别使用均值填补【分年级/性别
- 使用非缺失值的平均值或众数来代替缺失值
- 随机填补
- 在均值填补的基础上加上随机项,通过增加缺失值的随机性来改善缺失值分布过于集中的缺陷
- 假设数据集有n个样本,某特征f存在k个非缺失值和(n-k)个缺失值
- 贝叶斯Bootstrap方法
- ①从均匀分布U(0,1)中随机抽取k-1个随机数,并进行升序排序记为a1,a2,…,ak-1;②对(n-k)个缺失值,分别从非缺失值{f1,f2,…,fk}中以概率{a1,a2-a1,…,1-ak-1}采样一个值进行填补
- 近似贝叶斯Bootstrap
- ①从k个非缺失值{f1,f2,…,fk}中有放回的抽取k个值建立一个新的大小为k的集合F;②对于(n-k)个缺失值,分别从F中随机抽取一个值进行填补
- 贝叶斯Bootstrap方法
- 基于模型的填补
- 通过特征f的非缺失值构造训练集,训练分类或回归模型,使用构建的模型来预测特征f的缺失值
- 需要采用模型评估方法对模型的预测性能进行评估
- 将增大特征之间的相关性
- 其他缺失值处理方法
- 哑变量方法-离散型特征【将缺失值作为一个单独的取值进行处理,1表示观测数据中存在缺失值,0表示观测数据中不存在缺失值,对缺失数据进行特定值的插补(如均值插补),这样的好处是在缺失值处理时使用了全部变量的信息,但这样会导致估计有偏。
- EM算法【期望最大化】-缺失特征被当作隐含变量【利用不完整的信息实现概率模型的参数化估计,通过数据扩张,将不完全数据的处理问题转化为对完全数据的处理问题,切通过假设隐变量的存在,简化似然方程,将比较复杂的似然函数极大似然估计问题转化为较简单的极大似然估计问题。①用估计值替代缺失值②参数估计③假定2中的参数估计值是正确的,再对缺失值进行估计④再估计缺失值
- 删除法
- 在数据采集、传输和处理等过程中,由于某种原因导致数据不完整
-
数据标准化
- Z-score标准化
-
-
通过对数据集中的每个样本进行处理,使得处理后的数据具有固定均值和标准差
-
直观反映每一个取值距离平均值的标准差距离,从而理解特征的整体分布情况
-
当数据中存在离群值时,为了降低离群值的影响,将标准差替换成平均绝对偏差
-
Z-score标准化适用于特征的最大值或最小值未知和样本分布非常分散的情况
-
- Min-Max标准化
- 通过对特征作线性变换,使得转换后的特征取值分布在[0,1]区间内
- 适用于需要将特征取值简单线性映射到某一区间【保留了原始数据间的关系】
- 不足:当数据集中有新数据加入时,特征的最大值或最小值会发生变化,需重新标准化;同时Min-Max标准化需计算特征取值的最大值和最小值,当数据存在离群值时,标准化后的效果较差
- 小数定标标准化
- 移动特征取值的小数点位置来进行标准化,使得标准化后特征取值的绝对值总是小于1【说人话就是所有特征取值同时放大/缩小10j倍,使所有特征值小于1
- 适用于特征取值比较分散,尤其是分布在多个数量级的情况,简单实用
- 不足:如果特征取值分布在某几个量级上,则小数定标标准化后的特征取值也会集中在某几个值附近,不利于后续数据分析时的样本区分;效果受离群值的影响
- Logistic标准化
- 利用Logistic函数的特性,将特征取值映射到[0,1]
- 适用于特征取值**分布相对集中地在0两侧【均匀分布】**的情况,如果分散切均远离0,那么标准化后的特征取值会聚集于0/1附近,造成原始特征的分布及取值间关系被改变。【应用前线分析原始特征取值的分布情况】
- 数据标准化总结
- Z-score标准化
-
特征离散化
- 将连续型特征转换成离散型特征的过程
- 等距离散化
- 等频离散化
- 聚类离散化
- 信息增益离散化
- 卡方离散化
- 类别属性相互依赖最大化
-
离群值检测
- 基于统计的方法
- 仅存在随机误差
- 根据给定一个置信度确定相应的置信区间后,超过置信区间的误差就认为不属于随机误差的范围,含有这种误差的取值就被认为是离群值
- 拉依达准则【Pauta criterion】
- 假定数据集服从正态分布,并对数据集计算标准差,在给定置信度的情况下,如果有超过均值三倍标准差以上,则认为含有该误差的样本即为离群值【适用于测量册数较多时】
- Z-score标准化辅助识别离群值:|xZ-score|>3的样本认为是离群值
- 基于近邻的方法
- 以下两种方法都需计算数据集中样本之间的距离,当样本数量很大且维度较大时,这两种方法的计算代价都很大
- 基于K近邻算法的离群值检测方法
- 1计算每一个样本与其最近的k个近邻样本的距离,放入到集合C中
- 2对C中的所有元素进行降序排列
- 3根据给定的距离阈值,选取C中大于给定阈值的距离所对应的样本作为离群值
- 简单有效,常用;但它只能发现全局的离群值,无法发现局部的离群值
- 局部离群因子算法LOF
- 给数据集中每一个样本计算一个局部离群分数,该分数通过样本邻居的密度和当前样本的密度相对值来计算,在计算每一个样本的局部离群分数后,可以直接根据分数大小来识别离群样本
- 局部可达密度
- 局部离群因子
- 局部离群银子接近于1,则样本x与其近邻样本的局部可达密度相似,可认为是正常样本;若局部离群因子<1,则局部可达密度大于其近邻样本,x为正常样本;若局部离群银子>1,则x局部可达密度小于其近邻样本,x 可能为离群值
- 基于统计的方法
实践代码
Z-Score
法一:
import xlwt
import numpy as np
import pandas
if __name__ == '__main__':
dataset = []
for i in range(0,9):
f = xlwt.Workbook()
sheet1 = f.add_sheet(u'sheet1',cell_overwrite_ok=True)
df = pandas.read_excel('D:\\study\\3\\数据科学\\数据集\\混凝土强度数据集\\Concrete_Data.xls', usecols=[i], names=None) #读取原始数据
df = df.values.tolist()
data=(df-np.mean(df))/np.std(df)
dataset.append(data)
dataFrame = pandas.DataFrame(list(map(np.ravel, dataset)))
dataFrame = dataFrame.T #转置
with pandas.ExcelWriter('D:\\study\\3\\数据科学\\数据集\\混凝土强度数据集\\test.xlsx') as writer:
dataFrame.to_excel(writer,float_format='%.6f') #写入excel
writer.save() #保存
法二:
import pandas
from sklearn.preprocessing import StandardScaler
data = pandas.read_excel('D:\\study\\3\\数据科学\\数据集\\混凝土强度数据集\\Concrete_Data.xls')
## 创建Z-score对象,并使用fit()方法
std_scaler = StandardScaler().fit(data)
## 特征标准化,使用transform()方法
normal_df = std_scaler.transform(data)
## 均值
score_mean = std_scaler.mean_
## 方差
score_var = std_scaler.var_
## 打印
print(score_mean)
print(score_var)
## 打印
normal_df[0:]
均值填补
import pandas as pd
import numpy as np
##打开excel读取数据
datas = pd.read_excel('D:\\study\\3\\数据科学\\数据集\\皮肤病数据集\\dermatology.xlsx',names=['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','age','34'])
print(datas[datas['age']=='?'].index.tolist())
##求均值
datas1 = datas['age']
datas1 = datas1.tolist()
while '?' in datas1:
datas1.remove('?')
aver = np.mean(datas1[0:])
print(aver)
##填补缺失值
datas['age'].replace('?',aver,inplace=True)
##写入
with pd.ExcelWriter('D:\\study\\3\\数据科学\\数据集\\皮肤病数据集\\new.xlsx') as writer:
datas['age'].to_excel(writer)
writer.save()