科大讯飞-中文成语填空挑战赛:ERNIE MASK填空 80%精度
作者:互联网
赛事背景
中国文化博大精深源远流长,其中成语更是中国文化的精华。成语大多由四个字组成,一般都有典故或出处。有些成语从字面上不难理解,如“小题大做”、“后来居上”等。有些成语必须知道来源或典故才能懂得意思,如“朝三暮四”、“杯弓蛇影”等。
成语学习是小学语文和初中重要的学习内容,如何在语句中选择合适的成语?本次赛题中希望选手构建模型能理解中文成语。
https://challenge.xfyun.cn/topic/info?type=chinese-idioms
赛事任务
给定一个中文句子的情况下,需要选手在给定上下文的情况下从待选的成语中选择最为合适的成语。即给定句子的上下文,完成合适的成语填入对应位置。
赛事数据集
训练集5w条数据,测试集1w条数据。测试集中label字段为空,需要选手预测。
数据集样例:
- 原始文本:眼下,政府部门利用网络公开信息,汇集民意,提高工作效率,拉近与群众的距离,早已“[MASK].
- 待选成语:[‘不堪一击’, ‘蔚然成风’, ‘如风过耳’, ‘鬼工雷斧’]
- 正确答案:蔚然成风
评审规则
-
数据说明
赛题数据由训练集和测试集组成,训练集5w条数据,测试集1w条数据,均为csv格式,列使用\t分割。测试集提交案例见sample_submit.csv文件,不需要表头,直接按照顺序按行写入1w条成语即可。 -
评估指标
本次竞赛的评价标准采用分类准确率,最高分为1。评估代码参考:
from sklearn.metrics import accuracy_score
y_pred = [0, 2, 1, 3]
y_true = [0, 1, 2, 3]
accuracy_score(y_true, y_pred)
!pip install paddle-ernie > log.log
import sys
import numpy as np
import pandas as pd
from sklearn.metrics import f1_score
import paddle as P
test_df = pd.read_csv('test.csv',sep='\t')
train_df = pd.read_csv('train.csv',sep='\t')
train_df.head()
text | candidate | label | |
---|---|---|---|
0 | 作为时下最热门的数码产品,苹果iPad平板电脑已经被用户们大量入手,但不少网友在将心爱的iP... | ['彬彬有礼', '莫名其妙', '恋恋难舍', '探囊胠箧'] | 莫名其妙 |
1 | 以iPad最新的产品,大家俗称的iPad 2为例(虽然苹果公司从未称这款产品为iPad 2,... | ['衣不解带', '咂嘴咂舌', '运筹借箸', '从善如流'] | 从善如流 |
2 | 眼下,政府部门利用网络公开信息,汇集民意,提高工作效率,拉近与群众的距离,早已“[MASK]... | ['不堪一击', '蔚然成风', '如风过耳', '鬼工雷斧'] | 蔚然成风 |
3 | 一则名曰:“双胞胎政绩”。中原两个乡镇,在各自的政府网站上,挂出内容几乎完全一致的政绩报道。... | ['无独有偶', '顶天立地', '天下无双', '心劳日拙'] | 无独有偶 |
4 | 还有一则名曰:“问题‘已阅’”。不久前,某地一位网友向区长信箱反映出行难问题。过了6天,等来... | ['见怪不怪', '夫人裙带', '绝其本根', '罪应万死'] | 见怪不怪 |
train_df['text'].iloc[10]
'开拓新兴市场第一个问题就是要从头做起。在这些地区,对于网游娱乐有需求,但是没有任何现成的市场可以依托和借鉴。“这边连游戏内测、公测这样的术语也不知道。[MASK][MASK][MASK][MASK]推广的难度。”陈星对记者表示。'
解题思路
赛题已有的思路是一个典型的Mask填充的问题,具体可以使用两种思路解决:
- 使用MaskLM预测
- 使用QA文本问答
这里我们使用ERNIE来完整word-level的预测,这也是的非常契合ERNIE的模型。
定义模型
from ernie.modeling_ernie import ErnieModelForPretraining, ErnieModel
from ernie.tokenizing_ernie import ErnieTokenizer
import paddle.fluid.layers as L
import paddle.fluid.dygraph as D
class ErnieCloset(ErnieModelForPretraining):
def __init__(self, *args, **kwargs):
super(ErnieCloset, self).__init__(*args, **kwargs)
del self.pooler_heads
def forward(self, src_ids, *args, **kwargs):
pooled, encoded = ErnieModel.forward(self, src_ids, *args, **kwargs)
encoded_2d = L.gather_nd(encoded, L.where(src_ids == mask_id))
encoded_2d = self.mlm(encoded_2d)
encoded_2d = self.mlm_ln(encoded_2d)
# 转换为token预测结果
logits_2d = L.matmul(encoded_2d, self.word_emb.weight, transpose_y=True) + self.mlm_bias
return logits_2d
tokenizer = ErnieTokenizer.from_pretrained('ernie-1.0')
rev_dict = {v: k for k, v in tokenizer.vocab.items()}
rev_dict[tokenizer.pad_id] = '' # replace [PAD]
rev_dict[tokenizer.sep_id] = '' # replace [PAD]
rev_dict[tokenizer.unk_id] = '' # replace [PAD]
@np.vectorize
def rev_lookup(i):
return rev_dict[i]
ernie = ErnieCloset.from_pretrained('ernie-1.0')
ernie.eval()
ids, _ = tokenizer.encode('戊戌变法,又称百日维新,是[MASK][MASK][MASK] 、梁启超等维新派人士通过光绪帝进行 的一场资产阶级改良。')
mask_id = tokenizer.mask_id
print(ids)
ids = np.expand_dims(ids, 0)
ids = D.to_variable(ids)
logits = ernie(ids).numpy()
output_ids = np.argmax(logits, -1)
seg_txt = rev_lookup(output_ids)
print(seg_txt)
[ 1 3299 3721 282 72 4 311 351 502 139 534 102
4 10 3 3 3 6 1164 1087 634 43 534 102
809 8 391 124 93 325 1659 757 71 40 5 7
191 138 66 976 222 285 698 12043 2]
['康' '有' '为']
简单测试
for row in train_df.iloc[:10].iterrows():
print(row[1].text)
print(f'正确答案:{row[1].label}')
ids, _ = tokenizer.encode(row[1].text)
mask_id = tokenizer.mask_id
ids = np.expand_dims(ids, 0)
ids = D.to_variable(ids)
logits = ernie(ids).numpy()
candidates = eval(row[1].candidate)
candidate_logits = []
for s in candidates:
candidate_logits.append(logits[[0,1,2,3], tokenizer.encode(s)[0][1:-1]].mean())
print(f'预测结果:{candidates[np.argmax(candidate_logits)]}')
print('')
作为时下最热门的数码产品,苹果iPad平板电脑已经被用户们大量入手,但不少网友在将心爱的iPad抱回家后才发现,这东西多少有些[MASK][MASK][MASK][MASK]:iTunes、iOS系统、固件版本、 AppStore、JailbreakME越狱、同步等等好象是从字典里随机抽出的字母和文字组成的词汇出现在了大家的面前,让新入门的果粉们倍感焦躁。尽管被苹果产品弄得一头雾水,但这其实没什么不好意思的,包括小编我在内的每个苹果用户都曾有过这一经历,毕竟谁也没买东西前看说明书的习惯。
正确答案:莫名其妙
预测结果:莫名其妙
以iPad最新的产品,大家俗称的iPad 2为例(虽然苹果公司从未称这款产品为iPad 2,但这款产品确实是初代产品的升级版,所以大家不如[MASK][MASK][MASK][MASK],就称之为iPad 2),这款产品的规格有如下几个大家必须要明了的特性:
正确答案:从善如流
预测结果:从善如流
眼下,政府部门利用网络公开信息,汇集民意,提高工作效率,拉近与群众的距离,早已“[MASK][MASK][MASK][MASK]”。放眼望去,似乎没有哪个政府没有自己的网站,市长信箱、区长信箱不计其数,官员博客甚为流行。
正确答案:蔚然成风
预测结果:蔚然成风
一则名曰:“双胞胎政绩”。中原两个乡镇,在各自的政府网站上,挂出内容几乎完全一致的政绩报道。桐柏网和睢县人民政府网上,分别刊登了《程湾乡林业生态建设突出三个特色》和《睢县平岗镇林业生态建设突出三个特色》的文章,两个不同的乡镇,不仅土地面积和人口数量一致,就连种植的树苗也完全一样![MASK][MASK][MASK][MASK],今年初,“中国消防在线”网站上,河南开封消防支队和漯河消防支队的宣传稿也如出一辙,被网友戏称为“开封领导漯河指导工作”。
正确答案:无独有偶
预测结果:无独有偶
还有一则名曰:“问题‘已阅’”。不久前,某地一位网友向区长信箱反映出行难问题。过了6天,等来网上回复,就两个字:“已阅”。“已阅”两个字,不说是,又不说非,一级一级踢皮球,一级一级往下转。这个[MASK][MASK][MASK][MASK]的官场惯例,竟一脚踢到了网络上,踢到了区长信箱里。
正确答案:见怪不怪
预测结果:见怪不怪
“双胞胎政绩”、“官文博客”和“问题‘已阅’”的出现,让人[MASK][MASK][MASK][MASK],更让人敬而远之。因为群众透过这样的官网,看到的是一些官员对工作的敷衍和失职,和视群众为“愚民”的无礼和怠慢,哪里还有信息的平等化传播可言?
正确答案:啼笑皆非
预测结果:啼笑皆非
一位网友留言:领导博客不博客,根本不重要。问题是能真正体恤民情、关注民生,把群众利益无小事真正当一回事。如果这样,不管是网上还是网下,官气都将[MASK][MASK][MASK][MASK]。
正确答案:荡然无存
预测结果:荡然无存
11月18日,信产部副部长奚国华表示,固网日子现在不太好过,信产部将[MASK][MASK][MASK][MASK]推进发牌照。这一表态对没有移动牌照的中国电信及中国网通有利,此次中国移动也首次显露将会取得固网牌照并发展相关业务。新浪
正确答案:义不容辞
预测结果:目不转睛
“对IMEI应否进行管控的讨论[MASK][MASK][MASK][MASK],当初的结论是不需要。”一位资深业内人士表示,我国手机通过SIM卡入网,并非IMEI。事实是,用户每次通话,手机IMEI码都会先发到运营商后台。因此在国外,用户手机丢失后,可以要求运营商通过限制 IMEI码来停止手机使用。移动相关人士证实,我国运营商目前尚未提供此项服务。
正确答案:由来已久
预测结果:由来已久
随着中国网游市场的强劲增势,国产网游似乎在全球市场也是风光无限。网龙的《征服》正式进入中东等地,第一次在阿拉伯地区出现了中国网游的身影;蓝港的《西游记OL》在越南签约授权金高达100万美元,创下了国内网络游戏出口东南亚地区的最高纪录;而由金山、联众、目标软件、完美时空等15家企业组成的中国“舰队”首次现身日本电玩展。一时之间中国网游在海外似乎已经到了[MASK][MASK][MASK][MASK]的境地。然而真的是这样一帆风顺吗?
正确答案:开花结果
预测结果:春深似海
MAX_SEQLEN = 400
def make_data(df):
data = []
for i, row in enumerate(df.iterrows()):
text_id, _ = tokenizer.encode(row[1].text)
text_id = text_id[:MAX_SEQLEN]
text_id = np.pad(text_id, [0, MAX_SEQLEN-len(text_id)], mode='constant')
data.append((text_id, 1))
return data
test_data = make_data(test_df)
BATCH = 30
def get_batch_data(data, i):
d = data[i*BATCH: (i + 1) * BATCH]
feature, label = zip(*d)
feature = np.stack(feature) # 将BATCH行样本整合在一个numpy.array中
label = np.stack(list(label))
feature = P.to_tensor(feature) # 使用to_variable将numpy.array转换为paddle tensor
label = P.to_tensor(label)
return feature, label
批量预测
with P.no_grad():
ernie.eval()
test_idx = 0
test_pred = []
for j in range(len(test_data) // BATCH):
feature, label = get_batch_data(test_data, j)
logits = ernie(feature).numpy()
for ins_idx in range(feature.shape[0]):
candidates = eval(test_df['candidate'].iloc[test_idx])
candidate_logits = []
for s in candidates:
candidate_logits.append(
logits[ins_idx*4:(ins_idx+1)*4][[0,1,2,3], tokenizer.encode(s)[0][1:-1]].mean()
)
test_pred.append(
candidates[np.argmax(candidate_logits)]
)
test_idx+=1
pd.DataFrame({
'label': test_pred,
}).to_csv('submit.csv', index=None)
总结
本文使用MaskLM任务完成成语填空,具体的精度能够达到80%以上。此外还可以通过训练过程增加现有的精度。
标签:ernie,ERNIE,MASK,ids,test,填空,logits,id 来源: https://blog.csdn.net/m0_63642362/article/details/122273918