programing

파이썬과 Numpy를 사용하여 r-제곱을 계산하려면 어떻게 해야 합니까?

lastmoon 2023. 7. 21. 21:51
반응형

파이썬과 Numpy를 사용하여 r-제곱을 계산하려면 어떻게 해야 합니까?

저는 파이썬과 Numpy를 사용하여 임의의 정도의 가장 적합한 다항식을 계산하고 있습니다.x 값 목록, y 값 및 적합할 다항식의 정도(선형, 2차 등)를 전달합니다.

이 정도는 효과가 있지만, 저는 또한 r(상관계수)과 r-제곱(결정계수)도 계산하려고 합니다.Excel의 가장 적합한 추세선 기능과 계산한 r 제곱 값을 비교하고 있습니다.이를 사용하여 선형 최적 적합도(도는 1)에 대한 r-제곱을 올바르게 계산하고 있습니다.그러나 차수가 1보다 큰 다항식에서는 함수가 작동하지 않습니다.

Excel은 이것을 할 수 있습니다.Numpy를 사용하여 고차 다항식에 대한 r 제곱을 어떻게 계산합니까?

제 기능은 다음과 같습니다.

import numpy

# Polynomial Regression
def polyfit(x, y, degree):
    results = {}

    coeffs = numpy.polyfit(x, y, degree)
     # Polynomial Coefficients
    results['polynomial'] = coeffs.tolist()

    correlation = numpy.corrcoef(x, y)[0,1]

     # r
    results['correlation'] = correlation
     # r-squared
    results['determination'] = correlation**2

    return results

매우 늦은 답변입니다. 하지만 누군가 이를 위해 준비된 기능이 필요할 경우:

비망록.비망록.비망록.

예.

slope, intercept, r_value, p_value, std_err = scipy.stats.linregress(x, y)

@아담 마플스의 대답처럼.

yanl(아직 다른 라이브러리)로부터.sklearn.metrics기능이 있습니다.

from sklearn.metrics import r2_score

coefficient_of_dermination = r2_score(y, p(x))

바보 같은 놈한테서.다중 적합 문서, 적합 선형 회귀 분석입니다.특히, 바보야.정도가 'd'인 폴리핏은 평균 함수를 사용한 선형 회귀 분석을 적합시킵니다.

E(y|x) = p_d * x**d + p_{d-1} * x **(d-1) + ...p_1 * x + p_0

따라서 해당 적합치에 대한 R-제곱을 계산하면 됩니다.선형 회귀에 대한 위키백과 페이지는 자세한 내용을 제공합니다.당신은 몇 가지 방법으로 계산할 수 있는 R^2에 관심이 있습니다, 아마도 가장 쉬운 것은

SST = Sum(i=1..n) (y_i - y_bar)^2
SSReg = Sum(i=1..n) (y_ihat - y_bar)^2
Rsquared = SSReg/SST

여기서 'y_bar'를 y의 평균으로 사용하고 'y_ihat'을 각 점의 적합치로 사용합니다.

저는 numpy에 대해 잘 모르기 때문에(저는 보통 R에서 일합니다), 아마도 R 제곱을 계산하는 더 쉬운 방법이 있을 것입니다. 하지만 다음은 정확해야 합니다.

import numpy

# Polynomial Regression
def polyfit(x, y, degree):
    results = {}

    coeffs = numpy.polyfit(x, y, degree)

     # Polynomial Coefficients
    results['polynomial'] = coeffs.tolist()

    # r-squared
    p = numpy.poly1d(coeffs)
    # fit values, and mean
    yhat = p(x)                         # or [p(z) for z in x]
    ybar = numpy.sum(y)/len(y)          # or sum(y)/len(y)
    ssreg = numpy.sum((yhat-ybar)**2)   # or sum([ (yihat - ybar)**2 for yihat in yhat])
    sstot = numpy.sum((y - ybar)**2)    # or sum([ (yi - ybar)**2 for yi in y])
    results['determination'] = ssreg / sstot

    return results

저는 x와 y가 배열과 같은 이것을 성공적으로 사용하고 있습니다.

참고: 선형 회귀 분석 전용

def rsquared(x, y):
    """ Return R^2 where x and y are array-like."""

    slope, intercept, r_value, p_value, std_err = scipy.stats.linregress(x, y)
    return r_value**2

를 추천할 목적으로 했습니다.numpy.corrcoef어리석게도 원래 질문이 이미 사용되고 있다는 것을 깨닫지 못합니다.corrcoef그리고 사실은 고차 다항식 적합치에 대해 묻고 있었습니다.저는 통계 모형을 사용하여 다항식 r 제곱 질문에 실제 솔루션을 추가했고, 주제에서 벗어나 있지만 누군가에게 잠재적으로 유용한 원래 벤치마크를 남겼습니다.


statsmodels에는 계기 있이니다를 이 있습니다.r^2직접 다항식 적합의 두 가지 방법이 있습니다.

import statsmodels.api as sm
import statsmodels.formula.api as smf

# Construct the columns for the different powers of x
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

