背景与目的 在大数据时代的背景下,爆炸式增长的数据与传统算法的准召率低下的矛盾越来越严重,迫切需要一种可以从数据中自动学习规律的算法来处理大数据,减少人为的干预,机器学习算法应运而生。在此背景下,本项目采用目前大火的深度学习算法,通过较少的人工标注,可以自动地学习数据的规律,取得比传统算法优越的结果,这些结果又可以通过再学习的方式反过来提高算法的效果。通过实体抽取和分类,实体连接、实体融合等方法,最终构建招投标的知识图谱。 数据准备 一、 编号名称模型: 数据标注:从6000篇原始文章中,标注出编号和名称,如果有多个表达,则用分隔符“;”分隔。 测试数据:标注的数据中取10%的文章的数据 训练数据:不包含测试数据的标注数据
二、 角色模型: 数据标注:17000篇文章在经过NLP工具(foolnltk)处理后,取其中实体类型为“org”和“company”的数据,通过前后文各10个词,采用正则的方式标注数据,标注为6类,分别是招标人、代理人、中标/第一候选人、第二候选人、第三候选人、无。使用经过标注的数据迭代训练模型,迭代的方法是每轮取一小部分待修改数据,通过剩余数据训练出模型,使用这个模型预测待修改数据,超过某个阈值的数据便更改标签。重复这个过程使待修改数据遍历完所有数据。重复6轮。取出所有数据,通过前后文判断标注结果是否正确,取标注正确的数据作为标注数据 测试数据:标注的数据中取10%的文章的数据 训练数据:不包含测试数据的标注数据 三、 金额模型: 数据标注:6000篇文章在经过NLP工具(foolnltk)处理后,通过正则的方式抽取其中的金额数据,通过前后文各10个词,采用正则的方式标注数据,标注为3类,分别是预算金额、中投标金额、无。使用经过标注的数据迭代训练模型,迭代的方法是每轮取一小部分待修改数据,通过剩余数据训练出模型,使用这个模型预测待修改数据,超过某个阈值的数据便更改标签。重复这个过程使待修改数据遍历完所有数据。重复6轮。取出所有数据,通过前后文判断标注结果是否正确,取标注正确的数据作为标注数据 测试数据:标注的数据中取10%的数据 训练数据:不包含测试数据的标注数据 四、 联系人模型: 数据标注:4000篇文章在经过NLP工具(foolnltk)处理后,取其中实体类型为“person”的数据,通过前后文各10个词,采用正则的方式标注数据,标注为4类,分别是无、招标联系人、代理联系人、联系人。取出所有数据,通过前后文判断标注结果是否正确,修改错误的标注为正确的标注,以所有数据为标注数据 测试数据:标注的数据中取10%的数据 训练数据:不包含测试数据的标注数据
思路 对于角色、金额、联系人模型,采用先抽取后分类的方式。抽取采用的是NLP工具或者是正则方法,分类则是通过数据的特征分布(这些模型都是提取上下文特征),使用相应的模型进行分类。这几个模型的结果需要进行连接才能得到最终的结果,连接的方法是通过上下文(限制上下文句子数),拿到包号-角色id-实体名称-中投标金额-联系人-联系电话。其中包号和联系电话通过正则的方式获得。 对于编号和名称模型,由于不好做抽取,这里采用的是序列标注的方法。每个字分别属于某个类(B_C-编号开始,M_C-编号中间,E_C-编号末尾,B_N-名称开始,M_N-名称中间,E_N-名称末尾,O-其他字符),模型采用BiLSTM+CRF,通过BiLSTM提取每个字符观测序列上下文特征,通过CRF提取状态转移特征,使用数据准备阶段的数据进行训练得到模型。对预测结果使用正则的方式提取结果。如编号为1*B_C+x*M_C+1*E_C,名称为1*B_N+x*M_N+1*E_N。 完成上面两步之后,接下来是做招投标连接和实体连接。 招投标连接的背景是:一个招标公告会对应一个中标公告,甚至还有变更公告、撤销公告等等。招投标连接的目的是可以通过一个公告找到所有与之相关的公告,因此需要将这些公告联系起来,联系的方法是通过项目名称,根据联系紧密的公告的负责人都是同一个的假设前提下,出现在前面的标题中的名称一般会一样,可以通过编号和名称模型得到的结果,通过名称相同的条件去做查询,如果查询出某一类的多个公告,则用编号来进行判断,比如一个招标公告通过名称查询到多个名称相同的中标公告,则采用编号来辅助判断。 实体连接的背景是:同一个实体在不同的公告中采用的表达可能会有些微的差别。实体连接就是将这种实际上是同一个实体但表达不完全一样的实体连接起来。连接的方法是:提取实体中的地名,按照省市区三级地名的排列顺序去查找,若是只有省市而没有区,则只取省市,只有省而没有市区也一样;若是没有省市而只有区,若区是唯一的,则补全对应的省市,若区不唯一,则不补全,其他类似的情况一样处理。拿到实体的省市区之后,拿实体的简称,简称的规则是实体名称中不包含地名和类似于“公司”、“有限公司”,“子公司”等等通用词,可以理解为所有名称中这个公司独有的信息。然后使用地名和简称查询到可能的公司列表,通过完整公司名称的相似度来判断是否为同一个公司。
模型与效果 标注了200篇文章作为验证集,标注的规则与单独的模型不太一样,分别标注了编号、名称、包名-角色id-公司名称-金额、公司名称-联系人-联系电话-联系地址。分别统计了编号和名称、包名-角色id-公司名称、包名-公司名称-金额、公司名称-联系人的准召率,效果如下: 编号名称: CN_sum_predict:351,CN_sum_label:321,CN_predict_label:298,accurency:0.849003,recall:0.928349 包名-角色id-公司名称: role_sum_predict:658,role_sum_label:669,role_predict_label:618,accurency:0.939210,recall:0.923767 包名-公司名称-金额: money_predict:302,money_label:299,money_label_predict:251,acc:0.831126,recall:0.839465 公司名称-联系人: person_label:455,person_predict:431,person_label_predict:364,acc:0.844548,recall:0.800000
接口思路 接口使用redis+flask实现 web-server模块接收post请求,将数据放入到redis队列中,然后循环查询redis结果 model-server模块从redis队列中取数据,处理完后保存到redis中 只需要运行dl.interface包下的run_web_server.py和run_model_server.py即可
再训练 做完数据准备之后,若是数据是准确无误的,则确认各个模型对于包下的训练代码获取的数据源正确的情况下,运行训练代码即可,若数据不完全正确,可通过迭代的方式进行标注,最后人工筛选正确的作为正确数据,必要时还可以修改错误的数据