Python 规则10 实体识别数据预处理规则集-实例化

说明

上篇以识别公司实体为例构建了一个规则集(模板),现在假设我们要识别人名。由于整个流程非常相似,所以没有必要重新写一个规则集,而是只开发某条规则(有差异的地方),然后通过参数重新实例化原来的规则集模板就可以了。

内容

形式上,规则集(模板)就是一个df,只不过字段的类型有列表和字典而已。

用参数实例化就是把某条规则(某行记录)的值覆盖掉。

1 修改的部分

函数部分:原来目标提取公司,ss的最小长度是4,并且要包含公司实体的关键字,所以把原来的函数改一下,保存为新的函数就可以。
rulev002_get_person_ss_hash

...
sel = the_df['ss'].apply(len) >1
...

入参部分:也是改一下最小长度,还有通用的正则过滤就好了。

# 每个短句允许的最大长度,模型有处理的最大限制(人名最小不短于2个字)
ss_len_min = 2
ss_len_max = 100

# 如果考虑人名再加两个点 
default_pass_str = r'[\u4e00-\u9fa5\da-zA-Z\-()().,·•]'

2 构建新的参数数据框

一般情况下不允许修改规则函数名,因为这样可能导致不稳定。如果确实要修改,可以另外保存一份规则集。

  • 1 获取标准字段
param_df_cols = fs.get_rule_data(func_lmongo, 'rules', 'meta', 'r_002')
---
['prj_id',
 'prj_name',
 'rule_set',
 'rule_id',
 'name',
 'params',
 'conditions',
 'condition_mappings',
 'out_comes']
字段名 描述
prj_id(必填) 对应参数用在的项目id,主要是为了自己管理方便
prj_name(必填) 项目名称
rule_set(必填) 修改的是哪个规则集
rule_id(必填) 修改的对应规则
name(选填) 函数名称(一般不允许修改)
params(选填) 要使用的参数
conditions(选填) 在变量空间内的变量列表
condition_mappings(选填) 映射到函数的变量名
out_comes(选填) 输出的结果名称
  • 2 构建修改的参数数据框

只构建需要修改的部分,其他的字段可不填

para_df = pd.DataFrame(columns = param_df_cols)
r001_params ={'prj_id':'prj_002', 
              'prj_name':'ner_preprocessing', 
              'rule_set':'NerPreProcessing',
              'rule_id':'r_0002',
              'name':'rulev002_get_person_ss_hash'}
para_df = para_df.append(r001_params, ignore_index=True)

Python 规则10 实体识别数据预处理规则集-实例化

3 读取目标规则集

query_res_list =  func_lmongo.query_many(dbname='rules', cname='rules',kv_list = [{'rule_set':'NerPreProcessing'}], max_recs=10000)[0]
rule_set_df_template = pd.DataFrame(query_res_list)

Python 规则10 实体识别数据预处理规则集-实例化

4 使用参数实例化

the_rule_set = fs.gen_rule_set_df(rule_set_df_template,para_df,fs, mod_list=['name'])

Python 规则10 实体识别数据预处理规则集-实例化

5 使用实例化的规则集执行

# *定义

# 每个短句列表的最大长度,考虑内存/显存
max_ss_list_len = 4000

# 每个短句允许的最大长度,模型有处理的最大限制(人名最小不短于2个字)
ss_len_min = 2
ss_len_max = 100
# 这个参数也可以不写(默认左闭右开)
intever_type = 'left_close'

# 数据部分
data = [{'doc_id' : 'a001','content':'oppo公司竟然不支持鸿蒙'},
        {'doc_id':'a002','content':'华为公司开源了鸿蒙,是个好东西'},
        {'doc_id':'a003','content':'你觉得鸿蒙怎么样'},
        {'doc_id':'a004','content':'识别名字迪丽热巴·迪力木拉提,迪丽热巴•迪力木拉提'}]
data_type = 'dict_list'


# 一般性过滤文本
# default_pass_str = r'[\u4e00-\u9fa5\da-zA-Z\-()().,]'

# 如果考虑人名再加两个点 
default_pass_str = r'[\u4e00-\u9fa5\da-zA-Z\-()().,·•]'

# 输出模式 realtime/persistent
output_mode = 'realtime'
output_mode = 'persistent'
output_folder = './test_002/'

# -- 封装
cur_dict ={}
cur_dict['input_dict'] = {}
cur_dict['input_dict']['max_ss_list_len'] = max_ss_list_len
cur_dict['input_dict']['ss_len_min'] = ss_len_min
cur_dict['input_dict']['ss_len_max'] = ss_len_max
cur_dict['input_dict']['intever_type'] = intever_type
cur_dict['input_dict']['data'] = data
cur_dict['input_dict']['data_type'] = data_type
cur_dict['input_dict']['default_pass_str'] = default_pass_str
cur_dict['input_dict']['output_mode'] = output_mode
cur_dict['input_dict']['output_folder'] = output_folder

