分类:类内的倾斜数据
Posted
技术标签:
【中文标题】分类:类内的倾斜数据【英文标题】:Classification: skewed data within a class 【发布时间】:2018-07-30 12:30:00 【问题描述】:我正在尝试构建一个多标签分类器来预测某些输入数据为 0 或 1 的概率。我正在使用神经网络和 Tensorflow + Keras(以后可能是 CNN)。
问题如下: 数据高度倾斜。负面例子比正面例子多得多,可能是 90:10。所以我的神经网络几乎总是输出非常低的正样本概率。在大多数情况下,使用二进制数会预测为 0。
几乎所有类的性能都 > 95%,但这是因为它几乎总是预测为零... 因此,假阴性的数量非常多。
一些建议如何解决这个问题?
以下是我目前考虑的想法:
使用定制的损失函数来更多地惩罚假阴性(我的第一次尝试失败了)。类似于对类中的正面示例进行加权而不是负面示例。这类似于班级权重,但在班级内。 你将如何在 Keras 中实现这一点?
通过克隆正样本然后过拟合神经网络来对正样本进行过采样,从而平衡正样本和负样本。
提前致谢!
【问题讨论】:
您的解决方案看起来不错。一些常见的方法是放大代表性不足的类对损失函数的影响,您可以使用class_weights
。对于您的第一个想法,如果我理解正确,您可以使用this similar solution。您可以从代表性不足的班级分布中生成合成示例(假设图像,您可以翻转、添加噪声、倾斜等......)。您可以批量对类进行过采样/欠采样。您可以查看this paper 了解更多信息。
【参考方案1】:
我觉得你的两个建议已经很不错了。 当然,您也可以简单地对负类进行欠采样。
def balance_occurences(dataframe, zielspalte=target_name, faktor=1):
least_frequent_observation=dataframe[zielspalte].value_counts().idxmin()
bottleneck=len(dataframe[dataframe[zielspalte]==least_frequent_observation])
balanced_indices=dataframe.index[dataframe[zielspalte]==least_frequent_observation].tolist()
for value in (set(dataframe[zielspalte])-least_frequent_observation):
full_list=dataframe.index[dataframe[zielspalte]==value].tolist()
selection=np.random.choice(a=full_list,size=bottleneck*faktor, replace=False)
balanced_indices=np.append(balanced_indices,selection)
df_balanced=dataframe[dataframe.index.isin(balanced_indices)]
return df_balanced
您的损失函数可以结合其他一些测量来研究正类的召回率。
【讨论】:
【参考方案2】:你在正确的轨道上。
通常,您要么在训练前平衡数据集,即减少过度代表的类别,要么为代表不足的类别生成人工(增强)数据以提高其出现率。
减少过度代表的类 这个更简单,您只需随机选择与代表性不足的类中的样本一样多的样本,丢弃其余样本并使用新子集进行训练。当然,缺点是您正在失去一些学习潜力,具体取决于您的任务有多复杂(有多少功能)。
增强数据 根据您使用的数据类型,您可以“增强”数据。这只是意味着您从数据中获取现有样本并稍微修改它们并将它们用作附加样本。这非常适用于图像数据、声音数据。您可以翻转/旋转、缩放、添加噪声、降低/降低亮度、缩放、裁剪等。 这里重要的是,你要保持在现实世界中可能发生的事情的范围内。例如,如果您想识别“70mph 限速”标志,那么翻转它没有意义,您将永远不会遇到实际翻转的 70mph 标志。如果您想识别一朵花,可以翻转或旋转它。声音也一样,稍微改变音量/频率并不重要。但是反转音轨会改变其“意义”,您将不必识别现实世界中倒转的单词。
现在,如果您必须增加销售数据、元数据等表格数据...这会更加棘手,因为您必须小心不要将您自己的假设隐含地输入模型中。 p>
【讨论】:
以上是关于分类:类内的倾斜数据的主要内容,如果未能解决你的问题,请参考以下文章
关于C++模版的一个问题求教,如果取模板类内的一个结构体的指针。