たそらぼ

日頃思ったこととかメモとか。

StandardScalerのfit_transformを脳死で使ってたらハマった

StandardScalerのfit_transform()を乱用していたらハマってしまったのでメモです。

概要

データを標準化する際に、sklearn.preprocessing.StandardScalerを使うことが多いと思います。
scikit-learn.org

このモジュールにはfit_transformという、データへのfitと標準化をいっぺんにしてくれる便利関数があるのですが、
なにも考えずに使っていたらハマってしまったのでまとめました。

なにがまずかったか

学習データとテストデータ各々にfit_transformを使ってはだめでした。
データへのfitは学習データで行い、transformのみテストデータに行うのが良いです。

両方に対してfit_transformしてしまうと、
学習データは

 z = \frac{x - u}s

テストデータは

 z' = \frac{x - u'}{s'}

のように標準化のされ方が変わってしまいます。

失敗例

from sklearn.preprocessing import StandardScaler

obj=StandardScaler()

#ハマった標準化例
train[col_StandardScale]=obj.fit_transform(train)
test[col_StandardScale]=obj.fit_transform(test)

正しい例

from sklearn.preprocessing import StandardScaler

obj=StandardScaler()

#良い標準化例
train[col_StandardScale]=obj.fit_transform(train)
test[col_StandardScale]=obj.transform(test)

kaggleのpublic kernelを調べると、この方法がもっとも多かったです。
また、稀にtrainとtestを連結し、fit_transformしてから再度分割している人もいました。

起こったこと

バリデーションスコアより予測時のスコアが若干小さくなってしまいました。
テストに対してfit_transformした時も大きく値がずれる訳ではないので、ある程度予測精度がでると思われます。