说明
上篇以识别公司实体为例构建了一个规则集(模板),现在假设我们要识别人名。由于整个流程非常相似,所以没有必要重新写一个规则集,而是只开发某条规则(有差异的地方),然后通过参数重新实例化原来的规则集模板就可以了。
内容
形式上,规则集(模板)就是一个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)
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)
4 使用参数实例化
the_rule_set = fs.gen_rule_set_df(rule_set_df_template,para_df,fs, mod_list=['name'])
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)
保存
# 插入
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)
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条,那么就把规则集下载下来,保留需要的,再增量开发。例如这个例子,我可以把规则集的名字加个数字存到规则集的库中,下次就可以不必实例化。
实例化更大的作用是在于参数搜索。大部分时候我们应该只修改其中的部分参数,以获取不同需求的结果。如果搜索的面积很大,那么通过这种方式(高度流程化)可以让算法帮我们进行搜索和调优。