การใช้ LASSO จากแพ็คเกจ lars (หรือ glmnet) ใน R เพื่อเลือกตัวแปร


39

ขออภัยถ้าคำถามนี้เจอพื้นฐานเล็กน้อย

ฉันกำลังมองหาที่จะใช้การเลือกตัวแปร LASSO สำหรับตัวแบบการถดถอยเชิงเส้นหลายแบบในอาร์ฉันมีตัวทำนาย 15 ตัวซึ่งหนึ่งในนั้นคือหมวดหมู่ (นั่นจะทำให้เกิดปัญหาหรือไม่) หลังจากตั้งค่าและฉันฉันใช้คำสั่งต่อไปนี้:xy

model = lars(x, y)
coef(model)

coef(model)ปัญหาของฉันคือเมื่อฉันใช้ สิ่งนี้จะส่งกลับเมทริกซ์ที่มี 15 แถวโดยเพิ่มตัวทำนายพิเศษหนึ่งตัวในแต่ละครั้ง อย่างไรก็ตามไม่มีข้อเสนอแนะว่าควรเลือกรุ่นใด ฉันพลาดอะไรไปหรือเปล่า มีวิธีที่ฉันจะได้รับแพคเกจ lars เพื่อส่งกลับแบบ " ดีที่สุด " เพียงหนึ่งรุ่นหรือไม่?

มีโพสต์อื่น ๆ ที่แนะนำให้ใช้glmnetแทน แต่ดูเหมือนจะซับซ้อนกว่านี้ ความพยายามดังต่อไปนี้โดยใช้และเดียวกัน ฉันพลาดอะไรที่นี่ไหม: xy

cv = cv.glmnet(x, y)
model = glmnet(x, y, type.gaussian="covariance", lambda=cv$lambda.min)
predict(model, type="coefficients")

คำสั่งสุดท้ายส่งกลับรายการตัวแปรของฉันส่วนใหญ่มีค่าสัมประสิทธิ์แม้ว่าบาง = 0 นี่เป็นตัวเลือกที่ถูกต้องของรุ่น " ดีที่สุด " ที่เลือกโดย LASSO หรือไม่ ถ้าฉันพอดีกับโมเดลเชิงเส้นกับตัวแปรทั้งหมดที่มีค่าสัมประสิทธิ์not=0ฉันจะคล้ายกันมาก แต่ค่าประมาณสัมประสิทธิ์แตกต่างกันเล็กน้อย มีเหตุผลสำหรับความแตกต่างนี้หรือไม่? มันจะเป็นที่ยอมรับหรือไม่ที่จะดัดแปลงโมเดลเชิงเส้นด้วยตัวแปรเหล่านี้ที่ LASSO เลือกและนำมาเป็นโมเดลสุดท้ายของฉัน มิฉะนั้นฉันไม่สามารถเห็นค่า p ใด ๆ สำหรับความสำคัญ ฉันพลาดอะไรไปหรือเปล่า

ทำ

type.gaussian="covariance" 

ให้แน่ใจว่าglmnetใช้การถดถอยเชิงเส้นหลายรายการ?

การปรับสภาพของตัวแปรอัตโนมัติส่งผลกระทบต่อค่าสัมประสิทธิ์หรือไม่? มีวิธีใดบ้างที่จะรวมคำศัพท์ในการโต้ตอบในขั้นตอน LASSO?

ฉันกำลังมองหาที่จะใช้ขั้นตอนนี้มากขึ้นเพื่อแสดงให้เห็นว่า LASSO สามารถใช้งานได้อย่างไรมากกว่ารุ่นใด ๆ ที่จะใช้สำหรับการอนุมาน / การทำนายที่สำคัญหากการเปลี่ยนแปลงนั้นเกิดขึ้น

ขอบคุณที่สละเวลาอ่านข้อความนี้ ความคิดเห็นทั่วไปเกี่ยวกับ LASSO / lars / glmnet ก็จะได้รับการชื่นชมอย่างมากเช่นกัน


4
ในฐานะที่เป็นความคิดเห็นด้านข้างหากคุณต้องการตีความผลลัพธ์ให้แน่ใจว่าได้สาธิตชุดของตัวแปรที่เลือกโดย lasso ที่มีความเสถียร สิ่งนี้สามารถทำได้โดยใช้การจำลอง Monte Carlo หรือโดยการบูตชุดข้อมูลของคุณเอง
Frank Harrell

คำตอบ:


28

การใช้glmnetนั้นง่ายมากเมื่อคุณเข้าใจบทความสั้น ๆ ในhttp://web.stanford.edu/~hastie/glmnet/glmnet_alpha.html (คุณสามารถตรวจสอบหน้าแพ็คเกจ CRAN ได้) สำหรับแลมบ์ดาที่ดีที่สุดglmnetกฎของหัวแม่มือคือการใช้