# Use the formula API and construct a formula describing the polynomial
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 # or rsquared_adj

다음과 같은 이점을 더욱 활용하기 위해statsmodels 합니다. 이 요약은 Jupyter/JupyterRich HTML 할 수 .나는 Python 노트북.결과 개체는 유용한 통계 메트릭에 대한 액세스를 제공할 뿐만 아니라rsquared.

model = sm.OLS(y, xpoly)
results = model.fit()
results.summary()

아래는 다양한 선형 회귀 r^2 방법을 벤치마킹한 저의 원래 답변입니다.

질문에 사용된 코르코프 함수는 상관 계수를 계산합니다.r단일 선형 회귀에 대해서만, 그래서 그것은 질문을 다루지 않습니다.r^2고차 다항식 적합치의 경우.회귀의 인 계산 회귀라는 것을 r.

def get_r2_numpy_corrcoef(x, y):
    return np.corrcoef(x, y)[0, 1]**2

1000개의 랜덤(x, y) 포인트에 대해 여러 방법을 비교한 결과는 다음과 같습니다.

  • Python( Pure Python()r계산)
    • 1,000개의 루프(루프당 최고 3: 1.59ms)
  • Numpy 폴리핏(n차 다항식 적합치에 적용 가능)
    • 1000개 루프, 3개 루프당 최적: 326µs
  • (직접 Numpy Manual (직접))r계산)
    • 10000개 루프, 3개 루프당 62.1µs 최적
  • Numpy Corrcoef (으)로 표시)r계산)
    • 10000개 루프(루프당 56.6µs), 최적의 3개 루프
  • Scipy를 사용한 분석)r결과로서)
    • 1000개 루프, 루프당 3:676µs 중 최고치
  • 통계분석 모형(일차 다항식 및 기타 여러 적합치)
    • 1,000개의 루프(루프당 3:422µs)

코르코프 방법은 numpy 방법을 사용하여 r^2를 "수동으로" 계산하는 것을 아슬아슬하게 능가합니다.이는 폴리핏 방법보다 >5배 빠르고 scipy.lin 회귀보다 ~12배 빠릅니다.Numpy가 당신에게 하는 일을 강화하기 위해, 그것은 순수한 파이썬보다 28배 더 빠릅니다.같은 에 대해 잘 에 다른 그 할 입니다. 이 numba와 pypy라는 것을 할 수 합니다. 하지만 저는 이것이 저에게 충분히 설득력이 있다고 생각합니다.corrcoef 가적도다니구입한합장에ating▁for다를 계산하는 데 가장 좋은 입니다.r단순 선형 회귀 분석의 경우.

여기 제 벤치마킹 코드가 있습니다.제가 주피터 노트북(아이피톤 노트북이라고 하기는 힘들지만...)에서 복사 붙여넣기를 했기 때문에 도중에 뭔가 고장이 났다면 사과드립니다.%timeit magic 명령에는 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)

7월 28일/21일 벤치마크 결과. (파이썬 3.7, 누피 1.19, 스키피 1.6, 통계 모델 0.12)

Python
2.41 ms ± 180 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Numpy polyfit
318 µs ± 44.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Numpy Manual
79.3 µs ± 4.05 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Numpy corrcoef
83.8 µs ± 1.37 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Scipy
221 µs ± 7.12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Statsmodels
375 µs ± 3.63 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

다음은 Python과 Numpy의 가중치 r 제곱을 계산하는 함수입니다(대부분의 코드는 sklearn에서 옵니다).

from __future__ import division 
import numpy as np

def compute_r2_weighted(y_true, y_pred, weight):
    sse = (weight * (y_true - y_pred) ** 2).sum(axis=0, dtype=np.float64)
    tse = (weight * (y_true - np.average(
        y_true, axis=0, weights=weight)) ** 2).sum(axis=0, dtype=np.float64)
    r2_score = 1 - (sse / tse)
    return r2_score, sse, tse

예:

from __future__ import print_function, division 
import sklearn.metrics 

def compute_r2_weighted(y_true, y_pred, weight):
    sse = (weight * (y_true - y_pred) ** 2).sum(axis=0, dtype=np.float64)
    tse = (weight * (y_true - np.average(
        y_true, axis=0, weights=weight)) ** 2).sum(axis=0, dtype=np.float64)
    r2_score = 1 - (sse / tse)
    return r2_score, sse, tse    

def compute_r2(y_true, y_predicted):
    sse = sum((y_true - y_predicted)**2)
    tse = (len(y_true) - 1) * np.var(y_true, ddof=1)
    r2_score = 1 - (sse / tse)
    return r2_score, sse, tse

def main():
    '''
    Demonstrate the use of compute_r2_weighted() and checks the results against sklearn
    '''        
    y_true = [3, -0.5, 2, 7]
    y_pred = [2.5, 0.0, 2, 8]
    weight = [1, 5, 1, 2]
    r2_score = sklearn.metrics.r2_score(y_true, y_pred)
    print('r2_score: {0}'.format(r2_score))  
    r2_score,_,_ = compute_r2(np.array(y_true), np.array(y_pred))
    print('r2_score: {0}'.format(r2_score))
    r2_score = sklearn.metrics.r2_score(y_true, y_pred,weight)
    print('r2_score weighted: {0}'.format(r2_score))
    r2_score,_,_ = compute_r2_weighted(np.array(y_true), np.array(y_pred), np.array(weight))
    print('r2_score weighted: {0}'.format(r2_score))

