讯飞AI算法挑战大赛-校招简历信息完整性检测挑战赛-三等奖方案

前言

本文公开了”讯飞AI算法挑战大赛-校招简历信息完整性检测挑战赛“赛道的技术方案,本次比赛主要采用pdf解析特征工程的方法,通过使用lightgbm的树模型10折交叉验证进行二分类的任务,最终取得三等奖的成绩。

一、赛题任务

简历智能化判断,需要大量的数据集作为支撑,同时简历的半结构化数据特点和多变的简历风格给简历智能化判断带来了挑战,本次大赛将提供脱敏的学生中文简历数据集(pdf或docx格式)作为训练样本,参赛选手需要基于提供的样本数据构建模型,预测简历是否符合简历投递基本要求。任务如下:

简历完整性检测。根据要求提取简历要素特征数据,并根据样本数据构建模型,预测简历是否符合简历投递基本要求,预测结果可分为两个类别:即完整(标签1)不完整(标签0)

二、数据和评价指标

数据:脱敏后的学生简历数据集(pdf或docx格式)。训练数据提供脱敏后的数据集,共800余份。测试集不可见,由真实简历数据组成,共100余份。训练集全部为pdf格式。

注:数据集分为正样本负样本,其中正样本为完整性简历数据集,符合简历投递基本要求;负样本为不完整简历数据集,不符合简历投递基本要求。

评价指标:F1 score

三、方案

3.1.方案概述

本次比赛主要采用pdf解析和特征工程的方法,通过使用lightgbm的树模型10折交叉验证进行二分类的任务。

3.2.pdf2text解析

本次比赛主要实验了以下几种解析工具,最终最高分选择了pymupdf

  • pdfplumber
  • PyPDF2
  • pymupdf

3.3.特征工程

主要文本特征如下:

  • 页数

  • pdf2text的文本长度

  • 按行切分后的平均长度

  • 按行切分后的最大长度

  • 按行切分后的长度标准差

  • text字符集合的大小

  • pdf2text的文本长度-text字符集合的大小

  • text字符集合的大小/(pdf2text的文本长度+1)

  • text空格切分后的列表大小

  • text换行符切分后的列表大小

  • -的数量

  • x的数量

  • xxx的数量

  • 数字的数量

  • @的数量

  • .com的数量

  • *的数量

  • :的数量

  • ****的数量

  • 正则匹配电话号码的数量

特征提取对应的code

pattern = r"[\D]+(1\d{10})+(?!\d)"def extract_feature_from_pdf(path):doc = fitz.open(path)all_content = []page_nums = 0for i in doc.pages():page_nums += 1all_content.append(i.get_text())text = ''.join(all_content)text = ''.join(text.split('\n'))feat = [page_nums,len(text),np.mean([len(x) for x in text.split('\n')]),np.max([len(x) for x in text.split('\n')]),np.std([len(x) for x in text.split('\n')]),len(set(text)),len(text) - len(set(text)),len(set(text)) / (len(text) + 1),len(text.split()),len(text.split('\n')),text.count('-'),text.count('x'),text.count('xxx'),sum([text.count(x) for x in '0123456789']),text.count('@'),text.count('.com'),text.count('*'),text.count(':'),text.count('****'),len(re.compile(pattern).findall(text)),1 if '正样本' in path else 0,]return feat

3.4.训练代码

本次比赛主要使用的是lightgbm的树模型,视为二分类任务,进行10折交叉验证的训练。

