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

对于实验结果召回率不高的情况有什么优化建议吗 #31

Open
18782961008 opened this issue Mar 23, 2020 · 29 comments
Open

Comments

@18782961008
Copy link

通过CSD过滤我获取到了较高的精准度,但召回率仅有56%,即使无过滤召回率也只有65%,请问有进一步提高召回率的思路吗,比如更换bert模型哈工大的Chinese-BERT-wwm和最新albert模型,增加更丰富的训练数据,这样可行吗?

@eugene-yh
Copy link
Collaborator

通过CSD过滤我获取到了较高的精准度,但召回率仅有56%,即使无过滤召回率也只有65%,请问有进一步提高召回率的思路吗,比如更换bert模型哈工大的Chinese-BERT-wwm和最新albert模型,增加更丰富的训练数据,这样可行吗?

是的,在CSD最大化精确和召回的情况下,只有通过用性能更好的MLM来召回更多正确候选项从而提高模型整体的召回。

@18782961008
Copy link
Author

我尝试用RoBERTa-wwm-ext-large模型替换bert生成候选字符,确实在召回率上有了约6%的提升。同时调研资料时看到去年又出了一个新的MLM叫ELECTRA,作者有关注到吗,由于RoBERTa跟bert用法是一样的所以比较好验证,但我不知道ELECTRA是不是可以继续用你的源码微调训练后替换bert做DAE

@BigWavelet
Copy link

hi 请问你复现实验结果是在什么样的机器上fine-tune的模型呀,这里的fine-tune实际上是bert的pre-train对吧?对机器gpu要求有多高, 谢谢

@18782961008
Copy link
Author

hi请问你复现实验结果是在某种类型的机器上fine-tune的模型呀,这里的fine-tune实际上是bert的pre-train对吧?对机器gpu要求有多高,谢谢

实验复现是bert基础上fine-tune和pre-training,bert的GPU要求12G

@BigWavelet
Copy link

hi请问你复现实验结果是在某种类型的机器上fine-tune的模型呀,这里的fine-tune实际上是bert的pre-train对吧?对机器gpu要求有多高,谢谢

实验复现是bert基础上fine-tune和pre-training,bert的GPU要求12G

pre-train steps learning_rate设置的多少呢, 跑了多长时间呀

@18782961008
Copy link
Author

hi请问你复现实验结果是在某种类型的机器上fine-tune的模型呀,这里的fine-tune实际上是bert的pre-train对吧?对机器gpu要求有多高,谢谢

实验复现是bert基础上微调和预训练,bert的GPU要求12G

训练前的步骤learning_rate设置的多少呢,跑了多长时间呀

train_batch_size=32 --max_seq_length=128 --max_predictions_per_seq=20 --num_train_steps=10000 --num_warmup_steps=2000 --learning_rate=2e-5
我的在GPU上大概跑了20个小时

@BigWavelet
Copy link

hi请问你复现实验结果是在某种类型的机器上fine-tune的模型呀,这里的fine-tune实际上是bert的pre-train对吧?对机器gpu要求有多高,谢谢

实验复现是bert基础上微调和预训练,bert的GPU要求12G

训练前的步骤learning_rate设置的多少呢,跑了多长时间呀

train_batch_size=32 --max_seq_length=128 --max_predictions_per_seq=20 --num_train_steps=10000 --num_warmup_steps=2000 --learning_rate=2e-5
我的在GPU上大概跑了20个小时

哦哦, 感谢! 是单gpu跑的是吧, 具体gpu什么型号方便告知一下吗, 想入手一台捣鼓一下。。。

@18782961008
Copy link
Author

hi请问你复现实验结果是在某种类型的机器上fine-tune的模型呀,这里的fine-tune实际上是bert的pre-train对吧?对机器gpu要求有多高,谢谢

实验复现是bert基础上微调和预训练,bert的GPU要求12G

训练前的步骤learning_rate设置的多少呢,跑了多长时间呀

train_batch_size=32 --max_seq_length=128 --max_predictions_per_seq=20 --num_train_steps=10000 --num_warmup_steps=2000 --learning_rate=2e-5
我的在GPU上大概跑了20个小时

哦哦, 感谢! 是单gpu跑的是吧, 具体gpu什么型号方便告知一下吗, 想入手一台捣鼓一下。。。

