Scikit-learn: パンダイン、パンダアウト?

作成日 2015年10月22日  ·  59コメント  ·  ソース: scikit-learn/scikit-learn

現時点では、ほとんどのsklearn fit / predict / transformメソッドの入力としてpandasデータフレームを使用できますが、numpy配列が出力されます。 あなたがそれを入れたのと同じフォーマットでデータを取り出すことができるのは本当に素晴らしいことです。

あなたのデータフレームが数値でない列が含まれている場合、彼らは可能ウィルので、その後、中間numpyのアレイは、sklearnが失敗する原因になりますので、これは、完全に単純ではありませんdtype=objectの代わりに、 dtype=float 。 これは、非数値データを数値データ(たとえば、クラス/カテゴリを表す整数)にマップするDataframe-> ndarrayトランスフォーマーを使用することで解決できます。 sklearn-pandasはすでにこれを行っていますが、現在inverse_transformはありませんが、追加するのは難しいことではありません。

このような変換は、sklearnで使用すると_本当に_便利だと思います。これは、複数のデータ型を持つデータセットを操作する人なら誰でも役立つと思うようなものです。 このようなものをsklearnに組み込むには何が必要ですか?

最も参考になるコメント

DataFrame与えられると、すべてのトランスフォーマーはDataFrame返します。
300列のDataFramePipelineし、500列のndarrayを受け取った場合、たとえばfeature_selectionなど、それから多くを効果的に学ぶことはできません。 mutual_info_classifで、列30と75のみが重要であると言われた場合、元のPipelineを本番用に簡略化する方法がわかりません。
したがって、私のユースケースでは、データをDataFrameに保持することが重要です。
ありがとうございました。

全てのコメント59件

Scikit-learnは、非常に一般的な入力形式で動作するように設計されています。 おそらく、scikit-learnを取り巻く世界は、パンダの統合をより重要にする方法で大きく変化しました。 それでも、主にサードパーティのラッパーによって提供される可能性があります。

しかし、より広い質問とは別に、標準的な推定量からのパンダに優しい出力がどのように異なり、使いやすさに違いをもたらすかについての例を挙げてみるべきだと思います。 私が考えることができる例:

  • すべてのメソッドが入力からインデックスをコピーできます
  • トランスフォーマーは適切な名前の列を出力する必要があります
  • マルチクラスpredict_probaは、列にクラス名のラベルを付けることができます

うん、頭のてっぺんから:

  • インデックスは、たとえば、時間差のある変数を作成する場合などに非常に役立ちます(たとえば、1日のラグ、日が欠落している毎日のデータ)
  • sklearnリグレッサは、カテゴリデータで透過的に使用できます(混合データフレームを渡し、LabelBinarizerでカテゴリ列を変換し、inverse_transformを元に戻します)。
  • sklearn-pandasは、データフレームを渡し、データのサブセットのみを使用し、個々の列を任意に変換できる優れたインターフェイスをすでに提供しています。

これがすべて変換に含まれている場合、デフォルトでsklearnがどのように機能するかには実際には影響しません。

トランスとしてうまく実装できるとは思いません。 それはそのようになります
1つ以上のメタエスティメータまたはミックスイン。 最初はそうあるべきだと思います
外部に実装され、有用であることが実証された

午前17時40分に2015年10月22日、naught101 [email protected]書きました:

うん、頭のてっぺんから:

  • インデックスは、たとえば時間差のあるラグを作成する場合などに非常に役立ちます。
    変数(たとえば、1日の遅れ、一部の欠落した日がある毎日のデータ)
  • sklearnリグレッサは、カテゴリデータで透過的に使用できます
    (混合データフレームを渡し、LabelBinarizerを使用してカテゴリ列を変換します。
    reverse_transform it back)。
  • sklearn-pandasは、次のことを可能にする優れたインターフェイスをすでに提供しています。
    データフレームを渡し、データのサブセットのみを使用し、任意に使用する
    個々の列を変換します。

これがすべて変換に含まれている場合、sklearnの方法には実際には影響しません
デフォルトで動作します。


このメールに直接返信するか、GitHubで表示してください
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -150123228

「パンダイン」をより良くすることは、カラムトランスPR#3886の背後にある一種のアイデアでした。 sklearn-pandasがすでに行っていることをもっと詳しく調べておくべきだったのかもしれません。 前進するための最善の方法が何であるかは完全にはわかりません。

もう1つの便利な点は、変換で列名を保持すること/特徴選択を行うときに列名を選択することです。 今、これについて話し合った問題は見つかりません。 たぶん@jnothmanは覚えています。 列名を保持するために入力検証を伴う大手術が必要になりますが、私は本当にそれを望んでいます:-/

関連#4196

ただし、入力検証を伴う大手術が必要になります。
列名を保持します:-/

入力検証だけでなく、すべての変換はそれが何であるかを記述しなければなりません
入力列に対して行います。

本当ですが、それはいいと思います;)