#!/usr/bin/env python
# _*_coding:utf-8_*_
# Author   :    Junhui Yuimport warningswarnings.simplefilter('ignore')import gcimport pandas as pdpd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', 100)from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import accuracy_score, classification_reportimport lightgbm as lgbimport globimport pandas as pd
from tqdm import tqdm
import numpy as np
import re
import fitzpattern = r"[\D]+(1\d{10})+(?!\d)"def extract_feature_from_pdf(path):doc = fitz.open(path)all_content = []page_nums = 0for i in doc.pages():page_nums += 1all_content.append(i.get_text())text = ''.join(all_content)text = ''.join(text.split('\n'))feat = [page_nums,len(text),np.mean([len(x) for x in text.split('\n')]),np.max([len(x) for x in text.split('\n')]),np.std([len(x) for x in text.split('\n')]),len(set(text)),len(text) - len(set(text)),len(set(text)) / (len(text) + 1),len(text.split()),len(text.split('\n')),text.count('-'),text.count('x'),text.count('xxx'),sum([text.count(x) for x in '0123456789']),text.count('@'),text.count('.com'),text.count('*'),text.count(':'),text.count('****'),len(re.compile(pattern).findall(text)),1 if '正样本' in path else 0,]return feattrain_paths = glob.glob('../xfdata/校招简历信息完整性检测训练集/*/*.pdf')df_train = pd.DataFrame(columns=['page_nums','text_len','text_len_mean','text_len_max','text_len_std','text_set_len','lentext-lenset','lenset_div_lentext','text_split_len','text_split_ent_len','-_nums','x_nums','xxx_nums','dig_sum','@_nums','.com_nums','*_nums',':_nums','****_nums','phone_nums','label'])for t_p in tqdm(train_paths):df_train.loc[len(df_train)] = extract_feature_from_pdf(t_p)not_use_feats = ['label']
use_features = [col for col in df_train.columns if col not in not_use_feats]
print(len(use_features))
train = df_train[df_train['label'].notna()]NUM_CLASSES = 2
FOLDS = 10
TARGET = 'label'def run_lgb(df_train, use_features):target = TARGEToof_pred = np.zeros((len(df_train), NUM_CLASSES))folds = StratifiedKFold(n_splits=FOLDS, shuffle=True, random_state=42)for fold, (tr_ind, val_ind) in enumerate(folds.split(train, train[TARGET])):print(f'Fold {fold + 1}')x_train, x_val = df_train[use_features].iloc[tr_ind], df_train[use_features].iloc[val_ind]y_train, y_val = df_train[target].iloc[tr_ind], df_train[target].iloc[val_ind]train_set = lgb.Dataset(x_train, y_train)val_set = lgb.Dataset(x_val, y_val)params = {'learning_rate': 0.1,'metric': 'multiclass','objective': 'multiclass','num_classes': NUM_CLASSES,'feature_fraction': 0.75,'bagging_fraction': 0.75,'bagging_freq': 2,'n_jobs': -1,'seed': 1029,'max_depth': 10,'num_leaves': 100,'lambda_l1': 0.5,'lambda_l2': 0.8,'verbose': -1}model = lgb.train(params,train_set,num_boost_round=500,early_stopping_rounds=100,valid_sets=[train_set, val_set],verbose_eval=100)oof_pred[val_ind] = model.predict(x_val)print('acc:', accuracy_score(np.argmax(oof_pred, axis=1), df_train['label']))del x_train, x_val, y_train, y_val, train_set, val_setgc.collect()return oof_pred, modeloof_pred, model = run_lgb(train, use_features)
print(classification_report(np.argmax(oof_pred, axis=1), df_train['label']))model.save_model('model.txt')

3.5.推理代码

#!/usr/bin/env python
# _*_coding:utf-8_*_
# Author   :    Junhui Yuimport globimport pandas as pd
import numpy as np
import re
import fitzimport lightgbm as lgbpatter = r"[\D]+(1\d{10})+(?!\d)"def extract_feature_from_pdf(path):doc = fitz.open(path)all_content = []page_nums = 0for i in doc.pages():page_nums += 1all_content.append(i.get_text())text = ''.join(all_content)text = ''.join(text.split('\n'))feat = [page_nums,len(text),np.mean([len(x) for x in text.split('\n')]),np.max([len(x) for x in text.split('\n')]),np.std([len(x) for x in text.split('\n')]),len(set(text)),len(text) - len(set(text)),len(set(text)) / (len(text) + 1),len(text.split()),len(text.split('\n')),text.count('-'),text.count('x'),text.count('xxx'),sum([text.count(x) for x in '0123456789']),text.count('@'),text.count('.com'),text.count('*'),text.count(':'),text.count('****'),len(re.compile(patter).findall(text)),1 if '正样本' in path else 0,]return featdf = pd.DataFrame(columns=['page_nums','text_len','text_len_mean','text_len_max','text_len_std','text_set_len','lentext-lenset','lenset_div_lentext','text_split_len','text_split_ent_len','-_nums','x_nums','xxx_nums','dig_sum','@_nums','.com_nums','*_nums',':_nums','****_nums','phone_nums','label'])test_paths = glob.glob('/work/data/integrity-check-of-resume-test-set/*.pdf')[:]for t_f in test_paths:df.loc[len(df)] = extract_feature_from_pdf(t_f)not_use_feats = ['label']
use_features = [col for col in df.columns if col not in not_use_feats]model = lgb.Booster(model_file='model.txt')y_pred = model.predict(df[use_features])predict_label = np.argmax(y_pred, axis=1)pd.DataFrame({'ResumeID': [x.split('/')[-1] for x in test_paths],'label': predict_label.astype(int)
}).to_csv('/work/output/result.csv', index=None)

