決定木/ランダムフォレストの機能としての文字列


64

決定木/ランダムフォレストのアプリケーションでいくつかの問題を行っています。機能として数字と文字列(国名など)を持つ問題を解決しようとしています。ライブラリであるscikit-learnは、パラメータとして数字のみを使用しますが、文字列を注入するだけでなく、かなりの知識が必要です。

このようなシナリオをどのように処理しますか?

Pythonのハッシュなどのメカニズムにより、文字列を数値に変換できます。しかし、決定木問題で文字列を処理する方法に関するベストプラクティスを知りたいと思います。


sckitlearnの場合、カテゴリ変数をエンコードする必要があることがわかりました。それ以外の場合、fitメソッドは、ValueError:string to float to float
Kar

回答:


56

確立された機械学習システムのほとんどでは、カテゴリ変数は自然に処理されます。たとえば、Rでは因子を使用し、WEKAでは名義変数を使用します。これはscikit-learnには当てはまりません。scikit-learnで実装される決定木は、数値的特徴のみを使用し、これらの特徴は常に連続数値変数として解釈されます

したがって、文字列をハッシュコードで単純に置き換えることは避ける必要があります。これは、使用するコーディングが連続的な数値機能と見なされるため、データに存在しない順序が誘導されるためです。

たとえば、['red'、 'green'、 'blue']を[1,2,3]でコーディングすると、「red」は「blue」よりも低く、「red」を平均すると「青」の場合は「緑」になります。[1,2,3]で['low'、 'medium'、 'high']をコーディングすると、さらに微妙な例が発生する可能性があります。後者の場合、理にかなっている順序付けが行われる場合がありますが、「中」が「低」と「高」の中間にない場合、いくつかの微妙な矛盾が発生する可能性があります。

最後に、あなたの質問に対する答えは、カテゴリ機能を複数のバイナリ機能にコーディングすることにあります。たとえば、['red'、 'green'、 'blue']を3つの列(各カテゴリに1つ)でコーディングすると、カテゴリが一致する場合は1、それ以外の場合は0になります。これはone-hot-encoding、バイナリエンコーディング、one-of-k-encodingなどと呼ばれます。カテゴリフィーチャのエンコードフィーチャ抽出-ハッシュと辞書については、こちらのドキュメントをご覧ください。明らかに、ワンホットエンコーディングはスペース要件を拡大し、時にはパフォーマンスも低下させます。


2
カテゴリ変数を適切に処理しないのはscikitの実装です。この回答が示す方法のような再コーディングは、おそらく最善の方法です。より深刻なユーザーは、代替パッケージを探す可能性があります。
-SmallChess

3
カテゴリ変数のワンホットエンコーディングにsklearn.preprocessing.LabelBinarizerを使用できます。
グスク

@rapaioバイナリコーディングは、ホットエンコードとは異なります。バイナリコーディングは、3つの列を持つ8つのカテゴリ、または4つの列を持つ9〜16のカテゴリなどを表す場合です。私が間違っている?
Alokナーヤカ

patsy pythonパッケージは、カテゴリ変数のワンホットエンコーディングを処理します。patsy.readthedocs.io/en/latest/quickstart.html
zhespelt

5
LabelBinarizerを使用せず、sklearn.preprocessing.OneHotEncoderを使用します。パンダを使用してデータをインポートおよび前処理する場合、pandas.get_dummiesを使用して直接行うこともできます。scikit-learnはカテゴリ変数をサポートしていないのは残念です。
リカルドクルス

11

sci-kitがMLアルゴリズムに使用できる数値機能として文字列をエンコードする必要があります。この機能は前処理モジュールで処理されます(例については、sklearn.preprocessing.LabelEncoderを参照してください)。


3
rapaioは答えで、これが間違った結果を得る理由を説明します
キース

7

通常、ランダムフォレストを含むscikit-learnモデルのカテゴリ変数をワンホットエンコードする必要があります。ランダムフォレストは多くの場合、ワンホットエンコードを使用しなくても正常に機能しますが、通常、ワンホットエンコードを実行するとパフォーマンスが向上します。ワンホットエンコーディングと「ダミー」変数は、このコンテキストでは同じことを意味します。Scikit-learnにはsklearn.preprocessing.OneHotEncoderがあり、Pandasにはこれを実現するためのpandas.get_dummiesがあります。

ただし、代替手段があります。KDnuggetsの記事「Beyond One-Hot」では、カテゴリー変数をエンコードする必要がある理由とワンホットエンコードの代替を説明する素晴らしい仕事をしています。

RやH2Oなどのワンホットエンコーディングを必要としないランダムフォレストの代替実装があります。Rでの実装は計算コストあなたの特徴は、多くの種類を持っている場合は動作しません。H2Oは、多数のカテゴリで機能します。Continuumは、H2OをAnaconda Pythonで利用できるようにしました。

あり、直接カテゴリ機能を扱うscikitが学習させるための継続的な努力が