Fri Apr 10 10:16:16 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.01 Driver Version: 418.87.01 CUDA Version: 10.1 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Tesla T4 Off | 00000000:17:00.0 Off | 0 |
| N/A 44C P0 29W / 70W | 6706MiB / 15079MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 1 Tesla T4 Off | 00000000:65:00.0 Off | 0 |
| N/A 45C P0 28W / 70W | 4428MiB / 15079MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 2 GeForce GTX 108... Off | 00000000:B3:00.0 Off | N/A |
| 23% 36C P8 15W / 250W | 2538MiB / 11176MiB | 0% Default |

@BigWavelet
Copy link

hi请问你复现实验结果是在某种类型的机器上fine-tune的模型呀,这里的fine-tune实际上是bert的pre-train对吧?对机器gpu要求有多高,谢谢

实验复现是bert基础上微调和预训练,bert的GPU要求12G

训练前的步骤learning_rate设置的多少呢,跑了多长时间呀

train_batch_size=32 --max_seq_length=128 --max_predictions_per_seq=20 --num_train_steps=10000 --num_warmup_steps=2000 --learning_rate=2e-5
我的在GPU上大概跑了20个小时

哦哦, 感谢! 是单gpu跑的是吧, 具体gpu什么型号方便告知一下吗, 想入手一台捣鼓一下。。。

Fri Apr 10 10:16:16 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.01 Driver Version: 418.87.01 CUDA Version: 10.1 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Tesla T4 Off | 00000000:17:00.0 Off | 0 |
| N/A 44C P0 29W / 70W | 6706MiB / 15079MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 1 Tesla T4 Off | 00000000:65:00.0 Off | 0 |
| N/A 45C P0 28W / 70W | 4428MiB / 15079MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 2 GeForce GTX 108... Off | 00000000:B3:00.0 Off | N/A |
| 23% 36C P8 15W / 250W | 2538MiB / 11176MiB | 0% Default |

十分感谢, 那看起来一块Tesla T4 16G的就够的样子?

@JohnParken
Copy link

我尝试用RoBERTa-wwm-ext-large模型替换bert生成候选字符,确实在召回率上有了约6%的提升。同时调研资料时看到去年又出了一个新的MLM叫ELECTRA,作者有关注到吗,由于RoBERTa跟bert用法是一样的所以比较好验证,但我不知道ELECTRA是不是可以继续用你的源码微调训练后替换bert做DAE

请问是在什么数据集上做的优化呢,我用RoBERTa-wwm-ext-large复现结果不太理想,还有能透露一下目前达到的效果是什么样子的吗,感谢感谢

@xxzcool
Copy link

xxzcool commented Apr 26, 2020

@18782961008 求助大佬,一直无法复现char_meta.txt,能发一份处理好的给我吗?或者复现这一步的code也行。[email protected]

@cb1473258684
Copy link

@18782961008 求助大佬,一直无法复现char_meta.txt,能发一份处理好的给我吗?或者复现这一步的code也行。[email protected]

你好,请问你的char_meta.txt文件处理好了吗?方不方便分享一下或者指导一下过程

@nonva
Copy link

nonva commented May 20, 2020

CSD过滤

CSD过滤是人工画曲线写过滤函数,可否分享下这个过滤函数的定义?看看大概是什么样的函数簇

@hscspring
Copy link

在作者提供的测试集上跑出的结果(只用了 rank0,difference 配置):

corretion:
char_p=774/882
char_r=774/1303
sent_p=544/731
sent_r=544/1000
sent_a=544/1000
detection:
char_p=846/882
char_r=846/1303
sent_p=603/731
sent_r=603/1000
sent_a=603/1000

@AnddyWang
Copy link

AnddyWang commented Nov 9, 2020

在作者提供的测试集上跑出的结果(只用了 rank0,difference 配置):

corretion:
char_p=774/882
char_r=774/1303
sent_p=544/731
sent_r=544/1000
sent_a=544/1000
detection:
char_p=846/882
char_r=846/1303
sent_p=603/731
sent_r=603/1000
sent_a=603/1000

@hscspring difference 配置,这个是怎么配置的呢,我试验了下没有跑出来你这么好的效果呢,方便沟通下吗

@hscspring
Copy link

@AnddyWang 就是设置 top_difference 为 True 时的结果。主要是要手工画出那条分割线。

@AnddyWang
Copy link

@AnddyWang 就是设置 top_difference 为 True 时的结果。主要是要手工画出那条分割线。

我们建议按照如下顺序来为每组子候选字符组来寻找过滤曲线:

top_difference=True, sim_type='shape', rank=0
top_difference=True, sim_type='shape', rank=1
top_difference=True, sim_type='shape', rank=2
... , ... , ...
top_difference=True, sim_type='sound', rank=0
top_difference=True, sim_type='sound', rank=1
top_difference=True, sim_type='sound', rank=2
... , ... , ...
top_difference=False, sim_type='shape', rank=0
top_difference=False, sim_type='shape', rank=1
top_difference=False, sim_type='shape', rank=2
... , ... , ...
top_difference=False, sim_type='sound', rank=0
top_difference=False, sim_type='sound', rank=1
top_difference=False, sim_type='sound', rank=2
difference_1-rank_0-results_0

@hscspring 我按照作者建议的这种方式,画出来的图好多是空的呢,difference_1-rank_0-results_0的图是上边这个,该怎么画分割线呢。

@hscspring
Copy link

hscspring commented Nov 11, 2020 via email

@AnddyWang
Copy link

你这个不好画,是配置还是计算相似度那里有问题,看起来应该类似这样: [image: shape_split_curve_difference_1-rank_0-results_0.png] AnddyWang [email protected] 于2020年11月10日周二 下午5:27写道:

@AnddyWang https://github.com/AnddyWang 就是设置 top_difference 为 True 时的结果。主要是要手工画出那条分割线。 我们建议按照如下顺序来为每组子候选字符组来寻找过滤曲线: top_difference=True, sim_type='shape', rank=0 top_difference=True, sim_type='shape', rank=1 top_difference=True, sim_type='shape', rank=2 ... , ... , ... top_difference=True, sim_type='sound', rank=0 top_difference=True, sim_type='sound', rank=1 top_difference=True, sim_type='sound', rank=2 ... , ... , ... top_difference=False, sim_type='shape', rank=0 top_difference=False, sim_type='shape', rank=1 top_difference=False, sim_type='shape', rank=2 ... , ... , ... top_difference=False, sim_type='sound', rank=0 top_difference=False, sim_type='sound', rank=1 top_difference=False, sim_type='sound', rank=2 [image: difference_1-rank_0-results_0] https://user-images.githubusercontent.com/19400072/98654926-da92c980-2379-11eb-8244-2e0a708af317.png @hscspring https://github.com/hscspring 我按照作者建议的这种方式,画出来的图好多是空的呢,difference_1-rank_0-results_0的图是上边这个,该怎么画分割线呢。 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#31 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZDQ4I4B2FALM2LXW3KSGTSPEBRFANCNFSM4LRTMTVA .

@hscspring 上传的图没法查看,方便重新传下么?另外 difference 配置和计算相似度哪里可能会有问题呢,大佬,方便具体说下么?做划线实验的时候是用默认的curve_null吧?

@hscspring
Copy link

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。

比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。

difference_1-rank_0-results_0

还不行的话可以邮件进一步联系。

@AnddyWang
Copy link

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。

比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。

difference_1-rank_0-results_0

还不行的话可以邮件进一步联系。

好的,多谢,我再试试

@blueseven77
Copy link

你好,我在运行到训练CSD时的总体设置,第一个命令top_difference=True, sim_type='shape', rank=0,一开始弹出来的图只有一个红点,后来保存的两个图一片空白,什么都没有,其中运行时我遇到了一个问题,就是在faspell第292行:char = sentences[i][j - 1],访问字符串越界,然后我限定了j<=len(sentences[i]),可否请问这是怎么了

@winniechiou
Copy link

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。

比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。

difference_1-rank_0-results_0

还不行的话可以邮件进一步联系。

您好!因為作者在readme中僅提到建議的訓練順序,但我對於訓練CSD的步驟不太理解,不知道要執行哪段程式碼才能畫出此圖進行訓練,因此想請教您,謝謝

@winniechiou
Copy link

以及想知道readme csd 中Setting the dump_candidates to a saving path will help you save the candidates,這段我該如何產生candidates,以及保存的格式是什麼呢?謝謝

@hscspring
Copy link

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。
比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。
difference_1-rank_0-results_0
还不行的话可以邮件进一步联系。

您好!因為作者在 readme 中僅提到建議的訓練順序,但我對於訓練 CSD 的步驟不太理解,不知道要執行哪段程式碼才能畫出此圖進行訓練,因此想請教您,謝謝

README 中有给出训练代码。

