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

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

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

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

В нашем наборе данных всего четыре столбца, также называемые «особенности», и 44 строки (45, если вы включаете заголовок, который нам не нужен), каждая из которых представляет одну рыбу. Здесь важно отметить, что мы хотим позже игнорировать этот столбец индекса и решить, какой столбец является нашей меткой или что мы хотим предсказать.

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

С математической точки зрения мы хотим построить модель в форме y = θ0 + θ1x:, 1 +…, где theta (s) - наши изученные параметры.

Подготовка данных

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

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

Когда мы используем data.head (4), мы получаем такой вывод:

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

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

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

Обучение, тестирование и оптимизация

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

Выходные данные нашего фрагмента кода выше показывают, что x_train.shape - это (30,2), а y_train.shape - (30,1), что указывает на то, что наши обучающие функции - это 30 строк и два столбца, а наши цели обучения - 30 строк и один столбец. .

Итак, теперь мы можем вычислить наши параметры. Мы можем пойти двумя путями. Мы можем использовать встроенный в sklearn класс и функции LinearRegression () или сделать это с нуля с помощью numpy.

Приведенные выше фрагменты кода выводят наш перехват (θ0) и коэффициенты (θ1 и θ2). Здесь важно отметить, что у нас есть два коэффициента, потому что у нас есть две функции в нашем наборе данных. . Теперь, когда у нас есть параметры и мы можем делать прогнозы, мы можем поговорить о вычислении ошибки и оптимизации наших параметров, чтобы минимизировать ошибку.

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

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

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

Прежде чем углубляться в математику всего, что мы сделали выше, последний шаг к завершению линейной регрессии на данный момент - это оптимизация наших параметров путем их обновления с помощью градиентного спуска. Чтобы начать оптимизацию наших параметров, нам необходимо понять, какие ошибки допускает наша модель. В этом конкретном примере мы будем использовать RMSE (среднеквадратичную ошибку). Наиболее четкое определение RMSE, которое я видел, исходит от этого пользователя stackoverflow: RMSE отвечает на вопрос:« Насколько в среднем похожи числа в list1 на list2? . Два списка должны быть одинакового размера. Я хочу смыть шум между любыми двумя заданными элементами, смыть размер собранных данных и ощутить изменение с течением времени одним числом. В математических терминах:

На языке Python с использованием sklearn:

Для ученых и профессоров, которые хотят все с нуля:

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

new_weight = old_weight - скорость обучения * gradient_wrt_old_weight.

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

Здесь мы начинаем разбираться в основных различиях между линейной регрессией в закрытой форме (как мы делали выше) и оптимизированной линейной регрессией (думаю, я только что придумал эту фразу). В закрытой форме мы просто делаем один шанс найти параметры для вставки в наше уравнение y = mx + b с помощью серии скалярных произведений между нашими функциями, транспонированными функциями и метками. Когда мы выбираем маршрут оптимизации, мы фактически инициализируем эти параметры с самого начала - либо нулями, либо случайными числами, либо тщательно продумываем наши значения, что выходит за рамки этого сообщения, но также является интересной темой для обсуждения.

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

Теперь, когда у нас есть процесс нахождения оптимальных значений параметров, мы должны использовать новый раздел наших данных, набор тестов или проверок для выполнения новых прогнозов с использованием наших вновь найденных значений параметров. Этот механизм прогнозирования так же прост, как вставка значений в y = mx + b, где x - значение из нашего тестового набора, а m и b наши параметры, полученные с помощью градиентного спуска.