1つの質問は、これをパイプラインだけで必要なのか、それともどこでも必要なのかということです。 パイプラインに限定すると、入力検証手術はそれほど大きくありません。 しかし、それがどれほど役立つかはわかりません。

パイプラインは、1つだけでいつでも実行できますよね? したがって、最初はパイプラインのみに制限することで、すべてのケースを処理します(ただし、1つのオブジェクトの制限ではハッキーです)。

+1。 パイプラインから始めるのはいいですね。次のステップですべてのトランスフォーマーをカバーします。

私はまた、パンダとsklearnの統合を備えたimplを持っています。これは、 inverse_transformを介して列情報を元に戻すことができます(ただし、ダーティハック...)

http://pandas-ml.readthedocs.org/en/latest/sklearn.html

•インデックスは、たとえば時限ラグ変数を作成する場合などに非常に役立ちます。
(たとえば、1日の遅れ、一部の欠落した日がある毎日のデータ)

私は少し愚かですが、サンプルの何かについて話していません
フィーチャーの方向ではなく、ここの方向?

•sklearnリグレッサは、カテゴリデータで透過的に使用できます(パス
混合データフレーム、LabelBinarizerを使用してカテゴリ列を変換します。
reverse_transform it back)。

•sklearn-pandasは、
データフレーム、およびデータのサブセットのみを使用し、任意に変換します
個々の列。

OK、でもそれはパンダを取り込む1つのトランスフォーマーのレベルです。
データマトリックスを出しますね。 試みるのではなく
scikit-learnのすべてのオブジェクトの変更(これは危険です
努力者)、私たちは最初にこの変圧器を実装することができました(私はそれを信じています
@amuellerはこれを頭に入れています)。

特徴の方向ではなく、ここでサンプルの方向?

うん。

OK、でもそれはパンダを取り込んでデータマトリックスを出す1つのトランスフォーマーのレベルですよね?

うん、それは私が最初に考えていたものです。 Xyをデータフレームとして処理するラッパーに満足しています。 sklearnの内部をねじ込む明確な理由はわかりません。

OK, but that's all at the level of one transformer that takes Pandas in,
and gives a data matrix out, isn't it?

うん、それは私が最初に考えていたものです。 私はもっ​​と幸せになるでしょう
Xとyをデータフレームとして処理するラッパー。 明らかな理由がわかりません
sklearnの内部をねじ込みます。

次に、同じページにいます。 @amuellerに
これ、そして私たちはいくつかの議論を見るかもしれません、そして多分すぐにコーディングします。

もう1つの便利な点は、変換で列名を保持すること/特徴選択を行うときに列名を選択することです。 今、これについて話し合った問題は見つかりません。

5172

