准备数据:如何处理出完整、干净的数据?
原始的数据本身也存在着各种各样的问题:
如不够准确、格式多样、部分特征缺失、标准不统一、特殊数据、错误数据等
一、找到数据
你要知道每个项目需要什么数据,并从哪里获取。
需要你掌握一些数据库的使用技巧:
- 关系型数据库MySQL、大数据使用的Hbase、HIVE、搜索引擎数据库ES、内存数据库Redis。
- 图数据库,如NEO4j或者JanusGraph等。
- 还要跟各种业务部门沟通协商以获取数据。
二、数据探索
你要对数据进行分析、预处理以及转换等基础工作以构建出更加贴合你所要预测结果的特征
我把这个环节叫作把数据变多或者数据升维。
假设你要做一个给新闻内容分类的项目
已经从数据仓获取了新闻内容、新闻标题、新闻发布时间等数据并从运营部门获得了运营给这些新闻标注的分类数据。
要把数据变多,可以进行如下操作:
把内容进行分词,就获得了一个分词后的字段
把分词后的内容进行词语的统计,看看哪个词出现得更多
把标题进行分词,进行词语的统计
可以对词语的词性进行标注,获得一份词性数据
可以找到一些特殊的词,比如名人的名字、机构的名字、地点的名字等一些信息
如果是数值型的数据
通过计算均值、方差、中位数、标准差、最大值、最小值等去探索、扩展。
三、数据清洗
处理扩展后的数据、解决所发现的问题。
同时又要顾及处理后的数据是否适合应用于下一个步骤。
1、缺失值的处理
一条新闻可能只有正文没有标题、发布地点、发布时间等任意数据。你需要区分这些数据缺失的情况,通过分析,了解数据缺失的原因以及数据缺失的影响范围
缺失值处理 API: sklearn.preprocessing.Imputer
缺失值处理方法:
删除 | 插补 |
如果每列或者行数据缺失值达到一定的比例,建议放弃整行或者整列 | 可以通过缺失值每行或者每列的平均值、中位数来填充 |
建议按每一列的特征进行填补。
Imputer语法:
-Imputer(missing_values=‘NaN’, strategy=‘mean’, axis=0)
完成缺失值插补
-Imputer.fit_transform(X,y)
X:numpy array格式的数据[n_samples,n_features]
返回值:转换后的形状相同的array
from sklearn.preprocessing import Imputer import numpy as np def im(): """缺失值处理""" #missing_value 缺失值标记 #strategy 填补策略 mean平均值 #axis 1行 0列 im=Imputer(missing_values='NaN',strategy='mean',axis=0) data=im.fit_transform([[1, 2], [np.nan, 3], [7, 6]] ) print(data) return None if __name__ == '__main__': im()
pandas处理:dropna,fillna
pandas处理和Imputer处理都需要把缺失值处理为np.nan格式
这里可以去采用replace函数进行替换。
关于np.nan(np.NaN):
numpy的数组中可以使用np.nan/np.NaN来代替缺失值,属于float类型
如果是文件中的一些缺失值,可以替换成nan,通过np.array转化成float
型的数组即可
2、异常值的处理
异常值――与样本空间中绝大多数数据分布差距过大的数据
错误的情况
比如医院录入病人病历的时候,忘了给数字输入小数点
正常的情况
在平均充值为100元的游戏中,有人充了100万元,直接使用到模型中可能会影响到平均值的计算,影响模型训练的效果。只有1000万在线用户的App,突然拥有十亿的在线用户,有可能是应用网络受到了攻击。
不同情况的异常值有不同的处理办法:
数据本身的错误―—需要对数据进行修正,或者直接丢弃
数据是正确的―—需要根据业务需求进行处理
如果目标是发现异常情况,异常值需要保留下来,甚至需要特别关照。
如果目标跟异常值没有关系,可以对这些异常值做一些修正。
3、数据偏差的处理
UGC内容(UserGenerated Content,用户生成内容)的质量。
质量较差的内容占大多数,质量好的占少数,质量非常好的是少之又少有些算法会倾向于预测占比较大的数据。
比如质量好的内容只占2%,而质量差的内容占到了98%,模型倾向于给出质量差的结果。
数据偏差可能导致后面训练的模型过拟合或者欠拟合
如果需要比较均衡的样本,可以考虑丢弃较多的数据,或者补充较少的数据
补充较少的数据时,考虑使用现有数据去合成一些数据,或者直接复制一些数据从而增加样本数量
4、数据标准化
对数据的标准进行整理,可以防止某个维度的数据因为数值的差异,而对结果产生较大的影响
有些算法中,每一个维度的数据标准都需要进行统一
另外一些算法中,需要统一数据的类型
在预测一个地区的房价时,房屋的房间数可能是个位数地区平均单价可能是以万为单位的
一个处理方法是把这些维度的数据都进行标准化比如把这些数据都规范到0~1的区间。
在sklearn模块中,使用MinMaxScaler 函数进行Min-Max标准化:
import pandas as pd from sklearn.preprocessing import MinMaxScaler data = pd.read_csv('../form/数据标准化.csv',encoding = 'gbk') #特征变量 x = data[['注册时长','营收收入','成本']] #目标变量 y = data['是否续约'] #生成标准化对象 scaler = MinMaxScaler() #训练标准化对象 scaler.fit(x) #将数据转换为标准化数据 scalerX = scaler.transform(x)
5、特征选择
尽可能留下较少的数据维度,而又可以不降低模型训练的效果。
维度越多,数据就会越稀疏,模型的可解释性就会变差、可信度降低。
过多维度会造成运算的缓慢,同时多余的维度可能会对模型的结果产生不好的影响。
需要用到特征选择的技巧
比如自然语言处理里的关键词提取,或者去掉屏蔽词,以减少不必要的数据维度
对于数值型的数据,可以使用主成分分析等算法来进行特征选择。
from sklearn.decomposition import PCA from sklearn.preprocessing import scale import pandas as pd import numpy as np df = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\data-pca.xlsx', index_col=0) # 读取数据 data = scale(df.values) # 标准化,标准化之后就自动根据协方差矩阵进行主成分分析了 # data2 = np.corrcoef(np.transpose(data)) # 没有必要单独计算协方差阵或相关系数阵 pca = PCA() # 可以调整主成分个数,n_components = 1 pca.fit(data) print(pca.explained_variance_) # 输出特征根 print(pca.explained_variance_ratio_) # 输出解释方差比 print(pca.components_) # 输出主成分
6、构建训练集与测试集
在训练之前,要把数据分成训练集和测试集,有些还会有验证集
如果是均衡的数据,即各个分类的数据量基本一致
直接随机抽取一定比例的数据作为训练样本,另外一部分作为测试样本
如果是非均衡的数据,比如风险类数据一般远远少于普通型数据
使用分层抽样以保障每种类型的数据都可以出现在训练集和测试集中
训练集和测试集的构建,比如:
留出法,直接把整个数据集划分为两个互斥的部分,使得训练集和测试集互不干扰。
交叉验证法,先把数据集划分成n个小的数据集,每次使用n-1个数据集作为训练集,剩下的作为测试集进行n次训练。
自助法,通过重复抽样构建数据集,通常在小数据集的情况下非常适用。
留出法:
from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression cancer = load_breast_cancer() X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=0) logreg = LogisticRegression().fit(X_train,y_train) print("Test set score:{:.2f}".format(logreg.score(X_test,y_test)))
- 缺点一:浪费数据
- 缺点二:容易过拟合,且矫正方式不方便
交叉验证:
就是进行多次train_test_split划分;每次划分时,在不同的数据集上进行训练、测试评估,从而得出一个评价结果;如果是5折交叉验证,意思就是在原始数据集上,进行5次划分,每次划分进行一次训练、评估,最后得到5次划分后的评估结果,一般在这几次评估结果上取平均得到最后的 评分。k-fold cross-validation ,其中,k一般取5或10。
优点:原始采用的train_test_split方法,数据划分具有偶然性;交叉验证通过多次划分,大大降低了这种由一次随机划分带来的偶然性,同时通过多次划分,多次训练,模型也能遇到各种各样的数据,从而提高其泛化能力;与原始的train_test_split相比,对数据的使用效率更高。train_test_split,默认训练集、测试集比例为3:1,而对交叉验证来说,如果是5折交叉验证,训练集比测试集为4:1;10折交叉验证训练集比测试集为9:1。数据量越大,模型准确率越高!
缺点:这种简答的交叉验证方式,从上面的图片可以看出来,每次划分时对数据进行均分,设想一下,会不会存在一种情况:数据集有5类,抽取出来的也正好是按照类别划分的5类,也就是说第一折全是0类,第二折全是1类,等等;这样的结果就会导致,模型训练时,没有学习到测试集中数据的特点,从而导致模型得分很低,甚至为0!为了避免这种情况,又出现了其他的各种交叉验证方式。
from sklearn.model_selection import cross_val_score logreg = LogisticRegression() scores = cross_val_score(logreg,cancer.data, cancer.target) #cv:默认是3折交叉验证,可以修改cv=5,变成5折交叉验证。 print("Cross validation scores:{}".format(scores)) print("Mean cross validation score:{:2f}".format(scores.mean()))