if __name__ == "__main__":
    main()
    #cProfile.run('main()') # if you want to do some profiling

출력:

r2_score: 0.9486081370449679
r2_score: 0.9486081370449679
r2_score weighted: 0.9573170731707317
r2_score weighted: 0.9573170731707317

이는 공식(미러)에 해당합니다.

enter image description here

f_i는 적합치의 예측 값이고, y_{av}는 관측 데이터의 평균 y_i는 관측 데이터 값입니다.w_i는 각 데이터 점(일반적으로 w_i=1)에 적용되는 가중치입니다.SSE는 오차로 인한 제곱합이고 SST는 전체 제곱합입니다.


관심이 있는 경우 R: https://gist.github.com/dhimmel/588d64a73fa4fef02c8f (미러)의 코드입니다.

다음은 y와 y_hat가 판다 계열이라고 가정할 때 실제 및 예측 값으로부터 R^2를 계산하는 매우 간단한 파이썬 함수입니다.

def r_squared(y, y_hat):
    y_bar = y.mean()
    ss_tot = ((y-y_bar)**2).sum()
    ss_res = ((y-y_hat)**2).sum()
    return 1 - (ss_res/ss_tot)

R-제곱은 선형 회귀 분석에만 적용되는 통계량입니다.

기본적으로 선형 회귀 분석을 통해 데이터의 변동을 설명할 수 있는 정도를 측정합니다.

따라서 각 결과 변수의 평균으로부터의 총 제곱 편차인 "총 제곱합"을 계산합니다.

formula1

여기서 y_bar는 그들의 평균입니다.

그런 다음 적합치가 평균과 얼마나 다른지 나타내는 "회귀 제곱합"을 계산합니다.

formula2

그리고 그 둘의 비율을 찾아보세요.

이제 다항식 적합치를 위해 해야 할 일은 해당 모델의 y_hats를 연결하는 것뿐이지만, r-제곱이라고 부르는 것은 정확하지 않습니다.

여기 제가 찾은 링크가 그것을 조금 말해줍니다.

r 제곱에 대한 위키백과 기사는 단순한 선형 회귀가 아닌 일반 모델 적합에 사용될 수 있음을 시사합니다.

numpy 모듈 사용(python3에서 테스트됨):

import numpy as np
def linear_regression(x, y): 
    coefs = np.polynomial.polynomial.polyfit(x, y, 1)
    ffit = np.poly1d(coefs)
    m = ffit[0]
    b = ffit[1] 
    eq = 'y = {}x + {}'.format(round(m, 3), round(b, 3))
    rsquared = np.corrcoef(x, y)[0, 1]**2
    return rsquared, eq, m, b

rsquared, eq, m, b = linear_regression(x,y)
print(rsquared, m, b)
print(eq)

출력:

0.013378252355751777 0.1316331351105754 0.7928782850418713 
y = 0.132x + 0.793

참고: r² ≠ R²
r²를 "결정 계수"라고 합니다.
R²는 Pearson 계수의 제곱입니다.

공식적으로 r²로 통합되는 R²는 최소 제곱 적합이므로 아마도 원하는 것일 것입니다. R²는 단순한 합의 부분보다 더 좋습니다.Numpy는 Pearson이 사실상의 상관 계수라고 가정하는 "corcoef"라고 부르는 것을 두려워하지 않습니다.

이 코드를 직접 실행하면 다항식을 찾을있으며, 더 많은 설명이 필요할 경우 아래에 주석을 달 수 있는 R-값을 찾을있습니다.

from scipy.stats import linregress
import numpy as np

x = np.array([1,2,3,4,5,6])
y = np.array([2,3,5,6,7,8])

p3 = np.polyfit(x,y,3) # 3rd degree polynomial, you can change it to any degree you want
xp = np.linspace(1,6,6)  # 6 means the length of the line
poly_arr = np.polyval(p3,xp)

poly_list = [round(num, 3) for num in list(poly_arr)]
slope, intercept, r_value, p_value, std_err = linregress(x, poly_list)
print(r_value**2)

scipy.stats.lin회귀 소스에서.평균 제곱합 방법을 사용합니다.

import numpy as np

x = np.array(x)
y = np.array(y)

# average sum of squares:
ssxm, ssxym, ssyxm, ssym = np.cov(x, y, bias=1).flat

r_num = ssxym
r_den = np.sqrt(ssxm * ssym)
r = r_num / r_den

if r_den == 0.0:
    r = 0.0
else:
    r = r_num / r_den

    if r > 1.0:
        r = 1.0
    elif r < -1.0:
        r = -1.0

언급URL : https://stackoverflow.com/questions/893657/how-do-i-calculate-r-squared-using-python-and-numpy

반응형