DS(データサイエンス) python データサイエンス 非エンジニア向け

【Python Coding】Label Encoding

こんにちは、TAKです。

以前、カテゴリ変数を数値化する方法として「One-hotエンコーディング」と「クラスラベルのマッピング処理」について紹介しました。今回は、それらに追加する形で「Labelエンコーディング」という方法について解説していきたいと思います。

「カテゴリ変数を数値化する必要性」という記事の中で、カテゴリ変数を数値化する必要性や手法の全体像を紹介しているので、良ければそちらも参考にしてみてください。

python codingなので、いつものようにJupyter Notebookベースでコードを紹介していきます。
必要に応じて、みなさんもローカル環境で実装トライしてみてくださいね。

そして今回は、「欠損値がない場合」と「欠損値がある場合」の2パターンにわけてみていきます。

Label エンコーディング処理 | 欠損値がないケース

必要ライブラリのインポート(共通)

今回はpandasとsklearnライブラリを使うので、上記コードをインポートします。
今回のメイン部分が「LabelEncoder」となりますので、前処理ライブラリからインポートしておきます。
pandasはデータ作成用に使っていきます。

データの準備(欠損値なし)

今回は、以下のような特に意味のないデータを作成します。
具体的には、下記イメージのような簡単なデータを用意していきますが、カテゴリ変数を含んでいる点に着目しておいてください。また、欠損値を含まないデータを作成していきます。

■ 具体例データ

データの作成(欠損値なし)

では実際にpandasを用いて先ほどのデータを作成しましょう。

■ 簡易データの作成(欠損値なし)

● pandasのDataFrameで新しくデータを作成出来ます
これで先ほどのデータが作成出来ましたね。
このデータフレームに含まれているカテゴリ変数(列名「Color」と「Rank」)対して、Labelエンコーディング処理を施していくことが今回の目的になります。

Labelエンコーディングの適用

では実際に、今回のメイン処理となる「Labelエンコーディング処理」をしていきます。
そもそもLabelエンコーディングとは何なのか、簡単に説明しておきます。

Labelエンコーディング処理は、カテゴリ変数を数値に変換する処理のことを言います。
より具体的に言うと、あるカテゴリ変数の種類が「N個」あった場合、それらのデータを「0~(N-1)」の数値に変換する処理を意味します。

例えば、先ほど作った簡易データの列名「Rank」を例に挙げてみると、ランクAからEまでの合計5種類が含まれていますよね。つまりN=5となるので、A-Eまでの文字列を0-4に変換するようなイメージとなります。ちなみに、どの文字列にどの値がラベリングされたかは重要ではないです。

Labelエンコーディング処理を施す前に、カテゴリ変数の種類がいくつあるか確認しておきます。
下記コーディング結果を見てもらえばわかるように、それぞれ5個ずつ種類がありますね。

それでは、Labelエンコーディングに関連するコードを見ていきます。
Labelエンコーディング処理のポイントは以下2点です。

ポイント①:LabelEncoderを呼び出してインスタンス化しておく
ポイント②:対象となるカテゴリ変数に対して、「fit_transform()」を適用する

これを適用した結果が以下となります。

Labelエンコーディング処理をした結果、カテゴリ変数を含む列「Color」と「Rank」の値がそれぞれ0-4の値に変換されていることがわかるかと思います。

ちなみに、上記コーディングではカテゴリ変数となっている列名を指定して変換処理していますが、以下のような自作関数で汎用的に処理してもOKです。
いずれも同じ結果が得られていることがわかるかと思います。

このような前処理をすることによって、モデルに対してデータを学習させていくことが可能となります。
以上が欠損値がない場合のデータに対するLabelエンコーディング処理となります。

Label エンコーディング処理 | 欠損値があるケース

データの準備(欠損値あり)

では次に、データに欠損値が含まれるケースについて見ていきましょう。

