Как заставить нулевой перехват в линейной регрессии? - PullRequest
18 голосов
/ 03 апреля 2012

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

У меня есть еще илименее линейные данные вида

x = [0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 20.0, 40.0, 60.0, 80.0]
y = [0.50505332505407008, 1.1207373784533172, 2.1981844719020001, 3.1746209003398689, 4.2905482471260044, 6.2816226678076958, 11.073788414382639, 23.248479770546009, 32.120462301367183, 44.036117671229206, 54.009003143831116, 102.7077685684846, 185.72880217806673, 256.12183145545811, 301.97120103079675]

Я использую scipy.optimize.leastsq, чтобы подогнать линейную регрессию к этому:

def lin_fit(x, y):
    '''Fits a linear fit of the form mx+b to the data'''
    fitfunc = lambda params, x: params[0] * x + params[1]    #create fitting function of form mx+b
    errfunc = lambda p, x, y: fitfunc(p, x) - y              #create error function for least squares fit

    init_a = 0.5                            #find initial value for a (gradient)
    init_b = min(y)                         #find initial value for b (y axis intersection)
    init_p = numpy.array((init_a, init_b))  #bundle initial values in initial parameters

    #calculate best fitting parameters (i.e. m and b) using the error function
    p1, success = scipy.optimize.leastsq(errfunc, init_p.copy(), args = (x, y))
    f = fitfunc(p1, x)          #create a fit with those parameters
    return p1, f    

И это прекрасно работает (хотя я не уверен, что scipy.optimize - правильная вещь для использования здесь, это может быть немного чрезмерно?).

Однако из-за того, что точки данных лежат, это не дает мне перехват оси Y в 0. Я знаю, однако, что в этом случае он должен быть нулем, if x = 0 than y = 0.

Есть ли способ, которым я могу это заставить?

Ответы [ 2 ]

31 голосов
/ 03 апреля 2012

Как уже упоминалось @AbhranilDas, просто используйте линейный метод.Нет необходимости в нелинейном решателе, таком как scipy.optimize.lstsq.

Как правило, вы бы использовали numpy.polyfit для подгонки строки к вашим данным, но в этом случае вам нужно будет использовать numpy.linalg.lstsq напрямую, так как вы хотите установить перехват на ноль.

В качестве быстрого примера:

import numpy as np
import matplotlib.pyplot as plt

x = np.array([0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 
              20.0, 40.0, 60.0, 80.0])

y = np.array([0.50505332505407008, 1.1207373784533172, 2.1981844719020001,
              3.1746209003398689, 4.2905482471260044, 6.2816226678076958,
              11.073788414382639, 23.248479770546009, 32.120462301367183, 
              44.036117671229206, 54.009003143831116, 102.7077685684846, 
              185.72880217806673, 256.12183145545811, 301.97120103079675])

# Our model is y = a * x, so things are quite simple, in this case...
# x needs to be a column vector instead of a 1D vector for this, however.
x = x[:,np.newaxis]
a, _, _, _ = np.linalg.lstsq(x, y)

plt.plot(x, y, 'bo')
plt.plot(x, a*x, 'r-')
plt.show()

enter image description here

9 голосов
/ 03 апреля 2012

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

fitfunc = lambda params, x: params[0] * x + params[1]  

на:

fitfunc = lambda params, x: params[0] * x 

Также удалите строку:

init_b = min(y) 

И измените следующую строку на:

init_p = numpy.array((init_a))

Это должно избавить от второго параметра, который производит y-перехват, и пропустить подогнанную линию через начало координат.Возможно, вам придется сделать еще пару мелких изменений в остальной части кода.

Но да, я не уверен, сработает ли этот модуль, если вы просто выделите второй параметр вот так.Это зависит от внутренней работы модуля относительно того, может ли он принять эту модификацию.Например, я не знаю, где params, список параметров, инициализируется, поэтому я не знаю, изменит ли это только его длину.

И, как в сторону, так как выупомянутое, это, на самом деле, я думаю, что это какой-то излишний способ оптимизировать просто уклон.Вы могли бы немного прочитать линейную регрессию и написать небольшой код, чтобы сделать это самостоятельно после некоторого подсчета конвертов.Это довольно просто и понятно.На самом деле, я только что сделал некоторые вычисления, и я предполагаю, что оптимизированный наклон будет просто <xy>/<x^2>, то есть среднее значение x * y продуктов, деленное на среднее значение x ^ 2.

...