Регрессионная модель

  • Прямолинейный прогноз фондового рынка: линейная регрессия
  • Линейная регрессия: использование Statsmodels
  • Модель авторегрессии (AR): метод эффективного анализа временных рядов
  • Динамическая регрессионная модель с переключением Маркова

Прямолинейный прогноз фондового рынка: линейная регрессия

Не все линии равны

Один мудрый технический аналитик как-то сказал мне, что вы хороши настолько, насколько хороши линии, которые вы рисуете на графике. Когда я загрузил TradeStation в начале 2000-х годов, я был новорожденным детенышем оленя, пытающимся ходить. Я вышел на поле боя воином. Я подготовился с самыми важными книгами. Я прочитал энциклопедию японских свечей, The Zen Trader и книгу об основных технических индикаторах. Взволнованный, увидев свой первый график, я вытащил столько, сколько смог. Они были украшены с ног до головы в цветах. Я даже обманывал себя, думая, что знаю, что делаю. Хуже всего то, что… Я умел рисковать, но не мог на это справиться. Поэтому, как и многие торговые истории, я начал получать крупные выигрыши. Удачу ошибочно принимали за мастерство. Грехопадение было неизбежным. Настал день, когда рынок поставил меня на место. Из мечтаний о своем будущем Ferrari я превратился в крестьянина. Я знал, что пришло время поднять себя с пола после ночи, проведенной за прослушиванием Nickelback. Новый минимум. Оценив ситуацию, я поняла, что линии на моей диаграмме ничем не лучше тех, которые рисует малыш. Именно здесь я понял, что мои реплики должны что-то значить. Как и многие до меня и многие после меня, я вошел в линейную регрессию.

Это линейно так просто

Я часто натыкаюсь на статьи, объясняющие математику, но не реализующие эти инструменты с нуля. Я считаю, что, когда вы идете по пути машинного обучения, важно уметь создавать то, что вы реализуете. Несмотря на то, что существуют отличные пакеты, которые вы, безусловно, должны использовать, важно понимать, что происходит под капотом. Здесь часто будут писать о машинном обучении, и моя цель будет состоять в том, чтобы показать, как его построить самостоятельно. Если вы предпочитаете смотреть его, заходите на наш YouTube. Линейная регрессия является отличной отправной точкой. Он знакомит со многими повторяющимися темами, оставаясь при этом довольно простым для понимания. Большинство людей знакомы со многими математическими операциями, которые будут показаны. Если нет, то это все равно удивительная отправная точка. Не совершайте тех же ошибок, что и я. Выучите правильные линии.

Что нам нужно знать, прежде чем начать?

Мы будем строить класс линейной регрессии с нуля. Это позволит обрабатывать как простую линейную регрессию, так и множественную линейную регрессию. Математика будет представлена в следующем разделе. А пока поймите, что первый соответствует строке, а второй — гиперплоскости данных. По сути, можно обрабатывать несколько входных объектов и не ограничиваться 2D-плоскостью. Есть несколько ключевых требований, которые мы хотели бы изучить при использовании модели линейной регрессии.

  1. Линейное допущение — Модель предполагает, что связь между переменными является линейной.
  2. Изменить масштаб входных данных — Мы хотим нормализовать или масштабировать наши входные данные. Это будет иметь больше смысла, когда вы видите модели, но если ввод объектов намного больше, чем другие, он может доминировать в модели. Это приводит к печальной линейной регрессии.
  3. Нет коллинеарности — Мы бы хотели, чтобы входные данные не были сильно коррелированы. Если наши черты слишком коррелируют друг с другом, то он будет пересоответствовать. Входные данные будут предоставлять избыточную информацию.
  4. Noise Removed — Модель будет предполагать, что входные и выходные переменные не зашумлены, поэтому мы должны удалить выбросы, если это возможно.
  5. Нормальное распределение — Модель будет делать более точные прогнозы, если у нас есть нормально распределенные входные и выходные данные. Мы бы хотели, чтобы данные были как можно более нормальными.

После того, как мы осознаем вышеуказанные требования, пришло время приступить к их выполнению! Мы должны обучить нашу модель, то есть найти наилучшие коэффициенты для линейной формулы. Мы можем сделать это с помощью градиентного спуска. Мы углубимся в эту тему после того, как представим всю интересную математику, стоящую за этим. Если вы еще не знаете, мы собираемся получить больше удовольствия, чем когда 50 и 200 скользящих средних соприкасаются с кончиками… Я имею в виду кроссовер.

Сложна ли математика?

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

Простая и множественная линейная регрессия

Первое уравнение представляет собой простую линейную регрессию, которая очень незначительно отличается от множественной линейной регрессии. Вы, вероятно, видели это в учебнике математики еще в средней школе. Y = mx + b было движением в те времена. Оказывается, от этого может быть какая-то польза. Часто вы будете видеть значение Beta{0} как b, а значения Beta{i} как w. Бета{0} будет вашей предвзятостью, а другие бета-версии будут вашими весами. Это те части, для которых вы будете оптимизированы. Наши входные данные — это x с прогнозируемым значением yhat (ŷ). Простой способ превратить верхнюю формулу в множественную линейную регрессию — представить эти значения в виде матриц. Вы увидите, что это делается в коде, поэтому я не буду описывать их все как таковые. Как я уже говорил выше, нам нужно оптимизировать эти параметры. Для чего мы оптимизируем? Вот тут-то и приходит на помощь наша удобная функция стоимости денди. Наша цель будет состоять в том, чтобы свести к минимуму функцию затрат. Наиболее распространенным методом, который мы используем, является среднеквадратичная ошибка (MSE), и она имеет большой смысл.

Среднеквадратичная ошибка

Выше приведена формула среднеквадратичной ошибки. Заметьте, как мы можем поменять местами наш yhat сверху в формулу, если мы хотим ее расширить. Это средняя разница между фактическим значением и нашим прогнозируемым значением. Поэтому логично, что мы хотим свести это к минимуму! Если мы хотим свести к минимуму MSE, нам нужно найти весовые коэффициенты и смещения, которые дают нам наименьшее значение. Если вы знакомы с частичными деривативами, то следующая часть будет иметь большой смысл. Если нет, просто знайте, что он сообщает нам скорость изменения данной многомерной функции по отношению к одной выбранной переменной, в то время как все остальные переменные рассматриваются как постоянные.

Формулы частных производных

Итак, как вы можете видеть, мы берем частичное по отношению к весам и по отношению к смещению. Я заменил бета-версии для простоты. Как только мы достигнем этого, все, что нам нужно сделать, это то, что называется градиентным спуском. Здесь мы обновляем весовые коэффициенты и смещения предыдущих итераций, вычитая частную производную, умноженную на скорость обучения. Скорость обучения не должна быть слишком большой или маленькой. Если он слишком большой, он может перескочить через минимум, который мы ищем, а если он слишком маленький, это может занять много времени. Ни у кого нет на это времени. Когда вы соберете все вместе, у нас будут две формулы, которые выглядят следующим образом для наших обновлений.

Формула обновления

Как видите, у нас есть наши новые веса/смещения, равные их значению, вычитаемому на скорость обучения (альфа), умноженную на частичное. Теперь, когда все математические расчеты перечислены, вы готовы увидеть, как они реализованы в коде!

Готовим код в нашей мультиварке

