Pythonで共線変数を体系的に削除するにはどうすればよいですか?[閉まっている]


17

これまで、相関テーブルを調べ、特定のしきい値を超える変数を削除することにより、データ準備プロセスの一部として共線変数を削除しました。これを行うより受け入れられた方法はありますか?さらに、一度に2つの変数間の相関関係を調べるだけでは理想的ではないことを認識しています。VIFのような測定では、いくつかの変数間の潜在的な相関関係が考慮されます。多重共線性を示さない変数の組み合わせを体系的に選択するにはどうすればよいでしょうか?

パンダのデータフレーム内にデータがあり、sklearnのモデルを使用しています。


3
部分最小二乗回帰または主成分回帰を検討することをお勧めします。これらのいずれかがおそらくサポートされています。
spdrnl

そうですか。したがって、正しく理解すれば、PCAを実行すると独立した主成分のセットが得られ、各主成分は他の成分と共線ではないため、モデルの共変量として使用できますか?
orange1

2
丁度。一部のコンポーネントは無関係である可能性が高いです。これは、変数をドロップするよりも簡単です。
-spdrnl

というわけで、私の意図は、予測目的ではなく説明目的でモデルを実行することです。主成分を共変量として使用したモデルをどのように解釈しますか?
orange1

1
その場合、コンポーネントの解釈はやや暗い芸術であるため、役に立ちません。
spdrnl

回答:


13

Thanks SpanishBoy-これは良いコードです。@ilanman:これはVIF値をチェックし、VIFが5を超える変数をドロップします。「パフォーマンス」とは、実行時間を意味すると思います。上記のコードは、約300変数、5000行で実行するのに約3時間かかりました。

ところで、私はいくつかの余分なループを削除するように修正しました。また、私はそれを少しきれいにし、変数を減らしてデータフレームを返しました。このバージョンは、実行時間を半分に短縮しました!私のコードは以下です-それが役立つことを願っています。

from statsmodels.stats.outliers_influence import variance_inflation_factor    

def calculate_vif_(X, thresh=5.0):
    variables = list(range(X.shape[1]))
    dropped = True
    while dropped:
        dropped = False
        vif = [variance_inflation_factor(X.iloc[:, variables].values, ix)
               for ix in range(X.iloc[:, variables].shape[1])]

        maxloc = vif.index(max(vif))
        if max(vif) > thresh:
            print('dropping \'' + X.iloc[:, variables].columns[maxloc] +
                  '\' at index: ' + str(maxloc))
            del variables[maxloc]
            dropped = True

    print('Remaining variables:')
    print(X.columns[variables])
    return X.iloc[:, variables]

ありがとうございました。両方の機能の出力を比較しましたか?VIFのR関数(パッケージusdmメソッドvifstep)を見つけましたが、実行時間は本当にクールでした。前に言ったように、上記のバリアントと(半分に最適化された)RはRと比較して非常に遅いです。他に最適化する方法はありますか?
スペイン語少年

1
このアプローチについて質問があります。A、B、Cの機能があるとしましょう。AはCと相関しています。フィーチャをループすると、AとCのVIFは5を超えるため、削除されます。実際には、機能を削除するたびにVIFを再計算してはいけません。私の例では、AとCの両方をドロップしますが、Aをドロップした後にVIF(C)を計算すると、5を超えることはありません
Titus Pullo

3

以下のコードを使用してみてください:

from statsmodels.stats.outliers_influence import variance_inflation_factor

def calculate_vif_(X):

    '''X - pandas dataframe'''
    thresh = 5.0
    variables = range(X.shape[1])

    for i in np.arange(0, len(variables)):
        vif = [variance_inflation_factor(X[variables].values, ix) for ix in range(X[variables].shape[1])]
        print(vif)
        maxloc = vif.index(max(vif))
        if max(vif) > thresh:
            print('dropping \'' + X[variables].columns[maxloc] + '\' at index: ' + str(maxloc))
            del variables[maxloc]

    print('Remaining variables:')
    print(X.columns[variables])
    return X

それは機能しますが、私はそのアプローチのパフォーマンスが好きではありません


このアプローチが何をするかについて、もう少しコメントしたいですか?そして、なぜあなたはパフォーマンスが好きではないのですか?
イランマン

2

SpanishBoyの答えを試してみたところ、データフレームに対して実行したときにサーバーエラーが見つかりました。これがデバッグされたソリューションです。

from statsmodels.stats.outliers_influence import variance_inflation_factor    

def calculate_vif_(X, thresh=100):
cols = X.columns
variables = np.arange(X.shape[1])
dropped=True
while dropped:
    dropped=False
    c = X[cols[variables]].values
    vif = [variance_inflation_factor(c, ix) for ix in np.arange(c.shape[1])]

    maxloc = vif.index(max(vif))
    if max(vif) > thresh:
        print('dropping \'' + X[cols[variables]].columns[maxloc] + '\' at index: ' + str(maxloc))
        variables = np.delete(variables, maxloc)
        dropped=True

print('Remaining variables:')
print(X.columns[variables])
return X[cols[variables]]

また、パフォーマンスに問題はありませんでしたが、広範囲にテストしていません。


これはすてきで、私にとってはうまくいきます。それはominious警告を返し除く:RuntimeWarning: divide by zero encountered in double_scalars
user2205916
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.