จะลบตัวแปร collinear ใน Python อย่างเป็นระบบได้อย่างไร [ปิด]


18

ป่านนี้ฉันได้ลบตัวแปร collinear เป็นส่วนหนึ่งของกระบวนการเตรียมข้อมูลโดยดูที่ตารางสหสัมพันธ์และกำจัดตัวแปรที่อยู่เหนือขีด จำกัด ที่แน่นอน มีวิธีที่ยอมรับมากขึ้นในการทำเช่นนี้? นอกจากนี้ฉันทราบว่าการดูความสัมพันธ์ระหว่างตัวแปร 2 ตัวต่อครั้งนั้นไม่เหมาะการวัดเช่น VIF คำนึงถึงความสัมพันธ์ที่อาจเกิดขึ้นกับตัวแปรหลายตัว เราจะเลือกชุดค่าผสมของตัวแปรที่ไม่แสดงความหลากหลายทางชีวภาพได้อย่างไร

ฉันมีข้อมูลของฉันภายในกรอบข้อมูลแพนด้าและฉันใช้โมเดลของ sklearn


3
คุณอาจต้องการพิจารณาการถดถอยกำลังสองน้อยที่สุดหรือการถดถอยส่วนประกอบหลัก หนึ่งในนั้นอาจได้รับการสนับสนุน
spdrnl

ฉันเห็น. ดังนั้นถ้าฉันเข้าใจถูกต้องการใช้ PCA จะให้ส่วนประกอบหลักที่เป็นอิสระซึ่งฉันสามารถใช้เป็น covariates สำหรับโมเดลของฉันได้เนื่องจากส่วนประกอบหลักแต่ละตัวไม่ได้อยู่กับคนอื่นหรือไม่
orange1

2
เผง ส่วนประกอบบางอย่างมีแนวโน้มว่าจะไม่เกี่ยวข้อง ง่ายกว่าการวางตัวแปร
spdrnl

หืมดังนั้นความตั้งใจของข้าคือการใช้นางแบบเพื่ออธิบายมากกว่าการทำนาย เราจะตีความเกี่ยวกับโมเดลที่ใช้องค์ประกอบหลักเป็น covariates อย่างไร
orange1

1
ในกรณีนี้มันไม่ได้ช่วยอะไรเพราะการตีความองค์ประกอบต่าง ๆ ค่อนข้างมืด
spdrnl

คำตอบ:


13

ขอบคุณ SpanishBoy - มันเป็นโค้ดที่ดี @ilanman: นี่ตรวจสอบค่า VIF แล้วปล่อยตัวแปรที่มี VIF มากกว่า 5 ด้วย "ประสิทธิภาพ" ฉันคิดว่าเขาหมายถึงเวลาทำงาน รหัสด้านบนใช้เวลาประมาณ 3 ชั่วโมงในการรันตัวแปร 300 ตัวและ 5,000 แถว

โดยวิธีการที่ฉันได้แก้ไขมันเพื่อลบลูปพิเศษบางอย่าง นอกจากนี้ฉันได้ทำให้มันสะอาดขึ้นเล็กน้อยและคืนค่าดาต้าเฟรมด้วยตัวแปรที่ลดลง รุ่นนี้ลดเวลาทำงานของฉันลงครึ่งหนึ่ง! รหัสของฉันอยู่ด้านล่าง - หวังว่าจะช่วยได้

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]

ขอขอบคุณ. คุณเปรียบเทียบผลลัพธ์ของทั้งสองฟังก์ชันแล้วหรือยัง ฉันเห็นฟังก์ชั่น R ( usdmวิธีการแพคเกจvifstep) สำหรับ VIF และเวลาทำงานนั้นยอดเยี่ยมจริงๆ ดังที่ฉันพูดก่อนหน้านี้ตัวแปรด้านบนและของคุณ (ปรับให้เหมาะสมครึ่งหนึ่ง) นั้นช้ามากเมื่อเทียบกับอาร์แนวคิดอื่น ๆ วิธีการเพิ่มประสิทธิภาพหรือยัง
SpanishBoy

1
ฉันมีคำถามเกี่ยวกับวิธีการนี้ สมมติว่าเรามีคุณสมบัติ A, B และ C A มีความสัมพันธ์กับ C หากคุณวนลูปมากกว่าฟีเจอร์ A และ C จะมี VIF> 5 ดังนั้นมันจะถูกทิ้ง ในความเป็นจริงคุณไม่ควรคำนวณ VIF ซ้ำทุกครั้งหลังจากที่คุณวางคุณสมบัติ ในตัวอย่างของฉันคุณจะดรอปทั้ง A และ C แต่ถ้าคุณคำนวณ VIF (C) หลังจาก A ถูกดร็อปจะไม่เป็น> 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

มันใช้งานได้ แต่ฉันไม่ชอบประสิทธิภาพของวิธีการนั้น


คุณต้องการที่จะแสดงความคิดเห็นอีกเล็กน้อยเกี่ยวกับวิธีการนี้จะทำอย่างไร แล้วทำไมคุณถึงไม่ชอบการแสดงล่ะ?
ilanman

2

ฉันลองคำตอบของ SpanishBoy และพบข้อผิดพลาด serval เมื่อใช้งานสำหรับ data-frame นี่คือทางออกที่ดีบั๊ก

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

ฉันยังไม่มีปัญหาเกี่ยวกับประสิทธิภาพ แต่ไม่ได้ทดสอบอย่างกว้างขวาง


นี่เป็นสิ่งที่ดีและใช้ได้สำหรับฉัน ยกเว้นมันจะส่งกลับคำเตือนเป็นลางสังหรณ์:RuntimeWarning: divide by zero encountered in double_scalars
user2205916
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.