注:この機能をユーザーに提供するために、最も外側の推定量をアンサンブルでラップするだけでよいのではないかと思いました。 答えは次のとおりです。いいえ、パイプライン内でデータフレーム対応のトランスフォーマーを使用できるようにするために、アトミックトランスフォーマーもラップしたいと考えています(なぜですか?)。 これをミックスインとして実装しないと、不要なパラメーターのプレフィックスやクローン作成の問題が発生する可能性があります(#5080のように)。

:+1:

私が使用しているソリューションを捨てたかっただけです:

def check_output(X, ensure_index=None, ensure_columns=None):
    """
    Joins X with ensure_index's index or ensure_columns's columns when avaialble
    """
    if ensure_index is not None:
        if ensure_columns is not None:
            if type(ensure_index) is pd.DataFrame and type(ensure_columns) is pd.DataFrame:
                X = pd.DataFrame(X, index=ensure_index.index, columns=ensure_columns.columns)
        else:
            if type(ensure_index) is pd.DataFrame:
                X = pd.DataFrame(X, index=ensure_index.index)
    return X

次に、変換の出力でこの関数を呼び出すsklearnの推定量のラッパーを作成します。

from sklearn.preprocessing import StandardScaler as _StandardScaler 
class StandardScaler(_StandardScaler):
    def transform(self, X):
        Xt = super(StandardScaler, self).transform(X)
        return check_output(Xt, ensure_index=X, ensure_columns=X)

入力データフレームXのインデックスを使用する必要がある分類器は、そのインデックスを使用できます(指摘されたように時系列に役立ちます)。

このアプローチには、既存のsklearnデザインと完全に互換性があり、計算速度も維持できるという利点があります(数学演算とデータフレームのインデックス作成は、numpy配列よりも最大10倍遅くなります。http://penandpants.com/2014/09/05 / performance-of-pandas-series-vs-numpy-arrays /)。 残念ながら、それを利用できる各推定量に追加するのは面倒な作業です。

たぶん、この魔法でパイプラインバリアントを作成する必要があるだけです...

午前2時30分に2016年1月15日、ディーンWyatteの[email protected]書きました:

私が使用しているソリューションを捨てたかっただけです:

def check_output(X、ensure_index = None、ensure_columns = None):
"" "
利用可能な場合、Xをensure_indexのインデックスまたはensure_columnsの列と結合します
"" "
sure_indexがNoneでない場合:
sure_columnsがNoneでない場合:
type(ensure_index)がpd.DataFrameで、type(ensure_columns)がpd.DataFrameの場合:
X = pd.DataFrame(X、index = ensure_index.index、columns = ensure_columns.columns)
そうしないと:
type(ensure_index)がpd.DataFrameの場合:
X = pd.DataFrame(X、index = ensure_index.index)
Xを返す

次に、この関数を呼び出すsklearnの推定量のラッパーを作成します
変換の出力について、例えば、

sklearn.preprocessingからStandardScalerを_StandardScalerとしてインポートします
クラスMinMaxScaler(_MinMaxScaler):
def transform(self、X):
Xt = super(MinMaxScaler、self).transform(X)
check_output(Xt、ensure_index = X、ensure_columns = X)を返します

入力データフレームXのインデックスを使用する必要がある分類器は、
そのインデックスを使用します(指摘されたように時系列に役立ちます)。

このアプローチには、
計算速度を維持しながら、既存のsklearnデザイン
(データフレームでの数学演算とインデックス作成は、numpyよりも最大10倍遅くなります
アレイ)。 残念ながら、各推定量に追加するのは面倒な作業です。
それを利用することができます。


このメールに直接返信するか、GitHubで表示してください
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171674105

それとも、パイプライン/見積もりをラップするものだけですか?

ただチェックする以上のことをしているのに、なぜそのような関数を「check_ *」と呼ぶのかよくわかりません...

2016年1月14日10時45分44秒午前CSTで、ジョエルNothmanの[email protected]書きました:

たぶん、この魔法でパイプラインバリアントを作成する必要があるだけです...

午前2時30分に2016年1月15日、ディーンWyatte [email protected]
書きました:

私が使用しているソリューションを捨てたかっただけです:

def check_output(X、ensure_index = None、ensure_columns = None):
"" "
Xをensure_indexのインデックスまたはensure_columnsの列と結合します
利用可能な場合
"" "
sure_indexがNoneでない場合:
sure_columnsがNoneでない場合:
type(ensure_index)がpd.DataFrameであり、
type(ensure_columns)はpd.DataFrameです:
X = pd.DataFrame(X、index = ensure_index.index、
columns = ensure_columns.columns)
そうしないと:
type(ensure_index)がpd.DataFrameの場合:
X = pd.DataFrame(X、index = ensure_index.index)
Xを返す

次に、これを呼び出すsklearnの推定量のラッパーを作成します
関数
変換の出力について、例えば、

sklearn.preprocessingからStandardScalerを_StandardScalerとしてインポートします
クラスMinMaxScaler(_MinMaxScaler):
def transform(self、X):
Xt = super(MinMaxScaler、self).transform(X)
check_output(Xt、ensure_index = X、ensure_columns = X)を返します

入力データフレームXのインデックスを使用する必要がある分類器は次のことができます。
ただ
そのインデックスを使用します(指摘されたように時系列に役立ちます)。

このアプローチには、
既存のsklearnデザインでありながら、
計算
(データフレームでの数学演算とインデックス作成は、最大で10倍遅くなります
numpy
アレイ)。 残念ながら、それぞれに追加するのは面倒な作業です。
推定量
それを利用することができます。


このメールに直接返信するか、GitHubで表示してください

https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171674105


このメールに直接返信するか、GitHubで表示してください。
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171697542

K-9メールでAndroidデバイスから送信されました。 簡潔に申し訳ありません。

すべての列名の継承は推定器固有であるため、パイプラインが適切な開始場所であるかどうかはわかりません。たとえば、スケーラーは入力データフレームの列名を継承する必要がありますが、PCAなどのモデルは継承しないでください。 特徴選択推定器は特定の列名を継承する必要がありますが、それは別の問題であり、おそらく#2007に関連しています。

すべての配列のn_rowsが変換中に保持されるのは常に事実ですか? もしそうなら、入力のインデックス(存在する場合)を継承するだけで安全に思えますが、デフォルトの列名([0、1、2、3、...]など)でデータフレームを取得することが安全かどうかはわかりませんエンドユーザーの観点からは現在の動作よりも優れていますが、明示的なラッパー/メタエスティメータが使用されている場合、少なくともユーザーは何を期待できるかを知っています。

また、check_ *は不適切な名前であることに同意しました。関数でかなり多くの検証を行っており、データフレームロジックを削除してここに投稿しました。

列名を適切にマップするすべての推定器に何かを追加する必要がありますが、パイプラインが開始点になると思います。

トランスフォーマーは、適切な名前の列@ naught101を出力する必要があります

ただし、列名を保持するには、入力検証を伴う大手術が必要になります:-/ @amueller

入力の検証だけでなく、すべての変換で入力列に対して何を行うかを記述する必要があります。 @GaelVaroquaux

トランスフォーマーからトランスフォーマーに名前を渡す方法、そしておそらく来歴を追跡する方法の仕組みについて誰かが考えましたか? これはどこに保管しますか?

私の友人である@cbrummittも同様の問題を抱えており、計画行列の各列が関数形式(たとえば、x ^ 2、x ^ 3、x_1 ^ 3x_2 ^ 2、sympy式として表される)であり、トランスフォーマーがあります。 PolynomialFeaturesと同様に機能し、関数形式を取り込んで、それに基づいてより多くの形式を生成できます。 しかし、彼はsympyを使用して古い式を取得し、新しい式を生成しています。式を文字列ラベルとして保存しても、それはカットされず、関数変換をレイヤー化すると複雑になります。 彼はこれらすべてをパイプラインの外で行うことができましたが、GridSearchなどのメリットを享受できません。

私たちの質問のより一般的なバージョンは、データ自体ではなく、変圧器から変圧器に渡される情報をどのように入手するかということだと思います。 パイプライングローバル状態を持たないか、各トランスフォーマー/エスティメータに前の状態を認識させるか、各ステップで複数のものを返すか、何かを行わなければ、素晴らしい方法を思い付くことができません。

次に、これを追跡するためにパイプラインを変更するというアイデアも思いつきました。_fit()と_transform()、そしておそらく他のいくつかのことを変更する必要があります。 それが私たちの最善の選択肢のようです。

これはおかしなことに聞こえますが、データマトリックスをシンピー式にしたいので、変換するたびに新しい式が生成されるように感じます。 これはひどいものであり、check_array()はそれが起こらないようにし、パイプラインの他のステップを怒らせます。

現在のアイデアについては、#6425を参照してください。

必要なのは、各変圧器(のパイプラインを含む)のマッピングです。
トランスフォーマー)、入力機能名から出力機能名(またはいくつか
変換の構造化された表現、これはもっと多いと思います
私たちが取得しようとしているよりもエンジニアリング)。 それが#6425が提供するものです。

午前3時42時2016年10月8日、アンドレアス・ミューラー[email protected]
書きました:

#6425 https://github.com/scikit-learn/scikit-learn/issues/6425を参照してください
現在のアイデア。


あなたが言及されたので、あなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -252301608、
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/AAEz65fBsMwqmkDq3DEjMSUC-W-nfn9zks5qxnZxgaJpZM4GThGc

これを調べてみます、ありがとうございます!

誰かがこの問題について世界の状態に関する一般的な最新情報を提供できますか?

パンダのDataFrameサポートは常にYMMVのものになりますか?
ndarrayだけでなく、パンダDataFrame安全に使用できるかどうかについてのガイダンスが役立ちます。 おそらく、次のようなものです(作成された例の表):

module / category | pandasDataFrameを安全に消費できます
-|-
sklearn.pipeline | SAFE
sklearn.feature_selection | SAFE
リグレッサ| YMMV
sklearn.feature_extraction |安全ではありません、実装する予定はありません
など|..。

今のところ、「試して例外がスローされるかどうかを確認する」以外のアプローチはわかりません。

パンダのDataFrameを受け入れても問題なく機能するように見えるいくつかの手作業でコーディングされた例をテストしましたが、一見些細なパイプラインコンポーネントの交換が必要であると判断したときに、これが必然的に機能しなくなると考えざるを得ません...その時点で、すべてが謎めいたスタックトレースのカードの家のように倒れます。

私の最初の思考プロセスは、パンダDataFrameを消費できる置換パイプラインオブジェクトを作成することDataFrameオブジェクトをnumpy ndarrayに変換します。必要に応じてDataFrameプリミティブを利用できるように、独自のカスタムセレクター/トランスフォーマーを作成できますが、それは少し手間がかかるようです。 特にそうです、もし私たちが彼らを「公式に」サポートすることの最前線にいるのなら。

私はいくつかの異なるPRをフォローしてきましたが、どのPRが放棄されているか、および/または現在の考え方を反映しているのかを理解するのは困難です。
例:

6425(このスレッドでは上記の2016年10月を参照)

9012(sklearn-pandasと明らかに重複していますが、実験的な注釈が付けられていますか?)

3886(#9012に取って代わられましたか?)

これは、「パンダのDataFrameを安全に消費できる」という意味に大きく依存します。 浮動小数点数のみを含むDataFrameを意味する場合は、すべてが機能することを保証します。 どこかに文字列が1つでもある場合、何も機能しません。

自明ではない(または自明でさえある)操作のデータフレームを返すscikit-learn推定器は、決して起こらないかもしれないものだと思います(それは望んでいますが)。

9012が発生し、安定します。PRは最初の反復です(または、マージされていないものを数える場合は10番目の反復です;)

パンダとは完全には関係ありませんが、6425が発生する可能性があります。

3886は確かに#9012に取って代わられています

機能#6425は現在実装されています(一部の変圧器および
他の人に拡張可能)での単一ディスパッチを介して
https://codecov.io/gh/TeamHG-Memex/eli5その価値について。

13:25で2017年6月21日、アンドレアス・ミュラー[email protected]書きました:

9012 https://github.com/scikit-learn/scikit-learn/pull/9012 will

発生して安定するようになると、PRは最初の反復です。

6425https ://github.com/scikit-learn/scikit-learn/issues/6425

パンダとは完全には関係ありませんが、起こりそうです。

3886https ://github.com/scikit-learn/scikit-learn/pull/3886は確かに

#9012に取って代わられました
https://github.com/scikit-learn/scikit-learn/pull/9012


あなたが言及されたので、あなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment-309952467
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/AAEz61lgGBW1AoukPm_87elBjF2NGOUwks5sGI0-gaJpZM4GThGc

ああ、「浮動小数点数のみを含むDataFrameを意味する場合は、すべてが機能することを保証します」と言います。 つまり、ロケーションベースの列のインデックス付けです。 トレーニングとテストセットの列は、位置によって同じであると想定されています。

これは、「パンダのDataFrameを安全に消費できる」という意味に大きく依存します。 浮動小数点数のみを含むDataFrameを意味する場合は、すべてが機能することを保証します。 どこかに文字列が1つでもある場合、何も機能しません。

それで十分だと思います。

カスタムコンポーネントのパイプライン(パイプラインに対応していない既存のツールの薄いラッパー)を使用して、セレクターやモデルなどのscikit-learnコンポーネントに到達する前に、エンコード/スケーリングを介して混合型(文字列、float、int)をfloatに変換しています。

DataFrame与えられると、すべてのトランスフォーマーはDataFrame返します。
300列のDataFramePipelineし、500列のndarrayを受け取った場合、たとえばfeature_selectionなど、それから多くを効果的に学ぶことはできません。 mutual_info_classifで、列30と75のみが重要であると言われた場合、元のPipelineを本番用に簡略化する方法がわかりません。
したがって、私のユースケースでは、データをDataFrameに保持することが重要です。
ありがとうございました。

@ sam-s私は完全に同意します。 「短期」では、これはhttps://github.com/scikit-learn/scikit-learn/pull/13307およびhttps://github.com/scikit-learn/enhancement_proposals/pull/18によって対処されます

パンダのデータフレームは取得できませんが、作成するための列名は取得できます。

もっと具体的な例を挙げていただけますか? すべてのトランスフォーマーがDataFrameを返す場合、物事は機能するはずです(または、上記の提案よりも簡単に機能するように作成する必要があります)。

https://github.com/pandas-dev/pandas/issues/27211を介したわずかな更新
それは私の希望にダンパーを置きます。 ゼロコピーの往復があるとは信じられないようです。そのため、パンダにラップしたりアンラップしたりすると、かなりのコストがかかります。

pandas-dev / pandas#27211を介したわずかな更新で、私の希望にダンパーがかかります。 ゼロコピーの往復があるとは信じられないようです。そのため、パンダにラップしたりアンラップしたりすると、かなりのコストがかかります。

ええ、でも、機能とサンプルの小道具(行名と「インデックス」はちょっとしたサンプルの小道具です)をカバーしたら、パンダが必要なほとんどの関連するユースケースをカバーするでしょう?

@adrinjalali 「パンダが必要な最も関連性の高いユースケース」とはどういう意味か

好奇心から、パンダの互換性の向上が期待される時間枠はありますか? 私は特にパンダイン->パンダアウトStandardScaler興味があります。

Pipeline各ステップでパンダのデータフレームを保持する必要があるユースケースがあります。 たとえば、1)データに基づいて特徴をフィルタリングする特徴選択ステップ、2)データ変換ステップ、3)特定の特徴列名または元のインデックスをフィルタリングする別の特徴選択ステップ、4)標準化、5)分類を含むパイプライン。

