fitで学び、transformで適用する
変換器は第二の仕事を持つエスティメータです。fit(X) はデータから数(平均、分位点、語彙)を学び、末尾がアンダースコアの属性に保存して self を返します。transform(X) はその保存した数を、新旧どんなデータにも、そのデータを見て何かを決めることなく適用します。この分離こそが要点で、数は学習行で一度だけ学ばれ、テスト行は変換されるだけです。ウィンザライザーは良い最初の例です。fit は列ごとに下側と上側の分位点を学び、transform はその間で np.clip します。もし transform が受け取ったデータで分位点を再計算すると、各データがそれぞれの範囲に切り詰められ、学習の情報がテストに届きません。TransformerMixin と BaseEstimator を継承すれば、fit_transform とパラメータの仕組みも手に入ります。
実際の表は数値とカテゴリが混ざっているので、scikit-learnは ColumnTransformer([(名前, 変換器, 列), ...]) を用意しています。各ブランチが自分の列を処理し、出力は横に連結されます。ここでは数値ブランチが make_pipeline(Winsorizer(0.02, 0.98), StandardScaler())、カテゴリブランチが OneHotEncoder(handle_unknown='ignore') で、未知のカテゴリはエラーでなくゼロの行になります。sparse_threshold=0 は密な配列を強制します。出力列に名前を付けるには、すべての段が get_feature_names_out に答える必要があり、だからこそウィンザライザーにも実装が要ります(受け取った名前をそのまま返すだけです)。黄金律は、学習行には fit_transform、テスト行には transform だけを呼ぶことです。株式パネル(26銘柄、10,296行)では、2023年1月1日で分割すると学習5,564行・テスト4,732行になり、テストのモメンタムの約2.2%が学習の2%〜98%の範囲外で、学習の境界に切り詰められます。
- 一度学び、どこにでも適用:
fitは学習行から数を保存し、transformはそれを適用するだけ。 - 1つの前処理器、2つのブランチ:
ColumnTransformerは数値とカテゴリをそれぞれの段に送る。handle_unknown="ignore"は新しいカテゴリに耐える。 - 約束事を最後まで実装する:出力列に名前を付けられない変換器は、パイプライン全体の
get_feature_names_outを壊す。
ラボ:採点される内容
- コンストラクタ5点
- fit と transform20点
- 特徴量名とパイプライン10点
- 2ブランチの前処理器15点
- 日付で分割10点
- 過去だけで学習10点
- パネルの研究30点