Я начну с того, что выпишу функции одну за другой. Затем, в конце, я оставлю весь код помещенным в класс. После этого вы можете поиграть с ним и опробовать его на некоторых данных! Помните, что требования, перечисленные выше, важны. Если вы используете его на финансовых данных, будьте очень скептически настроены по отношению к своим результатам. Если это кажется слишком хорошим, чтобы быть правдой, то, скорее всего, так оно и есть! Итак, во-первых, в нашем классе линейной регрессии, я думаю, у нас должна быть функция, которая позволит нам отслеживать среднеквадратичную ошибку, если мы захотим. Это позволяет нам строить графики и отслеживать наши потери на протяжении нескольких итераций.import numpy as np

def mean_squared_error(y, y_hat):

return np.square(np.subtract(np.array(y), np.array(y_hat))).mean()

Приведенный выше код выполняет вычисление MSE с numpy. Это позволит нам поместить массив значений для y и yhat. Сначала он вычтет два вектора. Затем он возведет значения в квадрат и найдет среднее значение. Часто бывает полезно попытаться найти способы векторизации вычислений. Машинное обучение обрабатывает большой объем данных. Если набор данных, на котором вы обучаетесь, огромен, то такие мелочи ускорят процесс. Далее мы напишем функции для подгонки, обновления и прогнозирования модели.import numpy as np

class LinearRegression() :

def __init__(self, learning_rate, iterations):

self.lr = learning_rate
self.iterations = iterations

# Fit the Regression
def fit(self, X, Y):

# Rows and Columns
self.m, self.n = X.shape

# Initialize array of zeros size of X’s columns
self.W = np.zeros(self.n)
self.b = 0
self.X = X
self.Y = Y

# Learning through gradient descent
for i in range(self.iterations):

self.update()

return self

# Cleans up fit() by updating in seperate method
def update(self):

Y_pred = self.predict(self.X)

# Partial Derivatives (vectorized)

dW = -(2 * (self.X.T).dot(self.Y — Y_pred)) / self.m

db = -2 * np.sum(self.Y — Y_pred) / self.m

# update weights

self.W = self.W — self.lr * dW

self.b = self.b — self.lr * db

return self

# Model prediction with current weights and bias
def predict(self, X):

return X.dot(self.W) + self.b

Выше приведен полноценный класс, реализующий описанные нами функции. Мы инициализируем класс количеством итераций, которые мы хотели бы выполнить, и скоростью обучения. Затем мы подгоняем наш обучающий набор данных с помощью метода подгонки. Он будет проходить через каждую итерацию и обновлять веса и смещение. При этом вызывается метод update, который выполняет градиентный спуск. Наша функция predict — это просто наше простое предсказание. Вы заметите, что все делается с помощью матриц. Это ускоряет вычисления, поэтому при обучении на большом количестве данных это не займет у нас много времени. Я бы предпочел закончить быстро (лол). Приведенный выше код в буквальном смысле просто подключает математику. Мы постоянно получаем свой прогноз, а затем немного подстраиваем параметры с помощью градиентного спуска. Это продолжается до тех пор, пока итерации не закончатся. Тогда у нас будет оптимальная модель, которая сделает нас сладкими деньгами!

Заключение

Сегодня был важный день! Вы разобрались, какие линии правильные! Похлопайте себя по спине. Это большой шаг в правильном направлении. Хотя линейная регрессия не всегда является самым эффективным инструментом, она часто может быть довольно мощной в определенных ситуациях. Мы можем использовать его для решения широкого спектра задач, выходящих за рамки простого прогнозирования цены. Линейная регрессия является строительным блоком для многих более сложных моделей в будущем, а также отличным введением. Вы обнаружите, что он довольно мощный, когда вы мыслите нестандартно. Часто мы хотим знать, имеет ли что-то линейную зависимость, и это помогает нам в этом! С великим знанием приходит великая сила. Используйте то, чему научились, во благо! Я добавлю ссылку на наше видео о линейной регрессии на YouTube, если вы хотите увидеть код в действии! Я также поставлю MSE вместе с классом ниже.import numpy as np

class LinearRegression() :

def __init__(self, learning_rate, iterations):

self.lr = learning_rate
self.iterations = iterations
self.loss = []

@staticmethod
def mean_squared_error(y, y_hat):

return np.square(np.subtract(np.array(y), np.array(y_hat))).mean()

# Fit the Regression
def fit(self, X, Y):

# Rows and Columns
self.m, self.n = X.shape

# Initialize array of zeros size of X’s columns
self.W = np.zeros(self.n)
self.b = 0
self.X = X
self.Y = Y

# Learning through gradient descent
for i in range(self.iterations):

self.update()

return self

# Cleans up fit() by updating in seperate method
def update(self):

Y_pred = self.predict(self.X)

# Log to be able to view later
mse = self.mean_squared_error(self.Y, Y_pred)
loss.append(mse)

# Partial Derivatives (vectorized)

dW = -(2 * (self.X.T).dot(self.Y — Y_pred)) / self.m

db = -2 * np.sum(self.Y — Y_pred) / self.m

# update weights

self.W = self.W — self.lr * dW

self.b = self.b — self.lr * db

return self

# Model prediction with current weights and bias
def predict(self, X):

return X.dot(self.W) + self.b

Линейная регрессия: использование Statsmodels

Знакомство

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

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

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

Начнем с загрузки всех необходимых библиотек.# Basic libraries
import pandas as pd
import numpy as np

# Data Visualization
import plotly.express as px
import plotly.graph_objs as go
import plotly.subplots as sp
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import plotly.io as pio
from IPython.display import display
from plotly.offline import init_notebook_mode
init_notebook_mode(connected=True)

# Diabetes dataset
from sklearn.datasets import load_diabetes

# For splitting the dataset into training and testing sets
from sklearn.model_selection import train_test_split

# Metric for evaluation
from sklearn.metrics import mean_squared_error

# Statsmodels for Linear Regression
import statsmodels.api as sm

# Hiding warnings
import warnings
warnings.filterwarnings(«ignore»)

Что такое линейная регрессия?

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

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

Линия определяется следующим уравнением:

Где:

Y — зависимая переменная.

β₀ — это перехват.

β₁, β₂, β3₃, … – коэффициенты для каждой независимой переменной.

Х₁, Х₂, Х₃, … представляют каждую независимую переменную.

ε — это член ошибки, который фиксирует случайный шум в зависимой переменной. Это стохастическая составляющая.

В этом уравнении каждый компонент служит определенной цели. Intercept(β₀), например, является константным членом, представляющим значение Y (зависимая переменная), когда все независимые переменные XX₂, … равны нулю. Он определяет местоположение линии вверх или вниз по оси Y в декартовой системе координат, как вы можете видеть на изображении ниже.

Когда X = 0Y = β₀

В случае одной единственной независимой переменной точка пересечения вычисляется следующим образом:

Где:

Y̅ – среднее значение зависимой переменной Y.

 – среднее значение независимой переменной X.

Коэффициенты (β₁, β₂, β3₃, …) — значения, измеряющие величину влияния каждой независимой переменной на зависимую переменную. Например, изменение X₁ на одну единицу приведет к изменению Y на β₁, если все остальные X постоянны.

Уравнение для нахождения значения β₁ в простой модели линейной регрессии только с одной независимой переменной задается следующим образом:

Где:

Xi и Yi представляют собой i-ю выборку как X, так и Y.

 и  представляют собой средние значения как для X, так и для Y.