3.6.特征重要度与f1-score

                feature  split       gain
16              *_nums     96  23.080862
15           .com_nums     68  15.428008
6       lentext-lenset    126  12.632440
7   lenset_div_lentext    222  10.997545
13             dig_sum    218   7.045122
1             text_len    110   4.449556
17              :_nums    179   4.178767
8       text_split_len    165   4.169549
10              -_nums    137   3.483447
5         text_set_len    184   3.018025
14              @_nums     13   2.870494
11              x_nums     94   2.141016
19          phone_nums     16   1.668496
18           ****_nums     12   1.608449
12            xxx_nums     24   1.249654
2        text_len_mean     31   1.066294
0            page_nums     31   0.803168
3         text_len_max      5   0.109109
9   text_split_ent_len      0   0.000000
4         text_len_std      0   0.000000precision    recall  f1-score   support0       0.75      0.84      0.79       1051       0.98      0.96      0.97       710accuracy                           0.94       815macro avg       0.86      0.90      0.88       815
weighted avg       0.95      0.94      0.94       815

四、延伸

本次比赛任务相对简单,如果真正做到应用级别还需要考虑更多维度综合对简历的完整性进行评价。比如:简历中核心字段的填充率、设计简历中核心字段的重要性权值等等多维度信息。涉及技术可能有基于实体识别的简历解析(从本文特征工程也可以看出)技术等。

结论

本文仅记录8月份参与该比赛思路,至于代码也很普通。该比赛任务由于比较简单,线下指标虚高,训练数据与线上评测数据较少(耐心做特征工程分数可以非常高),并且技术价值不高。因此,前前后后投入差不多一个小时左右时间速刷了一下,最后偶然获奖。

参考文献

【1】校招简历信息完整性检测挑战赛:https://challenge.xfyun.cn/topic/info?type=information-integrity&option=ssgy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/133474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

精读《算法题 - 二叉树中的最大路径和》

今天我们看一道 leetcode hard 难度题目:二叉树中的最大路径和。 题目 二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点…

随时随地时时刻刻使用GPT类应用

疑问 很多人说GPT的广泛使用可能会使人们失业,会对一些互联网公司的存活造成挑战,那么这个说法是真的吗? 这个说法并不完全准确。虽然GPT等AI技术的广泛应用可能会对某些行业和职业产生影响,但并不意味着它会导致人们失业或互联网…

群晖7.2版本安装Jellyfin

一、添加三方套件库 打开桌面【套件中心】,点击右上角的【设置】-【套件来源】-【新增】,添加矿神库 名称:我不是矿神 位置:https://spk7.imnks.com/ 二、安装Jellyfin 【套件中心】-搜索【Jellyfin】-【安装套件】 集显版群…

【MySQL--->索引】

文章目录 [TOC](文章目录) 一、索引概念二、B树与B树1.B树的特点:2.B树的特点:3.为什么使用B树而不使用B树 三、聚簇索引和非聚簇索引四、索引操作1.创建索引2. 删除索引3.全文索引 一、索引概念 mysql的查询的过程是从文件中提取到内存中查询,MySQL启动时会在内存中维护一个b…

LED点阵显示原理(取字模软件+Keil+Proteus)

前言 写这个的时候我还是有点生气的,因为发现完全按照书上面的步骤来,结果发现不理想,后面还是自己调试才解决了。-_-说多了都是泪,直接进入正文。 软件的操作还是参考我之前的博客。 LED数码管的静态显示与动态显示&#xff0…

LabelImg使用笔记

LabelImg使用笔记 文章目录 LabelImg使用笔记一、LabelImg简介1.1、特性1.2、LabelImg的热键 二、LabelImg安装三、3种格式的使用3.1、VOC格式标注3.2、yolo格式标注3.3、json格式 四、LabelMe 和 LabelImg适用场景 一、LabelImg简介 LabelImg 是一个用于图像标注的开源工具&a…

Ubuntu下Anaconda安装

Ubuntu下Anaconda安装 进入anaconda官网 https://www.anaconda.com/ 下载Linux64位版本; 将下载好的".sh"文件放入虚拟机中; 运行指令sudo bash Anaconda3-2023.09-0-Linux-x86_64.sh 此后会自动加载安装程序,中途会停止两次&am…

win11下使用VMmare设置CentOS7里面的静态IP

1,win11上的VMware 8 设置 2,选择VMmare上的虚拟网络编辑进行设置 #3,接下来进入虚拟机设置(就是进入CentOS7 打开终端 右键 Open Terminal ) # 切换root su root #ksana #编辑网络配置文件 vi /etc/sysconfig/networ…

