С кодом на Python

Введение

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

В этом сообщении блога мы узнаем об одномерной линейной регрессии, что означает линейную регрессию всего с одной переменной. В конце этой статьи мы поймем основные понятия машинного обучения, такие как гипотеза, функция стоимости и градиентный спуск. Кроме того, мы напишем необходимый код для этих функций и обучим/проверим линейную модель для набора данных Kaggle с помощью Python[1].

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

Базовые концепты

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

Приложения машинного обучения обычно делятся на три категории:

  • Контролируемое обучение
  • Неконтролируемое обучение
  • Обучение с подкреплением

В обучении с учителем [2] данные имеют идентичные признаки, которым можно сопоставить некоторую метку. Обучение с учителем бывает двух видов.

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

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

При неконтролируемом обучении [3] набор данных не имеет помеченных данных. После процесса обучения модель обнаруживает закономерности в данных. Классификация клиентов веб-сайта электронной коммерции является примером обучения без учителя.

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

Линейная регрессия

Как мы уже говорили выше, регрессия сопоставляет входные данные бесконечному количеству выходных данных. Кроме того, линейная регрессия предполагает линейную зависимость между входными данными и результатами [6]; сложно визуализировать это, если у нас есть более одной входной переменной. Если у нас есть одна входная переменная, нам нужно нарисовать линию в плоскости XY; если у нас есть две входные переменные, нам нужно построить плоскость в трехмерной системе координат. Трудно представить себе более двух входных переменных. В результате мы продемонстрируем линейную регрессию с использованием одномерных данных. Ниже приведены цены на жилье в Портленде, штат Орегон [7], которые мы будем использовать в качестве примера.

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

Например, мы можем предсказать, что цена дома площадью 3000 футов² составит примерно 500 тысяч долларов, как показано на графике ниже.

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

Обратите внимание, что в этой статье используется набор данных Линейная регрессия [1] и блокнот Одномерная линейная регрессия с нуля [8] от Kaggle. Как описано в содержательной части набора данных, он имеет обучающий набор данных из 700 и тестовый набор данных из 300 элементов. Данные состоят из пар (x,y), где x — числа от 0 до 100, а y были сгенерированы с помощью функции Excel НОРМИНОБ(СЛЧИС(), x, 3). Также дано, что наилучшей оценкой для y должно быть x.

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

Гипотеза

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

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

Для задачи одномерной линейной регрессии гипотеза имеет вид:

Пересечение оси Y с линией гипотезы называется точкой пересечения. В нашей формуле это θ₀, а наклон линии гипотезы равен θ₁.

Если мы знаем значения x, θ₀ и θ₁, мы можем предсказать целевое значение для системы машинного обучения. Например, в приведенном выше примере с ценами на жилье θ₀ = 0,00008, а θ₁ = 0,16538 для красной линии. Таким образом, для дома площадью 3000 футов² (x = 3000) ожидаемая цена составит:

Как видно, для записи функции гипотезы нам нужны три параметра. Это x (вход), θ₀ и θ₁. Итак, давайте напишем функцию Python для гипотезы:

Процесс довольно прост. Нам просто нужно вернуть (θ₀+θ₁* x).

Функция стоимости

Когда у нас есть гипотеза (т. е. мы знаем значения θ₀ и θ₁), мы должны решить, насколько хорошо эта гипотеза соответствует нашим данным. Возвращаясь к примеру с ценами на жилье, возьмем θ₀ за 500 и θ₁ за -0,1 и проведем линию на наших данных.

Как видно из изображения выше, гипотеза с θ₀ = 500 и θ₁ = -0,1 не очень хорошо подходит для нашего набора данных. Мы не хотим, чтобы такая гипотеза была нашей моделью, поскольку она дает ошибочные результаты, за исключением нескольких моментов. Давайте нарисуем еще несколько линий, чтобы лучше понять.

У нас есть три гипотезы на изображении выше с разными значениями θ. Интуитивно мы можем легко выбрать синюю линию (θ₀ = 0, θ₁ = 0,165) как наиболее подходящую для наших данных. Вопрос в том, как мы можем выбрать лучшее соответствие математически? Другими словами, как мы можем выбрать наилучшие значения θ₀ и θ₁, которые дают оптимальное решение нашей цели — найти модель, которую мы можем использовать для прогнозирования новых входных данных?

