Ban đầu tôi đăng các điểm chuẩn bên dưới với mục đích khuyến nghị numpy.corrcoef
, thật ngu ngốc khi không nhận ra rằng câu hỏi ban đầu đã sử dụng corrcoef
và trên thực tế đang hỏi về các khớp đa thức bậc cao. Tôi đã thêm một giải pháp thực tế cho câu hỏi bình phương r đa thức bằng cách sử dụng mô hình thống kê và tôi đã để lại các điểm chuẩn ban đầu, mặc dù lạc đề, nhưng có khả năng hữu ích cho ai đó.
statsmodels
có khả năng tính toán r^2
phù hợp đa thức trực tiếp, đây là 2 phương pháp ...
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
Để tận dụng lợi thế hơn nữa statsmodels
, người ta cũng nên xem bản tóm tắt mô hình được trang bị, có thể được in hoặc hiển thị dưới dạng bảng HTML phong phú trong sổ ghi chép Jupyter / IPython. Ngoài ra, đối tượng kết quả cung cấp quyền truy cập vào nhiều chỉ số thống kê hữu ích rsquared
.
model = sm.OLS(y, xpoly)
results = model.fit()
results.summary()
Dưới đây là Câu trả lời ban đầu của tôi, nơi tôi đã chuẩn hóa các phương pháp hồi quy tuyến tính r ^ 2 khác nhau ...
Hàm corrcoef được sử dụng trong Câu hỏi tính toán hệ số tương quan r
, chỉ cho một hồi quy tuyến tính duy nhất, do đó, nó không giải quyết câu hỏi về các r^2
khớp đa thức bậc cao. Tuy nhiên, đối với giá trị của nó, tôi nhận thấy rằng đối với hồi quy tuyến tính, nó thực sự là phương pháp tính toán nhanh nhất và trực tiếp nhất r
.
def get_r2_numpy_corrcoef(x, y):
return np.corrcoef(x, y)[0, 1]**2
Đây là kết quả thời gian của tôi từ việc so sánh một loạt các phương pháp cho 1000 điểm ngẫu nhiên (x, y):
- Python thuần túy (
r
tính toán trực tiếp )
- 1000 vòng, tốt nhất là 3: 1,59 ms mỗi vòng
- Numpy polyfit (áp dụng cho các khớp đa thức bậc n)
- 1000 vòng, tốt nhất là 3: 326 µs mỗi vòng
- Numpy Manual (
r
tính toán trực tiếp )
- 10000 vòng, tốt nhất là 3: 62,1 µs mỗi vòng
- Numpy corrcoef (
r
tính toán trực tiếp )
- 10000 vòng, tốt nhất là 3: 56,6 µs mỗi vòng
- Scipy (hồi quy tuyến tính với
r
dưới dạng đầu ra)
- 1000 vòng, tốt nhất là 3: 676 µs mỗi vòng
- Statsmodels (có thể làm đa thức bậc n và nhiều kiểu phù hợp khác)
- 1000 vòng lặp, tốt nhất là 3: 422 µs mỗi vòng lặp
Phương pháp corrcoef gần như đánh bại việc tính toán r ^ 2 "theo cách thủ công" bằng phương pháp numpy. Nó nhanh hơn> 5 lần so với phương pháp polyfit và nhanh hơn ~ 12 lần so với scipy.linregress. Chỉ để củng cố những gì numpy đang làm cho bạn, nó nhanh hơn 28 lần so với python thuần túy. Tôi không thành thạo về những thứ như numba và pypy, vì vậy người khác sẽ phải lấp đầy những khoảng trống đó, nhưng tôi nghĩ rằng điều này rất thuyết phục đối với tôi đó corrcoef
là công cụ tốt nhất để tính toán r
cho một hồi quy tuyến tính đơn giản.
Đây là mã điểm chuẩn của tôi. Tôi đã sao chép từ Máy tính xách tay Jupyter (khó có thể gọi nó là Máy tính xách tay IPython ...), vì vậy tôi xin lỗi nếu có bất kỳ điều gì bị hỏng trên đường đi. Lệnh ma thuật% timeit yêu cầu 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)