そもそも、なぜ欠損値の有無に応じて処理をわける必要があるかと言うと、①One-hotエンコーディングの時のように、欠損値を自動で処理する機能がないこと、②欠損値を意識せずにLabelエンコーディングをすると不都合が生じることの2点が理由として挙げられます(不都合の詳細は最後に紹介しています)。

実務では様々なデータを扱う上、欠損値がないようなパーフェクトなデータに出くわすことはほぼないので、欠損値があるケースにも対処出来るようにしておくことが大切ですね。

用いるデータとしては、先ほどのデータ数を5個から100個に拡張し、「Color」と「Rank」にランダムで欠損値(None)を含んだデータを想定したいと思います。

■ 具体例データ

データの作成(欠損値あり)

では実際にpandasを用いて先ほどのデータを作成しましょう。

■ 簡易データ(欠損値あり)の作成

● 内容表記やランダム関数を用いて各列を作成しています
● 最終的に、pandasのconcat機能でSeries型データを結合しています
これで先ほどのデータが作成出来ましたね。欠損データも41個含んでいることがわかります。
先ほどと同様に、データフレームに含まれているカテゴリ変数(列名「Color」と「Rank」)対して、Labelエンコーディング処理を施していくことが今回の目的になります。欠損値Noneが含まれている点が先ほどと異なります。

Labelエンコーディングの適用

では実際に、欠損値を含むデータに対して「Labelエンコーディング処理」をしていきましょう。
Labelエンコーディング処理のポイントは先ほどと変わりませんが、pandasの「not_null()」を用いて欠損値以外のデータを指定して処理する点が重要となります。

列名「Color」に限定してコーディング結果が以下となります。

列名「Color」に対してLabelエンコーディング処理をした結果、「Color」の値が数値に変換されているとともに、欠損値はそのままになっていることがわかるかと思います。

Rank変数に対しても同様に処理を行っていきましょう。
以下では自作関数を用いてLabelエンコーディング処理をしています。
以上のように、赤枠部分が適切にLabelエンコーディング処理されているのがわかりますね。
NaNはもともと欠損値となっている部分なので、そこを避けてうまく処理出来ています。

欠損値に対してLabelエンコーディングを適用した場合

ここで一つ疑問が湧くかもしれません。
それは「欠損値データに対してLabelエンコーディング処理を行ったらどうなるのか?」という疑問です。
僕自身も疑問に持ったことがあったのですが、結論から言うと「欠損値は欠損のままにして、欠損値以外のデータに対してLabelエンコーディング処理をすべき」です。

なぜなら、欠損値同士が異なる値としてラベル変換されてしまうからです。
欠損値に対してもLabelエンコーディング処理を行ったコードが以下なのですが、以下赤丸部分を見てもらった方がわかりやすいかと思います。

先ほどの欠損部分と比較してもらえればわかるように、欠損値も何かしらの数値に変換されているのがわかります。そして、欠損値がすべて同じ数値として変換されるわけではなく、各々異なる数値として変換されてしまっているのです。

モデルを構築する上で、「欠損」という状態が何かしら意味を持つと考える方法もありますが、各々の欠損値自体に違いはないはずですよね。同じ数値(例えば999)として変換されるならまだしも、全く別の数値として変換されてしまっている以上、モデル精度を下げかねない前処理になってしまいます。

そのため、Labelエンコーディング処理を施す場合には、欠損値の有無でわけた方がいいというわけです。

まとめ

いかがだったでしょうか?
今回は、カテゴリ変数の数値化処理として「Labelエンコーディング」について紹介してきました。

欠損値がある場合には、pandas操作がかなり重要となるので、今一つわからなかった方はこれを機会に復習してみてください。勉強法がわからないという方は、以下のpandas書籍を辞書代わりに使って一つずつレベルアップしていくことをオススメします。

● pandasレベルアップ用の書籍 → Pythonデータ分析 | pandasライブラリ活用入門

では今回はこのへんで。