Для этого мы можем выбрать θ₀ и θ₁ так, чтобы h(x) было близко к фактическому значению для всех обучающих примеров [10]. Мы делаем ошибки для каждой точки набора данных для конкретной гипотезы (с известными значениями θ₀ и θ₁). Если мы каким-то образом добавим все те ошибки, которые мы сделали для каждой точки данных в этом наборе данных, мы сможем выбрать наиболее подходящую линию, выбрав минимальную сумму (что означает, что мы делаем меньше ошибок).

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

j(θ₀, θ₁) называется функцией стоимости. Это функция θ₀ и θ₁, которые являются пересечением и наклоном гипотезы. h(xᵢ) — y(xᵢ) — это ошибка, которую мы допустили для i-го обучающего примера. И возводя его в квадрат, мы получаем два существенных преимущества; во-первых, мы наказываем за большие ошибки, а во-вторых, избавляемся от знака минус, если h(x) ‹ y. Разделив общую сумму ошибок на количество выборок, мы находим среднюю ошибку, которую мы сделали. Как описано выше, меньшие значения функции стоимости предполагают лучшее совпадение, поэтому мы пытаемся минимизировать функцию стоимости для лучшего соответствия.

Чтобы написать функцию стоимости, мы должны импортировать NumPy, известную библиотеку машинного обучения, используемую для задач линейной алгебры. NumPy ускорит наши вычисления. Нам также нужны четыре параметра, а это θ₀, θ₁, X (вход) и y (фактический вывод).

Внутри функции первое, что нужно сделать, — это вычислить ошибки для каждой точки данных, используя функцию вычитания NumPy. Затем мы можем вычислить квадратичные ошибки для каждой точки данных, используя квадратную функцию NumPy. Наконец, мы можем вычислить общую квадратичную ошибку, используя sum(), и разделить на количество примеров, чтобы получить среднюю ошибку. Обратите внимание, что все обучающие данные передаются функции в виде массива NumPy. Кроме того, поскольку мы используем функцию гипотезы внутри функции стоимости, мы должны записать ее заранее. Помните также, что мы еще не пытаемся минимизировать функцию стоимости. Мы увидим, как это сделать позже, в теме «Градиентный спуск».

Градиентный спуск

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

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

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

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

Чтобы лучше понять концепцию градиента, мы будем использовать функцию стоимости случайной квадратичной ошибки с θ₀ = 0, как показано ниже. Мы выбираем θ₀ как ноль; в противном случае мы бы боролись с 3D-графиком, а не с 2D-графиком.

На изображении выше предположим, что мы находимся в точке = 6 (то есть мы выбрали наше начальное θ₁ равным 6) и пытаемся достичь глобального минимума. Отрицательный градиент в этой точке направлен вниз, как показано стрелкой. Поэтому, если мы сделаем еще один шаг в этом направлении, мы закончим с точкой меньше 6. Затем, как показано ниже, мы можем повторить ту же процедуру до сходимости в точке = 2.

Давайте попробуем другую точку, как показано ниже. Если бы мы выбрали другое значение θ₁, например, точку = -2, отрицательный градиент в этой точке был бы нисходящим, как показано стрелкой. Поэтому, если мы сделаем еще один шаг в этом направлении, мы закончим со значением, превышающим -2.

Затем, как показано ниже, мы можем повторить ту же процедуру до сходимости в точке = 2.

Один хороший вопрос, который можно задать, — как решить, когда мы сошлись. То есть, какое у нас условие остановки на коде? У нас есть два варианта. Мы можем либо проверить значение функции стоимости и остановиться, если оно меньше или равно предварительно определенному значению, либо мы можем проверить разницу между последовательными значениями функции стоимости и остановиться, если оно меньше или равно пороговому значению. Мы выберем последнее, поскольку из-за выбора начальных значений θ мы никогда не сможем достичь предварительно определенного значения стоимости, которое мы выбрали.

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

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

В результате для одномерного набора данных с гипотезой вида h(x) = θ₀ +θ₁* x и функцией стоимости квадрата ошибки J(θ₀, θ₁), значенияθ для каждого шага можно рассчитать следующим образом:

Как уже говорилось, α — это скорость обучения, а m — количество обучающих примеров.