∑ⁿi ₌ ₁ представляет собой сумму, начиная с первого элемента ряда до n-го элемента ряда.

В этом уравнении коэффициент β₁ является результатом отношения ковариации между X и Y, представленного произведением отклонений между X и Y от их соответствующих средних, и дисперсии X, заданной суммой квадратов отклонений каждого X от его среднего. Влияние независимой переменной на зависимую переменную можно резюмировать следующим образом:

• β₁> 0: Y увеличивается по мере увеличения X.

• β₁ < 0: Y уменьшается при увеличении X.

• β₁ = 0: X не влияет на Y.

В случае линейной регрессии с несколькими независимыми переменными коэффициенты и точка пересечения получаются с помощью матричной алгебры:

Где:

β — вектор, содержащий пересечение и коэффициенты.

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

XT — транспонирование матрицы X.

(XTX)⁻¹ является величиной, обратной произведению матрицы X на ее транспонирование.

Y — вектор значений зависимой переменной.

Целью этой операции является получение оценок параметров в векторе β, которыми являются коэффициенты и точка пересечения.

Линейная регрессия с несколькими независимыми переменными может быть задана следующим уравнением:

На рисунке ниже можно правильно отобразить матричную форму приведенного выше уравнения.

Первый столбец матрицы X заполняется единицей для точки пересечения, которая представлена β1 в векторе β.

Чтобы продемонстрировать, как работает Линейная регрессия, давайте загрузим набор данных диабета и получим значения и Y.# Loading dataset
X, y = load_diabetes(return_X_y=True)# Creating a DataFrame for the Independent variables
X_df = pd.DataFrame(X, columns = [f’Feature_{i+1}’ for i in range(X.shape[1])])
X_df

Характеристики от 1 до 10 являются нашими независимыми переменными X₁, X₂, X₃, …, X₁.# Creating a DataFrame for the Dependent variable
y_df = pd.DataFrame(y, columns = [‘Target’])
y_df

Выше у нас есть зависимая переменная, также называемая целевой переменной.

Мы также можем комбинировать оба фрейма данных.# Concatenating both X and Y dataframes into one single dataframe
df = pd.concat([X_df, y_df], axis = 1)
df

Допущения для линейной регрессии

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

1. Между независимой переменной и зависимой переменной должна быть линейная зависимая зависимость.

2. Мультиколлинеарность в данных должна быть незначительной или отсутствовать. То есть независимые переменные не должны слишком сильно коррелировать друг с другом.

3. Наблюдения должны быть независимы друг от друга.

4. Остатки — ошибки между прогнозируемыми и истинными значениями — должны быть распределены нормально.

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

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

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

Мы можем начать с определения того, существует ли линейная зависимость между объектом 9 и целевой переменной, построив точечную диаграмму.

Мы можем четко определить положительную линейную зависимость между Feature_9 и целевой переменной, так как мы видим, что по мере увеличения значений по оси X значения по оси Y также увеличиваются.

Аналогичная линейная зависимость, хотя и отрицательная, наблюдается между Feature_7 и целевой переменной, где уменьшение оси Y приводит к увеличению оси X.

Мы также можем построить корреляционный график, содержащий значения Пирсона R между целевой переменной и независимыми переменными.

На графике значения будут находиться в диапазоне от -1 до 1, где -1 указывает на идеальную отрицательную связь, а 1 — на идеальную положительную связь. Значения, близкие к 0, указывают на отсутствие линейной зависимости.

Мы видим, что целевая переменная имеет самую сильную положительную линейную связь с Feature_3, самую сильную отрицательную линейную связь с Feature_7, и, возможно, нет никакой реальной связи между целевой переменной и Feature_2.

Мы также можем использовать корреляционные графики для проверки мультиколлинеарности, чтобы увидеть, существует ли какая-либо сильная корреляция между независимыми переменными.

Можно увидеть очень сильную корреляцию между Feature_6 и Feature_5. Давайте посмотрим, как они соотносятся друг с другом на точечной диаграмме.

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

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

Моделирование

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

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

Где:

Yi — истинное значение для Y в i-й выборке.

Ŷi — прогнозируемое значение для Y в i-й выборке.

RMSE — это просто квадратный корень из среднего квадрата разности между фактическим и прогнозируемым значениями. Она выражается в тех же единицах, что и целевая переменная, что делает ее очень интуитивно понятной. Чем ближе к 0, тем точнее прогнозы.

Чтобы начать процесс моделирования, мы еще раз разделим датафрейм на независимые переменные X и зависимую переменную Y.X = df.drop(‘Target’, axis = 1) # Selecting independent features
y = df.Target # Selecting target variable

Мы также должны разделить данные на обучающий и тестовый наборы для подгонки и оценки производительности модели.# Creating training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size = .3, # 30% of data for testing
shuffle = True, # Shuffling values
random_state = 42)

Мы также добавим константу к кадрам данных X. По сути, это первый столбец единиц, который мы видели ранее, используемый для пересечения, который является β в векторе β.# Adding a Constant term for the Intercept
X_train = sm.add_constant(X_train)
X_test = sm.add_constant(X_test)X_train # Visualizing X dataframe with the constant

Теперь мы можем подогнать модель под данные и сделать какие-то выводы, взглянув на сводку.# Fitting model
model = sm.OLS(y_train, X_train).fit()
print(model.summary(alpha = 0.05))

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

Вспомните уравнение линейной регрессии:

Intercept(β₀) равен 151.0082. Это означает, что прогнозируемое значение Y будет равно 151,0082, когда все остальные объекты равны 0.

Коэффициент β₁ представляет собой среднее изменение Y при изменении X₁ на одну единицу, что является Feature_1 переменной. В этом случае увеличение Feature_1 на одну единицу будет представлять собой увеличение прогнозируемого значения для примерно на 29,2540, когда все остальные признаки постоянны.

Мы также можем видеть отрицательные коэффициенты, что является случаем коэффициента Feature_5. Это говорит о том, что при увеличении этого признака на одну единицу мы можем ожидать уменьшения прогнозируемого значения Y примерно на 901,9597 до тех пор, пока все остальные признаки остаются постоянными.

У нас также есть в сводке стандартные ошибки std err values. При рассмотрении этой метрики мы хотим, чтобы значения были как можно ниже, что указывает на более надежную оценку значений коэффициентов. P>|t| говорит нам, является ли признак статистически значимым или нет. Мы хотим, чтобы эти значения были ниже 0,050,05, чтобы считать признак статистически значимым для прогнозирования результата Y.

Имея это в виду, мы можем заметитьчто наиболее надежными независимыми переменными были Feature_2Feature_3Feature_4 и Feature_9.

У нас также есть другие важные показатели, на которые стоит обратить внимание. Метрика R-квадрат, равная 0,524, предполагает, что моя модель способна объяснить примерно 52,452,4% дисперсии целевой переменной.

Статистика Дурбина-Уотсона используется для обнаружения автокорреляции между остатками. Значения DW находятся в диапазоне от 0 до 4 и, как правило, значения от 1,5 до 2,5 позволяют предположить, что автокорреляции между остатками нет, и наши выборки независимы друг от друга. Учитывая, что наше значение DW равно 1,764, это соответствует одному из ключевых допущений линейной регрессии.

