Как вычислять R2 и R2, скорректированные с помощью poly_fit numpy, pandas [duplicate]

Я знаю, что эта ветка довольно старая, и ftp не так популярен, как когда-то, но в любом случае, если это помогает кому-либо, я бы хотел внести дополнительный вклад. Я столкнулся с аналогичной ситуацией, пытаясь подключиться к ftp-серверу с помощью IMPLICIT (Port 990) ftps в режиме PASSIVE. В этой ситуации сервер, после согласования начального соединения, обычно предоставляет новый IP-адрес и порт хоста, которые, скорее всего, отличаются от тех, которые были использованы для первоначального подключения, по которому предполагается фактическая передача данных. Без особых проблем клиенты ftps, включая python, могут справиться с этим, только этот конкретный сервер предоставляет немаршрутизируемый (вероятно, внутренний для брандмауэра) IP-адрес. Я заметил, что FileZilla не связан никакой проблемой, но python ftplib не смог. Затем я столкнулся с этим потоком:

Как заменить немаршрутизируемый IP-адрес адресом сервера на ftplib

, который помог мне войти. Использование методологии Гжегожа Вержовецкого Я расширил метод, упомянутый в этом потоке, и придумал это, что решило мою проблему.

import ftplib, os, sys
import socket
import ssl
FTPS_OBJ = ftplib.FTP_TLS



def conn_i_ftps(FTP_Site, Login_Name, Login_Password):
    print "Starting IMPLICIT ftp_tls..."
    ftps = tyFTP()
    print ftps.connect(host=FTP_Site, port=990, timeout=120)
    ftps.prot_p()
    ftps.login(user=Login_Name, passwd=Login_Password)
    print "Logged In"
    ftps.retrlines('LIST')
    # return ftps


class tyFTP(FTPS_OBJ):
    def __init__(self, host='', user='', passwd='', acct='', keyfile=None, certfile=None, timeout=60):
        FTPS_OBJ.__init__(self, host, user, passwd, acct, keyfile, certfile, timeout)

    def connect(self, host='', port=0, timeout=-999):
        if host != '':
            self.host = host
        if port > 0:
            self.port = port
        if timeout != -999:
            self.timeout = timeout

        try:
            self.sock = socket.create_connection((self.host, self.port), self.timeout)
            self.af = self.sock.family
            self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile)
            self.file = self.sock.makefile('rb')
            self.welcome = self.getresp()
        except Exception as e:
            print e
        return self.welcome

    def makepasv(self):
        print port #<---Show passively assigned port
        print host #<---Show the non-routable, passively assigned IP
        host, port = FTPS_OBJ.makepasv(self)
        host = socket.gethostbyname(self.host) #<---- This changes the host back to the original IP that was used for the connection
        print 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
        print host #<----Showing the original IP
        return host, port

Затем код вызывается так

FTP_Site       =  "ftp.someserver.com"
Login_Name     =  "some_name"
Login_Password =  "some_passwd"

conn_i_ftps(FTP_Site, Login_Name, Login_Password)

Я полагаю, что один может обернуть строки, в которых хост будет изменен с помощью оператора IF, идентифицирующего немаршрутизируемые адреса, например:

if host.split(".")[0] in (10, 192, 172):
     host = socket.gethostbyname(self.host)
     .
     .
     .

65
задан Travis Beale 22 May 2009 в 18:40
поделиться

8 ответов

Из документации numpy.polyfit соответствует линейная регрессия. В частности, numpy.polyfit со степенью «d» соответствует линейной регрессии со средней функцией

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

Так что вам просто нужно вычислить R-квадрат для этой подгонки. Страница wikipedia на линейной регрессии дает полную информацию. Вас интересует R ^ 2, который вы можете рассчитать несколькими способами: easisest, вероятно, являющийся

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
47
ответ дан holocronweaver 19 August 2018 в 05:21
поделиться
  • 1
    Я просто хочу указать, что использование функций массива numpy вместо понимания списка будет намного быстрее, например. numpy.sum ((yi - ybar) ** 2) и легче читать – Josef 18 October 2010 в 04:31
  • 2
    Согласно wiki-странице ru.wikipedia.org/wiki/Coefficient_of_determination , наиболее общим определением R ^ 2 является R^2 = 1 - SS_err/SS_tot, причем R^2 = SS_reg/SS_tot является лишь частным случаем. – LWZ 29 April 2013 в 01:03

