วิธีการถดถอยสันที่ไม่เป็นลบ


10

วิธีการถดถอยสันที่ไม่เป็นลบ บาศแบบไม่เป็นค่าลบมีให้บริการscikit-learnแต่สำหรับสันเขาฉันไม่สามารถบังคับใช้แบบไม่ลบล้างของเบต้าและแน่นอนฉันได้รับค่าสัมประสิทธิ์เชิงลบ ไม่มีใครรู้ว่าทำไมถึงเป็นเช่นนี้?

นอกจากนี้ฉันสามารถใช้สันในแง่ของกำลังสองน้อยที่สุดได้หรือไม่? ย้ายสิ่งนี้ไปยังคำถามอื่น: ฉันสามารถใช้การถดถอยแบบสันในแง่ของการถดถอยแบบ OLS ได้หรือไม่?


1
มีคำถามสองมุมฉากอยู่ที่นี่ฉันจะพิจารณาแยก "ฉันสามารถใช้สันเขาในแง่ของกำลังสองน้อย" เป็นคำถามแยกต่างหาก
Matthew Drury

คำตอบ:


8

คำตอบที่ต่อต้านภูมิอากาศที่ค่อนข้างจะ " ใครรู้ว่าทำไมนี้คืออะไร? " คือว่าไม่มีใครใส่ใจเพียงพอที่จะดำเนินการตามขั้นตอนการถดถอยสันเขาที่ไม่เป็นลบ หนึ่งในเหตุผลหลักคือคนเริ่มใช้งาน รูทีน net elastic non-negative (ตัวอย่างเช่นที่นี่และที่นี่ ) ตาข่ายยืดหยุ่นรวมถึงการถดถอยของสันเป็นกรณีพิเศษ (อันที่จริงแล้วส่วนหนึ่งตั้งค่า LASSO ให้มีน้ำหนักเป็นศูนย์) ผลงานเหล่านี้ค่อนข้างใหม่ดังนั้นจึงยังไม่ได้รวมอยู่ใน scikit-Learn หรือชุดการใช้งานทั่วไปที่คล้ายกัน คุณอาจต้องการสอบถามผู้เขียนเอกสารเหล่านี้เพื่อขอรหัส

แก้ไข:

ในฐานะที่เป็น @ amoeba และฉันพูดคุยเกี่ยวกับความคิดเห็นการดำเนินการที่เกิดขึ้นจริงนี้ค่อนข้างง่าย สมมติว่ามีปัญหาการถดถอยต่อไปนี้:

y=2x1x2+ϵ,ϵN(0,0.22)

ที่และมีทั้งภาวะปกติมาตรฐานเช่น:(0,1) สังเกตุฉันใช้ตัวแปรทำนายมาตรฐานดังนั้นฉันไม่จำเป็นต้องทำให้เป็นมาตรฐานในภายหลัง เพื่อความง่ายฉันไม่รวมถึงการสกัดกั้นอย่างใดอย่างหนึ่ง เราสามารถแก้ปัญหาการถดถอยนี้ได้ทันทีโดยใช้การถดถอยเชิงเส้นมาตรฐาน ดังนั้นใน R มันควรเป็นแบบนี้:x1x2xpN(0,1)

rm(list = ls()); 
library(MASS); 
set.seed(123);
N = 1e6;
x1 = rnorm(N)
x2 = rnorm(N)
y = 2 * x1 - 1 * x2 + rnorm(N,sd = 0.2)

simpleLR = lm(y ~ -1 + x1 + x2 )
matrixX = model.matrix(simpleLR); # This is close to standardised
vectorY = y
all.equal(coef(simpleLR), qr.solve(matrixX, vectorY), tolerance = 1e-7)  # TRUE

สังเกตเห็นบรรทัดสุดท้าย เกือบทั้งหมดถดถอยเชิงเส้นการใช้งานประจำการสลายตัว QR เพื่อประเมิน\เราต้องการใช้สิ่งเดียวกันสำหรับปัญหาการถดถอยของสันเขา ณ จุดนี้อ่านโพสต์นี้โดย @whuber; เราจะดำเนินการตามขั้นตอนนี้อย่างแน่นอน ในระยะสั้นเราจะเพิ่มเมทริกซ์การออกแบบต้นฉบับของเราด้วยเมทริกซ์ทแยงมุมและเวกเตอร์การตอบสนองของเราพร้อมศูนย์ ด้วยวิธีนี้เราจะสามารถแสดงปัญหาการถดถอยแนวสันเดิมได้อีกครั้งเป็น โดยที่βXλIpyp(XTX+λI)1XTy(X¯TX¯)1X¯Ty¯¯สัญลักษณ์รุ่นเติม ตรวจสอบสไลด์ที่ 18-19 จากบันทึกเหล่านี้ด้วยเพื่อความสมบูรณ์ฉันพบว่าตรงไปตรงมาทีเดียว ดังนั้นใน R เราต้องการบางอย่างดังต่อไปนี้:

myLambda = 100;  
simpleRR = lm.ridge(y ~ -1 + x1 + x2, lambda = myLambda)
newVecY = c(vectorY, rep(0, 2))
newMatX = rbind(matrixX, sqrt(myLambda) * diag(2))
all.equal(coef(simpleRR), qr.solve(newMatX, newVecY), tolerance = 1e-7)  # TRUE

และมันใช้งานได้ ตกลงดังนั้นเราจึงได้ส่วนการถดถอยของสัน เราสามารถแก้ปัญหาด้วยวิธีอื่นได้ แต่เราสามารถกำหนดเป็นปัญหาการหาค่าเหมาะที่สุดที่ผลบวกส่วนที่เหลือของกำลังสองเป็นฟังก์ชันต้นทุนแล้วปรับเทียบกับมันเช่น 2 เราสามารถทำสิ่งนี้ได้:minβ||y¯X¯β||22

myRSS <- function(X,y,b){ return( sum( (y - X%*%b)^2 ) ) }
bfgsOptim = optim(myRSS, par = c(1,1), X = newMatX, y= newVecY, 
                  method = 'L-BFGS-B')
all.equal(coef(simpleRR), bfgsOptim$par, check.attributes = FALSE, 
          tolerance = 1e-7) # TRUE

ซึ่งเป็นไปตามคาดอีกครั้ง ดังนั้นตอนนี้เราแค่ต้องการ:ที่0 ซึ่งเป็นเพียงปัญหาการเพิ่มประสิทธิภาพเดียวกัน แต่มีข้อ จำกัด เพื่อให้การแก้ปัญหาที่ไม่เป็นเชิงลบminβ||y¯X¯β||22β0

bfgsOptimConst = optim(myRSS, par = c(1,1), X=newMatX, y= newVecY, 
                       method = 'L-BFGS-B', lower = c(0,0))
all(bfgsOptimConst$par >=0)  # TRUE
(bfgsOptimConst$par) # 2.000504 0.000000

ซึ่งแสดงให้เห็นว่างานการถดถอยสันสันที่ไม่เป็นลบสามารถแก้ไขได้โดยการปรับโครงสร้างใหม่ให้เป็นปัญหาการปรับให้เหมาะสมแบบง่าย คำเตือนบางอย่าง:

  1. ฉันใช้ตัวแปรตัวทำนายปกติ (จริง) คุณจะต้องคำนึงถึงการฟื้นฟูด้วยตนเอง
  2. สิ่งเดียวกันก็เกิดขึ้นเพื่อการสกัดกั้นที่ไม่เป็นมาตรฐาน
  3. ผมใช้optimของL-BFGS-Bโต้แย้ง มันเป็นตัวแก้ปัญหาวานิลลา R มากที่สุดที่ยอมรับขอบเขต ฉันแน่ใจว่าคุณจะได้พบกับนักแก้ปัญหาที่ดีกว่าหลายสิบคน
  4. โดยทั่วไปปัญหาเชิงเส้นกำลังสองน้อยที่สุดเชิงเส้นจะถูกวางเป็นงานการหาค่าเหมาะที่สุดกำลังสอง นี่คือ overkill สำหรับโพสต์นี้ แต่โปรดจำไว้ว่าคุณสามารถรับความเร็วที่ดีขึ้นหากจำเป็น
  5. ดังที่กล่าวไว้ในความคิดเห็นที่คุณสามารถข้ามสันเขาถดถอยเป็นส่วนเติมเชิงเส้นถดถอยและเข้ารหัสฟังก์ชั่นค่าใช้จ่ายสันเขาโดยตรงเป็นปัญหาการเพิ่มประสิทธิภาพ นี่จะง่ายกว่านี้มากและโพสต์นี้เล็กลงอย่างมาก เพื่อประโยชน์ในการโต้แย้งฉันผนวกโซลูชั่นที่สองนี้ด้วย
  6. ผมไม่ได้สนทนาได้อย่างเต็มที่ในหลาม แต่เป็นหลักคุณสามารถทำซ้ำงานนี้โดยใช้ NumPy ของlinalg.solveและ SciPy ของการเพิ่มประสิทธิภาพการทำงาน
  7. ในการเลือกไฮเปอร์พารามิเตอร์ฯลฯ คุณเพียงแค่ทำ CV-step ปกติตามที่คุณต้องการในทุกกรณี ไม่มีอะไรเปลี่ยนแปลงλ

รหัสสำหรับจุดที่ 5:

myRidgeRSS <- function(X,y,b, lambda){ 
                return( sum( (y - X%*%b)^2 ) + lambda * sum(b^2) ) 
              }
bfgsOptimConst2 = optim(myRidgeRSS, par = c(1,1), X = matrixX, y = vectorY,
                        method = 'L-BFGS-B', lower = c(0,0), lambda = myLambda)
all(bfgsOptimConst2$par >0) # TRUE
(bfgsOptimConst2$par) # 2.000504 0.000000

1
สิ่งนี้ค่อนข้างทำให้เข้าใจผิด การถดถอยสันเขาที่ไม่เป็นลบนั้นมีความสำคัญอย่างยิ่งที่จะนำไปใช้: เราสามารถเขียนการถดถอยสันสันเป็นการถดถอยตามปกติในข้อมูลที่ขยาย (ดูความคิดเห็นที่stats.stackexchange.com/questions/203687 ) แล้วใช้กิจวัตรการถดถอย
อะมีบา

ฉันเห็นด้วยว่ามันง่ายที่จะนำไปใช้ (ฉันโหวตขึ้นก่อนหน้านี้ของคุณและความคิดเห็นของเกลนในหัวข้ออื่น ๆ ด้วย) คำถามคือทำไมไม่ใช้แม้ว่าไม่ใช่เรื่องยาก ในเรื่องนั้นฉันสงสัยอย่างยิ่งว่าการกำหนดงาน NNRR นี้โดยตรงปัญหาการปรับให้เหมาะสมนั้นง่ายยิ่งขึ้นซึ่งการกำหนดเป็นครั้งแรกเป็นการถดถอยข้อมูลที่ขยายออกไปแล้วใช้ Quad Prog การเพิ่มประสิทธิภาพเพื่อแก้ปัญหาการถดถอยนี้ ฉันไม่ได้พูดสิ่งนี้ในคำตอบของฉันเพราะมันจะเสี่ยงในส่วนการดำเนินงาน
usεr11852

หรือเพียงแค่เขียนเป็นสแตน
Sycorax พูดว่า Reinstate Monica

อ่าโอเค; ฉันเข้าใจว่า Q เป็นส่วนใหญ่ถามวิธีการทำสันเขาที่ไม่เป็นลบ ฉันยังแก้ไขเพื่อใส่ลงในชื่อ ไม่ว่าในกรณีใดฉันจะทำอย่างไรกับคำถามที่น่าสนใจกว่านี้ หากคุณสามารถอัปเดตคำตอบของคุณพร้อมคำอธิบายเกี่ยวกับวิธีการใช้สันเขาที่ไม่เป็นลบฉันคิดว่ามันจะมีประโยชน์มากสำหรับผู้อ่านในอนาคต (และฉันยินดีที่จะโหวตขึ้น :)
อะมีบา

1
เยี่ยมฉันจะทำมันในภายหลัง (ฉันไม่ได้สังเกตเห็นชื่อใหม่ขอโทษเกี่ยวกับเรื่องนั้น) ฉันอาจจะให้การดำเนินการในแง่ของ OLS / การสังเกตหลอกดังนั้นเราจึงตอบคำถามอื่นด้วย
usεr11852

4

glmnet ของบรรจุภัณฑ์ R ที่ใช้ตาข่ายยืดหยุ่นและดังนั้น lasso และ ridge จึงยอมให้สิ่งนี้ ด้วยพารามิเตอร์lower.limitsและupper.limitsคุณสามารถตั้งค่าต่ำสุดหรือสูงสุดสำหรับแต่ละน้ำหนักแยกกันดังนั้นถ้าคุณตั้งค่าขีด จำกัด ล่างเป็น 0 มันจะทำงานแบบยืดหยุ่นเชิงลบ (lasso / ridge)

นอกจากนี้ยังมีเครื่องห่องูหลามhttps://pypi.python.org/pypi/glmnet/2.0.0


2

จำได้ว่าเราพยายามที่จะแก้ปัญหา:

minimizexAxy22+λx22s.t. x>0

เทียบเท่ากับ:

minimizexAxy22+λxIxs.t. x>0

ด้วยพีชคณิตเพิ่มเติม:

minimizexxT(ATA+λI)x+(2ATy)Txs.t. x>0

วิธีแก้ปัญหาใน pseudo-python ง่าย ๆ ในการ:

Q = A'A + lambda*I
c = - A'y
x,_ = scipy.optimize.nnls(Q,c)

โปรดดูที่: หนึ่งไม่ทำเบาบางที่ไม่ใช่เชิงลบน้อยสแควร์โดยใช้ regularizers ของแบบฟอร์ม ?KxRkx

สำหรับคำตอบทั่วไปเพิ่มเติมเล็กน้อย


ควรบรรทัด c = - A'y ไม่ได้อ่าน c = A'y? ฉันคิดว่านี่ถูกต้อง แต่เราควรทราบว่าวิธีแก้ปัญหานั้นแตกต่างจาก scipy.optimize.nnls (newMatX, newVecY) โดยที่ newMatX คือแถว X ที่เพิ่มขึ้นพร้อมเมทริกซ์ทแยงมุมที่มี sqrt (แลมบ์ดา) ตามแนวทแยงมุมและ NewVecY คือ Y เติมด้วยศูนย์ nvar ผมคิดว่าวิธีที่คุณพูดถึงเป็นหนึ่งที่ถูกต้อง ...
ทอม Wenseleers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.