122

PythonとNumpyを使用して、任意の次数の最適な多項式を計算しています。x値、y値、および適合させたい多項式の次数(線形、2次など)のリストを渡します。

これは大いに機能しますが、r(相関係数)とr-squared(決定係数)も計算したいと思います。結果をExcelの最適な近似曲線機能、およびそれが計算する決定係数値と比較しています。これを使用して、線形最適化(次数は1)の決定係数を正しく計算していることがわかります。ただし、私の関数は、次数が1より大きい多項式では機能しません。

Excelはこれを行うことができます。Numpyを使用して高次多項式の決定係数を計算するにはどうすればよいですか?

これが私の関数です:

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
4

12 に答える 12

163

非常に遅い返信ですが、誰かがこれのための準備ができた機能を必要とする場合に備えて:

scipy.stats.linregress

すなわち

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

@AdamMarplesの答えのように。

于 2009-10-04T21:15:51.133 に答える
75

numpy.polyfitのドキュメントから、線形回帰に適合しています。具体的には、次数'd'のnumpy.polyfitは、平均関数を使用した線形回帰に適合します。

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

したがって、その適合の決定係数を計算する必要があります。線形回帰に関するウィキペディアのページに詳細が記載されています。あなたはいくつかの方法で計算できる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の平均に「y_bar」を使用し、各ポイントの適合値に「y_ihat」を使用します。

私はnumpy(私は通常Rで作業します)にあまり精通していないので、おそらくR-squaredを計算するためのより良い方法がありますが、以下は正しいはずです

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
于 2009-05-21T20:48:35.393 に答える
69

From yanl(yet-another-library)sklearn.metricsにはr2_score機能があります。

from sklearn.metrics import r2_score

coefficient_of_dermination = r2_score(y, p(x))
于 2015-06-12T13:41:03.323 に答える
29

私はこれをうまく使っています。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
于 2012-12-17T16:37:46.943 に答える
25

numpy.corrcoef私は元々 、元の質問がすでに使用されていることに気づかずcorrcoef、実際には高階多項式の適合について質問していたことを推奨する目的で、以下のベンチマークを投稿しました。statsmodelsを使用して、多項式のr-squared質問に実際のソリューションを追加しました。元のベンチマークは残しました。これは、トピックから外れていますが、誰かに役立つ可能性があります。


statsmodelsr^2多項式フィットのを直接計算する機能があります。ここに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/IPythonノートブックでリッチHTMLテーブルとして印刷または表示できるフィットモデルの概要も確認する必要があります。結果オブジェクトは、に加えて多くの有用な統計メトリックへのアクセスを提供しますrsquared

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

以下は、さまざまな線形回帰r^2メソッドのベンチマークを行った元の回答です...

質問で使用されるcorrcoef関数は、単一の線形回帰に対してのみ相関係数を計算するため、高階多項式近似rの問題には対応していません。r^2ただし、その価値については、線形回帰の場合、実際に最も速く、最も直接的な計算方法であることがわかりましたr

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

これらは、1000個のランダム(x、y)ポイントの一連のメソッドを比較した結果です。

  • 純粋なPython(直接r計算)
    • 1000ループ、ベスト3:ループあたり1.59ミリ秒
  • Numpy polyfit(n次多項式近似に適用可能)
    • 1000ループ、ベスト3:ループあたり326 µs
  • Numpyマニュアル(直接r計算)
    • 10000ループ、ベスト3:ループあたり62.1 µs
  • Numpy corrcoef(直接r計算)
    • 10000ループ、ベスト3:ループあたり56.6 µs
  • Scipy(r出力としての線形回帰)
    • 1000ループ、ベスト3:ループあたり676 µs
  • Statsmodels(n次多項式および他の多くの近似を実行できます)
    • 1000ループ、ベスト3:ループあたり422 µs

corrcoefメソッドは、numpyメソッドを使用して「手動で」r^2を計算するよりもわずかに優れています。polyfitメソッドよりも5倍以上速く、scipy.linregressよりも12倍速くなります。numpyがあなたのために何をしているかを補強するために、それは純粋なpythonより28倍高速です。私はnumbaやpypyのようなものに精通していないので、他の誰かがそれらのギャップを埋める必要がありますが、これは単純な線形回帰corrcoefを計算するための最良のツールであると私には十分に説得力があると思います。r

これが私のベンチマークコードです。Jupyter Notebookからコピーして貼り付けたので(IPython Notebookとは呼ばないでください...)、途中で何かが壊れた場合はお詫びします。%timeitmagicコマンドには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ベンチマーク結果。(Python 3.7、numpy 1.19、scipy 1.6、statsmodels 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)
于 2016-01-05T17:21:45.813 に答える
8

PythonとNumpyを使用して重み付き決定係数を計算する関数を次に示します(ほとんどのコードは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

これはミラー)に対応します:

ここに画像の説明を入力してください

f_iは近似からの予測値であり、y_{av}は観測データの平均です。y_iは観測データ値です。w_iは、各データポイントに適用される重みであり、通常はw_i=1です。SSEは誤差による二乗和であり、SSTは二乗和の合計です。


興味がある場合は、Rのコード:https ://gist.github.com/dhimmel/588d64a73fa4fef02c8f (ミラー

于 2017-08-07T00:55:37.317 に答える
5

決定係数は、線形回帰にのみ適用される統計です。

基本的に、線形回帰によってデータの変動をどの程度説明できるかを測定します。

したがって、「総平方和」を計算します。これは、各結果変数の平均からの偏差の合計です。。。

式1

ここで、y_barはyの平均です。

次に、「回帰二乗和」を計算します。これは、FITTED値が平均値とどの程度異なるかを示します。

フォーミュラ2

そしてそれら2つの比率を見つけます。

さて、多項式フィットのためにあなたがしなければならないのは、そのモデルからのy_hatをプラグインすることだけですが、そのr-squaredを呼び出すのは正確ではありません。

これが私が見つけたリンクで、少しそれを物語っています。

于 2009-05-21T16:54:49.733 に答える
5

r-squaredsに関するウィキペディアの記事は、線形回帰だけでなく、一般的なモデルのフィッティングに使用できることを示唆しています。

于 2009-08-25T06:06:24.767 に答える
4

yとy_hatがパンダシリーズであると仮定して、実際の値と予測値からR^2を計算する非常に単純なPython関数を次に示します。

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)
于 2020-05-01T18:48:17.113 に答える
2

このコードを直接実行できます。これにより、多項式が検出され、さらに説明が必要な場合は、下にコメントを付けることができる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)
于 2020-07-01T13:38:34.167 に答える
1

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²はピアソン係数の2乗です

公式にr²として統合されたR²は、最小二乗近似であるため、おそらく必要なものです。これは、r²の単純な合計の割合よりも優れています。Numpyは、それを「corrcoef」と呼ぶことを恐れていません。これは、ピアソンが事実上の相関係数であることを前提としています。

于 2021-08-21T23:50:32.107 に答える
0

scipy.stats.linregressソースから。彼らは二乗和の平均法を使用しています。

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
于 2019-11-16T00:43:40.177 に答える