Другой важной метрикой является статистика Жака-Бера, которая говорит нам, нормально ли распределены остатки или нет. Как правило, если JB слишком далек от нуля, это указывает на то, что данные не распределены нормально. В этом случае JB, равное 1,417, говорит о том, что наши остатки могут быть нормально распределены. Значения эксцесса, близкие к 3,0, и Skew, близкие к 0, также являются важными метриками, позволяющими предположить, что наши остатки действительно распределены нормально. Это еще один положительный знак, когда речь идет о предположениях относительно моделей линейной регрессии.

Чтобы подтвердить, нормально ли распределены остатки или нет, мы можем использовать график гистограммы, чтобы визуализировать их распределение.

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

Другие метрики, такие как логарифмическое правдоподобиеAIC и BIC, актуальны только при сравнении двух разных моделей друг с другом. К ним мы еще вернемся.

Давайте пойдем дальше и спрогнозируем значения для нашей зависимой переменной Y в проверочном наборе.y_pred = model.predict(X_test) # Running predictions
rmse = mean_squared_error(y_test, y_pred,squared = False) # Computing RMSE

print(f’\nRoot Mean Squared Error for Baseline Model: {rmse:.2f}’)Root Mean Squared Error for Baseline Model: 53.12

RMSE показывает нам, что в среднем наша модель ошибается в значении Y на 53,12 единицы.

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

За основу можно взять первую модель, приведенную выше. Ниже мы можем попробовать изменить наши данные, чтобы увидеть, можем ли мы улучшить производительность.

Несмотря на тоFeature_2 было сочтено актуальным в резюме выше, я хочу проверить, насколько хорошо мы работаем без него. Я хочу удалить эту функцию из-за низкого значения R Пирсона, когда мы проверяли ее корреляцию с целевой переменной. Я также собираюсь удалить Feature_6 из-за его высокой корреляции с Feature_5 и более низкой корреляции с целевой переменной.# Selecting feature to remove
features_to_remove = [‘Feature_2’,
‘Feature_6’]

# Removing them
new_X_train = X_train.drop(features_to_remove, axis =1)
new_X_test = X_test.drop(features_to_remove, axis =1)

# Fitting model
model = sm.OLS(y_train, new_X_train).fit()
print(model.summary())

Начнем с того, что R-Squared, равный 0,502, ниже предыдущего. Это может указывать на то, что эта модель способна объяснить меньший процент дисперсии по Y, чем предыдущая модель.

Мы также можем использовать метрики Log-LikelihoodAIC и BIC для сравнения обеих моделей. В целом, логарифмическое правдоподобие, близкое к 0, и более низкие значения AIC и BIC, являются предпочтительными. При этом данная модель работает хуже предыдущей, хотя и не намного.

Значения эксцессаасимметрии и статистики Дурбина-Уотсона также помещают распределение невязок в этом случае немного дальше от нормального распределения по сравнению с предыдущей моделью.

Давайте сделаем прогноз на тестовой выборке, чтобы узнать, как работает эта модель.y_pred = model.predict(new_X_test)
rmse = mean_squared_error(y_test, y_pred,squared = False)

print(f’\nRoot Mean Squared Error for Baseline Model: {rmse:.2f}’)Root Mean Squared Error for Baseline Model: 53.64

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

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

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

Вернемся к выводам, которые мы сделали при анализе значений P>|t| для независимых переменных первой модели. Мы могли наблюдать, что признаки с большими p-значениями, такие как Feature_7 с 0,622, считались не очень статистически значимыми. В ячейке ниже мы выберем все эти признаки с высокими p−значениями и удалим их из наших наборов X.# Selecting feature to remove
features_to_remove = [‘Feature_1’,
‘Feature_5’,
‘Feature_6’,
‘Feature_7’,
‘Feature_8’,
‘Feature_10’]

# Removing features
new_X_train = X_train.drop(features_to_remove, axis =1)
new_X_test = X_test.drop(features_to_remove, axis =1)

Теперь у нас есть более компактный набор X с 4 функциями плюс константа.# Fitting model
model = sm.OLS(y_train, new_X_train).fit()
print(model.summary())

По сравнению с первой моделью, мы снова имеем худшие значения для логарифмического правдоподобия и AIC. Однако для БИК в данном случае мы имеем более низкое значение, считающееся лучшим, чем чуть более высокое значение первой модели.

Эта модель также имеет более низкий R-квадрат, объясняющий 48,1% дисперсии целевой переменной, что немного ниже, чем у первой модели.

При рассмотрении независимых переменных кажется, что все они статистически значимы, учитывая, что P>|t| ниже 0,05. Feature_2 — единственный, который немного выше этого порога, а также единственный с отрицательным коэффициентом.

Также заметно, что статистика Жака-Бера указывает на то, что остатки могут быть распределены ненормально. Давайте построим график распределения, чтобы увидеть, как оно формируется.

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

Давайте спрогнозируем значения Y на проверочном наборе, чтобы увидеть, как среднеквадратичная ошибка соотносится с предыдущими моделями.y_pred = model.predict(new_X_test)
rmse = mean_squared_error(y_test, y_pred,squared = False)

print(f’\nRoot Mean Squared Error for Baseline Model: {rmse:.2f}’)Root Mean Squared Error for Baseline Model: 52.68

Эта модель достигает лучшего показателя RMSE, оценивая значение ниже, чем две другие модели. Мы также можем построить диаграмму рассеяния между фактическим и прогнозируемым значениями.

Третья модель лучше обобщалась на проверочную выборку, чем другие модели. Однако, судя по метрикам, кажется, что первая модель может лучше всего соответствовать предположениям линейной регрессии, обеспечивая более надежные оценки и прогнозы.

Тем не менее, уместно отметить, что все три модели являются статистически значимыми, согласно F-статистике и их очень низким значениям Prob (F-статистика), что указывает на то, что наши независимые переменные Xs действительно полезны для предсказания значений Y.

Заключение

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

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

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

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

Большое спасибо за вашу поддержку!

Дополнительная литература…

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

Модель авторегрессии (AR): метод эффективного анализа временных рядов

Освоение прогнозирования временных рядов с помощью моделей авторегрессии (AR): подробное руководство

Авторегрессионные модели предназначены для прогнозирования временного ряда, полагаясь исключительно на его предыдущие значения, также известные как запаздывания. Они основаны на предположении, что текущее значение переменной временного ряда линейно зависит от ее прошлых значений. Другими словами, авторегрессионная модель предсказывает будущие значения переменной, используя линейную комбинацию своих предыдущих наблюдений.

«Авторегрессивная» часть модели относится к тому факту, что она регрессирует переменную против самой себя. Порядок авторегрессионной модели, обозначаемый как AR(p), указывает количество запаздывающих наблюдений, используемых для прогнозирования текущего значения. Например, модель AR(1) использует только непосредственное прошлое наблюдение, в то время как модель AR(2) использует два последних наблюдения.

Модель AR(p) может быть представлена в виде:

  • y(t) является переменной в момент времени t.
  • c — постоянный член.
  • φ — коэффициенты авторегрессии, подогнанные к лагам.
  • ε_t — это член ошибки, который фиксирует случайные флуктуации или необъяснимую изменчивость.

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

Рекурсивная зависимость. Изображение автора.

Выбор ордера

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

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

Существует несколько часто используемых методов определения соответствующего порядка (p) для модели дополненной реальности.

Автоматическая корреляция (ACF — PACF)

Функции автокорреляции — это статистические инструменты для измерения и идентификации структуры корреляции в наборе данных временных рядов.

