2016-04-01 24 views
0

beta = inv(X'X)X'Y'un normal denklemini izleyerek kendi kodumu doğrusal regresyon için yazmaya çalıştım. Ancak, kare hatası, numpy.linalg'daki lstsq işlevinden çok daha büyüktür. Herkes bana SVD yönteminin (bu lstsq kullanır) normal denklemden daha doğru olduğunu açıklayabilir mi? TeşekkürlerEn küçük kareler yöntemleri: normal denklem vs svd

+1

bir tekrarlanabilir örnek verin. Birkaç olası sebep var, ancak verileriniz olmadan, yalnızca sorunuzun cevabını tahmin edebiliriz (ki yine de yapacağım :). –

cevap

2

Verileriniz condition number yüksekliğinden dolayı X'X matrisinden şüpheleniyorum. Böyle bir matrisin sayısal tersini hesaplamaya çalışmak büyük hatalara neden olabilir. Bir ters matrisi açıkça hesaplamak genellikle kötü bir fikirdir (bkz. Örneğin, http://www.johndcook.com/blog/2010/01/19/dont-invert-that-matrix/ veya http://epubs.siam.org/doi/abs/10.1137/1.9780898718027.ch14).

Durum numarasını numpy.linalg.cond kullanarak denetleyebilirsiniz.

İşte bir örnek. İlk X ve Y oluşturun: Bu rasgele X için

In [186]: X = np.random.randn(500, 30) 

In [187]: Y = np.linspace(0, 1, len(X)) 

, koşul numarası büyük değil:

In [188]: np.linalg.cond(X.T.dot(X)) 
Out[188]: 2.4456380658308148 

Normal denklemi ve lstsq aynı sonucu verir (numpy.allclose göre bu işlevin varsayılan kullanırken argümanlar):

In [189]: betan = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y) 

In [190]: betal, res, rnk, s = np.linalg.lstsq(X, Y) 

In [191]: np.allclose(betan, betal) 
Out[191]: True 

Şimdi ince ayar X neredeyse iki sütun yaparak aynı. Bu X'X neredeyse tekil yapar ve bunu bir çok koşul numarası verir:

In [192]: X[:,0] = X[:,1] + 1e-8*np.random.randn(len(X)) 

In [193]: np.linalg.cond(X.T.dot(X)) 
Out[193]: 3954529794300611.5 

Şimdi normal bir denklem lstsq daha farklı bir sonuç verir:

In [194]: betan = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y) 

In [195]: betal, res, rnk, s = np.linalg.lstsq(X, Y) 

In [196]: np.allclose(betan, betal) 
Out[196]: False 
İlgili konular