eva-n27 / BERT-for-Chinese-Question-Answering

Apache License 2.0
78 stars 18 forks source link

run_squad.py 代码片段 #2

Closed hitxujian closed 5 years ago

hitxujian commented 5 years ago

感谢分享:在代码 run_squad.py 中,关于代码片段: if (example.start_position < doc_start or example.end_position < doc_start or example.start_position > doc_end or example.end_position > doc_end): continue example.start_position 和 end_position 是答案在 分词后的文本中的位置(这个分词一般是jieba分词,和bert自带的分词粒度不一致) 但是 doc_start 和 doc_end 是 针对span的,而span的开始和结束位置都是 针对 bert分词的,因为下图的all_doc_tokens是针对bert分词计算的

_002

我觉得这里的代码意思就是对输入 段落 做过滤,只保留 截取的那个片段是 在真实答案中的,但是我觉得这个比较不太对,因为他们比较的粒度不一致(jieba分词和bert分词)

eva-n27 commented 5 years ago

您好,很感谢您提出的issue,预祝您新春快乐! 首先,输入到本代码的数据是raw text,是未经过分词或其他处理的。考虑到bert对中文分词处理的方法,我在本仓库中的run_squad.py使用bert的tokenizer进行分词,并没有使用jieba分词。如果使用jieba分词的话,jieba分词的产生的词并不出现在bert的词表中,输入中的词将大量被[UNK]替换,输入中的信息将大量丢失。start_position和end_position在run_squad.py的164-191行计算得到。 因此,使用bert的tokenizer进行分词的话,您所说的问题应该可以解决。 希望能够帮助到您。

hitxujian commented 5 years ago

多谢解释。你的输入example中的 example. doc_tokens 是分词后的单词序列(这个一般是jieba分词)。对于jieba分词后的每个单词,具有一个 subtoken的过程,代码如下,所以也不会是 [UNK]。此外我发现 torch版的bert和 tf版的处理方式是不一致的,您可以参考 https://github.com/google-research/bert/blob/master/run_squad.py代码 419行 for (i, token) in enumerate(example.doc_tokens): orig_to_tok_index.append(len(all_doc_tokens)) sub_tokens = tokenizer.tokenize(token) for sub_token in sub_tokens: 其实关键的2个问题如下: 1、如果您处理中文,最长长度如果设置成500,一般 batch大小 如果到了20,12g的显存已经爆掉了,不知您 最大长度设置为几,batch设置多大 2、请问您处理中文阅读理解效果怎样,我的是效果很一般。

eva-n27 commented 5 years ago

感谢您的分享!

  1. 本仓库的代码由于我自己的修改,并没有使用jieba分词和sub word的形式进行处理,而是直接使用tokenizer进行处理。原始代码中应该也是使用您分享的方法。
  2. 最大长度为500的,batch size为5的时候占用显存9707M。
  3. 实验效果(em和f1)确实很一般,不过我的应用场景不需要识别出严格的边界,实际使用效果还行。