ワンホットエンコーディングとは、都道府県や商品カテゴリのようなカテゴリ変数を、カテゴリごとの0と1の列へ変換する方法です。たとえば「赤・青・緑」という1列を、「色=赤」「色=青」「色=緑」の3列に展開し、該当する列だけを1にします。数値の大小を持たないカテゴリを、線形モデルや距離ベースのアルゴリズムへ入力しやすくする代表的な前処理です。
本記事では、ワンホットエンコーディングの仕組み、ラベルエンコーディングとの違い、カテゴリ数が多い場合の次元増加、未知カテゴリの扱い、訓練データとテストデータの整合、scikit-learnでの実装、データベースや推論環境での運用上の注意を解説します。変換した列を作ること自体が目的ではなく、モデルがカテゴリの意味を誤解しないよう設計することが重要です。
ワンホットエンコーディングとは?カテゴリを0と1の列に変換する方法
カテゴリ変数は、色、曜日、会員プラン、都道府県など、値の種類で意味を表す変数です。「赤」を1、「青」を2、「緑」を3と置き換えるだけでは、緑が青より大きいという順序をモデルが学習する恐れがあります。ワンホットエンコーディングは、各カテゴリを独立した二値列にすることで、カテゴリ間に不要な大小関係を持たせません。
3種類の色を持つデータなら、変換後は「色_赤」「色_青」「色_緑」という列になります。ある行が赤なら値は1,0,0、青なら0,1,0です。1行につき原則1列だけが1になるため、英語ではone-hotと呼ばれます。複数のタグを同時に持つデータは、1列だけが1になるカテゴリ変数ではなく、マルチラベルの二値化として扱います。
なぜワンホットエンコーディングを使うのか|数値化の誤解を避ける
ラベルエンコーディングは順序のないカテゴリに注意
ラベルエンコーディングはカテゴリを整数へ置き換える方法です。二値カテゴリなら0と1で表しても問題が少ないことがありますが、3種類以上で順序のないカテゴリを1,2,3へ変換すると、モデルによっては数値の距離や大小を意味として利用します。決定木系の一部は分割ルールの影響が異なりますが、アルゴリズムごとに挙動を決めつけず、入力表現とモデルの前提を確認します。
線形モデルや距離計算で特に使いやすい
線形回帰、ロジスティック回帰、線形SVMのように各特徴量へ係数を掛け合わせるモデルでは、ワンホット列ごとに異なる効果を学習できます。最近傍法やクラスタリングなど距離を使う手法でも、カテゴリ間の順序を数値で表すより、同じカテゴリかどうかを距離へ反映しやすくなります。ただし列数が増えるため、正則化や疎行列を組み合わせます。
ダミー変数の数|全列を残すか1列落とすか
切片を含む線形モデルで、Kカテゴリのワンホット列をすべて入れると、各行の合計が必ず1になります。この完全な線形従属は、ダミー変数トラップと呼ばれる問題につながります。係数の一意性や数値計算の安定性を重視する場合は、基準カテゴリを1つ落とし、残りK-1列を基準との差として解釈します。
一方、正則化されたモデル、木モデル、切片を使わないモデルでは、全列を残す設計が適する場合もあります。全列を落とすと、未知カテゴリや基準カテゴリの解釈が変わるため、係数の読み方を文書化します。scikit-learnのOneHotEncoderにはdrop引数があり、先頭カテゴリを落とす、明示したカテゴリを落とすなどの設定ができます。
カテゴリ数が多いときの課題|次元増加と疎な特徴量
商品ID、郵便番号、URLのパスなど、ほぼすべての行で異なる値を持つ列をワンホット化すると、列数が急増します。行列のほとんどが0になるため、密な配列へ変換するとメモリを大量に消費します。scikit-learnのOneHotEncoderは疎行列を返せる設定があり、対応するモデルと組み合わせることで保存容量と計算量を抑えられます。
頻度の低いカテゴリをまとめる
出現回数が少ないカテゴリは、学習データに偶然の係数が付きやすく、テスト時に未観測になる可能性も高い値です。業務上意味が近いカテゴリを「その他」へまとめる、出現頻度の閾値を決めて低頻度カテゴリを統合する、カテゴリを上位N件に制限するなどの方法があります。まとめるルールは訓練データだけで決め、予測時にも同じルールを適用します。
高カーディナリティでは別の表現も比較する
カテゴリ数が非常に多い場合は、頻度エンコーディング、ハッシュ化、ターゲットエンコーディング、埋め込み表現などを比較します。ターゲットエンコーディングは目的変数を使うため、検証データの情報が訓練側へ漏れやすく、交差検証内で計算する必要があります。ワンホットを避けることが目的ではなく、精度、説明しやすさ、メモリ、未知カテゴリへの対応を基準に選びます。
未知カテゴリと欠損の扱い|訓練時と推論時の差を吸収する
本番の入力には、訓練時に存在しなかった新しいカテゴリが現れます。たとえば新しい商品、海外の地域、追加されたプランなどです。未知カテゴリをエラーにすると推論全体が停止するため、OneHotEncoderのhandle_unknownをignoreにして全列0として扱う設計があります。ただし全列0が「どのカテゴリでもない」のか「欠損」なのかは別の情報なので、必要なら未知フラグを追加します。
欠損は、欠損専用カテゴリへ変換してからワンホット化する方法があります。欠損値補完器を先に置き、欠損フラグを残す設計も可能です。どちらを選ぶにしても、訓練、検証、テスト、本番で同じ前処理順を使います。空文字、文字列の「NaN」、PythonのNaNが混在していると別カテゴリになるため、入力段階で正規化します。
ワンホットエンコーディングの実装|ColumnTransformerで列を管理する
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.impute import SimpleImputer
numeric_pipe = Pipeline([
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler()),
])
category_pipe = Pipeline([
("imputer", SimpleImputer(strategy="most_frequent")),
("onehot", OneHotEncoder(handle_unknown="ignore")),
])
preprocess = ColumnTransformer([
("num", numeric_pipe, numeric_columns),
("cat", category_pipe, category_columns),
])この例では、数値列とカテゴリ列で異なる前処理を行い、ColumnTransformerで結合します。OneHotEncoderは訓練データでカテゴリ一覧を学習し、その列順を保存します。推論時に同じエンコーダーを再作成してはいけません。カテゴリの並びが変わると、モデルが「色_赤」のつもりで別の列を読む危険があります。前処理とモデルを一つのPipelineとして保存し、バージョンを管理します。
pandas.get_dummiesは探索用と本番用を分ける
pandasのget_dummiesは、データフレームを素早く確認する探索分析で便利です。ただし訓練データとテストデータを別々に変換すると、列の集合や順序が異なることがあります。連結してから変換する方法はテストのカテゴリを訓練処理へ見せることになり、評価の境界を曖昧にします。本番の学習では、訓練でfitしたエンコーダーを検証・テストへtransformする構成を優先します。
データリークを防ぐ設計|カテゴリ一覧も訓練データだけで学ぶ
ワンホット化は値を0と1へ置き換えるだけに見えますが、どのカテゴリを列として採用するかという情報を学習します。全データでカテゴリ一覧を作ると、テスト期間だけに出たカテゴリの存在を訓練処理が知ることになります。評価を厳密にするには、分割後の訓練データでエンコーダーをfitし、検証・テストはtransformだけにします。
交差検証では、各foldの訓練部分でカテゴリ一覧を作ります。あるfoldで未出現のカテゴリが検証部分にあれば、未知カテゴリとしてignoreするか、設計した「その他」へまとめます。分割の前後で列数が変わるのは自然な動作です。評価コードで無理に列をそろえるのではなく、パイプラインが同じ特徴量空間へ変換することを確認します。
変換方法の評価|モデル性能と解釈性を同じ条件で比べる
ワンホット化の採用判断では、ラベルエンコーディング、頻度エンコーディング、カテゴリをまとめる方法などを同じ分割と指標で比較します。分類ならF1、PR-AUC、再現率など業務の損失に関係する指標を選び、回帰ならMAEやRMSEを使います。検証分割を変えたときのばらつき、カテゴリ数、学習時間、推論メモリも合わせて記録します。
係数を説明するモデルでは、カテゴリ列ごとの係数を基準カテゴリとの差として読むのか、全列の係数として読むのかを明示します。カテゴリを「その他」へまとめた場合は、どの値が含まれるかをデータ辞書に残します。高いスコアだけでなく、現場が予測理由を確認できるか、カテゴリ追加のたびに再学習が必要かも採用基準です。
運用時の注意点|列順・未知値・スキーマを固定する
ワンホット化後の特徴量は、元のカテゴリ名と列順の対応が契約になります。モデルファイルだけでなく、エンコーダー、カテゴリ一覧、drop設定、未知値の扱い、欠損処理、出力列名を一緒に保存します。バッチ処理とオンライン推論で前処理の実装が別になる場合は、同じテストケースを両方へ通し、同じ入力が同じベクトルになることを確認してください。
運用監視では、カテゴリ別の出現頻度、未知カテゴリ率、全列0になった行の割合、特徴量の列数を追跡します。新商品や制度変更で未知カテゴリ率が上がった場合、ignoreで処理し続けるだけでは予測品質が落ちることがあります。一定の閾値を超えたらカテゴリ辞書を更新し、再学習と評価を行う手順を用意します。
ワンホットエンコーディングまとめ|変換より一貫した前処理が重要
ワンホットエンコーディングは、順序のないカテゴリを独立した0と1の列へ変換し、モデルに不要な大小関係を与えない方法です。線形モデルや距離ベースの手法で使いやすい一方、カテゴリ数が増えると次元とメモリが膨らみます。基準カテゴリを落とすか、全列を残すかは、モデルと係数の解釈を踏まえて決めます。
実装では訓練データだけでカテゴリ一覧を学習し、未知カテゴリ、欠損、低頻度カテゴリの処理を決めます。OneHotEncoderをColumnTransformerとPipelineに組み込み、エンコーダーとモデルを同じバージョンで保存すると、列順の事故を防ぎやすくなります。性能、説明性、運用コスト、カテゴリ追加の頻度を比較し、必要なら別の表現も検証してください。
よくある質問(FAQ)
Q. ワンホットエンコーディングとは何ですか?
カテゴリごとに0と1の列を作り、該当するカテゴリの列だけを1にする変換です。順序のないカテゴリを数値の大小として誤解させずにモデルへ入力できます。
Q. ラベルエンコーディングとの違いは何ですか?
ラベルエンコーディングはカテゴリを整数へ置き換えます。ワンホットはカテゴリごとに列を分けるため、順序のないカテゴリへ不要な大小関係を持たせにくい点が違います。
Q. 未知カテゴリが推論時に出たらどうしますか?
未知カテゴリをエラーにせず全列0として扱う、または「その他」へまとめる方法があります。未知率を監視し、増加した場合はカテゴリ辞書の更新と再学習を検討します。
Q. ダミー変数を1列落とすべきですか?
切片を含む線形モデルで係数の一意性を重視するなら基準カテゴリを1つ落とす設計があります。正則化や木モデルでは全列を残すこともあり、モデルと係数の解釈に合わせて比較します。
Q. ワンホット化でデータリークを防ぐには?
訓練データだけでエンコーダーをfitし、検証・テストはtransformだけにします。全データでカテゴリ一覧を作らず、交差検証では各foldの訓練部分でカテゴリを学習してください。
参考資料
- scikit-learn「OneHotEncoder」
https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html - scikit-learn User Guide「Categorical Feature Support」
https://scikit-learn.org/stable/modules/preprocessing.html#encoding-categorical-features - scikit-learn「ColumnTransformer」
https://scikit-learn.org/stable/modules/generated/sklearn.compose.ColumnTransformer.html - scikit-learn「Pipeline」
https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html - pandas「pandas.get_dummies」
https://pandas.pydata.org/docs/reference/api/pandas.get_dummies.html
