def run_predict_cv(self) -> None: """クロスバリデーションで学習した各foldのモデルの平均により、テストデータの予測を行う あらかじめrun_train_cvを実行しておく必要がある """ self.logger.info(f'{self.run_name} - start prediction cv') test_x = self.load_x_test() preds = [] # 各foldのモデルで予測を行う for i_fold in range(self.n_splits): self.logger.info(f'{self.run_name} - start prediction fold:{i_fold}') model = self.build_model(i_fold) model.load_model(self.out_dir_name) if self.metrics_name == 'RMSLE': pred = np.expm1(model.predict(test_x)) else: pred = model.predict(test_x) preds.append(pred) self.logger.info(f'{self.run_name} - end prediction fold:{i_fold}') # 予測の平均値を出力する if self.metrics_name == 'ACC': pred_avg = np.round(np.mean(preds, axis=0)) else: pred_avg = np.mean(preds, axis=0) # 推論結果の保存(submit対象データ) Util.dump_df_pickle(pd.DataFrame(pred_avg), self.out_dir_name + f'{self.run_name}_pred.pkl') self.logger.info(f'{self.run_name} - end prediction cv')
def run_train_cv(self) -> None: """クロスバリデーションでの学習・評価を行う 学習・評価とともに、各foldのモデルの保存、スコアのログ出力についても行う """ self.logger.info(f'{self.run_name} - start training cv') if self.cv_method in ['KFold', 'TrainTestSplit', 'CustomTimeSeriesSplitter']: self.logger.info(f'{self.run_name} - cv method: {self.cv_method}') else: self.logger.info(f'{self.run_name} - cv method: {self.cv_method} - group: {self.cv_target_gr_column} - stratify: {self.cv_target_sf_column}') scores = [] # 各foldのscoreを保存 va_idxes = [] # 各foldのvalidationデータのindexを保存 preds = [] # 各foldの推論結果を保存 # 各foldで学習を行う for i_fold in range(self.n_splits): # 学習を行う self.logger.info(f'{self.run_name} fold {i_fold} - start training') model, va_idx, va_pred, score = self.train_fold(i_fold) self.logger.info(f'{self.run_name} fold {i_fold} - end training - score {score}') # モデルを保存する model.save_model(self.out_dir_name) # 結果を保持する va_idxes.append(va_idx) scores.append(score) preds.append(va_pred) # 各foldの結果をまとめる va_idxes = np.concatenate(va_idxes) order = np.argsort(va_idxes) preds = np.concatenate(preds, axis=0) preds = preds[order] # 全体のスコアを算出 if self.cv_method not in ['TrainTestSplit', 'CustomTimeSeriesSplitter']: if self.metrics_name == 'RMSLE': score_all_data = np.sqrt(self.metrics(np.expm1(self.train_y), preds)) else: score_all_data = self.metrics(self.train_y, preds) else: score_all_data = None # oofデータに対するfoldごとのscoreをcsvに書き込む(foldごとに分析する用) self.score_list.append(['score_all_data', score_all_data]) self.score_list.append(['score_fold_mean', np.mean(scores)]) for i in self.fold_score_list: self.score_list.append(i) with open(self.out_dir_name + f'{self.run_name}_score.csv', 'a') as f: writer = csv.writer(f) writer.writerows(self.score_list) # foldごとのスコアもmlflowでトラッキングする def score_mean(df): df = df.groupby('run_name').mean().round(4).reset_index().sort_values('run_name') return df _score_df = pd.read_csv(self.out_dir_name + f'{self.run_name}_score.csv') _score_df = score_mean(_score_df) _score_df = _score_df.T _score_df.columns = _score_df.iloc[0] _score_df = _score_df.drop(_score_df.index[0]) for col in _score_df.columns.tolist(): mlflow.log_metric(col, _score_df[col].values[0]) # 学習データでの予測結果の保存 if self.save_train_pred: Util.dump_df_pickle(pd.DataFrame(preds), self.out_dir_name + f'.{self.run_name}_train.pkl') # 評価結果の保存 self.logger.result_scores(self.run_name, scores, score_all_data) # shap feature importanceデータの保存 if self.calc_shap: self.shap_feature_importance()