Функция автокорреляции (ACF) измеряет корреляцию между наблюдением и его запаздывающими значениями. Это помогает понять, как связаны между собой наблюдения на разных лагах.

Функция частичной автокорреляции (PACF) устраняет влияние промежуточных запаздывания. Он измеряет прямую корреляцию между двумя наблюдениями.

АКФ и ПАКФ. Изображение автора.

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

Например, репутация компании повышается, по мере повышения ее репутации все больше людей покупают акции этой компании. Цена среды коррелирует с ценой вторника, который, в свою очередь, коррелировал с ценой понедельника. По мере увеличения запаздывания корреляция может уменьшаться.

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

Мы можем использовать библиотеку statsmodels для построения графиков ACF и PACF в Python.import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Generate a random time series data
np.random.seed(123)
n_samples = 100
time = pd.date_range(‘2023-01-01′, periods=n_samples, freq=’D’)
data = np.random.normal(0, 1, n_samples).cumsum()

# Create a DataFrame with the time series data
df = pd.DataFrame({‘Time’: time, ‘Data’: data})
df.set_index(‘Time’, inplace=True)

# Plot the time series data
plt.figure(figsize=(10, 4))
plt.plot(df.index, df[‘Data’])
plt.xlabel(‘Time’)
plt.ylabel(‘Data’)
plt.title(‘Example Time Series Data’)
plt.show()

График данных временных рядов. Изображение автора.

from statsmodels.graphics.tsaplots import plot_acf

# ACF plot
plot_acf(df[‘Data’], lags=20, zero=False)
plt.xlabel(‘Lags’)
plt.ylabel(‘ACF’)
plt.title(‘Autocorrelation Function (ACF)’)

Сюжет АКФ. Изображение автора.

Метод plot_acf принимает несколько параметров:

  • x — массив данных временных рядов.
  • lags задает лаги для вычисления автокорреляции.
  • alpha — уровень достоверности, по умолчанию 0.05, что соответствует уровню достоверности 95%. Это означает, что доверительные интервалы на графике АКФ представляют собой диапазон, в пределах которого мы ожидаем, что истинные коэффициенты автокорреляции генеральной совокупности упадут с вероятностью 95%.

На графике ACF доверительные интервалы обычно отображаются в виде затененных областей, часто светло-голубого цвета. Эти интервалы указывают диапазон значений, которые можно было бы ожидать для автокорреляций, вычисленных на основе большого числа случайных выборок из процесса белого шума (где автокорреляция отсутствует). Это означает, что эти интервалы представляют собой диапазон значений, которые мы ожидаем увидеть, если бы мы неоднократно генерировали случайные данные, которые не коррелируют.

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

  • use_vlines указывает, следует ли строить вертикальные линии на каждом лаге для обозначения доверительных интервалов.
  • vlines_kwargs используется для определения дополнительных параметров внешнего вида.

from statsmodels.graphics.tsaplots import plot_pacf

plot_pacf(df[‘Data’], lags=20, zero=False)
plt.xlabel(‘Lags’)
plt.ylabel(‘PACF’)
plt.title(‘Partial Autocorrelation Function (PACF)’)

Сюжет PACF. Изображение автора.

plot_pacf принимает те же аргументы в качестве параметров, и, кроме того, мы можем выбрать, какой метод использовать:

  • «ywm» или «ywmle»: метод Юля-Уокера без регулировки. Это вариант по умолчанию.
  • «yw» или «ywadjusted»: метод Юля-Уокера с корректировкой размера выборки в знаменателе для оценки автоковариации.
  • «ols»: Обыкновенная регрессия временного ряда по методу наименьших квадратов на собственные запаздывающие значения и постоянный член.
  • «ols-inefficient»: регрессия МНК временного ряда по запаздывающим значениям с использованием одной общей выборки для оценки всех частных коэффициентов автокорреляции.
  • «ols-adjusted»: регрессия МНК временного ряда на его запаздывающие значения с корректировкой смещения.
  • «ld» или «ldadjusted»: метод рекурсии Левинсона-Дурбина с коррекцией смещения.
  • «ldb» или «ldbiased»: метод рекурсии Левинсона-Дурбина без коррекции смещения.

При оценке графиков ACF и PACF в первую очередь ищите коэффициенты корреляции, которые значительно отклоняются от нуля.

Затем обратите внимание на картину затухания на графике ACF. По мере увеличения запаздывания значения корреляции, как правило, должны уменьшаться и приближаться к нулю. Медленный спад указывает на устойчивую корреляцию, в то время как быстрый спад указывает на отсутствие долгосрочной зависимости. На графике PACF посмотрите, падает ли корреляция после некоторого запаздывания. Внезапное отключение говорит о том, что прямая связь существует только до этого лага.

Информационные критерии

Информационные критерии, такие как информационный критерий Акаике (AIC) или байесовский информационный критерий (BIC), являются статистическими мерами, которые уравновешивают соответствие модели и сложность. Эти критерии обеспечивают количественную меру для сравнения различных моделей с различными порядками. Модель с наименьшим значением AIC или BIC часто считается наиболее подходящей моделью.

Информационный критерий Акаике (AIC) учитывает, насколько хорошо модель соответствует данным и насколько она сложна. Он наказывает сложные модели, чтобы избежать переобучения, включая член, который увеличивается с числом параметров. Он стремится найти модель, которая хорошо соответствует данным, но при этом максимально проста. Чем ниже значение AIC, тем лучше модель. Он имеет тенденцию отдавать приоритет моделям с лучшей подгонкой, даже если они относительно более сложны.

Байесовский информационный критерий (BIC) накладывает более строгий штраф на сложность модели. Он включает в себя член, который растет с увеличением количества параметров в модели, что приводит к более значительному штрафу для сложных моделей. Он сильно наказывает за большую сложность, отдавая предпочтение более простым моделям. Он согласуется даже с меньшим размером выборки и предпочтителен, когда размер выборки ограничен. Опять же, чем ниже значение BIC, тем лучше модель.

Теперь давайте сгенерируем более сложные данные и рассчитаем AIC и BIC:import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.ar_model import AutoReg

# Generate complex time series data
np.random.seed(123)
n = 500 # Number of data points
epsilon = np.random.normal(size=n)
data = np.zeros(n)

for i in range(2, n):
data[i] = 0.7 * data[i-1] — 0.2 * data[i-2] + epsilon[i]

# Plot the time series data
plt.figure(figsize=(10, 4))
plt.plot(data)
plt.xlabel(‘Time’)
plt.ylabel(‘Data’)
plt.title(‘Time Series Data’)
plt.show()

Данные временных рядов. Изображение автора.

# Fit AutoReg models with different orders and compare AIC and BIC
max_order = 10
aic_values = []
bic_values = []

for p in range(1, max_order + 1):
model = AutoReg(data, lags=p)
result = model.fit()
aic_values.append(result.aic)
bic_values.append(result.bic)

# Plot AIC and BIC values
order = range(1, max_order + 1)
plt.plot(order, aic_values, marker=’o’, label=’AIC’)
plt.plot(order, bic_values, marker=’o’, label=’BIC’)
plt.xlabel(‘Order (p)’)
plt.ylabel(‘Information Criterion Value’)
plt.title(‘Comparison of AIC and BIC’)
plt.legend()
plt.show()

Сравнение АПК и БИЦ. Изображение автора.