Мы должны импортировать NumPy, как в функции стоимости, чтобы написать функцию градиентного спуска.Нам также нужны пять параметров, а это θ₀, θ₁, α (скорость обучения), X (вход) и y(фактический вывод). Мы также должны быть уверены, что не обновляем θ₀ перед вычислением θ₁ [10]. В противном случае мы получим ошибочный результат. Код для функции градиента выглядит следующим образом:

Внутри функции первое, что нужно сделать, — это вычислить ошибки для каждой точки данных с помощью функции вычитания NumPy и сохранить их в переменной. Затем мы можем умножить предыдущий результат на x и сохранить его в другой переменной. Обратите внимание, что все обучающие данные передаются функции в виде массива NumPy. Таким образом, эти переменные имеют тип массива, и функцию sum() можно использовать для получения общих значений, которые затем можно умножить на скорость обучения и разделить на количество примеров. В качестве последнего шага мы можем вычислить и вернуть новые значения θ.

Обучение модели

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

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

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

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

Результат

Нижеприведенный результат относится к начальным условиям в блоке кода обучения модели. Обучение заняло 27 итераций. θ₀ рассчитывается примерно как 0,015, а θ₁ составляет около 0,999. Окончательная стоимость рассчитывается примерно как 3,936. Результат очень близок к линии y = x, описанной в Наборе данных линейной регрессии. Мы также можем видеть изменение гипотезы для каждой итерации.

Проверка

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

Заключение

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

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

Спасибо за чтение!

Рекомендации

[1] В. Андонянс, Линейная регрессия, Kaggle.com, 2017 г. [Онлайн]. Доступно: https://www.kaggle.com/datasets/andonians/random-linear-regression. [Доступ: 12 сентября 2022 г.].

[2] Обучение с учителем — Википедия, En.wikipedia.org, 2022 г. [онлайн]. Доступно: https://en.wikipedia.org/wiki/Supervised_learning. [Доступ: 13 сентября 2022 г.].

[3] Обучение без учителя — Википедия, En.wikipedia.org, 2022 г. [онлайн]. Доступно: https://en.wikipedia.org/wiki/Unsupervised_learning. [Доступ: 13 сентября 2022 г.].

[4] Обучение с подкреплением — Википедия, En.wikipedia.org, 2022 г. [Онлайн]. Доступно: https://en.wikipedia.org/wiki/Reinforcement_learning. [Доступ: 13 сентября 2022 г.].

[5] Дж. Кэрью, Что такое обучение с подкреплением? Всесторонний обзор», SearchEnterpriseAI, 2021 г. [онлайн]. Доступно: https://www.techtarget.com/searchenterpriseai/definition/reinforcement-learning. [Доступ: 12 сентября 2022 г.].

[6] Дж. Браунли, Линейная регрессия для машинного обучения, https://machinelearningmastery.com/, 2022. [Онлайн]. Доступно: https://machinelearningmastery.com/linear-regression-for-machine-learning/. [Доступ: 11 сентября 2022 г.].

[7] JohnX, Цены на жилье, Портленд, Орегон, Kaggle.com, 2017 г. [Онлайн]. Доступно: https://www.kaggle.com/datasets/kennethjohn/housingprice. [Доступ: 11 сентября 2022 г.].

[8] Э. Хатипоглу, Одномерная линейная регрессия с нуля, Kaggle.com, 2022 г. [Онлайн]. Доступно: https://www.kaggle.com/code/erkanhatipoglu/univariate-linear-regression-from-scratch. [Доступ: 12 сентября 2022 г.].

[9] Дж. Браунли, Что такое гипотеза в машинном обучении?, machinelearningmastery.com, 2019 г. [Онлайн]. Доступно: https://machinelearningmastery.com/what-is-a-hypothesis-in-machine-learning/. [Доступ: 12 сентября 2022 г.].

[10] А. Нг, Stanford CS229: машинное обучение — линейная регрессия и градиентный спуск | Лекция 2 (осень 2018 г.), Youtube.com, 2018 г. [Онлайн]. Доступно: https://www.youtube.com/watch?v=4b4MUYve_U8&list=PLoROMvodv4rMiGQp3WXShtMGgzqpfVfbU&index=2. [Доступ: 12 сентября 2022 г.].