Линейная регрессия с принудительным пересечением нуля

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

#Estimate coefficients of linear equation y = a + b*x
    def calc_coefficients(_x, _y):
        x, y = np.mean(_x), np.mean(_y)
        xy = np.mean(_x*_y)
        x2, y2 = np.mean(_x**2), np.mean(_y**2)
        n = len(_x)

        b = (xy - x*y) / (x2 - x**2)
        a = y - b*x
        sig_b = np.sqrt((y2-y**2)/(x2-x**2)-b**2) / np.sqrt(n)
        sig_a = sig_b * np.sqrt(x2 - x**2)

        return a, b, sig_a, sig_b

пример данных:

_x= [(0.009412743,0.014965211,0.013263312,0.013529132,0.009989368,0.013932615,0.020849682,0.010953529,0.003608903,0.007220992,0.012750529,0.021608436,0.031742052,0.022482958,0.021137599,0.018703295,0.021633681,0.019866029,0.020260629,0.034433715,0.009241074,0.012027059)]

_y = 0.294158677,0.359935335,0.313484808,0.301917271,0.169190763,0.486254864,0.305846328,0.347077387,0.188928817,0.422194367,0.41157232,0.39281496,0.497935681,0.34763333,0.281712023,0.352045535,0.339958296,0.395932086,0.359905526,0.450004349,0.395200865,0.365162443)]

Однако мне нужно, чтобы a (y-точка пересечения) был равен нулю. (y = bx). Я пробовал использовать:

np.linalg.lstsq(_x, _y)

но я получаю эту ошибку:

LinAlgError: 1-dimensional array given. Array must be two-dimensional

Как лучше всего подобрать данные для y = bx?


person warrenfitzhenry    schedule 01.01.2018    source источник


Ответы (1)


Ошибка возникает из-за того, что вы передаете одномерный массив, который должен был быть двумерным массивом формы (n, 1) - то есть, матрица с 1 столбцом. Вы можете просто сделать x.reshape(-1, 1), но вот способ подгонки методом наименьших квадратов с произвольным набором степеней x:

import numpy as np
x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([3, 6, 5, 7, 9, 1])
degrees = [1]       # list of degrees of x to use
matrix = np.stack([x**d for d in degrees], axis=-1)   # stack them like columns
coeff = np.linalg.lstsq(matrix, y)[0]    # lstsq returns some additional info we ignore
print("Coefficients", coeff)
fit = np.dot(matrix, coeff)
print("Fitted curve/line", fit)

Матрица, которую вы передаете lstsq, должна иметь столбцы формы f (x), где f пробегает термины, которые вы разрешаете в модели. Итак, если это общая линейная модель, у вас будут x**0 и x**1. С принудительным нулевым перехватом это просто x**1. В общем, это также не обязательно должно быть степенью x.

Вывод для градусов = [1], модель y = bx

Coefficients [ 1.41818182]
Fitted curve/line [ 0.          1.41818182  2.83636364  4.25454545  5.67272727  7.09090909]

Вывод для градусов = [0, 1], модель y = a + bx

Coefficients [ 5.0952381   0.02857143]
Fitted curve/line [ 5.0952381   5.12380952  5.15238095  5.18095238  5.20952381  5.23809524]
person Community    schedule 01.01.2018