Класс AutoReg используется для аппроксимации моделей авторегрессии. Он принимает несколько параметров:

  • endog является зависимой переменной.
  • lags задает порядок запаздывания. Это может быть целое число, представляющее одно значение запаздывания, или список/массив значений запаздывания.
  • trend определяет компонент тренда, включенный в модель. Он может принимать следующие значения:

‘c’: добавляет постоянное значение в уравнение модели, допуская ненулевое среднее значение. Предполагается, что тренд представляет собой горизонтальную линию.

‘nc’: нет постоянного члена. Он исключает константу из уравнения модели, предполагая, что ряд имеет среднее значение, равное нулю. Ожидается, что тренд будет колебаться около нуля без систематического движения вверх или вниз.

‘t’: линейный тренд. Модель предполагает, что тренд следует по прямой линии вверх или вниз.

‘CT’: сочетает в себе постоянные и линейные тренды.

  • seasonal указывает, должна ли модель включать сезонный компонент.
  • exog — это экзогенные или внешние переменные, которые мы хотим включить в модель.
  • hold_back определяет количество исходных наблюдений, исключаемых из процесса аппроксимации.
  • period используется, когда seasonal=True и представляет длину сезонного цикла. Это целое число, обозначающее количество наблюдений за сезон.

model.fit() возвращает объект AutoRegResults, и мы можем получить AIC и BIC из соответствующих атрибутов.

Поскольку мы намеренно генерировали более сложные данные, ожидается, что BIC будет отдавать предпочтение более простым моделям, чем AIC. Таким образом, BIC выбрал модель более низкого порядка (более простую) по сравнению с AIC, что указывает на предпочтение простоты при сохранении разумного соответствия данным.

Тест Ljung-Box

Критерий Люнга-Бокса — это статистический тест, используемый для определения наличия какой-либо значимой автокорреляции во временном ряду.

Тест подгоняет авторегрессионную модель к данным. Невязки этой модели фиксируют необъяснимые или остаточные вариации в данных. Затем вычисляется статистика Ljung-Box для разных лагов. Они количественно определяют величину остаточной автокорреляции.

Чтобы определить, является ли автокорреляция статистически значимой, статистика Люнга-Бокса сравнивается с критическими значениями распределения хи-квадрат. Эти критические значения зависят от выбранного нами уровня значимости. Если статистика выше критического значения, это говорит о наличии значимой автокорреляции, указывающей на то, что модель не зафиксировала все зависимости в данных. С другой стороны, если статистика ниже критического значения, это означает, что автокорреляция в невязках незначима, что указывает на хорошее соответствие для модели авторегрессии.

Изучив результаты теста Ljung-Box для различных лагов, мы можем определить соответствующий порядок (p). Порядок запаздывания без значимой автокорреляции в невязках считается подходящим для модели.import numpy as np
from statsmodels.tsa.ar_model import AutoReg
from statsmodels.stats.diagnostic import acorr_ljungbox

max_order = 10
p_values = []

for p in range(1, max_order + 1):
model = AutoReg(data, lags=p)
result = model.fit()
residuals = result.resid

result = acorr_ljungbox(residuals, lags=[p])
p_value = result.iloc[0,1]
p_values.append(p_value)

# Find the lag order with non-significant autocorrelation
threshold = 0.05
selected_order = np.argmax(np.array(p_values) < threshold) + 1
print(«P Values: «, p_values)
print(«Selected Order (p):», selected_order)

«»»
P Values: [0.0059441704188493635, 0.8000450392943186, 0.9938379305765744, 0.9928852354721004, 0.8439698152504373, 0.9979352709556297, 0.998574234602306, 0.9999969308975543, 0.9999991895465976, 0.9999997412756536]
Selected Order (p): 1
«»»

Перекрестная проверка

Перекрестная проверка — это еще один метод определения соответствующего порядка (p). Во-первых, мы делим данные временных рядов на несколько сгибов или сегментов. Распространенным выбором является использование подхода со скользящим окном, когда мы перемещаем окно фиксированного размера по данным.

Для каждой свертки мы подбираем AR-модель с определенным порядком запаздывания (p), используя обучающую часть данных. Затем мы используем аппроксимированную модель для прогнозирования значений для тестовой части данных.

Затем мы вычисляем метрику оценки (например, среднеквадратичную ошибку, среднюю абсолютную ошибку) и вычисляем среднюю производительность для каждой сверты.

Наконец, мы выбираем порядок запаздывания (p), который дает наилучшую среднюю производительность по всем сгибам.import numpy as np
from statsmodels.tsa.ar_model import AutoReg
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import TimeSeriesSplit

np.random.seed(123)
data = np.random.normal(size=100)

max_order = 9
best_order = None
best_mse = np.inf

tscv = TimeSeriesSplit(n_splits=5)
for p in range(1, max_order + 1):
mse_scores = []

for train_index, test_index in tscv.split(data):
train_data, test_data = data[train_index], data[test_index]

model = AutoReg(train_data, lags=p)
result = model.fit()
predictions = result.predict(start=len(train_data), end=len(train_data) + len(test_data) — 1)

mse = mean_squared_error(test_data, predictions)
mse_scores.append(mse)

avg_mse = np.mean(mse_scores)

if avg_mse < best_mse:
best_mse = avg_mse
best_order = p

print(«Best Lag Order (p):», best_order)

«»»
Best Lag Order (p): 3
«»»

Прогнозирование

В этом примере мы рассмотрим датасет цен на акции. В частности, мы сосредоточимся на самом последнем 40-дневном периоде и проанализируем котировки акций компании AMD.

Эти пакеты нам понадобятся.import datetime
import numpy as np
import yfinance as yf
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import TimeSeriesSplit
from statsmodels.tsa.ar_model import AutoReg
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.stats.diagnostic import acorr_ljungbox

Мы можем использовать библиотеку yfinance на Python для доступа к историческим данным акций из Yahoo Finance.ticker = «AMD»
end_date = datetime.datetime.now().date()
start_date = end_date — datetime.timedelta(days=60)
data = yf.download(ticker, start=start_date, end=end_date)
closing_prices = data[«Close»]
print(len(closing_prices))

«»»
[*********************100%***********************] 1 of 1 completed
42
«»»plt.figure(figsize=(10, 6))
plt.plot(closing_prices)
plt.title(«AMD Stock Closing Prices (Last 42 Days)»)
plt.xlabel(«Date»)
plt.ylabel(«Closing Price»)
plt.xticks(rotation=45)
plt.grid(True)
plt.show()

Цены закрытия. Изображение автора.

Мы разделим набор данных, обозначив самую последнюю запись в качестве тестовых данных, а остальные записи будут использоваться для обучения. Наша цель — построить модели, которые могут предсказать цену текущего дня. Мы оценим и сравним производительность этих моделей на основе их прогнозов.n_test = 1
train_data = closing_prices[:len(closing_prices)-n_test]
test_data = closing_prices[len(closing_prices)-n_test:]
print(test_data)

«»»
Date
2023-06-14 127.330002
Name: Close, dtype: float64
«»»

