Определение линейной регрессии

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

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

Теперь давайте разберемся, что мы подразумеваем под регрессией. Регрессия — это задача прогнозирования значений зависимой переменной (y) с использованием независимых переменных (x₁, x₂, x₃ и т. д.). Это делается путем анализа обучающего набора данных, состоящего из значений независимой переменной и соответствующих им значений зависимой переменной.

Как представлена ​​линейная регрессия?

Простая модель линейной регрессии, состоящая из зависимых переменных (y), которая прогнозируется с использованием независимых переменных (x₁,x₂,x₃ и т. д.). Он представлен следующим образом:

y=c₀+c₁x₁+c₂x₂+c₃x₃+…+cₙxₙ

где c₀,c₁,c₂..cₙ — константы (также называемые параметрами нашей модели), которые необходимо рассчитать с помощью линейной регрессии. Цель линейной регрессии — найти наиболее подходящие значения этих констант и сделать формулу максимально точной.

Почему эта регрессия называется "линейной" и представлена ​​графически

Давайте возьмем приведенное выше уравнение до двух членов c₀ и c₁, тогда уравнение станет

y=c₀+c₁x

Теперь, если мы построим график, используя c₀=3 иc₁=2, он будет выглядеть следующим образом:

он образует линию, как в примере графика y=2x+3 выше. Благодаря такому формированию линии эта регрессия называется линейной регрессией. Когда у нас есть более одной входной переменной (x), нам нужно перейти к более высоким измерениям, и тогда эта линия становится гиперплоскостью или плоскостью. Следовательно, сложность модели линейной регрессии зависит от количества используемых в ней переменных.

Как настроить модель и найти ошибки в прогнозируемых значениях?

Теперь определение точности нашей модели становится действительно важным, поскольку нам нужна некоторая основа для точной настройки констант c₀,c₁,c₂..cₙ. Таким образом, есть много способов сделать это. Наиболее часто используемый из них называется регрессия ошибок методом наименьших квадратов. Эта процедура стремится найти квадрат ошибки из ожидаемых значений. Поэтому нам нужно выбрать значения констант таким образом, чтобы сумма квадратов разницы между ожидаемым и предсказанным нашей моделью значением была минимальной.

Какой способ уменьшить ошибку, которую дает модель?

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

Математика градиентного спуска

Нам нужно ввести несколько новых терминов для объяснения математики градиентного спуска. Теперь давайте назовем нашу модель, сгенерированную с некоторыми случайными начальными параметрами, функцией гипотезы θ(x) и нашими исходными целевыми значениями как y. Таким образом, мы знаем из определения наименьших квадратов как наша функция ошибок представляет собой сумму квадратов всех разностей между этими θ(x) и y. Пусть она будет называться J. Итак, наша цель — сократить эту J-функцию. На жаргоне машинного обучения это называется функцией стоимости. Он представлен следующим образом. Эта терминология взята из лекций Эндрю Нг. Пожалуйста, обратитесь за дополнительной информацией.

J=∑(h(x)-y)² /2m

где m — общее количество точек данных.

Итак, чтобы найти минимум J по каждому параметру. Нам нужно продифференцировать функцию ошибок по нему. В этом случае мы продифференцируем его по c₀ и c₁. Это подводит нас к формированию нашего алгоритма градиентного спуска. Итак, давайте посмотрим это шаг за шагом

  1. Создайте функцию стоимости
  2. Найдите частные производные этой функции стоимости по параметрам один за другим
  3. Обновите значения каждого параметра из производных
  4. Найдите функцию стоимости снова, повторите с шага 1.

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

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

Теперь, если мы находимся слева от минимумов, которые ниже ожидаемого минимального значения, тогда случай выглядит как линия 1. Частная производная кривой всегда является касательной к кривой, как показано выше. Итак, если мы посмотрим на линию, она имеет отрицательный наклон. Но мы хотим увеличить значение нашего, поэтому трюк состоит в том, чтобы вычесть это значение из существующего значения. Вот как мы обновляем значения параметров. Это нужно продолжать до тех пор, пока мы не достигнем минимума. Новый термин нуждается во введении, который называется скоростью обучения. Таким образом, мы умножаем наш производный член на скорость обучения, которая определяет, с какой скоростью мы достигаем наших минимумов. Аналогичная логика может быть применена к строке 2 .

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