Я использовал это успешно, где 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
16
ответ дан Adam Marples 19 August 2018 в 05:21
поделиться

Статья в wikipedia в r-squareds предполагает, что она может использоваться для подгонки общей модели, а не только для линейной регрессии.

4
ответ дан Andrew Dalke 19 August 2018 в 05:21
поделиться

R-squared - статистика, которая применяется только к линейной регрессии.

По существу, она измеряет, насколько вариации в ваших данных могут быть объяснены линейной регрессией.

Итак, вы вычисляете «Суммарную сумму квадратов», которая представляет собой полное квадратное отклонение каждой из ваших переменных результата от их среднего значения. , .

\ sum_ {i} (y_ {i} - y_bar) ^ 2

, где y_bar - среднее значение y.

Затем вы вычисляете «сумму регрессионных квадратов», которая зависит от того, насколько ваши значения FITTED отличаются от среднего

\ sum_ {i} (yHat_ {i} - y_bar) ^ 2

и найти соотношение этих двух.

Теперь все, что вам нужно сделать для полиномиального соответствия, - это подключить y_hat от этой модели, но неточно назвать это r-квадрат.

Здесь - ссылка, которую я нашел, что говорит с ней немного.

4
ответ дан Baltimark 19 August 2018 в 05:21
поделиться
  • 1
    Это, кажется, корень моей проблемы. Как Excel получает другое значение r-квадрата для полиномиального соответствия по сравнению с линейной регрессией? – Travis Beale 21 May 2009 в 17:59
  • 2
    вы просто даете excel припадки от линейной регрессии и подходят от полиномиальной модели? Он собирается рассчитать rsq из двух массивов данных и просто предположим, что вы даете ему соответствие от линейной модели. Что вы даете превосходству? Что такое команда «наилучшая подходящая трендовая линия» в excel? – Baltimark 21 May 2009 в 18:45
  • 3
    Это часть графических функций Excel. Вы можете распечатать некоторые данные, щелкнуть правой кнопкой мыши по нему, а затем выбрать один из нескольких типов линий тренда. Существует возможность видеть уравнение линии, а также значение r-квадрата для каждого типа. Значение r-квадрата также различно для каждого типа. – Travis Beale 21 May 2009 в 21:19
  • 4
    @Travis Beale - вы собираетесь получить разное r-квадрат для каждой другой средней функции, которую вы пытаетесь (если две модели не вложены, а дополнительные коэффициенты в более крупной модели все будут 0). Поэтому, конечно, Excel дает разные значения r-квадратов. @Baltimark - это линейная регрессия, поэтому она r-квадрат. – leif 21 May 2009 в 21:20

Из yaml (еще-другая-библиотека) sklearn.metrics имеет функцию r2_square ,

from sklearn.metrics import r2_score

coefficient_of_dermination = r2_score(y, p(x))
28
ответ дан danodonovan 19 August 2018 в 05:21
поделиться
  • 1
    (Beware: «Значение по умолчанию соответствует« variance_weighted », это поведение устарело с версии 0.17 и будет изменено на« uniform_average », начиная с 0,19») – Franck Dernoncourt 4 August 2017 в 22:03
  • 2
    r2_score в sklearn может быть отрицательным значением, что не является нормальным случаем. – Qinqing Liu 21 November 2017 в 12:25

Я изначально разместил тесты ниже с целью рекомендовать numpy.corrcoef, по глупости не понимая, что исходный вопрос уже использует corrcoef и на самом деле спрашивает о том, что полином более высокого порядка подходит. Я добавил фактическое решение вопроса о квадратичном r-квадрате с использованием шаблонов statsmodels, и я оставил исходные тесты, которые, хотя и вне темы, потенциально полезны кому-то.


statsmodels имеет возможность правильно вычислить r^2 полиномиального соответствия, вот 2 метода ...

import statsmodels.api as sm
import stasmodels.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

