決定木/ランダムフォレストのアプリケーションでいくつかの問題を行っています。機能として数字と文字列(国名など)を持つ問題を解決しようとしています。ライブラリであるscikit-learnは、パラメータとして数字のみを使用しますが、文字列を注入するだけでなく、かなりの知識が必要です。
このようなシナリオをどのように処理しますか?
Pythonのハッシュなどのメカニズムにより、文字列を数値に変換できます。しかし、決定木問題で文字列を処理する方法に関するベストプラクティスを知りたいと思います。
決定木/ランダムフォレストのアプリケーションでいくつかの問題を行っています。機能として数字と文字列(国名など)を持つ問題を解決しようとしています。ライブラリであるscikit-learnは、パラメータとして数字のみを使用しますが、文字列を注入するだけでなく、かなりの知識が必要です。
このようなシナリオをどのように処理しますか?
Pythonのハッシュなどのメカニズムにより、文字列を数値に変換できます。しかし、決定木問題で文字列を処理する方法に関するベストプラクティスを知りたいと思います。
回答:
確立された機械学習システムのほとんどでは、カテゴリ変数は自然に処理されます。たとえば、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などと呼ばれます。カテゴリフィーチャのエンコードとフィーチャ抽出-ハッシュと辞書については、こちらのドキュメントをご覧ください。明らかに、ワンホットエンコーディングはスペース要件を拡大し、時にはパフォーマンスも低下させます。
sci-kitがMLアルゴリズムに使用できる数値機能として文字列をエンコードする必要があります。この機能は前処理モジュールで処理されます(例については、sklearn.preprocessing.LabelEncoderを参照してください)。
通常、ランダムフォレストを含む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と同じ論文の長いバージョンを参照しています。
2018アップデート!
カテゴリ変数の埋め込み(高密度ベクトル)スペースを作成できます。多くの人がword2vecとfastextに精通しています。これらは、意味のある密なベクトル空間に単語を埋め込みます。ここでも同じ考えです-カテゴリ変数は何らかの意味を持つベクトルにマップされます。
エンティティの埋め込みは、ワンホットエンコーディングと比較してメモリ使用量を削減し、ニューラルネットワークを高速化するだけでなく、より重要なこととして、埋め込みスペースで類似した値を互いに近くにマッピングすることにより、カテゴリ変数の固有のプロパティを明らかにします。最近の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。
実際には、埋め込みを作成するためにニューラルネットワークを使用する必要はありません(ただし、この手法を避けることはお勧めしません)。可能な場合は、手作業または他の方法で独自の埋め込みを自由に作成できます。いくつかの例:
(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の
このようなシナリオでは、ダミー変数を使用できます。パンダ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
たとえば、一意の番号(1,2,3など)を割り当てた一意の国ごとに番号に変換します
また、ツリーは他のアルゴリズム(線形/ロジスティック回帰など)のように機能せず、遠くまでは機能しないため(ランダムフォレストで作業する場合、ワンホットエンコード(別名ダミー変数)を使用する必要はありません)あなたの機能のために良いの分割を見つけると仕事)ので、NO NEEDワンホットエンコーディングのための