Программирование линейной регрессии с помощью pytorch

Возьмем произвольные данные о температуре, осадках, влажности и урожайности апельсинов и манго, соответствующих этим сочетаниям. Вы можете использовать любые произвольные значения. На этом этапе мы больше сосредоточены на концепциях кодирования, а не на анализе результатов линейной регрессии. Сначала нам нужно установить pytorch. Для получения более подробной информации перейдите по ссылке https://pytorch.org/get-started/locally/. Как только вы закончите установку, импортируйте pytorch сюда.

import pytorch 

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

inputs=torch.tensor([[73, 67, 43],
                      [91, 88, 64],
                      [87, 134, 58],
                      [102, 43, 37],
                       [69, 96, 70]], dtype=torch.float32)

У нас будут выходы в виде урожая апельсинов и манго.

targets=torch.tensor([[56, 70],
                       [81, 101],
                       [119, 133],
                       [22, 37],
                       [103, 119]],dtype=torch.float32)

Теперь нам нужно сгенерировать случайные значения для этих параметров. Теперь снова на жаргоне машинного обучения коэффициенты (c₁) называются весами, а постоянный термин c₀ называется термином смещения. Таким образом, мы используем функцию torch.randn, которая создает тензор заданной формы с элементами, выбранными случайным образом из нормального распределения со средним значением 0 и стандартным отклонением 1.

# Creation of Weights and biases
w = torch.randn(2, 3, requires_grad=True)
b = torch.randn(2, requires_grad=True)
print(w)
print(b)

С PyTorch у нас есть возможность рассчитать градиент или производную потерь по отношению к к весам и смещениям, потому что для них require_grad установлено в True.

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

def model(x):
     return x @ w.t() + b

Теперь мы можем генерировать прогнозы, вводя данные в модель.

# Generate predictions
preds = model(inputs)
print(preds)

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

def mse(t1,t2):
  diff=t1-t2
  return torch.sum(diff*diff)/diff.numel()

Теперь мы можем вычислить потери, используя это.

loss=mse(targets,preds)
loss

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

# Computing the gradients here
loss.backward()

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

print(w.grad)
print(b.grad)

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

with torch.no_grad():
  w -= w.grad * 1e-5
  b -= b.grad * 1e-5
  w.grad.zero_()
  b.grad.zero_()

Итак, здесь мы будем использовать функцию pytorch из torch.no_grad(), чтобы отключить расчет градиентов, поскольку он потребляет много памяти. Это требуется только тогда, когда у нас есть require_grad=True для этих переменных, указанных ранее. Также еще одним важным моментом является сброс градиентов до нуля, поскольку pytorch продолжает накапливать градиенты. Следует заметить, что мы умножили новые веса и смещения с обучением. Решение об обучении приходит с использованием метода следов и ошибок. Какое значение дает более быстрое снижение значений ошибки, должно использоваться

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

# Train for 100 epochs
for i in range(100):
 preds = model(inputs)
 loss = mse(preds, targets)
 loss.backward()
 with torch.no_grad():
    w -= w.grad * 1e-5
    b -= b.grad * 1e-5
    w.grad.zero_()
    b.grad.zero_()

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

# Calculate loss
preds = model(inputs)
loss = mse(preds, targets)
print(loss)

Необходимо проверить близость значений прогнозов и целей.

print(preds)
print(targets)

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

Найдите ссылку на мой код по ссылке github: https://github.com/ketank26/Coding-linear-regression-with-pytorch/blob/main/Coding_linear_regression_with_pytorch.ipynb

Использованная литература:







Курс Эндрю Нг на Coursera по машинному обучению

https://www.coursera.org/learn/machine-learning?utm_source=gg&utm_medium=sem&utm_campaign=07-StanfordML-IN&utm_content=07-StanfordML-I

Для pytorch части обратитесь к этой блестящей серии лекций

https://www.youtube.com/watch?v=zEtukWs_B2I&list=PLyMom0n-MBroupZiLfVSZqK5asX8KfoHL