我有一个从网页上抓取的不平衡数据集,包含文本数据,我已经手动将其分类为正类,而另一类的负类可以包含任何类型的文本数据,我将其标记为负类。查看数据集后,很明显负样本非常少,大约1200个,共6000个样本。
负类 = 1200
正类 = 4800
最初使用不平衡的词干数据集时,模型偏向于多数类,具有高准确率,但在未见数据上的表现极差。
因此,我选取了1200个负样本和1200个正样本,使其平衡。
我使用Keras实现了一个具有4层64节点的密集模型,并使用0.5的正则化,成功在交叉验证中达到了60%的准确率,而训练准确率高达>95%。
查看val_acc
和acc
,我觉得在约20个周期后模型完全过拟合。此外,由于平衡数据集中数据行数较少,模型也无法泛化。
- 解决此类问题的办法有哪些?
- 单类SVM能否帮助单类别文本分类?
- 如果单类SVM能帮助,那么谁能提供一个基本的示例或实现资源?
回答:
首先,你确定在这6000个你认为是负类的样本中没有正类吗?垃圾输入,垃圾输出,确保这里不是这种情况。
解决此类问题的办法
我会按以下顺序来解决这个问题。
-
确保你的数据表示良好。如果你处理的是文本数据,你应该使用像预训练的word2vec这样的词向量,也可以在tensorflow和tensorflow hub中找到(你可以在这里找到更高级的词嵌入方法,如ELMo)。
-
获取更多样本 – 这一步通常会带来最好的结果(前提是上一步已经完成),但需要时间。
- 尝试不同的算法 – 有些算法并不在意类别不平衡。决策树及其变体是最突出的例子。我认为你应该尝试一下,从简单的决策树开始,然后是随机森林和提升树如xgboost、LightGBM或catboost,我认为后三者表现相当,xgboost可能由于相关资料丰富而是最好的选择。
- 不同的指标 – 准确率并不是最好的,因为它高度依赖于负类。使用其他指标,如精确率和召回率,并关注后者(因为你的算法可能无法找到足够的正类)。
- 加权损失 – 对正例的错误赋予比负例更高的权重。我更喜欢这种方法,因为模型试图适应数据。这里有一个在Tensorflow中自定义损失函数的例子。
- 上采样 – 与你所做的相反,给你的模型多次提供相同的正例(在这种情况下,每个正例提供5次,因此有6000个正例,与负例一样多)。你不会丢失信息,但训练时间会更长(对于你总共7200个样本来说,这基本上不是问题)。
- 下采样 – 你在这里所做的,但你会丢失很多关于负类的信息及其特征。更适合大型数据集,你的数据集较小。
- 创新方法 – 对于文本数据来说更难,如果不是这种情况,你可以尝试降维或其他数据表示方法,找到正负点之间差异的根本原因。最难的,可能对你的情况没有帮助。
单类SVM能否帮助
我对此持怀疑态度,它用于异常检测。7200个样本中的1200个数据点不应被视为异常。此外,它可能与负类共享很多特征,你无法利用你目前拥有的标记数据。
如果你仍然想尝试,sklearn中有一个实现,在这里。