Теперь перейдем к обучению моделей авторегрессии (AR) с порядками запаздывания от 1 до 10. Мы будем использовать эти модели для прогнозирования последней цены в наборе данных и вычисления ошибки для каждой модели.error_list = []
for i in range(1,11):
model = AutoReg(train_data, lags=i)
model_fit = model.fit()
predicted_price = float(model_fit.predict(start=len(train_data), end=len(train_data)))
actual_price = test_data.iloc[0]
error_list.append(abs(actual_price — predicted_price))plt.figure(figsize=(10, 6))
plt.plot(error_list)
plt.title(«Errors (Actual — Predicted)»)
plt.xlabel(«p»)
plt.ylabel(«Error»)
plt.xticks(rotation=45)
plt.grid(True)
plt.show()

Ошибки в значениях p-порядка. Изображение автора.

Заключение

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

Выбор порядка (p) является важным этапом в AR-моделировании, так как он определяет количество запаздывающих наблюдений, включаемых в модель. Мы рассмотрели наиболее распространенные приемы отбора заказов; визуальный контроль с использованием графиков ACF и PACF, информационных критериев, теста Ljung-Box и перекрестной проверки.

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

Источники

https://www.statsmodels.org/dev/generated/statsmodels.tsa.ar_model.AutoReg.html#statsmodels.tsa.ar_model.AutoReg

https://www.statsmodels.org/dev/generated/statsmodels.tsa.ar_model.AutoReg.fit.html#statsmodels.tsa.ar_model.AutoReg.fit

https://www.statsmodels.org/dev/generated/statsmodels.tsa.ar_model.AutoRegResults.html#statsmodels.tsa.ar_model.AutoRegResults

https://www.statsmodels.org/stable/generated/statsmodels.stats.diagnostic.acorr_ljungbox.html

https://www.researchgate.net/publication/337963027_Selecting_optimal_lag_order_in_Ljung-Box_test

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.TimeSeriesSplit.html

Динамическая регрессионная модель с переключением Маркова

Пока в моих исследованиях слово марков встречается очень часто. Если вы не знакомы с цепями и моделями Маркова, вот что будет упомянуто в большинстве онлайн-ресурсов: состояния, переходы и матрицы переходов. Например, в случае с акциями состоянием можно считать бычий или медвежий период времени. Переходы определяются как переход от бычьего или медвежьего состояния сегодня к бычьему или медвежьему состоянию завтра. Матрица переходов будет определять вероятности перехода из одного состояния в другое с учетом текущего состояния. Основываясь на этой информации, вы можете понять, почему она часто возникает. Состояниями может быть все, что вы можете придумать, что может дать ценную предсказательную силу с помощью условных вероятностей. Еще один интересный компонент матриц переходов Маркова заключается в том, что к ним можно добавить компонент долговременной памяти. Вы можете добавить компонент памяти, указав количество ордеров, 1… n. Ордера — это количество предыдущих состояний, предшествующих текущему состоянию.

Теперь, когда Марков рассмотрен, давайте перейдем к тому, как он включается в регрессионную модель. Как и во всех регрессионных моделях, то же самое относится и к марковской версии. Уравнение включает в себя пересечение, коэффициент для зависимой переменной и член ошибки[1].

  • lnr — логарифмические данные, возвращаемые в момент времени t в данных временных рядов
  • St (S sub t) — элемент режимных состояний, St (S sub t) ∈ {0, 1, …, k}, где k — количество состояний.
  • β – коэффициенты, зависящие от состояния. Beta naught — это зависимый от состояния перекресток, а beta sub m — коэффициенты для числа независимых экзогенных переменных, используемых для предсказания зависимой переменной. В этом случае m равно 1 при условии, что предыдущее логарифмическое возвращаемое значение является единственной экзогенной переменной в приведенной выше формуле.
  • σ — волатильность, зависящая от состояния
  • ε — член ошибки регрессионной модели. Член ошибки выбирается случайным образом из нормального распределения со средним значением 0 и стандартным отклонением, которое передается в модель в качестве параметра.

То, что делает приведенное выше уравнение способным охватить режимы, — это состояния. При переходе между состояниями коэффициенты, константы пересечения и волатильности переключаются на основе матрицы переходов. Например, если текущее состояние A имеет 95%-ную вероятность перехода в состояние C, то параметры регрессии для состояния C подставляются в формулу. Переключение этих параметров основано на марковском переходе k числа обозначенных состояний.

  • st — элемент числа состояний, st ∈ {0, 1 … k}
  • Строки в матрице переходов представляют текущее состояние, а столбцы — состояния, в которые осуществляется переход. Каждая строка представляет распределение вероятностей для каждого состояния и в сумме равно 1.
  • Все параметры в формуле, включая матрицу переходов, оцениваются с максимальным правдоподобием. Оценка параметров также может быть выполнена с помощью выборки Гиббса. Если вас заинтересовал пост о выборке Гиббса, обязательно оставьте комментарий.

В предыдущем абзаце упоминалось, что параметры меняются местами с помощью марковского процесса. Долгое время я размышлял над тем, как именно это выглядит. Сначала я думал, что состояние с наибольшей вероятностью перехода будет предсказанным. Тем не менее, это было бы не слишком надежно, если бы это было так. Например, в случае с вероятностью 51 % переход в состояние А и 49 % — в состояние Б, выбор состояния А каждый раз искажает распределение вероятностей текущего состояния. Изучив этот вопрос подробнее, я наткнулся на гораздо более надежный способ переключения параметров, зависящих от состояния.

Переключение коэффициентов фактически происходит в следующие этапы. Во-первых, матричное умножение регрессионной модели используется для вычисления прогнозируемых значений на основе состояния. И, наконец, математическое ожидание на каждом временном шаге возвращается в качестве окончательного результата с использованием распределения вероятностей текущего состояния в матрице переходов[2]. Ниже приведено наглядное представление матричного умножения регрессионной модели с использованием коэффициентов, зависящих от состояния.

Умножение матриц для приведенной выше формулы с использованием предыдущего логарифмического возврата, lnr в момент времени t.
Матричное умножение, предсказывающее логарифмическую доходность, lnr с использованием нескольких экзогенных переменных
  • Первая матрица в приведенном выше уравнении, X, представляет m объектов в наборе данных временных рядов. Индекс столбца 0, первый столбец, состоящий из 1s, используется для умножения нашей константы, зависящей от состояния, βθ
  • Форма матрицы равна t на m + 1. Где t ∈ {0, 1, …, T} и m ∈ {1, …, M}. 1, прибавленное к m, относится к столбцу для константы в уравнении
  • Вторая матрица, β представляет k коэффициентов, зависящих от состояния. Первая строка матрицы — это зависящие от состояния значения пересечения, которые будут умножены на первый столбец 1s в первой матрице, X. β sub m – коэффициенты для регрессорных/экзогенных переменных.
  • Когда 2 матрицы перемножаются вместе, результирующий результат представляет собой матрицу t на k прогнозируемых значений по состоянию.

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

Реализация кода

Ниже приведена реализация модели регрессии переключения Маркова с использованием statsmodel Python. Модель достаточно новая, после прочтения некоторых сообщений в Интернете. Из-за своей новизны такие методы, как прогнозирование на основе данных вне выборки, не были внедрены. Тем не менее, вы можете использовать приведенный ниже пример для извлечения некоторой ценной информации из данных временных рядов. Кроме того, основываясь на описании модели в предыдущем разделе, вы можете опробовать ее собственную реализацию. Оставьте комментарий, если вы хотите, чтобы я разместил реализацию прогнозирования значений вне выборки.

Извлеките данные и преобразуйте:# name of hte index.
housing = ‘ACTLISCOUUS’
start = date(2016, 1, 1)
end = date(2023, 11, 1)
df = pdr.DataReader(name=housing,
data_source=’fred’,
start=str(start),
end=str(end))

