Làm thế nào để loại bỏ các biến cộng tuyến trong Python một cách có hệ thống? [đóng cửa]


17

Cho đến nay, tôi đã loại bỏ các biến cộng tuyến như là một phần của quá trình chuẩn bị dữ liệu bằng cách xem xét các bảng tương quan và loại bỏ các biến nằm trên một ngưỡng nhất định. Có cách nào được chấp nhận hơn để làm điều này? Ngoài ra, tôi biết rằng chỉ nhìn vào tương quan giữa 2 biến tại một thời điểm là không lý tưởng, các phép đo như VIF có tính đến tương quan tiềm năng qua một số biến. Làm thế nào một người đi về việc lựa chọn một cách có hệ thống các kết hợp biến không thể hiện tính đa hình?

Tôi có dữ liệu của mình trong khung dữ liệu gấu trúc và đang sử dụng các mô hình của sklearn.


3
Bạn có thể muốn xem xét hồi quy từng phần nhỏ nhất hoặc hồi quy thành phần chính. Một trong số này có thể được hỗ trợ.
spdrnl

Tôi hiểu rồi. Vì vậy, nếu tôi hiểu chính xác, việc chạy PCA sau đó sẽ cung cấp cho tôi một bộ các thành phần chính độc lập, sau đó tôi có thể sử dụng làm đồng biến cho mô hình của mình, vì mỗi thành phần chính không phải là thông số chung với các thành phần khác?
cam1

2
Chính xác. Một số thành phần có khả năng hóa ra không liên quan. Điều này dễ hơn là bỏ các biến.
spdrnl

Hừm, vì vậy, ý định của tôi chủ yếu là chạy mô hình cho mục đích giải thích hơn là dự đoán. Làm thế nào một người sẽ đi về việc diễn giải một mô hình sử dụng các thành phần chính là hiệp phương sai?
cam1

1
Trong trường hợp đó, nó không giúp ích gì vì việc diễn giải các thành phần là một nghệ thuật đen tối.
spdrnl

Câu trả lời:


13

Cảm ơn Tây Ban Nha - Đó là một đoạn mã tốt. @ilanman: Điều này kiểm tra các giá trị VIF và sau đó bỏ các biến có VIF lớn hơn 5. Bằng "hiệu suất", tôi nghĩ rằng anh ta có nghĩa là thời gian chạy. Đoạn mã trên mất khoảng 3 giờ để chạy trên khoảng 300 biến, 5000 hàng.

Nhân tiện, tôi đã sửa đổi nó để loại bỏ một số vòng lặp thêm. Ngoài ra, tôi đã làm cho nó sạch hơn một chút và trả về khung dữ liệu với các biến giảm. Phiên bản này đã giảm một nửa thời gian chạy của tôi! Mã của tôi ở dưới- Hy vọng nó sẽ giúp.

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]

Cảm ơn bạn. Bạn đã so sánh đầu ra của cả hai chức năng? Tôi thấy một hàm R ( usdmphương thức gói vifstep) cho VIF và thời gian chạy thực sự rất tuyệt. Như tôi đã nói trước đây, biến thể ở trên và (được tối ưu hóa một nửa) của bạn rất chậm so với R. Bạn có ý tưởng nào khác để tối ưu hóa chưa?
Tây Ban NhaBoy

1
Tôi có một câu hỏi về phương pháp này. Hãy nói rằng chúng ta có các tính năng A, B và C. A tương quan với C. Nếu bạn lặp qua các tính năng, A và C sẽ có VIF> 5, do đó chúng sẽ bị loại bỏ. Trong thực tế, bạn không nên tính lại VIF sau mỗi lần bạn bỏ một tính năng. Trong ví dụ của tôi, bạn sẽ bỏ cả A và C, nhưng nếu bạn tính VIF (C) sau khi A bị bỏ, sẽ không> 5
Titus Pullo

3

Bạn có thể thử sử dụng mã dưới đây:

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

Nó hoạt động, nhưng tôi không thích hiệu suất của phương pháp đó


Bạn có muốn bình luận thêm một chút về cách tiếp cận này không? Và tại sao bạn không thích hiệu suất?
ilanman

2

Tôi đã thử câu trả lời của SpainBoy và tìm thấy lỗi dịch vụ khi chạy nó cho khung dữ liệu. Đây là một giải pháp sửa lỗi.

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

Tôi cũng không có vấn đề gì với hiệu suất, nhưng chưa thử nghiệm rộng rãi.


Điều này là tốt đẹp và làm việc cho tôi. ngoại trừ, nó trả về cảnh báo đáng ngại:RuntimeWarning: divide by zero encountered in double_scalars
user2205916
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.