"Bunun neden olduğunu bilen var mı? " Sorusunun iklim karşıtı yanıtı , hiç kimsenin negatif olmayan bir sırt regresyon rutini uygulamak için yeterince umurunda olmamasıdır. Ana nedenlerden biri, insanların zaten negatif olmayan elastik ağ rutinlerini uygulamaya başlamış olmasıdır
(örneğin burada ve burada ). Elastik ağ özel bir durum olarak sırt regresyonunu içerir (biri esas olarak LASSO parçasını sıfır ağırlıkta olacak şekilde ayarlar). Bu çalışmalar nispeten yenidir, bu nedenle henüz scikit-learn veya benzeri bir genel kullanım paketine dahil edilmemiştir. Kod için bu makalelerin yazarlarına danışmak isteyebilirsiniz.
DÜZENLE:
@ Amoeba ve ben yorumlarda tartıştığımız gibi, bunun gerçek uygulaması nispeten basittir. Diyelim ki şu regresyon problemi var:
y=2x1−x2+ϵ,ϵ∼N(0,0.22)
burada ve her ikisi de standart normallerdir: . Dikkat Daha sonra normalleştirmek zorunda değilim standartlaştırılmış tahmin değişkenleri kullanın. Basitlik için bir kesişim de eklemem. Bu regresyon problemini standart lineer regresyon kullanarak derhal çözebiliriz. Yani R'de şöyle bir şey olmalı:x1x2xp∼N(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
Son satıra dikkat edin. Hemen hemen tüm doğrusal regresyon rutini değerini tahmin etmek için QR ayrışmasını kullanır . Aynısını sırt regresyon problemimiz için de kullanmak istiyoruz. Bu noktada @whuber tarafından gönderilen bu yazıyı okuyun ; tam olarak bu prosedürü uygulayacağız . Kısacası, orijinal tasarım artırmada olacak matris bir diyagonal matris ve yanıt vektörü ile sıfır. Bu şekilde orijinal sırt regresyon problemini olarak buradaβXλ--√benpyp(XTX+ λ I)- 1XTy(X¯TX¯)- 1X¯Ty¯¯artırılmış versiyonu sembolize eder. Tamlık için bu notlardan 18-19 slaytlarını da kontrol edin , onları oldukça basit buldum. Yani R'de bazıları aşağıdakileri isteriz:
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
ve çalışıyor. Tamam, sırtın regresyon kısmını aldık. Yine de başka bir şekilde çözebiliriz, bunu karelerin kalan toplamının maliyet fonksiyonu olduğu bir optimizasyon problemi olarak formüle edebiliriz ve sonra buna karşı optimize edebiliriz, yani. . Tabii ki bunu yapabiliriz: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
yine beklendiği gibi çalışıyor. Şimdi şunu istiyoruz: burada . Bu sadece aynı optimizasyon problemidir ancak çözümün negatif olmaması için kısıtlanmıştır.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
Orijinal negatif olmayan sırt regresyon görevinin basit bir kısıtlanmış optimizasyon problemi olarak yeniden formüle edilerek çözülebileceğini gösterir. Bazı uyarılar:
- (Pratik olarak) normalleştirilmiş tahmin değişkenlerini kullandım. Normalleşmeyi kendiniz hesaplamanız gerekecektir.
- Aynı şey için de geçerli olmayan kesişim normalleşmesi.
- Kullandığım
optim
'nin L-BFGS-B değişken. Sınırları kabul eden en vanilya R çözücüsüdür. Eminim düzinelerce daha iyi çözücü bulacaksınız.
- Genel olarak, doğrusal en küçük kareler problemleri ikinci dereceden optimizasyon görevleri olarak ortaya konmaktadır . Bu, bu gönderi için bir overkill olduğunu, ancak gerekirse daha iyi hız alabileceğinizi unutmayın.
- Yorumlarda belirtildiği gibi, sırt-regresyonunu artırılmış doğrusal-regresyon parçası olarak atlayabilir ve sırt maliyet fonksiyonunu doğrudan bir optimizasyon problemi olarak kodlayabilirsiniz. Bu çok daha basit olurdu ve bu yazı önemli ölçüde daha küçük. Tartışma uğruna bu ikinci çözümü de ekliyorum.
- Python'da tamamen konuşmuyorum, ancak aslında bu işi NumPy'nin linalg.solve ve SciPy'nin optimize işlevlerini kullanarak çoğaltabilirsiniz .
- Hiperparametre vs.'yi seçmek için , her durumda yapacağınız normal CV adımını yapmanız yeterlidir; hiçbirşey değişmez.λ
5. nokta için kod:
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