fs.run_ruleset_v2('ner_preprocessing', the_rule_set, cur_dict, fs)
---
takes 0.00
data save to pickle:  ./test_002/523754ea0f275fca7a0500f5983818a0.pkl
{'name': 'ner_preprocessing',
 'status': True,
 'msg': 'ok',
 'duration': 52,
 'data': {'docid_sshash_df':   doc_id              ss                           ss_hash
  0   a001   oppo公司竟然不支持鸿蒙  77cd68c100290f4d92cfe3c508fa5298
  1   a002           是个好东西  c3be2e44aef7a1472b9880096d703a04
  2   a002       华为公司开源了鸿蒙  3cbbb2b44e0be524b25f9273e438fdf9
  3   a003        你觉得鸿蒙怎么样  7026f1ee4a9e08e2bdfe1522c6c9be7c
  4   a004      迪丽热巴•迪力木拉提  7a625c937fef464419e32bcb40ba4eca
  5   a004  识别名字迪丽热巴·迪力木拉提  b2297eb3ae93c5986989eda7a7cfcc60,
  'ss_list': [1    是个好东西
   Name: ss, dtype: object, 3    你觉得鸿蒙怎么样
   Name: ss, dtype: object, 2    华为公司开源了鸿蒙
   Name: ss, dtype: object, 4    迪丽热巴•迪力木拉提
   Name: ss, dtype: object, 0    oppo公司竟然不支持鸿蒙
   Name: ss, dtype: object, 5    识别名字迪丽热巴·迪力木拉提
   Name: ss, dtype: object],
  'data_hash': '523754ea0f275fca7a0500f5983818a0',
  'output_folder': './test_002/'}}

可以看到,这次的数据比较多,不含公司的句子也被留下了,名字中间的点也没有丢掉。

6 保存参数

生成pr_id

para_df.loc[:,'pr_id'] = (para_df['prj_id'] + '_' + para_df['rule_set'] + '_' + para_df['rule_id']).apply(fs.md5_trans)

Python 规则10 实体识别数据预处理规则集-实例化
保存

# 插入
fs.mongo_opr_insert_df_slice(func_lmongo, 'rules', 'params', para_df, 'pr_id', fs)
# 更新
# fs.mongo_opr_update_df_slice(func_lmongo, 'rules', 'params', para_df, 'pr_id', fs)

Python 规则10 实体识别数据预处理规则集-实例化

7 执行时

正常在使用时是这样的

# 1 读取规则集模板
query_res_list =  func_lmongo.query_many(dbname='rules', cname='rules',kv_list = [{'rule_set':'NerPreProcessing'}], max_recs=10000)[0]
rule_set_df_template = pd.DataFrame(query_res_list)
# 2 读入参数df
query_res_list =  func_lmongo.query_many(dbname='rules', cname='params',kv_list = [{'prj_id':'prj_002'}], max_recs=10000)[0]
params_df = pd.DataFrame(query_res_list)
# 3 实例化规则集
the_rule_set = fs.gen_rule_set_df(rule_set_df_template,params_df,fs, mod_list=['name'])
# 4 调用
fs.run_ruleset_v2('ner_preprocessing', the_rule_set, cur_dict, fs)
---
takes 0.00
data save to pickle:  ./test_002/523754ea0f275fca7a0500f5983818a0.pkl
{'name': 'ner_preprocessing',
 'status': True,
 'msg': 'ok',
 'duration': 52,
 'data': {'docid_sshash_df':   doc_id              ss                           ss_hash
  0   a001   oppo公司竟然不支持鸿蒙  77cd68c100290f4d92cfe3c508fa5298
  1   a002           是个好东西  c3be2e44aef7a1472b9880096d703a04
  2   a002       华为公司开源了鸿蒙  3cbbb2b44e0be524b25f9273e438fdf9
  3   a003        你觉得鸿蒙怎么样  7026f1ee4a9e08e2bdfe1522c6c9be7c
  4   a004      迪丽热巴•迪力木拉提  7a625c937fef464419e32bcb40ba4eca
  5   a004  识别名字迪丽热巴·迪力木拉提  b2297eb3ae93c5986989eda7a7cfcc60,
  'ss_list': [1    是个好东西
   Name: ss, dtype: object, 3    你觉得鸿蒙怎么样
   Name: ss, dtype: object, 2    华为公司开源了鸿蒙
   Name: ss, dtype: object, 4    迪丽热巴•迪力木拉提
   Name: ss, dtype: object, 0    oppo公司竟然不支持鸿蒙
   Name: ss, dtype: object, 5    识别名字迪丽热巴·迪力木拉提
   Name: ss, dtype: object],
  'data_hash': '523754ea0f275fca7a0500f5983818a0',
  'output_folder': './test_002/'}}

8 总结

通过规则集模板+参数的方法进行实例化,一方面可以减少重复的开发。例如某个规则集有10条规则,我们需要其中的5条,那么就把规则集下载下来,保留需要的,再增量开发。例如这个例子,我可以把规则集的名字加个数字存到规则集的库中,下次就可以不必实例化。

实例化更大的作用是在于参数搜索。大部分时候我们应该只修改其中的部分参数,以获取不同需求的结果。如果搜索的面积很大,那么通过这种方式(高度流程化)可以让算法帮我们进行搜索和调优。

上一篇:介绍Command Checker及重新生成Ribbon元数据的方法


下一篇:js正则验证