Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用BCELoss,计算Accuracy好像有错 #33657

Closed
DeepGeGe opened this issue Jun 18, 2021 · 13 comments
Closed

使用BCELoss,计算Accuracy好像有错 #33657

DeepGeGe opened this issue Jun 18, 2021 · 13 comments

Comments

@DeepGeGe
Copy link

   1)PaddlePaddle版本:2.1.0
   2)系统环境:Windows 10 Python3.7
二分类问题,设置输出节点数为1,使用BCELoss,发现整个训练过程和测试准确率均为0.5。(数据集中正负样本数相等)
Step into进去发现计算准确率的机制是:会将pred与label做比较,在作比较之前会将pred做一次argsort,即将pred中元素排序,返回各元素从小到大的索引,然后再将pred做一下切片。
在BCELoss情况下,pred中的shape为(batch_size, 1),这样经过pred之后pred值变成了全0,因此计算Accuracy错误。
请问这是BUG还是我的用法错误?(用法错误是指二分类问题中,最后一个输出节点不能像keras那样为1,也必须是2)
如果是我的用法错误,也就是说二分类,用BCELoss,最后一个输出节点数必须为2。但是如果输出节点数必须设置为2,那么应该用CrossEntropyLoss而不是BCELoss吧?
11
12

@DeepGeGe DeepGeGe changed the title BCELoss中计算Accuracy好像有错 使用BCELoss中计算Accuracy好像有错 Jun 18, 2021
@DeepGeGe DeepGeGe changed the title 使用BCELoss中计算Accuracy好像有错 使用BCELoss,计算Accuracy好像有错 Jun 18, 2021
@parap1uie-s
Copy link
Contributor

Accuracy里面应该是有取topk的逻辑,这个坑我也踩过。

@DeepGeGe
Copy link
Author

Accuracy里面应该是有取topk的逻辑,这个坑我也踩过。

我留意到了有取topk的逻辑,但是问题好像与这无关。是计算acc时候,会对pred做一个argsort,这么做加上后续处理逻辑,对输出维度为多维时候是正确的。但是当输出节点只有一个时候,argsort就会使得pred变成全0 tensor了。我觉得应该是没考虑到输出只有一个节点的情况。

@DeepGeGe
Copy link
Author

@FrostML

@DeepGeGe
Copy link
Author

@FrostML

大佬,这个问题不知道怎么没有被机器人分配到人,向您请教一下。

@Steffy-zxf
Copy link
Contributor

@parap1uie-s 你好!

BCELoss的输入数据input 一般是 sigmoid 的输出,shape为(batch_size, 1)。参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BCELoss_cn.html#bceloss

Accuracycompute(pred, label, *args)方法参数pred是N分类的概率值,shape为(batch_size, num_classes)。 label为真实数据label,shape为(batch_size, 1)。参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/metric/Accuracy_cn.html#accuracy

你的网络net 做后一个分类层paddle.nn.Linear()输出output_feature不应该是1,应该是数据类别数。

@DeepGeGe
Copy link
Author

@parap1uie-s 你好!

BCELoss的输入数据input 一般是 sigmoid 的输出,shape为(batch_size, 1)。参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/BCELoss_cn.html#bceloss

Accuracycompute(pred, label, *args)方法参数pred是N分类的概率值,shape为(batch_size, num_classes)。 label为真实数据label,shape为(batch_size, 1)。参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/metric/Accuracy_cn.html#accuracy

你的网络net 做后一个分类层paddle.nn.Linear()输出output_feature不应该是1,应该是数据类别数。

您好,非常感谢您的解答。也就是说在二分类问题中,PaddlePaddle框架设置输出节点必须是2,而不是像Keras那样输出节点为1?(我先学个tf和keras,后面了解到Paddle,正在往Paddle转)
但是如此(二分类中输出out_feature=2)的话,请问为什么要多弄一个BCELoss呢,而不是干脆直接统一用CrossEntropyLoss?(虽然CrossEntropyLoss会概率和为1,out_feature=2,输出经过sigmoid不会限制概率和为1,但是多弄一个BCELoss,他的优势在哪里?ps:API文档我看过很多遍了。。。)

@DeepGeGe
Copy link
Author

@Steffy-zxf
我觉得BCELoss是在二分类问题中,输出节点数为1,激活函数为sigmoid时,因为没办法计算softmax,所以设置了BCELoss。 计算cross_entropy的公式是一样的。只是BCELoss前面是一个输出节点,sigmoid函数激活,然后计算交叉熵,多分类问题是多个输出节点,softmax函数激活,然后再计算交叉熵。
当然,二分类问题也可以设置两个输出节点,然后用softmax+cross_entropy。实质是和一个输出节点,使用sigmoid+cross_entropy是一样的。只是我确实没见过二分类用两个输出节点,sigmoid函数激活,再计算交叉熵的。这样做导致两类概率和不是1,虽然理论也能够求损失,梯度下降,但是这么做感觉没道理。
(此外,我图片中最后没用sigmoid是因为损失函数用的BCEWithLogitsLoss,这个按照文档是相当于将sigmod整合进来了。)

@DeepGeGe
Copy link
Author

Accuracy里面应该是有取topk的逻辑,这个坑我也踩过。

请问您最后知道这个BCELoss的正确用法了吗?还是说用BCELoss不能直接用内置的计算accuracy方法,因为我发现它计算Loss是对的,只是计算accuracy好像是有问题的。

@parap1uie-s
Copy link
Contributor

Accuracy里面应该是有取topk的逻辑,这个坑我也踩过。

请问您最后知道这个BCELoss的正确用法了吗?还是说用BCELoss不能直接用内置的计算accuracy方法,因为我发现它计算Loss是对的,只是计算accuracy好像是有问题的。

后来我自己写了一个。或者你可以把sigmoid激活以后的模型输出二值化以后,直接和label进行比较。

@DeepGeGe
Copy link
Author

Accuracy里面应该是有取topk的逻辑,这个坑我也踩过。

请问您最后知道这个BCELoss的正确用法了吗?还是说用BCELoss不能直接用内置的计算accuracy方法,因为我发现它计算Loss是对的,只是计算accuracy好像是有问题的。

后来我自己写了一个。或者你可以把sigmoid激活以后的模型输出二值化以后,直接和label进行比较。

是的,这也是我想到的办法了。不能直接使用高阶API去训练模型,只能使用遍历epoch+batch双重循环,然后自己去计算acc。或者高阶API有传入自定义metrics的方法?不过,话说回来,这样处理还不如直接输出节点用2类,然后使用softmax+交叉熵了。问官方也没引起重视。

@DeepGeGe
Copy link
Author

没人管,算了。

@Steffy-zxf
Copy link
Contributor

@DeepGeGe 你好!如之前所说你可以在最后分类层,设置output_feature =num_classes,然后使用CrossEntropyLoss计算顺势函数值,使用paddle.nn.Accuracy计算准确率。

或者如果你想要BCELoss,最后分类层output_feature =1,但此时需要自己定义准确率acc的实现。

@DeepGeGe DeepGeGe reopened this Jun 25, 2021
@DeepGeGe
Copy link
Author

@DeepGeGe 你好!如之前所说你可以在最后分类层,设置output_feature =num_classes,然后使用CrossEntropyLoss计算顺势函数值,使用paddle.nn.Accuracy计算准确率。

或者如果你想要BCELoss,最后分类层output_feature =1,但此时需要自己定义准确率acc的实现。

了解了解,我是觉得这个应该是个BUG或者说可以进一步完善的地方,不应该这样情况下acc计算就会不支持,返回错误的结果。不过,还是非常感谢您的回复。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants