Python'daki collinear değişkenleri sistematik olarak nasıl kaldırırım? [kapalı]


18

Şimdiye kadar, korelasyon tablolarına bakarak ve belirli bir eşiğin üzerindeki değişkenleri kaldırarak veri hazırlama sürecinin bir parçası olarak eş doğrusal değişkenleri kaldırdım. Bunu yapmanın daha kabul edilmiş bir yolu var mı? Ayrıca, bir seferde sadece 2 değişken arasındaki korelasyona bakmanın ideal olmadığını biliyorum, VIF gibi ölçümler çeşitli değişkenler arasındaki potansiyel korelasyonu dikkate alıyor. Çoklu doğrusallık sergilemeyen değişken kombinasyonları sistematik olarak nasıl seçebiliriz?

Verilerimi panda veri çerçevesi içinde aldım ve sklearn modellerini kullanıyorum.


3
Kısmi En Küçük Kareler Regresyonunu veya Temel Bileşenler Regresyonunu düşünebilirsiniz. Bunlardan biri muhtemelen desteklenmektedir.
spdrnl

Anlıyorum. Peki doğru anlarsam, PCA'yı çalıştırmak bana daha sonra modelim için ortak değişken olarak kullanabileceğim bir dizi bağımsız temel bileşen verecekti, çünkü temel bileşenlerin her biri diğerleriyle uyuşmuyor mu?
orange1

2
Kesinlikle. Bileşenlerin bazılarının alakasız olması muhtemeldir. Bu değişkenleri bırakmaktan daha kolaydır.
spdrnl

Hmm, bu yüzden amacım modeli öngörücü amaçlardan ziyade açıklayıcı olarak çalıştırmaktır. Temel bileşenleri ortak değişkenler olarak kullanan bir modeli nasıl yorumlayabiliriz?
orange1

1
Bu durumda, bileşenleri yorumlamak biraz karanlık bir sanat olduğu için yardımcı olmaz.
spdrnl

Yanıtlar:


13

Teşekkürler SpanishBoy - İyi bir kod parçası. @ilanman: Bu, VIF değerlerini kontrol eder ve daha sonra VIF'i 5'ten fazla olan değişkenleri düşürür. "Performans" ile çalışma süresi anlamına gelir. Yukarıdaki kod yaklaşık 300 değişken, 5000 satır üzerinde çalışmak için yaklaşık 3 saat sürdü.

Bu arada, bazı ekstra döngüler kaldırmak için değiştirdim. Ayrıca, ben biraz daha temiz yaptım ve değişkenler ile dataframe dönmek. Bu sürüm çalışma süremi yarıya indirdi! Kodum aşağıda - Umarım yardımcı olur.

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]

Teşekkür ederim. Her iki fonksiyonun çıktılarını karşılaştırdınız mı? VIF için bir R işlevi (paket usdmyöntemi vifstep) gördüm ve çalışma süresi gerçekten harikaydı. Daha önce söylediğim gibi, yukarıdaki varyant ve sizin (yarı yarıya optimize edilmiş) R ile karşılaştırıldığında çok yavaştır.
SpanishBoy

1
Bu yaklaşımla ilgili bir sorum var. Diyelim ki A, B ve C özelliklerimiz var. A, C ile ilişkilidir. Eğer özellikler üzerinde döngü yaparsanız, A ve C'de VIF> 5 olur, bu nedenle düşürülürler. Gerçekte, bir özelliği her bıraktığınızda VIF'i yeniden hesaplamamanız gerekir. Örneğimde hem A hem de C'yi düşürürdünüz, ancak A düştükten sonra VIF (C) hesaplarsanız,> 5
Titus Pullo

3

Aşağıdaki kodu kullanmayı deneyebilirsiniz:

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

İşe yarıyor, ama bu yaklaşımın performansını sevmiyorum


Bu yaklaşımın ne yaptığı hakkında biraz daha yorum yapmak ister misiniz? Performansı neden sevmiyorsunuz?
ilanman

2

SpanishBoy'un yanıtını denedim ve bir veri çerçevesi için çalıştırırken serval hatalar buldum. İşte bir hata ayıklama çözümü.

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]]

Ayrıca performansla ilgili hiçbir sorunum olmadı, ancak kapsamlı bir şekilde test etmedim.


bu güzel ve benim için çalışıyor. dışında, ominious uyarısı döndürür:RuntimeWarning: divide by zero encountered in double_scalars
user2205916
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.