web-dev-qa-db-ja.com

ラベルエンコーディングの不明な値の処理

Sk-learnでラベルエンコーディングの不明な値を処理するにはどうすればよいですか?ラベルエンコーダーは、新しいラベルが検出されたことを除いて、爆発するだけです。

私が欲しいのはカテゴリ変数のエンコーディングone-hot-encoderです。ただし、sk-learnはそのための文字列をサポートしていません。そこで、各列にラベルエンコーダーを使用しました。

私の問題は、パイプラインの相互検証ステップで不明なラベルが表示されることです。基本的なワンホットエンコーダーには、このような場合を無視するオプションがあります。アプリオリpandas.getDummies /cat.codesは、パイプラインが未知のラベルを含む可能性のある実際の新鮮な受信データで動作する必要があるため、十分ではありません。

この目的でCountVectorizerを使用することは可能ですか?

14
Georg Heiler

編集:

Scikit-learnを使用してこの問題を処理するより最近の簡単な方法は、クラスsklearn.preprocessing.OneHotEncoderを使用することです。

from sklearn.preprocessing import OneHotEncoder

enc = OneHotEncoder(handle_unknown='ignore')
enc.fit(train)

enc.transform(train).toarray()

古い答え:

このための方法としてpandas.get_dummiesについて言及している回答がいくつかありますが、labelEncoderアプローチの方がモデルを実装するのにすっきりしています。他の同様の回答では、このためにDictVectorizerを使用することについて言及していますが、DataFrame全体をdictに変換することは、おそらく素晴らしいアイデアではありません。

次の問題のある列を想定します。

from sklearn import preprocessing
import numpy as np
import pandas as pd

train = {'city': ['Buenos Aires', 'New York', 'Istambul', 'Buenos Aires', 'Paris', 'Paris'],
        'letters': ['a', 'b', 'c', 'd', 'a', 'b']}
train = pd.DataFrame(train)

test = {'city': ['Buenos Aires', 'New York', 'Istambul', 'Buenos Aires', 'Paris', 'Utila'],
        'letters': ['a', 'b', 'c', 'a', 'b', 'b']}
test = pd.DataFrame(test)

Utilaはまれな都市であり、トレーニングデータには含まれていませんが、テストセットには含まれているため、推論時に新しいデータを検討できます。

トリックは、この値を「その他」に変換し、これをlabelEncoderオブジェクトに含めることです。その後、本番環境で再利用できます。

c = 'city'
le = preprocessing.LabelEncoder()
train[c] = le.fit_transform(train[c])
test[c] = test[c].map(lambda s: 'other' if s not in le.classes_ else s)
le_classes = le.classes_.tolist()
bisect.insort_left(le_classes, 'other')
le.classes_ = le_classes
test[c] = le.transform(test[c])
test

  city  letters
0   1   a
1   3   b
2   2   c
3   1   a
4   4   b
5   0   b

これを新しいデータに適用するには、Pickleで簡単に実行できる各列のleオブジェクトを保存するだけです。

この回答はこれに基づいています 質問 完全に明確ではないので、この例を追加しました。

12
marbel