ステップ3)データが3)に到達すると、元の特徴インデックスは無意味であるため、numpy配列を入力しても、現在sklearnでは不可能だと思います。1)には特徴選択ステップがあったためです。 パンダのデータフレームがパイプラインに保存されている場合は、3)の列名でフィルタリングできるため、機能します。

numpy配列入力を使用しても、現在これを行う方法がないと考えるのは間違っていますか?

あなたはそれがサポートされていないということは正しいです、そしてそれをサポートすることは簡単ではないでしょう。 あなたのユースケースに関連して、私たちはパイプラインに沿って機能名を渡すことに取り組んでいます(上記のリンクされたPRと提案に見られるように)。 それが終わったら、それがあなたのケースに役立つことを願っています。 それが役立つかどうかはわかりませんが、 https://github.com/scikit-learn-contrib/sklearn-pandas

あなたはそれがサポートされていないということは正しいです、そしてそれをサポートすることは簡単ではないでしょう。 あなたのユースケースに関連して、私たちはパイプラインに沿って機能名を渡すことに取り組んでいます(上記のリンクされたPRと提案に見られるように)。 それが終わったら、それがあなたのケースに役立つことを願っています。

確認していただきありがとうございます。はい、機能名(または他の機能プロパティ)をメソッドに合わせて渡し、各機能選択ステップで適切にスライスすることができれば、このユースケースでは問題ありません。

それが役立つかどうかはわかりませんが、 https://github.com/scikit-learn-contrib/sklearn-pandas

以前に彼らのドキュメントを読みましたが、おそらく私はそれを見ていませんが、彼らの機能のほとんど(またはすべて)は現在scikit-learn0.21でsklearn.compose.ColumnTransformer廃止されていますか? また、パンダをサポートしているようには見えませんが、変換後はゴツゴツした配列のように見えます。

(特徴選択でパンダをサポートすることは壊れるかどうか疑問に思います
多くの...)

コードを簡単にチェックするだけで、たとえばhttps://github.com/scikit-learn/scikit-learn/blob/939fa3cccefe708db7a81c5248db32a1d600bf8d/sklearn/utils/validation.py#を使用して、さまざまな場所で任意に行われるあらゆる種類のチェックがあります

さらに、多くの操作では、パンダのデータフレームでは受け入れられないような厄介な方法でインデックスを使用します。

パンダを出し入れすることは、日常のデータサイエンスIMOにとって必須ですが、scikit-learnは、実装が困難になるように設計されているようです。

パンダを出し入れすることは、日常のデータサイエンスIMOにとって必須ですが、
scikit-learnは、困難になるように設計されているようです
実装されました。

パンダのデータフレームに適切な数値を実装するのは困難です。 彼らはただ
特に多変量演算(数値
列間の操作)。

機械学習は主に多変量数値です。

パンダのデータフレームに適切な数値を実装するのは困難です。 これらは、特に多変量演算(列全体の数値演算)を対象としたものではありません。 機械学習は主に多変量数値です。

その決定はユーザーに任されるべきですか? 過去2年間にscikit-learnを広範囲に使用した私の経験では、欠落していて多くのMLユースケースに必須の2つのコア機能と重要な機能は、サンプルと機能のメタデータの受け渡しのサポートだと思います。 完全なパンダデータフレームのサポートは、これのいくつかに対処するための自然でエレガントな方法です。

この種のコア機能は、ユーザーベースを維持し、新しいユーザーを呼び込むために非常に重要です。 そうでなければ、例えばmlr3のようなライブラリは、データフレームとメタデータを完全にサポートしている(またはサポートする)ことを知っているので、最終的には成熟し、ユーザーをsklearnから引き離します。

その決定はユーザーに任されるべきですか?

ええと、ユーザーはアルゴリズムを実装していません。

そうでなければ、例えばmlr3のようなライブラリが最終的に成熟して
ユーザーをsklearnから引き離すのは、ユーザーがそうする(またはそうする)ことを知っているからです。
データフレームとメタデータを完全にサポートします。

mlr3はRにあり、データフレームはpandasデータフレームとはかなり異なります。
多分これは実装をより簡単にします。

機能名と異種データのサポートが向上することに同意します
タイプは重要です。 私たちは優れた技術的解決策を見つけることに取り組んでいます
パフォーマンスの低下や過度に複雑なコードにつながることはありません。

その決定はユーザーに任されるべきですか?
ええと、ユーザーはアルゴリズムを実装していません。
そうでなければ、例えばmlr3のようなライブラリは、データフレームとメタデータを完全にサポートしている(またはサポートする)ことを知っているので、最終的には成熟し、ユーザーをsklearnから引き離します。
mlr3はRにあり、データフレームはpandasデータフレームとはかなり異なります。 多分これは実装をより簡単にします。 機能名と異種データ型のより良いサポートが重要であることに同意します。 私たちは、パフォーマンスの低下や過度に複雑なコードを引き起こさない優れた技術的ソリューションの発見に取り組んでいます。

numpy配列に固執し、少なくとも機能名の受け渡し、またはさらに優れた複数機能メタデータをサポートするというあなたのアプローチは、多くのユースケースで機能すると思います。 トレーニングサンプルメタデータを渡すために、あなたはすでに**fit_paramsそれをサポートしており、デザインを改善するための努力があることを私は知っています。 しかし、 https://github.com/scikit-learn/enhancement_proposals/pull/16で、 transformメソッドに渡されるテストサンプルメタデータも必要になるユースケースがあり、これは現在サポートされていないことを述べました。

mlr3はRにあり、データフレームはpandasデータフレームとはかなり異なります。

ライフサイエンス研究の計算科学者は通常、PythonとRの両方に非常に慣れており、両方を一緒に使用します(私自身も含まれます)。 scikit-learnユーザーベースのかなりの割合がライフサイエンス研究者であると確信しています。

