Saya awalnya memposting tolok ukur di bawah ini dengan tujuan merekomendasikan numpy.corrcoef, dengan bodohnya tidak menyadari bahwa pertanyaan asli sudah digunakan corrcoefdan sebenarnya menanyakan tentang kecocokan polinomial tingkat tinggi. Saya telah menambahkan solusi aktual untuk pertanyaan polinomial r-squared menggunakan statsmodels, dan saya telah meninggalkan tolok ukur asli, yang sementara di luar topik, berpotensi berguna bagi seseorang.
statsmodelsmemiliki kemampuan untuk menghitung r^2kesesuaian polinom secara langsung, berikut adalah 2 metode ...
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
Untuk memanfaatkan lebih jauh statsmodels, kita juga harus melihat ringkasan model yang dipasang, yang dapat dicetak atau ditampilkan sebagai tabel HTML kaya di notebook Jupyter / IPython. Objek hasil menyediakan akses ke banyak metrik statistik yang berguna sebagai tambahan rsquared.
model = sm.OLS(y, xpoly)
results = model.fit()
results.summary()
Di bawah ini adalah Jawaban asli saya di mana saya membandingkan berbagai metode regresi linier r ^ 2 ...
Fungsi koreksi yang digunakan dalam Pertanyaan menghitung koefisien korelasi r, hanya untuk satu regresi linier, sehingga tidak menjawab pertanyaan tentang r^2kesesuaian polinomial orde tinggi. Namun, untuk apa nilainya, saya telah menemukan bahwa untuk regresi linier, itu memang metode penghitungan tercepat dan paling langsung r.
def get_r2_numpy_corrcoef(x, y):
return np.corrcoef(x, y)[0, 1]**2
Ini adalah hasil waktu saya dari membandingkan sekumpulan metode untuk 1000 poin acak (x, y):
- Python murni (
rperhitungan langsung )
- 1000 loop, terbaik 3: 1,59 ms per loop
- Poliit numpy (berlaku untuk kesesuaian polinomial derajat ke-n)
- 1000 loop, terbaik 3: 326 µs per loop
- Numpy Manual (
rperhitungan langsung )
- 10000 loop, terbaik 3: 62,1 µs per loop
- Numpy corrcoef (
rpenghitungan langsung )
- 10000 loop, terbaik 3: 56,6 µs per loop
- Scipy (regresi linier dengan
rsebagai keluaran)
- 1000 loop, terbaik 3: 676 µs per loop
- Statsmodels (dapat melakukan polinomial derajat ke-n dan banyak kecocokan lainnya)
- 1000 loop, terbaik 3: 422 µs per loop
Metode corrcoef mengalahkan penghitungan r ^ 2 "secara manual" menggunakan metode numpy. Ini> 5X lebih cepat dari metode polyfit dan ~ 12X lebih cepat dari scipy.linregress. Hanya untuk memperkuat apa yang numpy lakukan untuk Anda, ini 28X lebih cepat dari python murni. Saya tidak berpengalaman dalam hal-hal seperti numba dan pypy, jadi orang lain harus mengisi celah itu, tetapi saya pikir ini cukup meyakinkan bagi saya bahwa corrcoefini adalah alat terbaik untuk menghitung rregresi linier sederhana.
Ini kode pembandingan saya. Saya menyalin-tempel dari Notebook Jupyter (sulit untuk tidak menyebutnya sebagai Notebook IPython ...), jadi saya minta maaf jika ada yang rusak di jalan. Perintah sihir% timeit membutuhkan IPython.
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)