cvfit <- glmnet::cv.glmnet(x, y)
coef(cvfit, s = "lambda.1se")

lambda.minแทน

ที่จะทำเช่นเดียวกันสำหรับlarsคุณต้องทำมันด้วยมือ นี่คือทางออกของฉัน

cv <- lars::cv.lars(x, y, plot.it = FALSE, mode = "step")
idx <- which.max(cv$cv - cv$cv.error <= min(cv$cv))
coef(lars::lars(x, y))[idx,]

โปรดจำไว้ว่าสิ่งนี้ไม่เหมือนกันเพราะนี่คือหยุดที่ปมเชือก (เมื่อตัวแปรเข้า) แทนที่จะเป็นที่จุดใด ๆ

โปรดทราบว่าglmnetเป็นแพ็คเกจที่ต้องการตอนนี้มันได้รับการบำรุงรักษาอย่างแข็งขันมากกว่าlarsนี้และมีคำถามเกี่ยวกับglmnetvs larsตอบก่อนหน้านี้ (อัลกอริทึมที่ใช้แตกต่างกัน)

สำหรับคำถามของคุณเกี่ยวกับการใช้บ่วงบาศในการเลือกตัวแปรแล้วเหมาะสมกับ OLS มันเป็นการถกเถียงอย่างต่อเนื่อง Google สำหรับ OLS โพสต์ Lasso และมีบางบทความที่พูดถึงหัวข้อนี้ แม้แต่ผู้เขียนองค์ประกอบของการเรียนรู้ทางสถิติก็ยอมรับได้

แก้ไข : นี่คือรหัสที่จะทำให้เกิดขึ้นอย่างถูกต้องสิ่งที่glmnetไม่อยู่ในlars

  cv <- lars::cv.lars(x, y, plot.it = FALSE)
  ideal_l1_ratio <- cv$index[which.max(cv$cv - cv$cv.error <= min(cv$cv))]
  obj <- lars::lars(x, y)
  scaled_coefs <- scale(obj$beta, FALSE, 1 / obj$normx)
  l1 <- apply(X = scaled_coefs, MARGIN = 1, FUN = function(x) sum(abs(x)))
  coef(obj)[which.max(l1 / tail(l1, 1) > ideal_l1_ratio),]

+1 คำตอบยอดเยี่ยม! คุณหรือใครก็ได้อธิบายเพิ่มเติมว่าทำไม lambda.1se เป็นกฎง่ายๆแทนที่จะเป็น lambda.min
Erosennin

หลังจาก 4 ปีของการเขียน (และไม่ต้องใช้เชือกสักครู่) ความทรงจำของฉันก็หายไป ขออภัย!
Juancentro

8

ฉันกลับไปที่คำถามนี้มาระยะหนึ่งแล้วตั้งแต่ฉันคิดว่าฉันได้แก้ปัญหาที่ถูกต้องแล้ว

นี่คือแบบจำลองโดยใช้ชุดข้อมูล mtcars:

