Başlangıçta aşağıdaki kriterleri tavsiye etmek amacıyla yayınladım numpy.corrcoef
, aptalca orijinal sorunun halihazırda kullandığını corrcoef
ve aslında daha yüksek dereceden polinom uyumu sorduğunun farkında değildim . İstatistik modellerini kullanarak polinom r-kare sorusuna gerçek bir çözüm ekledim ve konu dışı olsa da potansiyel olarak birileri için yararlı olan orijinal kriterleri bıraktım.
statsmodels
r^2
doğrudan bir polinom uyumu hesaplama yeteneğine sahiptir , işte 2 yöntem ...
import statsmodels.api as sm
import statsmodels.formula.api as smf
def get_r2_statsmodels(x, y, k=1):
xpoly = np.column_stack([x**i for i in range(k+1)])
return sm.OLS(y, xpoly).fit().rsquared
def get_r2_statsmodels_formula(x, y, k=1):
formula = 'y ~ 1 + ' + ' + '.join('I(x**{})'.format(i) for i in range(1, k+1))
data = {'x': x, 'y': y}
return smf.ols(formula, data).fit().rsquared
Bundan daha fazla yararlanmak için statsmodels
, Jupyter / IPython not defterinde zengin bir HTML tablosu olarak yazdırılabilen veya görüntülenebilen uygun model özetine de bakılmalıdır. Sonuçlar nesnesi, birçok yararlı istatistiksel ölçüme ek olarak erişim sağlar rsquared
.
model = sm.OLS(y, xpoly)
results = model.fit()
results.summary()
Aşağıda, çeşitli doğrusal regresyon r ^ 2 yöntemlerini karşılaştırdığım orijinal Cevabım var ...
Corrcoef Soru kullanılan fonksiyon korelasyon katsayısı, hesaplar r
, yalnızca tek bir doğrusal regresyon için, bu yüzden sorusunu ele almaz r^2
yüksek mertebeden çokterimli için. Bununla birlikte, ne olursa olsun, doğrusal regresyon için bunun gerçekten de en hızlı ve en doğrudan hesaplama yöntemi olduğunu buldum r
.
def get_r2_numpy_corrcoef(x, y):
return np.corrcoef(x, y)[0, 1]**2
Bunlar benim zamanımdıBir grup yöntemi 1000 rastgele (x, y) nokta için karşılaştırmanın sonuçları:
- Saf Python (doğrudan
r
hesaplama)
- 1000 döngü, döngü başına en iyi 3: 1,59 ms
- Numpy polyfit (n-inci derece polinom uyumu için geçerlidir)
- 1000 döngü, döngü başına en iyi 3: 326 µs
- Numpy Kılavuzu (doğrudan
r
hesaplama)
- 10000 döngü, döngü başına en iyi 3: 62,1 µs
- Numpy corrcoef (doğrudan
r
hesaplama)
- 10000 döngü, döngü başına en iyi 3: 56,6 µs
- Scipy (
r
çıktı olarak doğrusal regresyon )
- 1000 döngü, döngü başına en iyi 3: 676 µs
- İstatistik modelleri (n. Derece polinom ve diğer birçok uyumu yapabilir)
- 1000 döngü, döngü başına en iyi 3: 422 µs
Corrcoef yöntemi, numpy yöntemlerini kullanarak "elle" r ^ 2 hesaplamasını dar bir şekilde yener. Polyfit yönteminden> 5X ve scipy.linregress'ten ~ 12X daha hızlıdır. Sadece numpy'nin sizin için ne yaptığını pekiştirmek için, saf python'dan 28 kat daha hızlı. Numba ve pypy gibi konularda çok bilgili değilim, bu yüzden başka birinin bu boşlukları doldurması gerekecekti, ama bence bu, basit bir doğrusal regresyon corrcoef
için hesaplama yapmak r
için en iyi araç olduğunun bana çok ikna edici olduğunu düşünüyorum .
İşte kıyaslama kodum. Bir Jupyter Not Defterinden kopyalayıp yapıştırdım (buna IPython Defter dememek zor ...), bu yüzden yolda bir sorun olursa özür dilerim. % Timeit sihirli komutu IPython gerektirir.
import numpy as np
from scipy import stats
import statsmodels.api as sm
import math
n=1000
x = np.random.rand(1000)*10
x.sort()
y = 10 * x + (5+np.random.randn(1000)*10-5)
x_list = list(x)
y_list = list(y)
def get_r2_numpy(x, y):
slope, intercept = np.polyfit(x, y, 1)
r_squared = 1 - (sum((y - (slope * x + intercept))**2) / ((len(y) - 1) * np.var(y, ddof=1)))
return r_squared
def get_r2_scipy(x, y):
_, _, r_value, _, _ = stats.linregress(x, y)
return r_value**2
def get_r2_statsmodels(x, y):
return sm.OLS(y, sm.add_constant(x)).fit().rsquared
def get_r2_python(x_list, y_list):
n = len(x_list)
x_bar = sum(x_list)/n
y_bar = sum(y_list)/n
x_std = math.sqrt(sum([(xi-x_bar)**2 for xi in x_list])/(n-1))
y_std = math.sqrt(sum([(yi-y_bar)**2 for yi in y_list])/(n-1))
zx = [(xi-x_bar)/x_std for xi in x_list]
zy = [(yi-y_bar)/y_std for yi in y_list]
r = sum(zxi*zyi for zxi, zyi in zip(zx, zy))/(n-1)
return r**2
def get_r2_numpy_manual(x, y):
zx = (x-np.mean(x))/np.std(x, ddof=1)
zy = (y-np.mean(y))/np.std(y, ddof=1)
r = np.sum(zx*zy)/(len(x)-1)
return r**2
def get_r2_numpy_corrcoef(x, y):
return np.corrcoef(x, y)[0, 1]**2
print('Python')
%timeit get_r2_python(x_list, y_list)
print('Numpy polyfit')
%timeit get_r2_numpy(x, y)
print('Numpy Manual')
%timeit get_r2_numpy_manual(x, y)
print('Numpy corrcoef')
%timeit get_r2_numpy_corrcoef(x, y)
print('Scipy')
%timeit get_r2_scipy(x, y)
print('Statsmodels')
%timeit get_r2_statsmodels(x, y)