使用Weka进行数据挖掘(Weka教程六)Weka采样Filter/Resample/SMOTE

时间:2023-02-13 18:27:16

数据预处理中,有一个原理很简单但是非常重要的部分:采样。良好的采样可以让数据集变得平衡,会大大的提高预测和分类的效果。
采样是很复杂的一个领域,背后涉及到数据的分布/数据的性质等很多内容。常见的采样有:
Simple Random Sampling(简单随机采样),
OfflineSampling(离线等可能K采样),
Online Sampling(在线等可能K采样),
Ratio-based Sampling(等比例随机采样),
Acceptance-RejectionSampling(接受-拒绝采样),
Importance Sampling(重要性采样),
MCMC(MarkovChain Monte Carlo 马尔科夫蒙特卡罗采样算法)。

  • 简单有放回随机采样

Filter支持多种采样方式,其中有监督的采样比较复杂,因此主要讲解有监督学习采样方法。Filter中的Resample采样就是简单的有放回抽样。
其参数有下面几个:

 -S <num>
Specify the random number seed (default 1)
指定随机数种子,随机数种子相同,则采样结果相同。
-Z <num>
The size of the output dataset, as a percentage of
the input dataset (default 100)
指定采样数据占整个数据的比例。
-B <num>
Bias factor towards uniform class distribution.
0 = distribution in input data -- 1 = uniform distribution.
(default 0)
是否按照原来数据类别的分布分层抽样。
-no-replacement
Disables replacement of instances
(default: with replacement)
-V
Inverts the selection - only available with '-no-replacement'.

由以上参数可以看出,Weka支持的比例好像最小为1%,其实并不是,你可以使用小数实现更低的采样比。此外,你可以将采样比例设置成大于100%,如果你这样做了,那么你的结果数据集将会出现重复的数据。这样是没有意义的。

使用Resample进行采样是比较简单的,下面是一个例子:

 public static Instances BoostrapSample(Instances data) {
String[] options = {"-S",1}
;

Resample convert = new Resample();
try {
convert.setOptions(options);
convert.setInputFormat(data);
data = Filter.useFilter(data, convert);
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
  • SMOTE采样
    随机采样比较简单,其实Weka还支持一种附加的采样方法,在Weka3.6版本以下,这个功能嵌入在Weka包里,Weka3.7版本开始,这个功能需要额外的第三方包的支持,这种采样就是SMOTE采样。
    SMOTE算法的思想是合成新的少数类样本,合成的策略是对每个少数类样本a,从它的最近邻中随机选一个样本b,然后在a、b之间的连线上随机选一点作为新合成的少数类样本。 这是一种过采样方法,通过制造更多模拟的少数类样本来实现各个样本之间的平衡。
    下图是其主要思想的形式化表示:
    使用Weka进行数据挖掘(Weka教程六)Weka采样Filter/Resample/SMOTE
    在Weka3.7版本,你必须先添加第三方包,最简单的方法就是添加一个新的maven依赖:
<dependency>
<groupId>nz.ac.waikato.cms.weka</groupId>
<artifactId>SMOTE</artifactId>
<version>1.0.3</version>
</dependency>

SMOTE采样实现代码如下:

public static Instances SMOTESample(Instances data,int normalElemFlag) {
SMOTE convert = new SMOTE();
int seed = (int) (Math.random() * 10);
String[] options = {"-S", String.valueOf(seed), "-P", "100.0", "-K", "5"};
Instances SmoteInstances = null;
try {
convert.setOptions(options);
convert.setInputFormat(data);
SmoteInstances = Filter.useFilter(data, convert);
} catch (Exception e) {
e.printStackTrace();
}
return SmoteInstances;
}

需要注意的是,在运行完毕SMOTE采样之后,多数类样本并不会随之减少,因此,如果你想让多数类和少数类样本平衡,就必须再使用简单采样丢弃多余的多数类样本。