TDSE株式会社
TDSEマガジン

本番データの前処理フロー管理術

データ分析

はじめに

みなさんは学習データの前処理はどのように管理しているでしょうか。また、学習済みモデルを本番運用するとき、予測データの前処理はどのように実装しているでしょうか。学習時と予測時で異なる前処理をしてしまうと予測結果が意図しないものになってしまい大変です。それを防ぐためにも前処理フローの管理は非常に大切です。そこで今回は、「予測データの前処理はどのように実装するのか」に焦点を当て、その基本的な管理方法について記事にしてみました。

学習済みモデルの運用コードを作成する際、まず考えるのは「予測データの前処理はどのようにするのか」ではないでしょうか。予測データの前処理はうまく設計しないと一貫性のないコードになってしまう恐れがあります。

早速本記事の要点を書いてしまいますが、学習済みモデルの運用コードを作成する際には「学習済みモデル」だけでなく、学習データを前処理する際に必要な情報をまとめた「メタデータ」も重要になります。この「メタデータ」をうまく作成することによって、一貫性のある予測データの前処理ができるようになります。

上記を具体的に見ていくために、Pythonでの簡単な予測モデル実装を考えてみましょう。今回はタイタニックデータ(https://www.kaggle.com/c/titanic)を利用して、乗客の生存者予測をロジスティック回帰にて行うことにします。

1)学習

まずはモジュールのインポートと学習データの読み込みをします。そして例によって学習データは学習データと検証データに分割します。

今回の学習では、以下の8つの変数を抽出し、PassengerIdはIDとして、Survivedは目的変数として、そのほかの変数は説明変数として利用することにします。

PassengerId: 乗客ID
Survived: 生存(1)、死亡(0)
Pclass: 乗客の階級
Sex: 性別
Age: 年齢
SibSp: タイタニック号に乗っていた兄弟、姉妹、義兄弟、義姉妹、夫、妻の数(自分を除く)
Parch: タイタニック号に乗っていた母親、父親、息子、娘の数
Fare: 乗船料金

さて、説明変数をいい感じに前処理することで、精度の良い学習をしたいので、以下のデータ前処理を考えます。

Fare → 標準化
Age, SibSp, Parch → よさげな区間でビンニング
Pclass, Sex, Embarked, Age(ビンニング後), SibSp(ビンニング後), Parch(ビンニング後) → ダミー化

ここで、予測データでも同様の前処理をするために、上記データ前処理に必要な情報を逐一保存しておくことにし、そのためのデータフレームを用意します。

詳しくはこの後じっくり見ていきますが、筆者は変数ごとにどのような前処理をするのかをflgで持ち、flgTrueである変数を予測データでも前処理する、というスタイルを好んで書きます。しかし、メタデータをどのように設計するかは、前処理手法やアルゴリズム、運用フローによって最適な方法を選択する必要があります。
ということで、変数の前処理を実装していきます。まずは標準化です。
標準化は学習データの平均・分散に依存するのでこれらの情報は保存する必要があります。(間違って検証/予測データの平均・分散を使ってしまうのはあるあるですね。)

次にビンニングです。
ビンニングでは数値をどの範囲でどれだけ区切るのか、という情報が必要なのでこれを保存します。

最後にダミー化です。
ダミー化では、ダミー化によって増えた変数と冗長性のため削除する変数が前処理情報として必要になります。ここでは冗長変数は最頻値のカテゴリーに対応する変数とします。

さて、これでデータの前処理が完了したので、前処理情報を保存します。

上図のような「メタデータ」が作成できました。これで、検証/予測データについても、meta.csvを参照することで学習時と同様の前処理ができるようになりました。
データの前処理が完了したので、ロジスティック回帰を用いて学習します。
ここで、scikit-learnLogisticRegressionは説明変数の順番に気を付けましょう。今回は変数名でソートすることにします。(場合によってはこの順番もメタデータとして保存してもよいかもしれません。)
学習したモデルはjoblibなどで保存します。

2)検証/予測

学習済みモデルを使って、検証/予測します。検証と予測はラベルがあるかないかの違いだけなので、データ前処理としては同じステップを踏むことになります。
まず、学習時に作成したデータ前処理メタデータを読み込みます。

このメタデータから、どの変数をどのように前処理するかを読み取ります。(IDや目的変数もメタデータに加えても良いですね。)

検証データまたは予測データを読み込みます。(適宜コメントアウト、アンコメントしてください。)

検証/予測データを前処理します。メタデータを元に、標準化、ビンニング、ダミー化それぞれを実施していきます。このとき、学習データの前処理と同様に実装してしまうと整合性が取れなくなることがあります。例えば、予測データの’Fare’には学習データにはなかった欠損値が存在していますし、学習データに存在したカテゴリーが検証/予測データには存在しない場合、get_dummies()するだけではその変数がダミー化されないままとなってしまいます。今回は欠損値を含む行は除外し、ダミー化時にはダミー化後のカラムをあらかじめ作成することにしています。(ダミー化時にはさらに、学習データに存在しなかったカテゴリーが検証/予測データには存在する場合にも注意が必要ですが、ここでは割愛します。)

これで検証/予測データに対して一貫性のある前処理を実装できました。前処理が実装できれば、学習済みモデルを読み込んで、検証/予測することができます。ここでもやはり変数の順番を学習データと同様になるように設定する必要があります。

3)まとめ

本番運用を見据えていると、データ前処理だけでも考慮しないといけないことはかなり多いです。私たちの実際の業務では考慮すべき事項がさらに増えることもあります。
手法を組み合わせることで前処理が複雑化しますし、予期せぬデータ(今回の‘Fare’の欠損値のようなデータ)は思わぬところで問題になることがあります。これらに対応するためにも、前処理の設計と前処理情報の一元管理は重要な役割を持ちます。前処理が複雑になり、今回のようにファイル等で管理しきれなくなったら、ワークフローエンジンやFeature storeの導入も検討してみてください。
また、少し余談ですが、データ前処理のメタデータはお客様との認識合わせツールとしても役に立ちます。メタデータを見ながら「この変数の前処理は問題ないか?」「なぜこのような前処理をしているのか?」を確認・共有しながら、よりお客様の運用に合ったモデル実装を進めることができます。

以上、本番データの前処理フローの管理について実演してみました。本記事がこれからデータサイエンティストを目指す方々の一助となれば幸いです。

DXやデータ分析に関するトレンドや活用法、
セミナー情報などをお届けします。

メールマガジンに無料で登録する

メールマガジン登録

DXやデータ分析に関する
トレンドや活用法、セミナー情報
などをお届けします

本フォームでは、個人情報と紐づけてweb閲覧履歴を取得しています。
上記個人情報のお取扱いをご確認、ご同意の上、フォームを送信してください。

上へ戻る