Paper速读-[Dealing with Difficult Minority Labels in Imbalanced Mutilabel Data Sets]-University of Granada-Neurocomputing2019
论文链接:Dealing with Difficult Minority Labels in Imbalanced Mutilabel Data Sets
1. 简介
好,今天咱们来看一个很经典的算法,用于多标签不平衡数据增广的MLSMOTE。这个算法的前身是一个叫做SMOTE的算法,可惜的是这个算法本身只能针对单标签数据。但是话虽然这么说,咱们还是先来看一下SMOTE这个算法是咋回事(SMOTE):
- Select data to over-sample (general data with minority class labels).
- Choose an instance of the data.
- Find its k nearest neighbours of that data point.
- Choose a random data point which is in k nearest neighbours of the selected data point and make a synthetic data point anywhere on the line joining both these points.
- Repeat the process until data is balanced.
简单来说呢,就是这样几个步骤。首先,
- 选出来所有的标签中,哪些是少数类别的标签;
- 比如说先考虑第一个少数类别 C 1 C_1 C1,从少数类别 C 1 C_1 C1中选出来一个幸运观众作为增广的基础;
- 找到所有 C 1 C_1 C1为正例的数据子集 M i n C 1 MinC_1 MinC1,在 M i n C 1 MinC_1 MinC1找到幸运观众的K个最近邻(很明显,这里的邻居都需要和幸运观众属于同一个类别);
- 随机选出幸运的一个邻居,在幸运观众和幸运邻居上面做一个线性插值,得到这个少数类别的一个新样本;重复上述过程,直到数据集分布平衡。
好,那么接下来咱们来说说细节:
2. 具体步骤
前面几个步骤,SMOTE和MLSMOTE都是一样的,咱们就统一说,到了不一样的地方咱们再展开。
2.1 选出少数类别
要做到这一步,我们需要理解两个量:
- Imbalance ratio per label:说白了,就是算每一个类别对应的不平衡系数。其中N是样本数,
L
1
L_1
L1是标签数。我再说的像人话一点,比如说你看这个公式,对于类别j来说,分母就是一共有多少个这个类别的正例,分子就是在所有的类别中,正例最多的那个类别有多少个正例。再换句话说,也就是对于所有的类别来说,分母都是一样的,最多数的那个类别的这个值就是1,而这个值越大,代表着这个类别越需要增广。
- Mean Imbalance ratio: 这个就更简单了,就是所有类别的IRPL求个平均值嘛
所有IRPL大于平均值的类别,都被选择为少数类别,也就是需要增广的类别。但是要注意一下,因为是多标签数据,也就是说针对一个样本,可能他包含第1,3,5个类别为正例,但是类别1和3都是少数类别,他就同时会作为两个少数类别的样本。也就是说,他会同时被选入到 M i n 1 Min1 Min1和 M i n 3 Min3 Min3中
2.1.1 代码
def get_tail_label(self, labels):
# Give tail label colums of the given label
irpl = np.zeros(self.cls_num)
for cls in range(self.cls_num):
irpl[cls] = sum(labels[:, cls])
print("cls : {} has {} samples".format(cls, irpl[cls]))
irpl = max(irpl)/irpl
mir = np.average(irpl)
tail_label = []
for i in range(self.cls_num):
if irpl[i] > mir:
tail_label.append(i)
return tail_label
2.2 插值生成新样本
这一步很简单啊,就是直接插值。但是新样本的标签咱们得说说。对于SMOTE来说,因为幸运观众和幸运邻居都是属于同一个类别,所以新生成的数据很明显还是这个类别。但是对于多标签数据来说, M i n C 1 MinC_1 MinC1里面的数据标签可不一样啊,他们唯一的共同点就是 C 1 C_1 C1都为正类,但是其他的类别可就不好说了。所以为了解决这一问题,我们有这样的办法,针对幸运观众和他的K个最近邻:
- Intersection: Only the labels which are in reference data point and also in all the neighbouring data points will be in synthetic data pint.
- Union: All the label which are in either in reference data point or any of the neighbour data point is in synthetic data.
- Ranking: We count the number of time each label occur in reference data point as well as in neighbour data point and only those label are considered in synthetic data which have frequency more than half of the instance considered.
说白了就是:
- 幸运观众+邻居在这个类别上都是1,新样本才是1
- 幸运观众+邻居在这个类别上有人是1,新样本就是1
- 幸运观众+邻居在这个类别上超过半数是1,新样本才是1
实验结果表明,第三种效果是最好的。
2.2.1 代码
def syn_label(self, ins_nn, data_index):
syn_label = np.zeros((self.cls_num))
for i in range(len(ins_nn)):
# ins_nn is list, which contains the index of nearest-neighbour of this sample
ins_n_label = self.labels[data_index[ins_nn[i]]]
syn_label += ins_n_label
for i in range(self.cls_num):
if syn_label[i] >= (self.K / 2):
syn_label[i] = 1
else:
syn_label[i] = 0
return syn_label
OK,那么以上就是本篇文章的全部内容了,感兴趣的小伙伴可以点击开头的链接阅读原文哦
关于更多的文章,请看这里哦文章分享专栏 Paper sharing Blog