現在、R IMHOで利用可能な成熟したMLライブラリは、適切に設計されたAPIを提供し、MLの実用的な部分(パイプライン、ハイパーパラメータ検索、スコアリングなど)を非常に単純にするという点で、scikit-learnに近づいていません。これらのライブラリを使用すると、ほとんど自分でコーディングする必要があります。 しかし、mlr3は、scikit-learnをゼロから正しい方法で設計しているため、scikit-learnの将来の大きな競争と見なしています。

パンダのデータフレームに適切な数値を実装するのは困難です。 彼らはただ
特に多変量演算(数値
列間の操作)。

何かが足りないかもしれませんが、( df.valuesを使用して)DataFrameをアンラップし、計算を行ってから、新しいDataFrameにラップバックすることはできませんか?

これは基本的に私がステップ間で手動で行うことであり、 Pipelineの使用を妨げる唯一のことです。

多分私は何かが足りないのですが、
DataFrame(df.valuesを使用)、計算を実行してから、新しいものにラップバックします
DataFrame?

一般的にはありません:動作しない可能性があり(異種列)、動作します
多くのメモリコピーにつながります。

一般的にいいえ:動作しない可能性があります(異種カラム)

カラムトランスなどは個別に対応できると思います。

それは多くのメモリコピーにつながります。

設計と実装の選択が難しいことを理解しています。それは確かな議論です。

ただし、sklearnが列のメタデータをサポートする方法を改善するのは良い考えではないと主張する理由がわかりません。

たとえば、機能を含むdfを取り込み、予測子のおかげで列を追加し、より多くのデータ操作を実行し、別の予測を実行できるようにすることは、パイプラインですべて、(たとえば)ハイパーパラメーターの最適化を可能にするので便利です。はるかに統合されたエレガントな方法で。

パンダの有無にかかわらずそれを行うことは、データを操作するための最も一般的で簡単で人気のある方法であり、彼らが行った以上に書き直すことの利点は見当たらないので、単なる提案です。

パフォーマンスを最適化するときにこのワークフローを使用しないことを決定するのはユーザーの責任です。

決定をユーザーに任せるには、明確に説明する必要があります
ユーザーへの選択。 ほとんどのユーザーは、
そのような選択を説明してください。 多くの人は、うまくいくと思うことを試してから、
彼らがそれが遅いと感じたときにあきらめ、それが彼らの選択であったことに気づかなかった
それを作ったダラフレーム。

したがって、ここでは注意して踏み出す必要があります。 しかし、私たちは解決し続ける必要があります
これは優先度が高いです。

最善の解決策は、サンプルと機能のプロパティのパンダデータフレームをサポートし、それらを適切に受け渡し、トレインにスライスして、フィット/変換をテストすることだと思います。 これにより、データマトリックスXの速度をnumpy配列として維持しながら、ほとんどのユースケースを解決できます。

この議論に欠けている重要な点の1つは、パンダがデータの列表現に向かっていることです。つまり、 np.array(pd.DataFrame(numpy_data))には2つの_保証された_メモリコピーがあります。 そのため、データフレームを維持し、速度が必要なときにvaluesを使用するほど簡単ではありません。

この議論に欠けている重要な点の1つは、パンダがデータの列表現に向かっていることです。つまり、 np.array(pd.DataFrame(numpy_data))には2つの_保証された_メモリコピーがあります。 そのため、データフレームを維持し、速度が必要なときにvaluesを使用するほど簡単ではありません。

以前の投稿で明確になったことを願っています。 scikit-learnは現在、Xデータ用のパンダデータフレームをサポートする必要はなく、スピーディーなnumpy配列として保持していると思います。 しかし、多くのユースケースを解決するのは、メタデータのパンダデータフレームのフレームワーク、つまりサンプルプロパティと機能プロパティを完全にサポートすることです。 これらの2つのデータ構造はXと比較してマイナーであり、実際にはこれらに対してサブセット化のみが行われるため、これはメモリコピーの場合でもパフォーマンスの負担にはなりません。

はい、これらの変更は多くのユースケースで役立ちます。現在、これらの変更に取り組んでいます。 しかし、この問題はそれを超えています: https

@hermidalc X numpy配列にし、他のデータフレームオブジェクトにメタデータを割り当てることを提案していますか?

@hermidalc X numpy配列にし、他のデータフレームオブジェクトにメタデータを割り当てることを提案していますか?

はい、パンダのデータフレームとしてサンプルプロパティと機能プロパティを完全にサポートしています。 他のPRや問題のサンプルプロパティと機能名については、すでに議論が行われています。たとえば、ここでは#9566と#14315です。

私はこの問題について読みましたが、ここには2つの主要なブロッカーがあるようです。

  1. https://github.com/pandas-dev/pandas/issues/27211
  2. そのパンダはND配列を処理しません。

代わりにxarrayのサポートを追加することを検討しましたか? パンダのような制限はありません。

X = np.arange(10).reshape(5, 2)
assert np.asarray(xr.DataArray(X)) is X
assert np.asarray(xr.Dataset({"data": (("samples", "features"), X)}).data).base is X.base