Чтобы дополнительно воспользоваться statsmodels, следует также взглянуть на подгонку модели сводку, которую можно распечатать или отобразить в виде богатой таблицы HTML в ноутбуке Jupyter / IPython. Объект результатов обеспечивает доступ ко многим полезным статистическим метрикам в дополнение к 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) точек:

  • Pure Python (прямой расчет r) 1000 циклов, лучше всего 3: 1,59 мс за цикл
  • Numpy polyfit (применимо к полиномам n-й степени) 1000 циклов, лучше всего 3: 326 мкс на петлю
  • Руководство по вычислению чисел (прямой расчет r) 10000 циклов, лучше всего 3: 62,1 мкс на loop
  • вычисление Numpy corrcoef (прямой расчет r) 10000 циклов, лучше всего 3: 56,6 мкс за цикл
  • Scipy (линейная регрессия с r в качестве выхода) 1000 циклов, наилучшее из 3: 676 мкс за цикл
  • Statsmodels (может выполнять многочлен n-й степени и многие другие возможности) 1000 циклов, лучше всего 3: 422 мкс на петлю

Метод corrcoef узко бьет, вычисляя r ^ 2 «вручную», используя numpy методы. Это> 5X быстрее, чем метод polyfit и ~ 12X быстрее, чем scipy.linregress. Чтобы укрепить то, что делает numpy для вас, это на 28 раз быстрее, чем чистый python. Я не разбираюсь в таких вещах, как numba и pypy, поэтому кому-то придется заполнить эти пробелы, но я думаю, что для меня это довольно убедительно, что corrcoef - лучший инструмент для вычисления r для простой линейной регрессия.

Вот мой бенчмаркинг. Я скопировал из Jupyter Notebook (трудно не называть его IPython Notebook ...), поэтому я приношу свои извинения, если что-то сломается. Для команды% 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)
    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)
11
ответ дан flutefreak7 19 August 2018 в 05:21
поделиться
  • 1
    Вы сравниваете 3 метода с установкой наклона и регрессии с помощью 3 методов без подгонки склона. – Josef 5 January 2016 в 19:37
  • 2
    Да, я так много знал ... но теперь я чувствую себя глупо, что не читаю оригинальный вопрос и вижу, что он уже использует corrcoef и конкретно обращается к r ^ 2 для полиномов более высокого порядка ... теперь я чувствую себя глупо для публикации моих тестов, которые были для другой цели. К сожалению ... – flutefreak7 5 January 2016 в 19:44
  • 3
    Я обновил свой ответ с помощью решения исходного вопроса, используя statsmodels, и извинился за ненужный бенчмаркинг методов линейной регрессии r ^ 2, который я сохранил как интересную, но не относящуюся к теме информацию. – flutefreak7 5 January 2016 в 21:32
  • 4
    Я все еще считаю интересным, потому что я не ожидал, что scipy linregress будет медленнее, чем statsmodels, который выполняет более общую работу. – Josef 5 January 2016 в 22:50
  • 5
    Обратите внимание, что np.column_stack([x**i for i in range(k+1)]) может быть векторизован в numpy с помощью x[:,None]**np.arange(k+1) или с помощью функций vander numpy, которые имеют обратный порядок в столбцах. – Josef 5 January 2016 в 22:51

Вот функция для вычисления взвешенных r-квадратов с 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

Это соответствует формуле ( mirror ):

с f_i - это предсказанное значение из подгонки, y_ {av} - среднее значение наблюдаемых данных y_i - наблюдаемое значение данных. w_i - это взвешивание, применяемое к каждой точке данных, обычно w_i = 1. SSE - сумма квадратов из-за ошибки, а SST - общая сумма квадратов.


Если интересно, код в R: https://gist.github.com/dhimmel / 588d64a73fa4fef02c8f ( mirror )

3
ответ дан Franck Dernoncourt 19 August 2018 в 05:21
поделиться

Очень поздний ответ, но на всякий случай кому-то нужна эта функция:

scipy.stats.stats.linregress

, т. е.

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

, как в ответе @Adam Marples.

92
ответ дан PetaPetaPeta 19 August 2018 в 05:21
поделиться
  • 1
    Разумно проанализировать с помощью коэффициент корреляции , а затем выполнить большую работу, регрессия . – 象嘉道 17 January 2012 в 20:59
  • 2
    Этот ответ работает только для линейной регрессии, которая является простейшей полиномиальной регрессией – tashuhka 4 August 2015 в 09:49
Другие вопросы по тегам:

Похожие вопросы: