今天老肥和大家分享的是我最近参加的一个自然语言处理的比赛,复赛Rank15,喜提小米充电宝一枚。因为之前已经分享过本次竞赛的Baseline, 具体的赛事信息就不在此赘述,有需要的同学可以点上面链接回顾一下。简单来说本次比赛是要完成一个表格文本多分类的任务,评价指标为准确率。
赛题难点
有些文件的扩展名与文件格式不匹配,比如有些扩展名为xls的文件实际上是csv文件,有些扩展名为csv的文件其实是html文件。另外这些文件的编码方式也不尽相同,这都导致了文件内容难以以统一的格式读取;
在比赛的复赛阶段,约有50%的文件名是纯数字,即无法通过标题文本来直接判断文本类别。
复赛方案
文本读取
表格的读取朴实无华,使用多层try...except...
嵌套。经观察发现,只要文件的编码不是ISO-8859-1
都可以使用open
直接读取,如果是的话先尝试使用xlrd
读取所有sheet的内容,此时依然有可能发生读取报错,需将文件格式更改为标准的csv文件再加以读取。
-
for i in tqdm(
range(
len(filename_list) )):
-
-
bytes = min(
32, os.path.getsize(filename_list[i]))
-
raw = open(filename_list[i],
'rb').read(bytes)
-
result = chardet.detect(raw)
-
encoding = result[
'encoding']
-
if encoding in [
'ISO-8859-1']:
-
try:
-
content = read_sheet(filename_list[i])
-
except:
-
try:
-
new_file_name = filename_list[i].split(
'.')[
0] +
'.csv'
-
if os.path.exists(new_file_name):
-
new_file_name = new_file_name[:
-4] +
'9999' +
'.csv'
-
os.rename(filename_list[i], new_file_name)
-
with open(new_file_name, encoding=
'utf-8') as f:
-
content = f.read()
-
os.rename(new_file_name, filename_list[i])
-
except:
-
error_list.
append(i)
-
content =
''
-
else:
-
with open(filename_list[i], encoding=
'utf-8') as f:
-
content = f.read()
基本策略
针对复赛文件的数字命名问题,我将测试集文件切分为两份,文件名为纯数字的一份,正常文件名的为另一份,前一份使用纯内容训练的模型来预测,后者使用纯标题内容训练的模型来预测。
模型采用了Bert进行训练与推断,最终将两部分的预测结果合并生成提交文件。
对于所有的文本内容,我采用正则表达式匹配所有中文汉字,并且将过长的文本内容截断前一部分作作为训练样本,此处可能遗漏了不少关键信息。
因为初赛的测试数据集的准确率相当之高(超过98%),这部分测试集的数据也可以被当作新的训练集和初始训练集合并来重新训练模型,这是一种较为有效的半监督学习的做法。
赛后总结
根据本次比赛前几名@挥霍的人生、@第二次打比赛-小迷弟等大佬的分享了解到自己本次比赛的大致思路和他们基本一致,包括标题模型和文档模型分别训练推断、伪标签的使用。
值得注意的是,本次比赛还可以采用规则的方法上分,通过对训练、测试数据集的观察,有相当一部分比例的文档存在内容一致的现象,即这部分文档可以直接使用训练集给出的标签(100%正确),另外因为训练集文本很多内容是重复的,需进行数据的去重处理。
最后,Bert不一定是最优的选择,在特定的任务上结合对业务的理解,其他模型还能做到更好。
——END——
扫码二维码
获取更多精彩
老肥码码码
转载:https://blog.csdn.net/lyc44813418/article/details/111659427