예제 #1
0
    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')
예제 #2
0
    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()