LabelエンコーディングとOrdinalエンコーディングの違いは?有効な活用場面で根拠を持ってエンコーディングしよう

ここではLabelエンコーディングとOrdinalエンコーディングの基本的な違いと、それぞれがどのようなデータ処理場面で有効に活用できるのかを詳しく解説します。また、LightGBMのCategoryFutureを使用する場合についても少し触れています。
目次
はじめに
LightGBMでモデルを実装した際にカテゴリ変数をOne-Hotエンコーディングするつもりはなく、LabelエンコーディングするべきかOrdinalエンコーディングするべきか迷ったので、ここではLabelエンコーディングとOrdinalエンコーディングの基本的な違いと、それぞれがどのようなデータ処理場面で有効に活用できるのかを詳しく解説します。
Labelエンコーディングとは何か?
Labelエンコーディングは、カテゴリカルデータの各カテゴリに一意の整数を割り当てる手法です。主に名義尺度の変数に適用されます。
例えば、色のカテゴリ「赤」「青」「緑」があった場合、これらにそれぞれ「0」「1」「2」というラベルを割り当てることができます。
この方法の主な特徴は、カテゴリ間の順序や大小関係を考慮しない点にあります。
実際にやってみる
from sklearn.preprocessing import LabelBinarizer
from sklearn import preprocessing
import pandas as pd
import numpy as np
# データの用意
df = pd.DataFrame(
data={'性別': np.array(['male', 'female', 'male', 'female', 'male']),
'血液型': np.array(['A', 'B', 'O', 'AB', 'O'])})
# ラベルエンコーディング(LabelEncoder)
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
encoded = le.fit_transform(df['血液型'].values)
df['re_血液型'] = encoded
結果「A→0」「B→2」「O→3」「AB→1」にエンコーディングされています。
ここでややこしいのが、複数行に対して一括ラベルエンコーディングするときはOrdinal Encoderを使用します。
# ラベルエンコーディング(OrdinalEncoder)
from sklearn.preprocessing import OrdinalEncoder
oe = preprocessing.OrdinalEncoder()
encoded = oe.fit_transform(df[['性別', '血液型']].values)
encoded = pd.DataFrame(encoded, columns=['encode性別', 'encode血液型'])
df = pd.concat([df, encoded], axis=1)
df
結果「male→1」「female→0」にエンコーディングされています。
Ordinalエンコーディングとは何か?
一方、Ordinalエンコーディングは、カテゴリに順序関係が存在する場合に適用される手法です。たとえば、「小」「中」「大」というサイズカテゴリに対して、Ordinalエンコーディングを用いると「0」「1」「2」のように、自然な順序を反映した数値を割り当てることができます。
この手法では、カテゴリ間の順序がエンコーディングによって保持されるため、モデルがこの情報を学習に活用できます。
実際にやってみる
# データの用意
df = pd.DataFrame(
data={
'ユーザー': np.array(['A', 'B', 'C', 'D', 'E']),
'評価': np.array(['非常に悪い','悪い', '普通', '良い', '非常に良い', np.nan])
})
df
from sklearn.preprocessing import OrdinalEncoder
# カテゴリーの順序を決める(左から0, 1...となる)
categories = [['非常に悪い','悪い','普通', '良い', '非常に良い']]
# オーディナルエンコーディング(OrdinalEncoder)
oe = OrdinalEncoder(categories=categories, handle_unknown='use_encoded_value', unknown_value=5)
df['encode評価'] = oe.fit_transform(df[['評価']])
df
評価は悪いから良いへの範囲で0からエンコードされています。さらに、handle_unknownでカテゴリーにないデータの処理方法を指定することも可能です。この例では、5つの評価以外のデータがある場合、5を返すよう指定しています。
主な違い
LabelエンコーディングとOrdinalエンコーディングの主な違いは、カテゴリ間の「順序」を考慮するかどうかにあります。Labelエンコーディングは順序を考慮しませんが、Ordinalエンコーディングはカテゴリ間の自然な順序を数値に反映させます。このため、Ordinalエンコーディングは順序が意味を持つカテゴリカルデータに対して特に有効です。
LightGBMのCategory Futureを使用するとき
決定木ベースのLightGBMのCategory Futureで順序を反映させたエンコーディングしたカラムを指定すると意味のないものになります。
Light GBMのCategory Futureは、数値としての大小関係を直接利用するのではなく、カテゴリ間の分割を最適化するために使用されます。カテゴリカル特徴を内部で最適な分割点を見つけるために使用し、それによってノードを分割します。このプロセスは、特徴の値が数値としての大小関係を持っているかどうかに依存しません。
したがって、Ordinal EncoderでエンコーディングされたカラムをLightGBMのカテゴリカルフィーチャーとして指定した場合、その順序性は直接的な意味を持たなくなります。
各エンコーディングが有効な活用場面
- Labelエンコーディング: 順序関係のないカテゴリカルデータに適しています。例えば、国名や性別、血液型など、順序を考慮する必要のないカテゴリに最適です。
- Ordinalエンコーディング: 順序関係が明確に存在するカテゴリカルデータに有効です。例えば、学歴(高卒、専門卒、大卒、大学院卒)や評価(悪い、普通、良い、非常に良い)など、自然な順序が存在する場合に適用します。
まとめ
LabelエンコーディングとOrdinalエンコーディングは、カテゴリカルデータを数値データに変換するための有効な手法ですが、それぞれが有効な場面は異なります。データの性質を正確に理解し、目的やモデルに応じて適切なエンコーディング手法を選択することが不可欠です。