中小企业如何实现数字化转型发展?

数字化转型已成为企业未来发展的必然趋势,行业头部企业在此过程中持续投入自动化、信息化及数字化技术。虽然大多数系统投入不能仅基于短期投资回报率决策,且资源投入大见效慢、失败率也高,但数字化转型是不可逆转的过程,未来生存的企业必须是数字化的企业。 中小企业可以…

【MongoDB】索引 - 单字段索引

MongoDB支持在集合文档中的任意字段上创建索引,默认情况下所有的集合都有一个_id字段的索引,用户和应用可以新增索引用于查询和操作。 一、准备工作 这里准备一些学生数据 db.students.insertMany([{ _id: 1, name: "张三", age: 20, clas…

集群调度-02

目录 1、亲和性 1.1 节点亲和性 1.2 Pod 亲和性 1.3 键值运算关系 1.4 Pod亲和性与反亲和性 1.5 使用 Pod 反亲和性调度 2、污点(Taint) 和 容忍(Tolerations) 2.1 污点(Taint) 2.2 容忍(Tolerations) 2.3 其它注意事项 2.4 维护操作 3、Pod启动阶段(相…

onnx-tensorrt-8.4-EA安装和使用

因项目需求要用到onnx-tensorrt,在安装过程中遇到不少坑,故这里简单记录一下,给大家一个参考。 首先是尝试在本机上直接安装,发现会出现版本对应不上一系列问题,故最终我还是选择在docker拉去一个镜像去配环境和使用。…

马斯克发布大模型Grok;主流AI创意生成工具图谱;Runway视频大赛获奖作品解析;DALL-E 3图像混合操作;42章经播客推荐 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 👀 马斯克「xAI」发布首个AI大模型「Grok」 https://grok.x.ai 11月5日,马斯克旗下人工智能公司 xAI 发布了首款 AI 聊天产品…

Capto2024专为Mac电脑设计的屏幕录制和视频编辑软件

不得不说视频编辑功能:Capto提供了多种视频编辑功能,例如剪辑、旋转、裁剪、调整音频和视频的音量、加入水印、添加注释等,你能够使用Capto编辑你的视频,使之更加专业和生动。有目共睹的是录制完成后,你能够使用Capto提…

20.7 OpenSSL 套接字SSL加密传输

OpenSSL 中的 SSL 加密是通过 SSL/TLS 协议来实现的。SSL/TLS 是一种安全通信协议,可以保障通信双方之间的通信安全性和数据完整性。在 SSL/TLS 协议中,加密算法是其中最核心的组成部分之一,SSL可以使用各类加密算法进行密钥协商,…

web3 dapp React项目引入 antd 对 balance 用户token信息组件进行样式改造

好 上文 web3 React dapp中编写balance组件从redux取出并展示用户资产 我们简单处理了用户资产的展示 那么 我们继续 先启动 ganache 环境 终端输入 ganache -d然后 打开我们的项目 将合约发布到区块链上 truffle migrate --reset然后 我们启动项目 确认一切正常 还原到上文…

k8s中实现mysql主备

文章目录 一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.1 安装nfs1.2.2 部署nfs-provisioner 1.3 安装mysql1.4 备库上查看是否同步 一、k8s中实现mysql主备 1.1 环境信息 机器操作系统ipmysql版本k8s版本storageClassmaster1CentOS7.8192.168.0.20mysql5.…

C++ 代码实例:多项式除法简单计算工具

文章目录 前言代码仓库代码说明核心片段 结果总结参考资料作者的话 前言 C 代码实例:多项式除法简单计算工具。 代码仓库 yezhening/Programming-examples: 编程实例 (github.com)Programming-examples: 编程实例 (gitee.com) 代码 说明 由于代码篇幅较多&#…

【蓝桥杯省赛真题41】Scratch电脑开关机 蓝桥杯少儿编程scratch图形化编程 蓝桥杯省赛真题讲解

目录 scratch电脑开关机 一、题目要求 编程实现 二、案例分析 1、角色分析

基于STM32的设计智慧超市管理系统(带收银系统+物联网环境监测)

一、前言 基于STM32+OneNet设计的智慧超市管理系统(2023升级版) 1.1 项目背景 随着IoT技术的不断发展,智能无人超市也越来越受到人们的关注。智能无人超市是指在无人值守的情况下,通过物联网、大数据等技术手段实现自助选购、结算和配送的新型商场。当前设计了一种基于STM32…