你可以先尝试理解一下这么做的原因,考虑到MLM给出对应位置的token候选字,但我们应该怎么选择最高的那个?可以naive地用置信度最高的,但是本文使用了CSD,就是综合考虑置信度和相似度(编辑距离、拼音等)。这个csd(confidence-similarity decoder)的参数就是就是这个分割曲线的参数,一次次拟合出来的。

@winniechiou
Copy link

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。
比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。
difference_1-rank_0-results_0
还不行的话可以邮件进一步联系。

您好!因為作者在 readme 中僅提到建議的訓練順序,但我對於訓練 CSD 的步驟不太理解,不知道要執行哪段程式碼才能畫出此圖進行訓練,因此想請教您,謝謝

README 中有给出训练代码。

你可以先尝试理解一下这么做的原因,考虑到MLM给出对应位置的token候选字,但我们应该怎么选择最高的那个?可以naive地用置信度最高的,但是本文使用了CSD,就是综合考虑置信度和相似度(编辑距离、拼音等)。这个csd(confidence-similarity decoder)的参数就是就是这个分割曲线的参数,一次次拟合出来的。

謝謝您的回覆!
我的理解是:對於top_difference=True的執行 python faspell.py -m e -t -d,然後更改faspell_configs.json的參數,以符合原作者提供的順序。但還是不明白dump_candidates保存路徑的檔案類別該設成什麼呢?

理解csd分割曲線參數的意義了!您在前面提到「主要是要手工画出那条分割线。」,想請問這邊的手工畫出分割線參數,該如何轉為csd分割曲線參數呢?

@hscspring
Copy link

hscspring commented Sep 27, 2022

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。
比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。
difference_1-rank_0-results_0
还不行的话可以邮件进一步联系。

您好!因為作者在 readme 中僅提到建議的訓練順序,但我對於訓練 CSD 的步驟不太理解,不知道要執行哪段程式碼才能畫出此圖進行訓練,因此想請教您,謝謝

README 中有给出训练代码。
你可以先尝试理解一下这么做的原因,考虑到 MLM 给出对应位置的 token 候选字,但我们应该怎么选择最高的那个?可以 naive 地用置信度最高的,但是本文使用了 CSD,就是综合考虑置信度和相似度(编辑距离、拼音等)。这个 csd(confidence-similarity decoder)的参数就是就是这个分割曲线的参数,一次次拟合出来的。

謝謝您的回覆! 我的理解是:對於 top_difference=True 的執行 python faspell.py -m e -t -d,然後更改 faspell_configs.json 的參數,以符合原作者提供的順序。但還是不明白 dump_candidates 保存路徑的檔案類別該設成什麼呢?

理解 csd 分割曲線參數的意義了!您在前面提到「主要是要手工画出那条分割线。」,想請問這邊的手工畫出分割線參數,該如何轉為 csd 分割曲線參數呢?

我记得保存那个参数里有设置,应该是避免重复计算,因为mlm每次结果都一样的,没必要重新算。

这里的「手工」应该是肉眼根据实验结果判断选择一条「合适」的曲线,这个见仁见智了,paper里有几张不同曲线的图可以参考参考。感觉线性或二次函数应该都可以,这个拟合就比较简单了,写好方程,估几个参数凑一下就差不多了。

我是这样理解的,供参考。

@winniechiou
Copy link

winniechiou commented Sep 28, 2022

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。
比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。
difference_1-rank_0-results_0
还不行的话可以邮件进一步联系。

您好!因為作者在 readme 中僅提到建議的訓練順序,但我對於訓練 CSD 的步驟不太理解,不知道要執行哪段程式碼才能畫出此圖進行訓練,因此想請教您,謝謝

README 中有给出训练代码。
你可以先尝试理解一下这么做的原因,考虑到 MLM 给出对应位置的 token 候选字,但我们应该怎么选择最高的那个?可以 naive 地用置信度最高的,但是本文使用了 CSD,就是综合考虑置信度和相似度(编辑距离、拼音等)。这个 csd(confidence-similarity decoder)的参数就是就是这个分割曲线的参数,一次次拟合出来的。

謝謝您的回覆! 我的理解是:對於 top_difference=True 的執行 python faspell.py -m e -t -d,然後更改 faspell_configs.json 的參數,以符合原作者提供的順序。但還是不明白 dump_candidates 保存路徑的檔案類別該設成什麼呢?
理解 csd 分割曲線參數的意義了!您在前面提到「主要是要手工画出那条分割线。」,想請問這邊的手工畫出分割線參數,該如何轉為 csd 分割曲線參數呢?

