在机器学习领域,时常会出现某一类的样本数量远远低于其他类的情况,即类不平衡问题。解决类不平衡问题通常有三种思路:
1. 欠采样
2.过采样
3.代价敏感学习
要解决类不平衡问题可以参考以下文献:
《Learning from Imbalanced Data》
本文主要介绍SMOTE算法的使用。
SMOTE算法是一种过采样方法,它通过KNN算法来填充少数类样本。博主在MATLAB中文论坛里找到了一个实现SMOTE算法的程序包,下载链接如下:
https://www.ilovematlab.cn/thread-167786-1-1.html
或者使用我的百度云链接:
链接:https://pan.baidu.com/s/1BpGdRciK8V0Qt16s1zd6bA
提取码:7bhm
打开这个程序包,先打开ReadMe.html,里面有相关的使用说明。建议先阅读该说明。
我们再打开sample_SmoteOverSampling.m文件,该文件是使用smote算法的一个样例,使用smote算法主要的程序段为:
[newTrain,newTrainLabel]=SmoteOverSampling(Train,TrainLabel,ClassType,C,attribute,5,'nominal');
完整代码如下:
1 % sample_SmoteOverSampling 2 % sample routine to use SmoteOverSampling algorithm 3 % step 1: Generate new training set using FUNCTION SmoteOverSampling 4 % step 2: Train a neural network N from the new training set 5 % step 3: Get cost-sensitive predictions or their real-value outputs using N 6 7 clear; 8 %------------prepare data------------ 9 10 load echocardiogram 11 Cost=CostMatrix(2,5); 12 C=sum(Cost);%convert cost matrix to cost vector 13 14 %-------------step 1: Generate new training set using FUNCTION OverSampling ------------------- 15 16 [newTrain,newTrainLabel]=SmoteOverSampling(Train,TrainLabel,ClassType,C,attribute,5,'nominal'); 17 newTrainTarget=LabelFormatConvertion(newTrainLabel,ClassType);% change to 2-value format 18 19 %-------------step 2: Train a neural network from the new training set------------- 20 21 net=newff(minmax(newTrain),[10,NumClass],{'logsig','logsig'},'trainrp'); 22 net.trainParam.show = 200; 23 net.trainParam.epochs = 200; 24 net=train(net,newTrain,newTrainTarget); 25 26 %-------------step 3: Get cost-sensitive predictions or their real-value outputs using N---- 27 28 cs_out=sim(net,Test); 29 cs_out=normalize(cs_out);% real-value outputs 30 cs_prediction=LabelFormatConvertion(cs_out,ClassType,2);%prediction
先假设我们的样本数量为m,特征数量为n。
SmoteOverSampling函数中,最主要的几点如下:
1. Train是训练数据,行数代表特征数量,列数代表样本数量
2.TrainLabel是训练数据对应的标签,对于二分类问题,可以用[0,1]来标记。
3.ClassType是标签中的类名称,对于二分类问题,一般设ClassType=[0,1]
4. C是代价向量(cost vector)。在这个程序包里,它是通过对代价矩阵每一列求和得到的,而代价矩阵却是通过随机数取得的(有点迷)。
对于具体的问题,读者应该自己建立代价矩阵,若不想考虑代价问题,我们可以简单地设C=[1,1]; % 二分类问题有两个1,n分类问题有n个1
5.attribute是对我们特征属性的一个说明。它是一个行向量,向量中只能取0或者1。比如第n个特征是数值型特征,我们把attribute的第n个元素设为0;
若第n个特征是标称特征(nominal attribute),我们把attribute的第n个元素设为1。那么什么是标称特征?简单地说,某个特征是用某个整数或字符来表示的,比如颜色特征,用0代表白色,用1代表黄色,用2代表黑色等等。那么头发颜色特征就是标称特征。很多时候我们的数据中并没有标称特征,这时候要注意了,由于这个程序包没有考虑这种全数值型特征的情况,所以把attribute设为全零向量(即zeros(1,n))会导致程序报错!!!为了解决这个问题,我们可以自行添加一个没啥用的标称特征,即在我们的Train训练数据最后一行下面添加一个全1向量。这时候我们的特征数量增加了一个,再对应地,把attribute先设为zeros(1,(n+1)),再设attribute(end)=1;这样我们就添加了一个标称特征.
6.SmoteOverSampling的最后两个参数我们可以保持默认,即 5,'nominal'。其中5是KNN的参数k,'nominal'是把标称特征按照标称特征对待(也可以设为'numeric',即按照数值型特征对待)