deepfm_v13_7.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # vim:fenc=utf-8
  4. #
  5. # Copyright © 2025 StrayWarrior <i@straywarrior.com>
  6. #
  7. # Distributed under terms of the MIT license.
  8. """
  9. 1.删除容易导致偏差的viewall特征
  10. 2.删除分桶不均匀的cpa特征
  11. 3.减少dense特征
  12. 4.增加U-I交叉统计
  13. 5.增加线性部分dense
  14. 6.减少wide部分embedding
  15. 7.减少部分bucket size
  16. 8.增加targeting/agent/customer/landing/user_layer_l6 id特征及k1-k4连续统计特征
  17. """
  18. raw_input = open("data_fields_v6.config").readlines()
  19. input_fields = dict(
  20. map(lambda x: (x[0], x[1]),
  21. map(lambda x: x.strip().split(' '), raw_input)))
  22. def read_features(filename, excludes=None):
  23. features = open(filename).readlines()
  24. features = [name.strip().lower() for name in features]
  25. if excludes:
  26. for x in excludes:
  27. if x in features:
  28. features.remove(x)
  29. return features
  30. exclude_features = ['viewall', 'cpa']
  31. dense_features = read_features("features_top300_new.config", exclude_features)
  32. top_dense_features = read_features('features_top50_new.config', exclude_features)
  33. # k1-k4 交叉统计连续特征
  34. _k_prefixes = ['k1', 'k2', 'k3', 'k4']
  35. _k_windows = ['2h', '4h', '6h', '12h', '1d', '3d', 'today', '1w']
  36. _k_metrics = ['view', 'click', 'conver', 'ctr', 'cvr', 'ctvr']
  37. k_dense_features = [
  38. f'{prefix}_{window}_{metric}'
  39. for prefix in _k_prefixes
  40. for window in _k_windows
  41. for metric in _k_metrics
  42. ]
  43. dense_features = dense_features + k_dense_features
  44. top_dense_features = top_dense_features + k_dense_features
  45. sparse_features = [
  46. "cid", "adid", "adverid",
  47. "region", "city", "brand",
  48. "vid", "cate1", "cate2",
  49. "apptype", "hour", "hour_quarter", "root_source_scene", "root_source_channel", "is_first_layer", "title_split",
  50. "user_has_conver_1y",
  51. "user_adverid_view_3d", "user_adverid_view_7d", "user_adverid_view_30d",
  52. "user_adverid_click_3d", "user_adverid_click_7d", "user_adverid_click_30d",
  53. "user_adverid_conver_3d", "user_adverid_conver_7d", "user_adverid_conver_30d",
  54. "user_skuid_view_3d", "user_skuid_view_7d", "user_skuid_view_30d",
  55. "user_skuid_click_3d", "user_skuid_click_7d", "user_skuid_click_30d",
  56. "user_skuid_conver_3d", "user_skuid_conver_7d", "user_skuid_conver_30d",
  57. "profession", "user_layer", "flag",
  58. "targeting_conversion", "agent_id", "customer_id", "landing_page_type", "user_layer_l6",
  59. # "category_name", "customer"
  60. ]
  61. tag_features = [
  62. "user_vid_return_tags_2h", "user_vid_return_tags_1d", "user_vid_return_tags_3d",
  63. "user_vid_return_tags_7d", "user_vid_return_tags_14d"
  64. ]
  65. seq_features = [
  66. "user_cid_click_list", "user_cid_conver_list"
  67. ]
  68. input_type_map = {
  69. 'BIGINT': 'INT64',
  70. 'DOUBLE': 'DOUBLE',
  71. 'STRING': 'STRING'
  72. }
  73. bucket_size_map = {
  74. 'adverid': 100000,
  75. 'region': 1000,
  76. 'city': 10000,
  77. 'brand': 10000,
  78. 'cate1': 10000,
  79. 'cate2': 10000,
  80. 'apptype': 1000,
  81. 'hour': 1000, # 实际上可以直接指定词表
  82. 'hour_quarter': 4000,
  83. 'root_source_scene': 100,
  84. 'root_source_channel': 1000,
  85. 'is_first_layer': 100,
  86. 'user_has_conver_1y': 100,
  87. 'profession': 500,
  88. 'category_name': 500,
  89. 'user_layer': 200,
  90. 'customer': 3000,
  91. 'landing': 100,
  92. 'flag': 50,
  93. 'targeting_conversion': 100,
  94. 'agent_id': 10000,
  95. 'customer_id': 10000,
  96. 'landing_page_type': 100,
  97. 'user_layer_l6': 200,
  98. }
  99. print("""train_config {
  100. optimizer_config {
  101. adam_optimizer {
  102. learning_rate {
  103. constant_learning_rate {
  104. learning_rate: 0.0010
  105. }
  106. }
  107. }
  108. use_moving_average: false
  109. }
  110. optimizer_config {
  111. adam_optimizer {
  112. learning_rate {
  113. constant_learning_rate {
  114. learning_rate: 0.0006
  115. }
  116. }
  117. }
  118. use_moving_average: false
  119. }
  120. optimizer_config {
  121. adam_optimizer {
  122. learning_rate {
  123. constant_learning_rate {
  124. learning_rate: 0.002
  125. }
  126. }
  127. }
  128. use_moving_average: false
  129. }
  130. num_steps: 200000
  131. sync_replicas: true
  132. save_checkpoints_steps: 2000
  133. log_step_count_steps: 200
  134. save_summary_steps: 200
  135. }
  136. eval_config {
  137. metrics_set {
  138. auc {
  139. }
  140. }
  141. eval_online: true
  142. eval_interval_secs: 1200
  143. }
  144. data_config {
  145. batch_size: 512
  146. num_epochs: 1
  147. """)
  148. for name in input_fields:
  149. input_type = input_type_map[input_fields[name]]
  150. default_spec = ''
  151. if name in dense_features:
  152. default_spec = '\n default_val: "0"'
  153. print(f""" input_fields {{
  154. input_name: "{name}"
  155. input_type: {input_type}{default_spec}
  156. }}""")
  157. # default_val: "0"
  158. print(""" label_fields: "has_conversion"
  159. prefetch_size: 32
  160. input_type: OdpsInputV2
  161. }
  162. """)
  163. for name in dense_features:
  164. print(f"""feature_configs {{
  165. input_names: "{name}"
  166. feature_type: RawFeature
  167. boundaries: [0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.0]
  168. embedding_dim: 6
  169. }}""")
  170. for name in sparse_features:
  171. bucket_size = bucket_size_map.get(name, 1000000)
  172. print(f"""feature_configs {{
  173. input_names: "{name}"
  174. feature_type: IdFeature
  175. hash_bucket_size: {bucket_size}
  176. embedding_dim: 6
  177. }}""")
  178. for name in tag_features + seq_features:
  179. bucket_size = bucket_size_map.get(name, 1000000)
  180. print(f"""feature_configs {{
  181. input_names: "{name}"
  182. feature_type: TagFeature
  183. hash_bucket_size: {bucket_size}
  184. embedding_dim: 6
  185. separator: ','
  186. }}""")
  187. def wide_and_deep():
  188. print("""
  189. model_config {
  190. model_class: "WideAndDeep"
  191. feature_groups: {
  192. group_name: 'wide'""")
  193. for name in dense_features + sparse_features:
  194. print(f""" feature_names: '{name}'""")
  195. print(""" wide_deep: WIDE
  196. }
  197. feature_groups: {
  198. group_name: 'deep'""")
  199. for name in dense_features + sparse_features + tag_features + seq_features:
  200. print(f""" feature_names: '{name}'""")
  201. print(""" wide_deep: DEEP
  202. }
  203. wide_and_deep {
  204. wide_output_dim: 8
  205. dnn {
  206. hidden_units: [256, 128, 64]
  207. }
  208. final_dnn {
  209. hidden_units: [64, 32]
  210. }
  211. l2_regularization: 1e-5
  212. }
  213. embedding_regularization: 1e-6
  214. }""")
  215. def deep_fm():
  216. print("""
  217. model_config {
  218. model_class: "DeepFM"
  219. feature_groups: {
  220. group_name: 'wide'""")
  221. for name in dense_features + sparse_features:
  222. print(f""" feature_names: '{name}'""")
  223. print(""" wide_deep: WIDE
  224. }
  225. feature_groups: {
  226. group_name: 'deep'""")
  227. for name in top_dense_features + sparse_features + tag_features + seq_features:
  228. print(f""" feature_names: '{name}'""")
  229. print(""" wide_deep: DEEP
  230. }
  231. deepfm {
  232. wide_output_dim: 2
  233. dnn {
  234. hidden_units: [256, 128, 64]
  235. }
  236. final_dnn {
  237. hidden_units: [64, 32]
  238. }
  239. l2_regularization: 1e-5
  240. }
  241. embedding_regularization: 1e-6
  242. }""")
  243. def fm():
  244. print("""
  245. model_config {
  246. model_class: "FM"
  247. feature_groups: {
  248. group_name: 'wide'""")
  249. for name in dense_features:
  250. print(f""" feature_names: '{name}'""")
  251. print(""" wide_deep: WIDE
  252. }
  253. feature_groups: {
  254. group_name: 'deep'""")
  255. for name in dense_features:
  256. print(f""" feature_names: '{name}'""")
  257. print(""" wide_deep: DEEP
  258. }
  259. fm {
  260. }
  261. embedding_regularization: 1e-5
  262. }""")
  263. def config_export():
  264. print("""
  265. export_config {
  266. exporter_type: "final"
  267. }
  268. """)
  269. deep_fm()
  270. config_export()