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

readme和代码实现中mask方法的逻辑不一致 #33

Closed
xiaochang129 opened this issue Mar 18, 2019 · 11 comments

Comments

@xiaochang129
Copy link

commented Mar 18, 2019

readme中:这个方法与bert最大的区别在于不是mask随机字,而是mask随机词。 代码batching中:以词为单位,首字和其他字的mask方法不一致! 非首字按bert方法mask,首字按15%,15%,70%分别mask,replace,不变。 个人看法:保持首字和其余字的mask方法一致,效果会更好。

@zhanghan1992

This comment has been minimized.

Copy link
Collaborator

commented Mar 18, 2019

首字和非首字是按同样的方式mask,你再理解下代码吧

@xiaochang129

This comment has been minimized.

Copy link
Author

commented Mar 18, 2019

不是一样的方法,你再看下代码吧

@zhanghan1992

This comment has been minimized.

Copy link
Collaborator

commented Mar 18, 2019

只根据首字的prob是否大于0.15决定该词是否mask;因此如果mask,首字的基准概率是0.15,非首字的基准概率是1.0;按基准概率的80%, 10%, 10%决定替换的token,首字和非首字的处理是一样的

@xiaochang129

This comment has been minimized.

Copy link
Author

commented Mar 18, 2019

首字和非首字的mask概率是一样的,但按照代码实现的方法,因为基准概率不同,mask的方法是不同的

@BucherLi

This comment has been minimized.

Copy link

commented Mar 26, 2019

首字和其他字的mask方法不一致

不是按照词mask的吗,你是说首词和其他词mask方法不一致?

@xiaochang129

This comment has been minimized.

Copy link
Author

commented Mar 27, 2019

嗯,不一致

@randomtutu

This comment has been minimized.

Copy link

commented Jun 18, 2019

代码的维护同学,你好呀

因为要用到以词为单位的mask方式,而且之前看到这个地方有争议,所以我最近仔细看了一下代码。

我先说一下我的结论,mask的方式确实是词,但是概率应该不是15%。

解释一下为什么,

首先,假设输入语料里有M个‘词’

那么,假如要mask 15% 的词,那么mask词的数目应该是0.15*M

代码prob_mask = np.random.rand(total_token_num)可以理解为对每一个token分配一个概率,而token得分布是正太分布。

而在判断是否要mask的时候用的条件是 prob <= 0.15 and token_seg_label == 0, prob代表token分配得到的概率,token_seg_label=0表示词首。且判断完成之后,是不会用到token的prob的了。

并且,显然的是token是否为‘词首’ 与 token分配得到的概率的分布 是独立的两个分布

因此,最终mask的数目因该是0.15 * M * P(词首),P(词首)代表一个token为词首的概率。

如有不妥请指正

最后,感谢你们的工作,感觉很好。

@zhanghan1992

This comment has been minimized.

Copy link
Collaborator

commented Jul 4, 2019

代码的维护同学,你好呀

因为要用到以词为单位的mask方式,而且之前看到这个地方有争议,所以我最近仔细看了一下代码。

我先说一下我的结论,mask的方式确实是词,但是概率应该不是15%。

解释一下为什么,

首先,假设输入语料里有M个‘词’
那么,假如要mask 15% 的词,那么mask词的数目应该是0.15*M
代码prob_mask = np.random.rand(total_token_num)可以理解为对每一个token分配一个概率,而token得分布是正太分布。
而在判断是否要mask的时候用的条件是 prob <= 0.15 and token_seg_label == 0, prob代表token分配得到的概率,token_seg_label=0表示词首。且判断完成之后,是不会用到token的prob的了。
并且,显然的是token是否为‘词首’ 与 token分配得到的概率的分布 是独立的两个分布
因此,最终mask的数目因该是0.15 * M * P(词首),P(词首)代表一个token为词首的概率。
如有不妥请指正

最后,感谢你们的工作,感觉很好。

你算的这个是一个token既是词首又被mask的概率。并不是整体的mask概率

@zhanghan1992

This comment has been minimized.

Copy link
Collaborator

commented Jul 4, 2019

针对mask机制的疑问,统一回复下。