sklearn-xarrayというパッケージがあります: https ://phausamann.github.io/sklearn-xarray/content/wrappers.html scikit推定量をラップして、xarrayを入力および出力として処理しますが、これは年。 しかし、ラッパーがここに行く方法であるかどうか疑問に思います。

xarrayは積極的に検討されています。 プロトタイプが作成され、ここで作業されています: https

(0.23リリースが終了したら、また戻ってきます)

私もこの機能に非常に興味があります。
それは無限の問題を解決するでしょう。 現在、これは私が使用しているソリューションです。
sklearn.preprocessingモジュールのラッパーを作成しました。これをsklearn_wrapperと呼びました。

したがって、 sklearn.preprocessingからインポートする代わりに、 sklearn_wrapperからインポートします。
例えば:

# this
from sklearn.preprocessing import StandardScaler 
# becomes 
from sklearn_wrapper import StandardScaler

このモジュールの実装の下。 試してみて、皆さんの考えを教えてください

from functools import wraps
from itertools import chain

import pandas as pd
from sklearn import preprocessing, compose, feature_selection, decomposition
from sklearn.compose._column_transformer import _get_transformer_list

modules = (preprocessing, feature_selection, decomposition)


def base_wrapper(Parent):
    class Wrapper(Parent):

        def transform(self, X, **kwargs):
            result = super().transform(X, **kwargs)
            check = self.check_out(X, result)
            return check if check is not None else result

        def fit_transform(self, X, y=None, **kwargs):
            result = super().fit_transform(X, y, **kwargs)
            check = self.check_out(X, result)
            return check if check is not None else result

        def check_out(self, X, result):
            if isinstance(X, pd.DataFrame):
                result = pd.DataFrame(result, index=X.index, columns=X.columns)
                result = result.astype(X.dtypes.to_dict())
            return result

        def __repr__(self):
            name = Parent.__name__
            tmp = super().__repr__().split('(')[1]
            return f'{name}({tmp}'

    Wrapper.__name__ = Parent.__name__
    Wrapper.__qualname__ = Parent.__name__

    return Wrapper


def base_pca_wrapper(Parent):
    Parent = base_wrapper(Parent)

    class Wrapper(Parent):
        @wraps(Parent)
        def __init__(self, *args, **kwargs):
            self._prefix_ = kwargs.pop('prefix', 'PCA')
            super().__init__(*args, **kwargs)

        def check_out(self, X, result):
            if isinstance(X, pd.DataFrame):
                columns = [f'{self._prefix_}_{i}' for i in range(1, (self.n_components or X.shape[1]) + 1)]
                result = pd.DataFrame(result, index=X.index, columns=columns)
            return result

    return Wrapper


class ColumnTransformer(base_wrapper(compose.ColumnTransformer)):

    def check_out(self, X, result):
        if isinstance(X, pd.DataFrame):
            return pd.DataFrame(result, index=X.index, columns=self._columns[0]) if self._remainder[1] == 'drop' \
                else pd.DataFrame(result, index=X.index, columns=X.columns). \
                astype(self.dtypes.iloc[self._remainder[-1]].to_dict())


class SelectKBest(base_wrapper(feature_selection.SelectKBest)):

    def check_out(self, X, result):
        if isinstance(X, pd.DataFrame):
            return pd.DataFrame(result, index=X.index, columns=X.columns[self.get_support()]). \
                astype(X.dtypes[self.get_support()].to_dict())


def make_column_transformer(*transformers, **kwargs):
    n_jobs = kwargs.pop('n_jobs', None)
    remainder = kwargs.pop('remainder', 'drop')
    sparse_threshold = kwargs.pop('sparse_threshold', 0.3)
    verbose = kwargs.pop('verbose', False)
    if kwargs:
        raise TypeError('Unknown keyword arguments: "{}"'
                        .format(list(kwargs.keys())[0]))
    transformer_list = _get_transformer_list(transformers)
    return ColumnTransformer(transformer_list, n_jobs=n_jobs,
                             remainder=remainder,
                             sparse_threshold=sparse_threshold,
                             verbose=verbose)


def __getattr__(name):
    if name not in __all__:
        return

    for module in modules:
        Parent = getattr(module, name, None)
        if Parent is not None:
            break

    if Parent is None:
        return

    if module is decomposition:
        Wrapper = base_pca_wrapper(Parent)
    else:
        Wrapper = base_wrapper(Parent)

    return Wrapper


__all__ = [*[c for c in preprocessing.__all__ if c[0].istitle()],
           *[c for c in decomposition.__all__ if c[0].istitle()],
           'SelectKBest']


def __dir__():
    tmp = dir()
    tmp.extend(__all__)
    return tmp

https://github.com/koaning/scikit-lego/issues/304は、sklearn.pipeline.FeatureUnionのホットフィックスによって別のソリューションを提供しました

このページは役に立ちましたか?
0 / 5 - 0 評価