Bläddra i källkod

add: 在线学习新增生成评分卡

yq 1 månad sedan
förälder
incheckning
e37ceb9d01
1 ändrade filer med 41 tillägg och 0 borttagningar
  1. 41 0
      online_learning/trainer.py

+ 41 - 0
online_learning/trainer.py

@@ -44,6 +44,8 @@ class OnlineLearningTrainer:
         self._model_original: LR
         self._model_optimized: LR
         self.sc_woebin = None
+        self.card_cfg = None
+        self.card = None
         # 报告模板
         self._template_path = os.path.join(dirname(dirname(realpath(__file__))),
                                            "./template/OnlineLearning报告模板_lr.docx")
@@ -60,6 +62,12 @@ class OnlineLearningTrainer:
             coef = json.loads(f.read())
             print(f"coef load from【{path_coef}】success.")
 
+        path_card_cfg = os.path.join(path, FileEnum.CARD_CFG.value)
+        if os.path.isfile(path_card_cfg):
+            with open(path_card_cfg, mode="r", encoding="utf-8") as f:
+                self.card_cfg = json.loads(f.read())
+                print(f"{FileEnum.CARD_CFG.value} load from【{path_coef}】success.")
+
         self._columns = list(coef.keys())
         # 排个序,防止因为顺序原因导致的可能的bug
         self._columns.sort()
@@ -96,6 +104,16 @@ class OnlineLearningTrainer:
         weight = nn.Parameter(torch.tensor(np.array(weight[0:-5])))
         return LR(weight)
 
+    def _f_get_scorecard(self, ):
+        class M:
+            def __init__(self, ):
+                pass
+
+        m = M()
+        m.coef_ = [self._model_optimized.linear.weight.tolist()]
+        m.intercept_ = [0]
+        self.card = sc.scorecard(self.sc_woebin, m, self._columns_woe, **self.card_cfg)
+
     def _f_get_metric_auc_ks(self, model_type: str):
         def _get_auc_ks(data, title):
             y = data[self._ol_config.y_column]
@@ -212,6 +230,9 @@ class OnlineLearningTrainer:
             y_prob = y_prob.detach().numpy()
             return y_prob
 
+    def score(self, x: pd.DataFrame) -> np.array:
+        return np.array(sc.scorecard_ply(x, self.card, print_step=0)["score"])
+
     def psi(self, x1: pd.DataFrame, x2: pd.DataFrame, points: List[float] = None) -> pd.DataFrame:
         y1 = self.prob(x1)
         y2 = self.prob(x2)
@@ -289,6 +310,12 @@ class OnlineLearningTrainer:
             f.write(j)
         print(f"model save to【{path}】success. ")
 
+        if self.card is not None:
+            df_card = pd.concat(self.card.values())
+            path = self._ol_config.f_get_save_path(FileEnum.CARD.value)
+            df_card.to_csv(path)
+            print(f"model save to【{path}】success. ")
+
     @staticmethod
     def load(path: str):
         ol_config = OnlineLearningConfigEntity.from_config(path)
@@ -305,6 +332,15 @@ class OnlineLearningTrainer:
             display.display(df_param)
 
         metric_value_dict = {}
+
+        # 评分卡
+        if not self.card_cfg is None:
+            self._f_get_scorecard()
+            df_card = pd.concat(self.card.values())
+            img_path_card = self._ol_config.f_get_save_path(f"card.png")
+            f_df_to_image(df_card, img_path_card)
+            metric_value_dict["评分卡"] = MetricFucResultEntity(table=df_card, image_path=img_path_card)
+
         # 样本分布
         metric_value_dict["样本分布"] = MetricFucResultEntity(table=self._data.get_distribution(self._ol_config.y_column),
                                                           table_font_size=10, table_cell_width=3)
@@ -366,6 +402,11 @@ class OnlineLearningTrainer:
             f_display_title(display, "压力测试")
             display.display(metric_value_dict["压力测试"].table)
 
+        # 评分卡
+        if "评分卡" in metric_value_dict.keys():
+            f_display_title(display, "评分卡")
+            display.display(metric_value_dict["评分卡"].table)
+
 
 if __name__ == "__main__":
     pass