我记得保存那个参数里有设置,应该是避免重复计算,因为mlm每次结果都一样的,没必要重新算。

这里的「手工」应该是肉眼根据实验结果判断选择一条「合适」的曲线,这个见仁见智了,paper里有几张不同曲线的图可以参考参考。感觉线性或二次函数应该都可以,这个拟合就比较简单了,写好方程,估几个参数凑一下就差不多了。

我是这样理解的,供参考。

了解了!謝謝您的回覆!我看作者有提供Curve的範例,但不太理解為什麼會有flag1, flag2兩條曲線,不是只要一條曲線分割開就好嗎?以及不理解這邊的function最後return會是False呢?

def curve_01(confidence, similarity):
        """
        we provide an example of how to write a curve. Empirically, curves are all convex upwards.
        Thus we can approximate the filtering effect of a curve using its tangent lines.
        """
        flag1 = 20 / 3 * confidence + similarity - 21.2 / 3 > 0
        flag2 = 0.1 * confidence + similarity - 0.6 > 0
        if flag1 or flag2:
            return True
        return False

還有一點是我是使用自己的資料去fine-tune model,但畫出的difference=True, rank=0, shape圖點的重疊度很高,模型效果很差,無法以曲線分割點,想請問這可能是model overfitting導致嗎?
截圖 2022-09-28 下午9 36 05

@hscspring
Copy link

划线的之前 shape 和 sound 是分开的。要按照 README 的顺序严格操作下来。
比如 difference=True, rank=0, shape 的图是这样,可以看出大概能画一条线把红圈(右上)和叉叉(左下)分开。我就是这么分的,不一定对,你参考看看。
difference_1-rank_0-results_0
还不行的话可以邮件进一步联系。

您好!因為作者在 readme 中僅提到建議的訓練順序,但我對於訓練 CSD 的步驟不太理解,不知道要執行哪段程式碼才能畫出此圖進行訓練,因此想請教您,謝謝

README 中有给出训练代码。
你可以先尝试理解一下这么做的原因,考虑到 MLM 给出对应位置的 token 候选字,但我们应该怎么选择最高的那个?可以 naive 地用置信度最高的,但是本文使用了 CSD,就是综合考虑置信度和相似度(编辑距离、拼音等)。这个 csd(confidence-similarity decoder)的参数就是就是这个分割曲线的参数,一次次拟合出来的。

謝謝您的回覆! 我的理解是:對於 top_difference=True 的執行 python faspell.py -m e -t -d,然後更改 faspell_configs.json 的參數,以符合原作者提供的順序。但還是不明白 dump_candidates 保存路徑的檔案類別該設成什麼呢?
理解 csd 分割曲線參數的意義了!您在前面提到「主要是要手工画出那条分割线。」,想請問這邊的手工畫出分割線參數,該如何轉為 csd 分割曲線參數呢?

我记得保存那个参数里有设置,应该是避免重复计算,因为 mlm 每次结果都一样的,没必要重新算。
这里的「手工」应该是肉眼根据实验结果判断选择一条「合适」的曲线,这个见仁见智了,paper 里有几张不同曲线的图可以参考参考。感觉线性或二次函数应该都可以,这个拟合就比较简单了,写好方程,估几个参数凑一下就差不多了。
我是这样理解的,供参考。

了解了!謝謝您的回覆!我看作者有提供 Curve 的範例,但不太理解為什麼會有 flag1, flag2 兩條曲線,不是只要一條曲線分割開就好嗎?以及不理解這邊的 function 最後 return 會是 False 呢?

def curve_01(confidence, similarity):
        """
        we provide an example of how to write a curve. Empirically, curves are all convex upwards.
        Thus we can approximate the filtering effect of a curve using its tangent lines.
        """
        flag1 = 20 / 3 * confidence + similarity - 21.2 / 3 > 0
        flag2 = 0.1 * confidence + similarity - 0.6 > 0
        if flag1 or flag2:
            return True
        return False

還有一點是我是使用自己的資料去 fine-tune model,但畫出的 difference=True, rank=0, shape 圖點的重疊度很高,模型效果很差,無法以曲線分割點,想請問這可能是 model overfitting 導致嗎? 截圖 2022-09-28 下午9 36 05

两条和一条没有本质区别,这里目的只是把点分开,return True和False 就表示点在哪一个区域。

你的横坐标都是0啊,不知道是confidence还是similarity,但无论是哪个全为0这说不通。重新检查一下步骤,只要按照readme完整下来应该是可以完全复现的。

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