token的mask概率:对于词首token,显而易见mask概率是0.15;对于非词首token,是否被mask的取决于其词首,因此被mask的概率也是0.15。
mask的替换方式,对于首字,被替换成[MASK]的概率是p(0.15 * 0.2 <prob[beg]<0.15) = 0.12;对于非首字,被替换成[MASK]的概率是p( prob[token_index] > 0.2 | prob[beg] < 0.15) * p(prob[beg] < 0.15) = 0.8 * 0.15=0.12。首字和非首字的替换方式是一样的。

@randomtutu

This comment has been minimized.

Copy link

commented Jul 4, 2019

代码的维护同学,你好呀
因为要用到以词为单位的mask方式,而且之前看到这个地方有争议,所以我最近仔细看了一下代码。
我先说一下我的结论,mask的方式确实是词,但是概率应该不是15%。
解释一下为什么,

首先,假设输入语料里有M个‘词’
那么,假如要mask 15% 的词,那么mask词的数目应该是0.15*M
代码prob_mask = np.random.rand(total_token_num)可以理解为对每一个token分配一个概率,而token得分布是正太分布。
而在判断是否要mask的时候用的条件是 prob <= 0.15 and token_seg_label == 0, prob代表token分配得到的概率,token_seg_label=0表示词首。且判断完成之后,是不会用到token的prob的了。
并且,显然的是token是否为‘词首’ 与 token分配得到的概率的分布 是独立的两个分布
因此,最终mask的数目因该是0.15 * M * P(词首),P(词首)代表一个token为词首的概率。
如有不妥请指正

最后,感谢你们的工作,感觉很好。

你算的这个是一个token既是词首又被mask的概率。并不是整体的mask概率

你说得没错,确实是既是词首又被mask的概率。

但是,重要的是想要mask的是词,首先需要有词首才会进入mask的流程。

虽然进入mask流程后,总体用的概率是15%。

if prob > 0.15: pass else: # 小于等于0.15进mask流程 for index in xrange(beg, token_index): prob = prob_mask[prob_index + index] base_prob = 1.0 # 下面的if语句,更改首字的基准,因为第一个if语句已经判断了prob[首字]<=0.15 if index == beg: base_prob = 0.15 # 下面的if语句要问一个问题,对于非首字,p(prob<=0.15 | 词首) 是不是等于p(prob<=0.15)? 如果答案是肯定的,那么才会有结论:15%tokens被mask。 # 谨慎一点,我大概能理解你的出发点,应该是词首代表词,非词首的字也是由词首决定的,所以对于所有的mask的token就是0.15。但是非词首的prob其实和之前词首的prob是有关联的,在一个正态分布里面。关键就是两种方法,假如有50个词,100个token,1)每次random一个随机数 and 是否词首和2)生成一个100个随机数的列表,然后根据token的位置来取值 and 是否词首,两者是不是有差别。 # 不过我真的感觉其实实现方法不是那么重要,关键是模型效果好。我也不是有意抬杠,主要的出发点其实是怕别人看到楼主的描述就对这个工作不信任,所以解释一下。 # 最后的结论:确实是mask的词~~ if base_prob * 0.2 < prob <= base_prob: mask_label.append(sent[index]) sent[index] = MASK mask_flag = True mask_pos.append(sent_index * max_len + index) elif base_prob * 0.1 < prob <= base_prob * 0.2: mask_label.append(sent[index]) sent[index] = replace_ids[prob_index + index] mask_flag = True mask_pos.append(sent_index * max_len + index) else: mask_label.append(sent[index]) mask_pos.append(sent_index * max_len + index)
最后,感谢回复!

@Sherriiie

This comment has been minimized.

Copy link

commented Aug 1, 2019

针对mask机制的疑问,统一回复下。

token的mask概率:对于词首token,显而易见mask概率是0.15;对于非词首token,是否被mask的取决于其词首,因此被mask的概率也是0.15。
mask的替换方式,对于首字,被替换成[MASK]的概率是p(0.15 * 0.2 <prob[beg]<0.15) = 0.12;对于非首字,被替换成[MASK]的概率是p( prob[token_index] > 0.2 | prob[beg] < 0.15) * p(prob[beg] < 0.15) = 0.8 * 0.15=0.12。首字和非首字的替换方式是一样的。

Ernie2.0 里面提到的entity 被mask 的概率是100%, 这个逻辑在代码的哪里实现的?在哪里区分要mask的是 phrase or entity的?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.