# get the log returns of the housing data
df[‘log returns’] = np.log(df[‘ACTLISCOUUS’]) — np.log(df[‘ACTLISCOUUS’].shift(1))

# Create the lagged values for the returns
df[‘lag_1’] = df[‘log returns’].shift(1)
# round the columns of interest
df[‘log returns’] = df[‘log returns’].round(decimals=3)
df[‘lag_1’] = df[‘lag_1’].round(decimals=3)

Отобразим данные:# get the distributions for both
COLOR = ‘#50C878’
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(15, 12))
sns.histplot(data=df, x=’ACTLISCOUUS’, color=COLOR, ax=axes[0, 0]).set_title(«US Housing Count»)
sns.lineplot(x=df.index, y=df[‘ACTLISCOUUS’], color=COLOR, ax=axes[0, 1]).set_title(«US Housing Count»)
sns.histplot(data=df, x=’log returns’, color=COLOR, ax=axes[1, 0]).set_title(«US Housing Count — Log Delta»)
sns.lineplot(x=df.index, y=df[‘log returns’], color=COLOR, ax=axes[1, 1]).set_title(«US Housing Count — Log Delta»)
# plt.savefig(‘housing_graph.png’, bbox_inches=’tight’) # uncomment if you want to save the graph
plt.show()

Автокорреляция графика:# plot autocorrelation plots
plot_acf(df[‘log returns’])
# plt.savefig(‘autocorr_msr.png’, bbox_inches=’tight’) # uncomment to save the figure

Статистика регрессии переключения Маркова:# seperate the data between in sample and out of sample tests
df.dropna(inplace=True)
in_sample_rec = int(df.shape[0] * 0.7)
in_sample = df.iloc[:in_sample_rec]
out_sample = df.iloc[in_sample_rec:]
# print the shapes of each dataframe
logging.info(f’Shape of the in sample dataset:\t{in_sample.shape}’)
logging.info(f’Shape of the out of sample dataset:\t{out_sample.shape}’)

# run the markov regression model on the in sample results
msr = sm.tsa.MarkovRegression(endog=in_sample[‘log returns’],
k_regimes=2,
trend=’c’,
exog=in_sample[‘lag_1’],
switching_trend=True,
switching_exog=True,
switching_variance=True)

msr_fit_1 = msr.fit()
logging.info(msr_fit_1.summary())# Code output

2023-11-28 23:27:39,132 [INFO] Shape of the in sample dataset: (60, 3)
2023-11-28 23:27:39,133 [INFO] Shape of the out of sample dataset: (26, 3)

Markov Switching Model Results
==============================================================================
Dep. Variable: log returns No. Observations: 60
Model: MarkovRegression Log Likelihood 137.023
Date: Tue, 28 Nov 2023 AIC -258.045
Time: 23:22:51 BIC -241.290
Sample: 09-01-2016 HQIC -251.492
— 08-01-2021
Covariance Type: approx
Regime 0 parameters
==============================================================================
coef std err z P>|z| [0.025 0.975]
——————————————————————————
const 0.0207 0.003 6.212 0.000 0.014 0.027
x1 0.4670 0.060 7.819 0.000 0.350 0.584
sigma2 8.404e-05 3.6e-05 2.337 0.019 1.36e-05 0.000
Regime 1 parameters
==============================================================================
coef std err z P>|z| [0.025 0.975]
——————————————————————————
const -0.0128 0.004 -2.974 0.003 -0.021 -0.004
x1 0.9604 0.080 12.019 0.000 0.804 1.117
sigma2 0.0006 0.000 4.253 0.000 0.000 0.001
Regime transition parameters
==============================================================================
coef std err z P>|z| [0.025 0.975]
——————————————————————————
p[0->0] 0.7152 0.112 6.375 0.000 0.495 0.935
p[1->0] 0.1286 0.057 2.241 0.025 0.016 0.241
==============================================================================

Warnings:
[1] Covariance matrix calculated using numerical (complex-step) differentiation.

В приведенном выше коде данные о жилье извлекаются с помощью пакета чтения данных pandas. ACTLISCOUUS — это индексный код для ряда данных Housing Inventory: Active Listing Count in United States. Более подробную информацию о рядах данных можно найти здесь. Величина значений в ряду исчисляется миллионами. Чтобы уменьшить значения до масштаба, а также сделать ряд более стационарным, логарифмические доходы вычисляются для каждого временного шага. Поскольку это не цены на активы, мы можем рассматривать логарифмическую доходность как изменение логарифмической дельты от предыдущего подсчета к текущему.

После загрузки данных отображается график исходного ряда данных и вычисленного изменения дельты журнала. В исходном ряду данных данные являются бимодальными. Это связано с подсчетами до и после ковида, как показано на линейном графике оригинальной серии. На гистограмме изменения логарифмической дельты данные нормализованы немного лучше с некоторой асимметрией. Асимметрия опять же является результатом показателей до и после ковида. На линейном графике величина пиков и впадин с 2021 по 2023 год намного больше по сравнению с предыдущими годами. Это может быть связано с тем, что процентные ставки были низкими в постковидные годы.

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

Наконец, модель MSR подгоняется под набор данных в выборке. Логарифмическое дельта-изменение (логарифмические возвраты) задаются в качестве эндогенных переменных в регрессионной модели. Режимы или состояния устанавливаются в 2. Придерживаясь формулы, упомянутой в математической части этого поста, в качестве экзогенной переменной используется изменение дельты за предыдущий месяц. Модель MSR в statsmodels позволяет переключать параметры в зависимости от состояния. Параметры для переключения установлены в true. Сводка модели содержит описание того, насколько хорошо модель смогла соответствовать данным.

Вы можете выполнить приведенный ниже код, чтобы создать график нахождения в любом из режимных состояний.msr_fit_1.smoothed_marginal_probabilities[1].plot(
title=»Probability of being in regime 1″, figsize=(12, 3), color=COLOR
)
plt.savefig(‘probability_regime.png’, bbox_inches=’tight’)

Заключение

Марковская регрессионная модель является отличным эконометрическим инструментом. Отличный способ обнаружения изменений режимов в данных временных рядов. Было интересно погрузиться в эту модель, однако, по правде говоря, я не уверен, как непрерывные переменные дискретизируются в состояния. Я предполагаю, что вы можете использовать процентили и группировать значения в зависимости от количества указанных состояний. Например, если число состояний равно 2, то все, что больше 50-го процентиля, является состоянием 0, а все, что равно или меньше — состоянием 1. Пока ничего на нем не нашел. Если вы в курсе, пожалуйста, не стесняйтесь оставлять комментарии. Если мне что-то попадется, я обязательно обновлю пост. Понимая логистику модели, можно увидеть области, которые можно настроить, чтобы они лучше соответствовали варианту использования того, что вы пытаетесь спрогнозировать. Как бы вы использовали эту модель и какие ее части вы бы изменили для анализа или прогнозирования?

[1]. Поморский и Д. Горс. Совершенствование модели регрессии с переключением Маркова за счет использования адаптивной скользящей средней. Препринт arXiv arXiv:2208.11574, 2022.

[2] Гамильтон, Д., 2020, Анализ временных рядов, Издательство Принстонского университета. ISBN: 0691218633

Источник

Источник

Источник

Источник