【火炉炼AI】机器学习015-如何处理样本数偏差较大的数据集
(本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
我们得到的数据集在绝大多数情况下,都不是理想的数据集,都需要经过各种各样的处理,其中的一个处理方式就是,如何处理样本数偏差较大的数据集。比如对于某种疾病的发生概率是1%,即获得的自然状态下的数据集中大约99%的样本都是正常的,那么此时,通过模型进行训练,得到的模型在对新样本进行预测时,也往往偏向于样本数较大的类别,此时或极大的降低小样本类别的召回率。
1. 查看数据集的特征
此处所使用的是书本《Python机器学习经典实例》第三章的非平衡数据集,此处我用pandas读取到内存中,通过info()来查看该数据集的基本情况,代码如下:
# 准备数据集data_path='E:\PyProjects\DataSet\FireAI/data_multivar_imbalance.txt'df=pd.read_csv(data_path,header=None)# print(df.head()) # 没有问题print(df.info()) # 查看数据信息,确保没有错误dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1]# print(dataset_X.head())# print(dataset_X.info())# print(dataset_y.head()) # 检查没问题dataset_X=dataset_X.values dataset_y=dataset_y.values
-------------------------------------输---------出--------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1200 entries, 0 to 1199
Data columns (total 3 columns):
0 1200 non-null float64
1 1200 non-null float64
2 1200 non-null int64
dtypes: float64(2), int64(1)
memory usage: 28.2 KB
None
--------------------------------------------完-------------------------------------
可以看出,该数据集只有两个features,一个label,且整个数据集有1200个样本。可以通过查看数据集的2D分布来初步的了解该数据集的样本偏差。如下图所示:
本数据集在不同类别上样本数偏差比较大
########################小**********结###############################
1. 数据集中不同类别之间样本数偏差比较大,此时需要做进一步处理。
2. 数据集的加载和显示等,在前面的文章中已经讲烂了,此处无需赘言。
#################################################################
2. 用线性SVM分类器构建分类模型
从上面的数据集分布图中可以大致看出,这个模型不是简单的线性模型,当然,为了对比效果,此处我仍然使用线性SVM分类器来构建分类模型,看一下效果。
代码如下:
# 将整个数据集划分为train set和test setfrom sklearn.model_selection import train_test_split train_X, test_X, train_y, test_y=train_test_split( dataset_X,dataset_y,test_size=0.25,random_state=42)# 如果用线性SVM分类器来进行分类,看看是什么结果# 使用线性核函数初始化一个SVM对象。from sklearn.svm import SVC classifier=SVC(kernel='linear') # 构建线性分类器classifier.fit(train_X,train_y)
然后在通过plot_classifier()函数将这个模型的分类效果画出来。
# 模型在训练集上的性能报告:from sklearn.metrics import classification_report plot_classifier(classifier,train_X,train_y) # 分类器在训练集上的分类效果target_names = ['Class-0', 'Class-1'] y_pred=classifier.predict(train_X) print(classification_report(train_y, y_pred, target_names=target_names))
线性SVM分类器对本数据集的分类效果
-------------------------------------输---------出--------------------------------
precision recall f1-score support
Class-0 0.00 0.00 0.00 151
Class-1 0.83 1.00 0.91 749
avg / total 0.69 0.83 0.76 900
--------------------------------------------完-------------------------------------
可以看出,线性SVM分类器完全没有将class_0区分出来,得到的各种指标都是0,从分类效果图中也可以看到,根本就没有线性平面。
########################小**********结###############################
1. 由于本数据集存在样本数量偏差,故而使用线性SVM分类器没有任何效果。
#################################################################
3. 解决样本数量偏差的方法
从上面可以看出,由于样本数量偏差的存在,使用线性SVM分类器没有任何效果,那么我们该怎么处理这种数据集了?
SVM内部存在一个class_weight参数,我们可以设置该参数为"balanced",来调节各种类别样本数量的权重,使其达到平衡。如下代码:
# 看来直接使用简单的线性SVM分类器难以将class_0区分出来,故而我们要调整数据集中样本的数量权重classifier2=SVC(kernel='linear',class_weight='balanced') # 比上面的分类器增加了 class_weight=‘balanced'参数classifier2.fit(train_X,train_y)# 模型在训练集上的性能报告:plot_classifier(classifier2,train_X,train_y) # 分类器在训练集上的分类效果target_names = ['Class-0', 'Class-1'] y_pred2=classifier2.predict(train_X)print(classification_report(train_y, y_pred2, target_names=target_names))
设置class_weight参数为balanced后分类效果图
-------------------------------------输---------出--------------------------------
precision recall f1-score support
Class-0 0.35 0.86 0.50 151
Class-1 0.96 0.68 0.79 749
avg / total 0.86 0.71 0.74 900
--------------------------------------------完-------------------------------------
从分类效果图中可以看出,此时可以使用线性SVM来对数据集进行训练,并能得到效果还不错的分类模型,从分类结果报告中可以看出,各种指标也还不错,但也存在较大的提升空间。
########################小**********结###############################
1. 在定义SVM分类器时,只需要设置class_weight=balanced即可消除数据集中样本数量偏差的问题。
2. 如果分类器的效果不理想,那么需要考虑是否是数据集存在明显的样本数量偏差问题。
#################################################################
注:本部分代码已经全部上传到(我的github)上,欢迎下载。
参考资料:
1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译
作者:炼丹老顽童
链接:https://www.jianshu.com/p/b78f64c66ecf
共同学习,写下你的评论
评论加载中...
作者其他优质文章