library(glmnet)
`%ni%`<-Negate(`%in%')
data(mtcars)

x<-model.matrix(mpg~.,data=mtcars)
x=x[,-1]

glmnet1<-cv.glmnet(x=x,y=mtcars$mpg,type.measure='mse',nfolds=5,alpha=.5)

c<-coef(glmnet1,s='lambda.min',exact=TRUE)
inds<-which(c!=0)
variables<-row.names(c)[inds]
variables<-variables[variables %ni% '(Intercept)']

'ตัวแปร' ให้รายการของตัวแปรที่แก้ปัญหาได้ดีที่สุด


1
ฉันกำลังมองหารหัสและพบว่า "การทดสอบ" ยังไม่ได้กำหนดดังนั้นรหัส: "final.list <-testing [-removed] #removing ตัวแปร" ให้ข้อผิดพลาด: วัตถุไม่พบดังนั้นมองไปที่รหัสฉัน สมมติว่าแทนที่จะใช้ "การทดสอบ" ควรใช้ "cp.list" เพื่อให้โค้ดเป็นดังนี้: final.list <-cp.list [-removed] #removing ตัวแปร final.list <-c (final.list, ซ้ำกัน) #adding ใน vars เหล่านั้นซึ่งถูกลบทั้งคู่แล้วเพิ่มในภายหลังแจ้งให้เราทราบว่านี่เป็นเรื่องที่ถูกต้องหรือไม่

3
`% พรรณี%` <-Negate ( `%% พรรณี`); ## ดูผิด ในขณะที่ `% ni%` <-Negate (`% เป็น%`); ## ดูถูกต้อง ผมคิดว่าการจัดรูปแบบ stackexchange messed ขึ้น ...
คริส

คุณสามารถอธิบายรายละเอียดวิธีการnfolds=5และalpha=0.5พารามิเตอร์ได้อย่างไร?
ลิน

7

บางทีการเปรียบเทียบกับการเลือกการถดถอยแบบขั้นตอนจะช่วยได้ (ดูลิงค์ต่อไปนี้ไปยังไซต์โดยหนึ่งในผู้เขียนhttp://www-stat.stanford.edu/~tibs/lasso/simple.html) นี่เป็นวิธีการที่ใช้ในบทที่ 3.4.4 ขององค์ประกอบของการเรียนรู้ทางสถิติ (มีให้ทางออนไลน์ฟรี) ฉันคิดว่าบทที่ 3.6 ในหนังสือเล่มนั้นช่วยให้เข้าใจความสัมพันธ์ระหว่างกำลังสองน้อยที่สุดเซตย่อยที่ดีที่สุดและเชือก (รวมถึงกระบวนการอื่นอีกสองสามอย่าง) ฉันยังพบว่ามีประโยชน์ในการแปลงค่าสัมประสิทธิ์ t (coef (model)) และ write.csv เพื่อให้ฉันสามารถเปิดใน Excel พร้อมกับสำเนาพล็อต (รุ่น) ที่ด้านข้าง คุณอาจต้องการเรียงลำดับตามคอลัมน์สุดท้ายซึ่งมีค่าประมาณกำลังสองน้อยที่สุด จากนั้นคุณจะเห็นได้อย่างชัดเจนว่าแต่ละตัวแปรได้รับการเพิ่มในแต่ละขั้นตอนทีละชิ้นและค่าสัมประสิทธิ์เปลี่ยนแปลงไปอย่างไร แน่นอนว่านี่ไม่ใช่เรื่องราวทั้งหมด แต่หวังว่ามันจะเป็นการเริ่มต้น


3

larsและglmnetดำเนินการเกี่ยวกับการฝึกอบรมดิบ ในการรวมเงื่อนไขการโต้ตอบคุณจะต้องสร้างเมทริกซ์ด้วยตัวเอง นั่นหมายถึงหนึ่งคอลัมน์ต่อการโต้ตอบ (ซึ่งก็คือต่อระดับต่อปัจจัยหากคุณมีปัจจัย) ดูlm()เพื่อดูว่ามันเป็นอย่างไร (คำเตือน: มีมังกร)

หากต้องการทำตอนนี้ให้ทำดังนี้: ในการสร้างข้อความโต้ตอบด้วยตนเองคุณสามารถทำได้ (แต่อาจไม่ควรเพราะช้า) ทำ:

int = D["x1"]*D["x2"]
names(int) = c("x1*x2")
D = cbind(D, int)

จากนั้นให้ใช้สิ่งนี้ในลาร์ส (สมมติว่าคุณมีการyเตะรอบ):

lars(as.matrix(D), as.matrix(y))

ฉันหวังว่าฉันสามารถช่วยคุณได้มากขึ้นด้วยคำถามอื่น ๆ ฉันพบอันนี้เพราะลาร์สให้ความเศร้าแก่ฉันและเอกสารประกอบในนั้นและบนเว็บนั้นบางมาก


2
"คำเตือน: มีมังกร" model.matrix()นี่คือสวยง่ายด้วย
Gregor

2

LARS แก้ไขเส้นทางการแก้ปัญหาทั้งหมด เส้นทางการแก้ปัญหาคือเชิงเส้นเป็นจำนวนชิ้น - มีจำนวนจุด "บาก" (เช่นค่าของพารามิเตอร์การทำให้เป็นมาตรฐาน) ที่การเปลี่ยนแปลงของวิธีแก้ปัญหา

เมทริกซ์ของการแก้ปัญหาที่คุณได้รับคือวิธีแก้ปัญหาที่เป็นไปได้ทั้งหมด ในรายการที่ส่งคืนควรให้ค่าของพารามิเตอร์การทำให้เป็นมาตรฐาน


ขอบคุณสำหรับคำตอบ. มีวิธีแสดงค่าของพารามิเตอร์การทำให้เป็นมาตรฐานหรือไม่? นอกจากนี้ยังมีวิธีในการเลือกระหว่างการแก้ปัญหาตามพารามิเตอร์นี้หรือไม่? (แลมบ์ดาพารามิเตอร์คืออะไรด้วย)
James

โปรดทราบว่าการเชิงเส้นแบบชิ้นเดียวไม่ได้หมายความว่าเส้นแนวนอนและดังนั้นการแก้ปัญหาจึงเปลี่ยนตลอดเวลาด้วยแลมบ์ดา ตัวอย่างเช่นสำหรับวัตถุประสงค์ในการทำนายหนึ่งจะมีตารางของค่าแลมบ์ดาไม่เพียง แต่ที่แต่ยังระหว่างนอต มีความเป็นไปได้ค่อนข้างมากที่บางจุดระหว่างปมจะให้ประสิทธิภาพการทำนายที่ดีที่สุด
Richard Hardy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.