この記事では、H2Oで使用されるアルゴリズムについて説明しています。学術論文A Streaming Parallel Decision Tree Algorithmと同じ論文の長いバージョンを参照しています。


5

2018アップデート!

カテゴリ変数の埋め込み(高密度ベクトル)スペースを作成できます。多くの人がword2vecとfastextに精通しています。これらは、意味のある密なベクトル空間に単語を埋め込みます。ここでも同じ考えです-カテゴリ変数は何らかの意味を持つベクトルにマップされます。

郭/ Berkhahn紙

エンティティの埋め込みは、ワンホットエンコーディングと比較してメモリ使用量を削減し、ニューラルネットワークを高速化するだけでなく、より重要なこととして、埋め込みスペースで類似した値を互いに近くにマッピングすることにより、カテゴリ変数の固有のプロパティを明らかにします。最近のKaggleコンペティションでこれをうまく適用し、比較的シンプルな機能で3番目の位置に到達することができました。

著者は、この方法でカテゴリ変数を表すことにより、ランダムフォレストを含む、テストされたすべての機械学習アルゴリズムの有効性が向上することを発見しました。

最良の例は、関連するピンをグループ化するためのPinterestの手法の適用かもしれません。

ここに画像の説明を入力してください

fastaiの人々は、カテゴリカルな埋め込みを実装し、コンパニオンデモノートブックで非常に素晴らしいブログ投稿を作成しました。

追加の詳細と説明

ニューラルネットを使用して、埋め込みを作成します。つまり、各カテゴリ値にベクトルを割り当てます。ベクトルを取得したら、数値を受け入れる任意のモデルで使用できます。ベクトルの各コンポーネントは入力変数になります。たとえば、色のカテゴリリストを埋め込むために3-Dベクトルを使用した場合、次のようになります。red=(0、1.5、-2.3)、blue =(1、1、0)など。 3つのコンポーネントに対応するランダムフォレストの入力変数。赤いものの場合、c1 = 0、c2 = 1.5、およびc3 = -2.3。青いものの場合、c1 = 1、c2 = 1、c3 = 0。

実際には、埋め込みを作成するためにニューラルネットワークを使用する必要はありません(ただし、この手法を避けることはお勧めしません)。可能な場合は、手作業または他の方法で独自の埋め込みを自由に作成できます。いくつかの例:

  1. 色をRGBベクトルにマップします。
  2. 場所を緯度/経度のベクトルにマップします。
  3. 米国の政治モデルでは、都市を左/右揃え、税負担などを表すいくつかのベクトルコンポーネントにマップします。

OKクールですが、何かを見逃さない限り、これはネットの開始から終了までです。埋め込みを作成し、その埋め込みをフォレストに渡す方法は?すべての機能を備えたネット全体をトレーニングし、最初のいくつかのレイヤーを取得して、Forrestへの入力機能として使用する必要があると思います。これがどのように行われるかは明らかではありません。
キース

@Keithニューラルネットを使用して、埋め込みを作成します。つまり、各カテゴリ値にベクトルを割り当てます。ベクトルを取得したら、数値を受け入れる任意のモデルで使用できます。ベクトルの各コンポーネントは入力変数になります。たとえば、色のカテゴリリストを埋め込むために3Dベクトルを使用した場合、次のようになります:red = (0, 1.5, -2.3)、blue = (1, 1, 0)など。3つのコンポーネントに対応するランダムフォレストで3つの入力変数を使用します。赤いものの場合、c1 = 0、c2 = 1.5、およびc3 = -2.3。青色のもの、C1 = 1、C2 = 1、およびC3 = 0の
ピート

この概念は非常に単純なので、完全に理解できます。これは実装でどのように行われるのでしょうか?リンクするfast.aiデモノートには、最後にRandomForestRegressorが少し付いていますが、これが埋め込みにどのように追加されるかはわかりません。
キース

私は、これはKerasのコードの良い例かもしれないと思うgithub.com/entron/entity-embedding-rossmann
キース

3

このようなシナリオでは、ダミー変数を使用できます。パンダpanda.get_dummiesを使用すると、デシジョンツリーまたはランダムフォレストに配置する文字列のダミー変数を作成できます。

例:

import pandas as pd
d = {'one' : pd.Series([1., 2., 3.,4.], index=['a', 'b', 'c','d']),'two' :pd.Series(['Paul', 'John', 'Micheal','George'], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)

df_with_dummies= pd.get_dummies(df,columns=["two"],drop_first=False)
df_with_dummies

2

たとえば、一意の番号(1,2,3など)を割り当てた一意の国ごとに番号に変換します

また、ツリーは他のアルゴリズム(線形/ロジスティック回帰など)のように機能せず、遠くまでは機能しないため(ランダムフォレストで作業する場合、ワンホットエンコード(別名ダミー変数)を使用する必要ありません)あなたの機能のために良いの分割を見つけると仕事)ので、NO NEEDワンホットエンコーディングのための


1
実際には、ツリーをトレーニングする特定のアルゴリズムに依存します。特に、scikitはカテゴリ変数をサポートしていません。
chuse
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.