predict.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #encoding=utf-8
  2. import os
  3. import re
  4. import tensorflow as tf
  5. import numpy as np
  6. import gensim
  7. from BiddingKG.dl.common.Utils import embedding
  8. import json
  9. import fool
  10. class IndustryPredictor():
  11. def __init__(self,):
  12. model_path = 'model.21-0.9929-0.7576.h5'
  13. self.model_path = 'industry_model'
  14. self.id2lb = {0: '专业施工', 1: '专用仪器仪表', 2: '专用设备修理', 3: '互联网信息服务', 4: '互联网安全服务', 5: '互联网平台', 6: '互联网接入及相关服务', 7: '人力资源服务',
  15. 8: '人造原油', 9: '仓储业', 10: '仪器仪表', 11: '仪器仪表修理', 12: '会计、审计及税务服务', 13: '会议、展览及相关服务', 14: '住宅、商业用房',
  16. 15: '体育场地设施管理', 16: '体育组织', 17: '体育设备', 18: '保险服务', 19: '信息处理和存储支持服务', 20: '信息技术咨询服务',
  17. 21: '信息系统集成和物联网技术服务', 22: '修缮工程', 23: '健康咨询', 24: '公路旅客运输', 25: '其他专业咨询与调查', 26: '其他专业技术服务',
  18. 27: '其他交通运输设备', 28: '其他公共设施管理', 29: '其他土木工程建筑', 30: '其他工程服务', 31: '其他建筑建材', 32: '其他运输业', 33: '农业和林业机械',
  19. 34: '农业服务', 35: '农产品', 36: '农副食品,动、植物油制品', 37: '出版业', 38: '办公消耗用品及类似物品', 39: '办公设备', 40: '化学原料及化学制品',
  20. 41: '化学纤维', 42: '化学药品和中药专用设备', 43: '医疗设备', 44: '医药品', 45: '卫星传输服务', 46: '卫生', 47: '印刷服务', 48: '图书和档案',
  21. 49: '图书档案设备', 50: '图书馆与档案馆', 51: '土地管理业', 52: '地质勘查', 53: '地震服务', 54: '场馆、站港用房', 55: '城市公共交通运输',
  22. 56: '塑料制品、半成品及辅料', 57: '天然石料', 58: '娱乐设备', 59: '婚姻服务', 60: '安全保护服务', 61: '安全生产设备', 62: '家具用具',
  23. 63: '家用电器修理', 64: '工业、生产用房', 65: '工业与专业设计及其他专业技术服务', 66: '工矿工程建筑', 67: '工程技术与设计服务', 68: '工程机械',
  24. 69: '工程监理服务', 70: '工程评价服务', 71: '工程造价服务', 72: '市场调查', 73: '广告业', 74: '广播', 75: '广播、电视、电影设备',
  25. 76: '广播电视传输服务', 77: '废弃资源综合利用业', 78: '建筑涂料', 79: '建筑物、构筑物附属结构', 80: '建筑物拆除和场地准备活动', 81: '建筑装饰和装修业',
  26. 82: '录音制作', 83: '影视节目制作', 84: '房地产中介服务', 85: '房地产开发经营', 86: '房地产租赁经营', 87: '房屋租赁', 88: '招标代理',
  27. 89: '探矿、采矿、选矿和造块设备', 90: '政法、检测专用设备', 91: '教育服务', 92: '教育设备', 93: '文物及非物质文化遗产保护', 94: '文物和陈列品',
  28. 95: '文艺创作与表演', 96: '文艺设备', 97: '新闻业', 98: '旅行社及相关服务', 99: '日杂用品', 100: '有色金属冶炼及压延产品', 101: '有色金属矿',
  29. 102: '木材、板材等', 103: '木材采集和加工设备', 104: '机械设备', 105: '机械设备经营租赁', 106: '林业产品', 107: '林业服务', 108: '架线和管道工程建筑',
  30. 109: '核工业专用设备', 110: '橡胶制品', 111: '殡葬服务', 112: '殡葬设备及用品', 113: '气象服务', 114: '水上交通运输设备', 115: '水上运输业',
  31. 116: '水利和水运工程建筑', 117: '水工机械', 118: '水文服务', 119: '水资源管理', 120: '污水处理及其再生利用', 121: '汽车、摩托车修理与维护',
  32. 122: '法律服务', 123: '洗染服务', 124: '测绘地理信息服务', 125: '海洋仪器设备', 126: '海洋工程建筑', 127: '海洋服务', 128: '消防设备',
  33. 129: '清洁服务', 130: '渔业产品', 131: '渔业服务', 132: '炼焦和金属冶炼轧制设备', 133: '烟草加工设备', 134: '热力生产和供应', 135: '焦炭及其副产品',
  34. 136: '煤炭采选产品', 137: '燃气生产和供应业', 138: '物业管理', 139: '特种用途动、植物', 140: '环保咨询', 141: '环境与生态监测检测服务',
  35. 142: '环境污染防治设备', 143: '环境治理业', 144: '玻璃及其制品', 145: '理发及美容服务', 146: '生态保护', 147: '电信',
  36. 148: '电力、城市燃气、蒸汽和热水、水', 149: '电力供应', 150: '电力工业专用设备', 151: '电力工程施工', 152: '电力生产', 153: '电子和通信测量仪器',
  37. 154: '电工、电子专用生产设备', 155: '电影放映', 156: '电气安装', 157: '电气设备', 158: '电气设备修理', 159: '畜牧业服务', 160: '监控设备',
  38. 161: '石油制品', 162: '石油和化学工业专用设备', 163: '石油和天然气开采产品', 164: '石油天然气开采专用设备', 165: '研究和试验发展', 166: '社会工作',
  39. 167: '社会经济咨询', 168: '科技推广和应用服务业', 169: '科研、医疗、教育用房', 170: '管道和设备安装', 171: '粮油作物和饲料加工设备', 172: '纸、纸制品及印刷品',
  40. 173: '纺织原料、毛皮、被服装具', 174: '纺织设备', 175: '绿化管理', 176: '缝纫、服饰、制革和毛皮加工设备', 177: '航空器及其配套设备', 178: '航空客货运输',
  41. 179: '航空航天工业专用设备', 180: '节能环保工程施工', 181: '装卸搬运', 182: '计算机和办公设备维修', 183: '计算机设备', 184: '计量标准器具及量具、衡器',
  42. 185: '货币处理专用设备', 186: '货币金融服务', 187: '质检技术服务', 188: '资本市场服务', 189: '车辆', 190: '边界勘界和联检专用设备', 191: '运行维护服务',
  43. 192: '通信设备', 193: '通用设备修理', 194: '道路货物运输', 195: '邮政专用设备', 196: '邮政业', 197: '采矿业和制造业服务',
  44. 198: '铁路、船舶、航空航天等运输设备修理', 199: '铁路、道路、隧道和桥梁工程建筑', 200: '铁路运输设备', 201: '防洪除涝设施管理', 202: '陶瓷制品',
  45. 203: '雷达、无线电和卫星导航设备', 204: '非金属矿', 205: '非金属矿物制品工业专用设备', 206: '非金属矿物材料', 207: '食品加工专用设备', 208: '食品及加工盐',
  46. 209: '餐饮业', 210: '饮料、酒精及精制茶', 211: '饮料加工设备', 212: '饲养动物及其产品', 213: '黑色金属冶炼及压延产品', 214: '黑色金属矿'}
  47. self.sess = tf.Session(graph=tf.Graph())
  48. self.get_model()
  49. with open('rule_kw_json/tw_industry_keyword_org/tw_industry_keyword_org.json', 'r',
  50. encoding='utf-8') as fp1:
  51. self.json_data_industry = json.load(fp1)
  52. with open('rule_kw_json/tw_company_classification_keyword/tw_company_classification_keyword.json', 'r',
  53. encoding='utf-8') as fp2:
  54. self.json_data_company = json.load(fp2)
  55. with open('rule_kw_json/tw_custom_keyword/tw_custom_keyword.json', 'r', encoding='utf-8') as fp3:
  56. self.json_data_custom = json.load(fp3)
  57. def get_model(self):
  58. with self.sess.as_default() as sess:
  59. with self.sess.graph.as_default():
  60. meta_graph_def = tf.saved_model.loader.load(sess,
  61. tags=['serve'],
  62. export_dir=os.path.dirname(__file__)+'/industry_model')
  63. signature_key = tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
  64. signature_def = meta_graph_def.signature_def
  65. self.title = sess.graph.get_tensor_by_name(signature_def[signature_key].inputs['title'].name)
  66. self.project = sess.graph.get_tensor_by_name(signature_def[signature_key].inputs['project'].name)
  67. self.product = sess.graph.get_tensor_by_name(signature_def[signature_key].inputs['product'].name)
  68. self.outputs = sess.graph.get_tensor_by_name(signature_def[signature_key].outputs['outputs'].name)
  69. def text2array(self, text, tenderee='', maxSententLen=20):
  70. tenderee = tenderee.replace('(', '(').replace(')', ')')
  71. text = text.replace('(', '(').replace(')', ')')
  72. text = re.sub(
  73. '(废标|终止|综?合?评审|评标|开标|资审|履约|验收|成交|中标人?|中选人?|单一来源|合同|候选人|结果|变更|更正|答疑|澄清|意向|需求|采购|招标|询比?价|磋商|谈判|比选|比价|竞价|议价)的?(公告|预告|公示)?|关于为?|选取|定点|直接|邀请函?|通知书?|备案|公开|公示|公告|记录|竞争性',
  74. '', text)
  75. text = text.replace(tenderee, '')
  76. text = ' ' if text=="" else text
  77. words_docs_list = fool.cut(text)
  78. words_docs_list = [[it for it in l if re.search('^[\u4e00-\u9fa5]+$', it)][-maxSententLen:] for l in words_docs_list]
  79. array = embedding(words_docs_list, shape=(len(words_docs_list), maxSententLen, 128))
  80. return array
  81. def process(self, title, project, product, tenderee):
  82. return self.text2array(title, tenderee), self.text2array(project, tenderee), self.text2array(product)
  83. def predict_model(self, title, project, product, tenderee=''):
  84. title_array, project_array, product_array = self.process(title, project, product, tenderee)
  85. rs = self.sess.run(self.outputs,
  86. feed_dict={
  87. self.title:title_array,
  88. self.project:project_array,
  89. self.product:product_array
  90. }
  91. )
  92. pred = np.argmax(rs[0])
  93. return self.id2lb[pred], rs[0][pred]
  94. # # 返回top2 结果
  95. # pred_list = np.argsort(-rs[0])
  96. # return self.id2lb[pred_list[0]], self.id2lb[pred_list[1]], rs[0][pred_list[0]], rs[0][pred_list[1]]
  97. def predict_rule(self, doctitle, tenderee, win_tenderer, project_name, product):
  98. doctitle = doctitle if doctitle else ''
  99. tenderee = tenderee if tenderee else ''
  100. win_tenderer = win_tenderer if win_tenderer else ''
  101. project_name = project_name if project_name else ''
  102. product = product if product else ''
  103. text_ind = (doctitle + project_name + product).replace(tenderee, '')
  104. text_com = win_tenderer
  105. length_ind_text = len(text_ind) + 1
  106. length_com_text = len(text_com) + 1
  107. # print(text)
  108. dic_res = {} # 行业分类字典
  109. score_lst = [] # 得分列表
  110. word_lst = [] # 关键词列表
  111. # 主要内容关键词
  112. if text_ind:
  113. # logging.info("data_ind%s"%str(_json_data_industry[0]))
  114. for data_industry in self.json_data_industry:
  115. industry = data_industry['xiaolei']
  116. key_word = data_industry['key_word']
  117. key_word_2 = data_industry['key_word2']
  118. power = float(data_industry['power']) if data_industry['power'] else 0
  119. this_score = power * (text_ind.count(key_word) * len(key_word) / length_ind_text)
  120. if key_word_2:
  121. # key_word_compose = key_word + "+" + key_word_2
  122. if text_ind.count(key_word_2) == 0:
  123. this_score = 0
  124. if this_score > 0:
  125. # print(industry,key_word,this_score)
  126. if industry in dic_res.keys():
  127. dic_res[industry] += this_score
  128. else:
  129. dic_res[industry] = this_score
  130. if key_word not in word_lst:
  131. word_lst.append(key_word)
  132. # 供应商关键词
  133. if text_com:
  134. for data_company in self.json_data_company:
  135. industry = data_company['industry_type']
  136. key_word = data_company['company_word']
  137. power = float(data_company['industry_rate']) if data_company['industry_rate'] else 0
  138. this_score = power * (text_com.count(key_word) * len(key_word) / length_com_text)
  139. if this_score > 0:
  140. # print(industry,key_word,this_score)
  141. if industry in dic_res.keys():
  142. dic_res[industry] += this_score
  143. else:
  144. dic_res[industry] = this_score
  145. if key_word not in word_lst:
  146. word_lst.append(key_word)
  147. # 自定义关键词
  148. if text_ind:
  149. custom_ind = [
  150. ['tenderee', '医院|疾病预防', ['设备', '系统', '器'], '医疗设备'],
  151. ['tenderee', '学校|大学|小学|中学|学院|幼儿园', ['设备', '器'], '教育设备'],
  152. ['tenderee', '学校|大学|小学|中学|学院|幼儿园|医院', ['工程'], '科研、医疗、教育用房'],
  153. ['tenderee', '供电局|电网|国网|电力|电厂|粤电', ['设备', '器', '物资'], '电力工业专用设备'],
  154. ['tenderee', '公安|法院|检察院', ['设备', '器'], '政法、检测专用设备'],
  155. ['tenderee', '^中铁|^中交|^中建|中国建筑', ['材料'], '其他建筑建材'],
  156. ['doctextcon', '信息技术服务|系统开发|信息化|信息系统', ['监理'], '信息技术咨询服务'],
  157. ['doctextcon', '工程', ['消防'], '专业施工'],
  158. ['doctextcon', '铁路|航空|船舶|航天|广铁', ['维修'], '铁路、船舶、航空航天等运输设备修理'],
  159. ['doctextcon', '设备|仪|器', ['租赁'], '机械设备经营租赁'],
  160. ['doctextcon', '交通|铁路|公路|道路|桥梁', ['工程'], '铁路、道路、隧道和桥梁工程建筑'],
  161. ['win_tenderer', '电力', ['设备', '器'], '电力工业专用设备'],
  162. ['win_tenderer', '信息|网络科技', ['系统'], '信息系统集成和物联网技术服务'],
  163. ['tenderee,doctextcon', '铁路|广铁|铁道', ['设备', '器', '物资', '材料', '铁路'], '铁路运输设备'],
  164. ]
  165. for data_custom in self.json_data_custom:
  166. industry_custom = data_custom['industry']
  167. key_word = data_custom['company_word']
  168. power = float(data_custom['industry_rate'])
  169. for k in range(len(custom_ind)):
  170. subject = ''
  171. if 'tenderee' in custom_ind[k][0]:
  172. subject += tenderee
  173. if 'win_tenderer' in custom_ind[k][0]:
  174. subject += win_tenderer
  175. if 'doctextcon' in custom_ind[k][0]:
  176. subject += text_ind
  177. ptn = custom_ind[k][1]
  178. # print('ptn',ptn)
  179. if re.search(ptn, subject) and industry_custom in custom_ind[k][2]:
  180. industry = custom_ind[k][3]
  181. else:
  182. continue
  183. this_score = power * (text_ind.count(key_word) * len(key_word) / len(subject))
  184. if this_score > 0:
  185. # print(industry,key_word,this_score)
  186. if industry in dic_res.keys():
  187. dic_res[industry] += this_score
  188. else:
  189. dic_res[industry] = this_score
  190. if key_word not in word_lst:
  191. word_lst.append(key_word)
  192. sort_res = sorted(dic_res.items(), key=lambda x: x[1], reverse=True)
  193. lst_res = [s[0] for s in sort_res]
  194. score_lst = [str(round(float(s[1]), 2)) for s in sort_res]
  195. if len(lst_res) > 0:
  196. return lst_res, score_lst, word_lst
  197. else:
  198. return [""], [], []
  199. def predict_merge(self, pinmu_type, industry_lst):
  200. '''
  201. 通过一系列规则最终决定使用模型还是规则的结果
  202. :param pinmu_type: 模型预测类别
  203. :param industry_lst: 规则预测类别列表
  204. :return:
  205. '''
  206. industry_type = industry_lst[0]
  207. if industry_type == "":
  208. return pinmu_type
  209. if industry_type == '专用设备修理' and re.search('修理|维修|装修|修缮', pinmu_type):
  210. final_type = pinmu_type
  211. elif industry_type == '其他土木工程建筑' and re.search('工程|建筑|用房|施工|安装|质检|其他专业咨询与调查', pinmu_type):
  212. final_type = pinmu_type
  213. elif pinmu_type == '专用设备修理' and re.search('工程|修理', industry_type):
  214. final_type = industry_type
  215. elif pinmu_type == '信息系统集成和物联网技术服务' and re.search('卫星传输|信息处理和存储支持服务|信息技术咨询服务|运行维护服务|其他专业技术服务|医疗设备|医药品',
  216. industry_type):
  217. final_type = industry_type
  218. elif industry_type == '仪器仪表' and re.search('仪器|器具|医疗设备', pinmu_type):
  219. final_type = pinmu_type
  220. elif industry_type == '医药品' and re.search('医疗设备', pinmu_type):
  221. final_type = pinmu_type
  222. elif industry_type == '医药品' and re.search('医疗设备', pinmu_type):
  223. final_type = pinmu_type
  224. elif re.search('设备', industry_type) and re.search('修理|维修', pinmu_type):
  225. final_type = pinmu_type
  226. elif industry_type == '社会工作' and re.search('工程', pinmu_type):
  227. final_type = pinmu_type
  228. elif industry_type == '信息系统集成和物联网技术服务' and re.search('信息处理|设备', pinmu_type):
  229. final_type = pinmu_type
  230. elif industry_type == '研究和试验发展' and re.search('其他专业咨询与调查|质检技术服务|信息系统集成|其他工程服务', pinmu_type):
  231. final_type = pinmu_type
  232. elif industry_type == '其他专业咨询与调查' and re.search('工程造价服务', pinmu_type):
  233. final_type = pinmu_type
  234. elif industry_type == '广告业' and re.search('印刷服务|影视节目制作|信息系统', pinmu_type):
  235. final_type = pinmu_type
  236. elif industry_type == '清洁服务' and re.search('工程|环境污染防治设备|修理', pinmu_type):
  237. final_type = pinmu_type
  238. elif industry_type == '其他公共设施管理' and re.search('信息系统', pinmu_type):
  239. final_type = pinmu_type
  240. elif industry_type == '其他专业技术服务' and re.search('工程技术与设计服务|质检技术服务|环境与生态监测检测服务', pinmu_type):
  241. final_type = pinmu_type
  242. elif industry_type == '机械设备经营租赁' and re.search('电信', pinmu_type):
  243. final_type = pinmu_type
  244. elif industry_type == '货币金融服务' and re.search('信息系统集成和物联网技术服务', pinmu_type):
  245. final_type = pinmu_type
  246. elif industry_type == '体育场地设施管理' and re.search('体育设备', pinmu_type):
  247. final_type = pinmu_type
  248. elif industry_type == '安全保护服务' and re.search('信息系统|监控设备|互联网安全服务', pinmu_type):
  249. final_type = pinmu_type
  250. elif industry_type == '互联网接入及相关服务' and re.search('通信设备', pinmu_type):
  251. final_type = pinmu_type
  252. elif industry_type == '卫生' and re.search('医疗设备|信息系统', pinmu_type):
  253. final_type = pinmu_type
  254. elif pinmu_type == '研究和试验发展' and re.search('其他工程服务', industry_type):
  255. final_type = industry_type
  256. elif pinmu_type == '办公设备' and re.search('教育设备', industry_type):
  257. final_type = industry_type
  258. elif re.search('车辆|机械设备经营租赁', pinmu_type) and re.search('公路旅客运输', industry_type):
  259. final_type = industry_type
  260. elif len(industry_lst) > 1 and pinmu_type == industry_lst[1] and re.search('会计|法律|物业|家具|印刷|互联网安全',
  261. industry_type) == None \
  262. and re.search('其他|人力资源服务', pinmu_type) == None:
  263. final_type = pinmu_type
  264. elif industry_type != "":
  265. final_type = industry_type
  266. else:
  267. final_type = pinmu_type
  268. return final_type
  269. def predict(self, title, project, product, tenderee="", win_tenderer=""):
  270. result_model, prob = self.predict_model(title, project, product, tenderee)
  271. industry_lst, score_lst, word_lst = self.predict_rule(title, tenderee, win_tenderer, project, product)
  272. final_type = self.predict_merge(result_model, industry_lst)
  273. print('模型:%s;规则:%s;最终:%s'%(result_model, industry_lst[0], final_type))
  274. return final_type
  275. if __name__ == "__main__":
  276. model_predictor = IndustryPredictor()
  277. s = '自用 ( )#split#自用#split#小便池 下水 弯管 , 捷星 角磨机 钢刷 , 宽 胶带 , 玻璃胶 , 空气 清新剂 , 窄 胶带 , 柠檬 超洁 洗洁精 , 窗帘环 , 舌 锁 , 晶华 胶带 , 电池 纽扣 电池 , 免钉 胶#split#盂县 禄鑫 商贸 有限公司'
  278. # s = '无锡 浩源 招投标 咨询 服务 有限公司 社会保险 相关 业务 文书 送达 服务 的#split#社会保险 相关 业务 文书 送达 服务#split#社会保险 相关 业务 文书 送达 服务 , 文书 送达 服务 , 业务 文书 送达 服务#split#中国 邮政 速递 物流 股份 有限公司 无锡市 分公司'
  279. # s = '小轿车#split#小轿车#split#小轿车#split# '
  280. # s = '2021年 12月 至 2022年 01月 政府#split#陆路 与 航空 口岸 疫情 防控 工作 专班 B13 栋 集中 居住 点 委托 运营 服务 项目#split#集中 居住 点 委托 运营 服务#split# '
  281. # s = '广州市 越秀区 云泉路 20 号 配电 柜 更换 项目#split#广州市 越秀区 云泉路 20 号 配电 柜 更换 项目#split#配电 柜 更换#split# '
  282. title, project, product, win_tenderer = s.replace(' ', '').split('#split#')
  283. print(model_predictor.predict(title, project, product, tenderee="", win_tenderer=win_tenderer))
  284. print()