请教个神经网络的问题

2021-12-30 09:47:05 +08:00
 zxCoder

在改一份代码,网络结构是一个 bert ,一个 dropout 层和最后一个 linear 层

我在把多分类改成多标签分类

就改改数据的输入输出格式,加个 sigmoid 激活函数

但是结果出现了问题,发现 loss 一直在降,但是 acc 缺掉到 0 ,一看才发现,练着练着,最后 linear 层输出是一个特别小的负数,而且越来越小,然后经过 sigmoid 后全部预测为 0 ,所以 loss 算起来还是很低

这种情况可能是出现什么问题呢

1527 次点击
所在节点    问与答
23 条回复
zhucegeqiu
2021-12-30 09:56:39 +08:00
预测全为 0 为啥 loss 就低,样本不平衡?
zxCoder
2021-12-30 09:58:54 +08:00
@zhucegeqiu 比如一共有 1000 个 label ,但是一个样本可能只有一两个 label 是 1 ,其他都是 0 ,直接预测全 0 ,用 BCE 计算 loss 好像就不高
sss3barry
2021-12-30 10:27:15 +08:00
样本也太不平衡了吧,感觉换 loss 也不一定有用,下采样负例稍微平衡一下?
ipwx
2021-12-30 10:30:33 +08:00
@zxCoder 你已经说出了原因了。神经网络做的是

1. 最大化 l(x,y) 在训练样本 p(x,y) = p(x)p(y|x) 上的期望。
2. 几乎不可能找到全局最优解,只能找到局部最优解。

在你的例子中,998/1000 以上的训练样本都是 0 。也就是说 p(y=0|x) = 0.998 。如果你是神经网络要学习 y=f(x),那么是不是很容易找到 y=f(x) 恒等于 0 这个局部最优解?
ipwx
2021-12-30 10:31:17 +08:00
p(y=0|x) = 0.998 ,约等于 p(y=0|x) = 1 。如果是后者,显然全局最优解就是 y=f(x) 恒等于 0 。
jdhao
2021-12-30 10:36:58 +08:00
使用 weighted cross entropy ,增大类别少的样本权重,或者想办法把各类数据均衡
ipwx
2021-12-30 10:39:37 +08:00
@jdhao 这个例子里面,imbalance 太严重了。说句难听的,只有 2 个正例,分分钟过拟合。

这种问题建议先 unsupervised training ,用得到的 hidden representation 做更稳的分类器。
zxCoder
2021-12-30 20:25:51 +08:00
@ipwx 检查了一下,一共 120 个标签,5 万多个训练样本
标签分布大概是
[656, 122, 380, 217, 2276, 794, 149, 458, 248, 626, 102, 135, 396, 127, 141, 3431, 161, 687, 352, 157, 1322, 1887, 423, 313, 994, 880, 125, 138, 295, 473, 263, 106, 1153, 221, 297, 1643, 150, 3083, 218, 403, 277, 258, 524, 5553, 246, 128, 205, 735, 115, 1089, 159, 201, 438, 1984, 536, 148, 666, 251, 103, 499, 263, 124, 217, 823, 136, 112, 157, 128, 747, 202, 189, 147, 115, 224, 122, 920, 2176, 235, 247, 1861, 110, 124, 1178, 199, 166, 106, 457, 3718, 154, 12597, 641, 182, 354, 164, 277, 230, 232, 106, 3445, 979, 1589, 132, 105, 150, 219, 188, 168, 535, 284, 2137, 1351, 101, 542, 115, 804, 114, 384, 125, 102, 1334]

感觉也还行吧,这算不均衡吗
zxCoder
2021-12-30 20:32:15 +08:00
而且同样的数据,之前在其他基于 bert 的模型上跑也没出现这问题啊
c0xt30a
2021-12-31 03:39:28 +08:00
这个问题的根源在于, 激活函数是 softmax 的时候,最后一层的输出强制非负并且和为 1;
更换到 sigmoid 之后,输出之和为 1 的限制被解去了。
当有 1000+ 个 label ,而一个样本最多有两个 label 是 1 的时候,网络输出全为 0 明显是一个局部最小,而且基本上不能跳出来的那种。
c0xt30a
2021-12-31 03:47:48 +08:00
我出个主意:
鉴于最多有两个标签是 1 ,那么可以依旧用 softmax 做激活,用 soft label 处理下数据。

