Линейная регрессия, форсирующая одно заданное значение c - PullRequest
0 голосов
/ 05 марта 2020

Я хочу вычислить простую линейную регрессию, где мне нужно принудительно установить конкретное значение для одной точки. А именно, у меня есть массивы x и y, и я хочу, чтобы моя регрессия f(x) вызвала f(x[-1]) == y[-1] - то есть прогноз по последнему элементу x должен быть равен последнему элементу y.

Есть ли способ сделать это, используя Python и scikit-learn?

Ответы [ 3 ]

2 голосов
/ 06 марта 2020

Вот немного обходной трюк, который сделает это.

Попробуйте перецентрировать ваши данные, т.е. вычтите x [-1], y [-1] из всех точек данных так, чтобы x [-1], y [-1] теперь является источником.

Теперь подгоните ваши данные, используя sklearn.linear_model.LinearRegression с fit_intercept, установленным в False. Таким образом, данные подгоняются так, что линия вынуждена проходить через начало координат. Поскольку мы перецентрировали данные, источник соответствует x [-1], y [-1].

Когда вы используете модель для прогнозирования, вычтите x [-1] из любой точки данных для которого вы делаете прогноз, затем добавьте y [-1] к результирующему прогнозу, и это даст вам те же результаты, что и принуждение вашей модели пройти через x [-1], y [-1].

Это немного обходной путь, но мне проще всего сделать это, используя функцию линейной регрессии sklearn (без написания своей собственной).

1 голос
/ 06 марта 2020

Предложение от HappyDog отлично подходит для быстрого подбора, однако я хотел бы представить другой метод, который не требует каких-либо манипуляций с вашими данными. Метод будет использовать метод scipy.optimize.curve_fit, чтобы соответствовать вашим данным.

Во-первых, нам нужно понять, что нормальная линейная регрессия найдет A и B такие, что y = Ax + B обеспечивает наилучшее соответствие входным данным. В ваших требованиях указано, что подгонка должна проходить через конечную точку в вашем наборе данных. По сути, мы будем отбрасывать линию, которая проходит через вашу конечную точку, и вращать ее вокруг этой точки, пока мы не сможем минимизировать ошибки.

Посмотрите на уравнение точки-наклона для линии: y-yi = m*(x-xi) где (xi, yi) - любая точка на этой линии. Если мы сделаем подстановку, что эта точка (xi, yi) является конечной точкой из вашего набора данных и решим для y, мы получим y=m*(x-xf)+yf. Эта модель нам подойдет.

Перевод этой модели в python -функцию, мы имеем:

def model(x, m, xf, yf):
  return m*(x-xf)+yf

Мы создаем набор фиктивных данных для этого примера и просто для В демонстрационных целях мы значительно сместим окончательное значение y:

x = np.linspace(0, 10, 100)
y = x + np.random.uniform(0, 3, len(x))
y[-1] += 10

Мы почти готовы выполнить подгонку. Функция curve_fit ожидает вызова вызываемой функции (model), данных x и y и списка догадок каждого параметра, который мы пытаемся подогнать. Поскольку наш model принимает два дополнительных «постоянных» аргумента (xf и yf), мы используем functools.partial для «установки» этих аргументов на основе наших данных.

partial_model = functools.partial(model, xf=x[-1], yf=y[-1])
p0 = [y[-1]/x[-1]] # Initial guess for m, as long as xf != 0

Теперь мы можем fit!

best_fit, covar = curve_fit(partial_model, x, y, p0=p0)
print("Best fit:", best_fit)
y_fit = model(x, best_fit[0], x[-1], y[-1])
intercept = model(0, best_fit[0], x[-1], y[-1]) # The y-intercept

И мы посмотрим на результаты:

plt.plot(x, y, "g*") # Input data will be green stars
plt.plot(x, y_fit, "r-") # Fit will be a red line
plt.legend(["Sample Data", f"y=mx+b ; m={best_fit[0]:.4f}, b={intercept:.4f}"])
plt.show()

Объединение всего этого в один блок кода и включая импорт дает:

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
import functools

def model(x, m, xf, yf):
  return m*(x-xf)+yf

x = np.linspace(0, 10, 100)
y = x + np.random.uniform(0, 3, len(x))
y[-1] += 10

partial_model = functools.partial(model, xf=x[-1], yf=y[-1])
p0 = [y[-1]/x[-1]] # Initial guess for m, as long as xf != 0

best_fit, covar = curve_fit(partial_model, x, y, p0=p0)
print("Best fit:", best_fit)
y_fit = model(x, best_fit[0], x[-1], y[-1])
intercept = model(0, best_fit[0], x[-1], y[-1]) # The y-intercept

plt.plot(x, y, "g*") # Input data will be green stars
plt.plot(x, y_fit, "r-") # Fit will be a red line
plt.legend(["Sample Data", f"y=mx+b ; m={best_fit[0]:.4f}, b={intercept:.4f}"])
plt.show()

bestfit

Мы видим линию, проходящую через конечную точку, как требуется, и нашли наилучший уклон для представления этого набора данных.

0 голосов
/ 05 марта 2020

Зачем вам нужна регрессия, если y [n] = x [n-1]? Вы можете просто выполнить «лаг» для массива. Если вы хотите использовать «белый шум» в регрессии, то вы можете использовать модель линейной регрессии Y = X + white noise, я использовал https://www.statsmodels.org/stable/index.html для простых вещей.

...