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
cevap
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
bir tekrarlanabilir örnek verin. Birkaç olası sebep var, ancak verileriniz olmadan, yalnızca sorunuzun cevabını tahmin edebiliriz (ki yine de yapacağım :). –