譬如,当某个样本只有 1 个标签的时候,把这个标签设置为 0.5 ,其他的 999 个平分剩下的 0.5 ;当某个样本有两个标签的时候,把这两个标签都设置为 0.5 ,其余的标签设置为 0 。

刚拍脑袋想出来的,不保证靠谱。
ipwx
2021-12-31 10:23:47 +08:00
@zxCoder 噗你不说我看 sigmoid 还以为你这是二分类。

多分类你用 sigmoid 做各维独立当然不太行。。。
zxCoder
2021-12-31 10:32:29 +08:00
@ipwx 啊 为啥啊,做的是多标签分类,之前一直用 sigmoid
ipwx
2021-12-31 10:39:31 +08:00
哦哦哦 等等,是多标签分类。

那你说不定可以试试在输出层的 loss 上,各维独立添加惩罚系数,就正比于根据你上面那个类别数量的倒数。

不过我觉得你说不定前面的网络哪里有问题。。。
ipwx
2021-12-31 10:53:14 +08:00
哦又重新看了看你的问题描述。

我懂了,你的问题果然还是各维独立做多标签这里出了问题。
记 C = sum(你上面那个频数列表)

np.percentile(C / C.sum(), [1,10,20,50,80,90,99])
=> array([0.00119775, 0.0013504 , 0.00157821, 0.00292978, 0.00979803,
0.01954908, 0.06111261])

这个 imbalance 太严重了。各个维度都输出 0 就是一个非常巨大的局部最小值点。

解决方法 1:在每一维输出的时候,如果是 1 就 loss 添加惩罚系数 C / 类别频率,0 就添加 C / (1 - 类别频率)。这样能把各维二分类各自的 imbalance 问题降下来。

解决方法 2:还是 softmax 做 top-k 分类推荐。额外添加一个分类器预测到底输入有多少个输出类。
ipwx
2021-12-31 10:55:57 +08:00
@zxCoder 从逻辑回归角度看 0-1 分类会有这样的结论:

对于一个二分类器而言,如果你的类别 A 出现概率是 p ,类别 B 出现概率是 1-p ,并且两类在 loss 上的贡献是等权的,那么最终你的分类器的决策边界大概在 p 附近。

你的所有类别都严重 imbalance ,p 的 99% 分位数都只有 0.06 ,那么你每一类的分类边界,小的大概在 0.001 ,大的也只有 0.06 。但是你在做预测的时候决策边界是 0.5 ,那么当然全部认为是 0 。

我说的那个惩罚系数就是强行把这个决策边界拉回 0.5 附近。
ipwx
2021-12-31 10:56:32 +08:00
想了想惩罚系数也可以这样

1 => (1 - 类别频率),0 => 类别频率
zxCoder
2021-12-31 11:02:37 +08:00
@ipwx 没辙了。。。加了 weight 也不行,把多标签分类改成多分类也不行,总是预测到同一个类别。。。这破论文怎么就还能发呢。。。
zxCoder
2021-12-31 11:14:32 +08:00
@ipwx
”1 => (1 - 类别频率),0 => 类别频率“

老哥能不能说下代码怎么实现这个啊。这个是要自己循环判断每个 label 的预测结果再计算 loss 吗?直接用 weight 好像只能是给每个 label 分配不同的权重
ipwx
2021-12-31 13:14:52 +08:00
@zxCoder 你们用 pytorch 的都没有自己写 train loop 的经历了么啊,只能 model.fit ??

class_prob = C / C.sum()

自己组 loss 不就随便搞了。伪代码:

binary_cross_entropy(logits, label) * torch.where(label == 1, 1-C[label], C[label])

肯定有辙啊

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/825206

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX