Разбираемся в ML без воды: от базы до Attention. Часть 1

от автора

Сколько статей на хабре про машинное обучение? Обозначим их количество за N и напишем N+1-ю.

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

Попробую всё описать максимально простым языком, минимально опираясь на математическую терминологию.

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

Возможно, важно

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

Итак, поехали!

0. Введение

Итак, что такое машинное обучение?

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

На практике данные обычно устроены так: есть признаки (features) — то, что описывает объект, и целевая переменная (target) — то, что мы хотим предсказать.

Классический пример — задача, в которой мы предсказываем цены квартир. В таком случае features — это площадь, этаж, количество комнат, а target — цена. Цель — построить на имеющихся данных модель.

Забегая вперёд, стоит отметить, что целевая переменная не обязательно одна — бывают задачи с несколькими target‑ами. Но пока будем рассматривать случай с одной целевой переменной.

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

Обозначим пространство признаков через X, а каждый объект из этого пространства — вектором признаков вида \overline{x} = (x_1, x_2, \dots, x_k), где x_i — это i‑й признак (например, площадь, этаж и так далее). Также обозначим пространство таргетов за Y, а его элементы — y.

Тогда задача машинного обучения сводится к поиску отображения f : X \to Y, которое по признакам объекта предсказывает соответствующий таргет.

То, насколько «ошибается»f при переводе \overline{x} в y, называется потерей (loss). Ясное дело, что степень «ошибки» можно измерять по‑разному (модуль разности, квадрат разности и так далее). Функция, которая считает loss, называется функцией потерь (Loss Function) и обозначается (как ни странно) буквой L. Выбор функции потерь — это критически важный этап, который напрямую зависит от типа решаемой задачи и особенностей данных.

Итак, задача машинного обучения формулируется как поиск функции f из некоторого класса функций \mathcal{F}, минимизирующей ошибку на данных:

\min_{f \in \mathcal{F}} \frac{1}{n} \sum_{i=1}^{n} L(y_i, f(x_i))

Чуть подробнее о классе функций

Это набор всех возможных моделей конкретного типа. Например:

  • Если мы решили, что зависимость линейная y = \langle \omega, x \rangle + b, то \mathcal{F} — это класс линейных функций

  • Если мы строим дерево решений, то \mathcal{F} — это множество всех деревьев заданной глубины

  • и так далее

Зачем вообще ограничивать?

Казалось бы, почему не взять «вообще все мыслимые функции»?

  1. Вычислимость: Нам нужно уметь математически искать лучшую функцию. Если класс функций слишком сложный, мы просто не сможем найти минимум ошибки.

  2. Обобщающая способность: Если \mathcal{F} слишком богат (например, функция может изгибаться как угодно), модель просто «зазубрит» тренировочные данные.

Всё через компромисс:

  • Слишком простой \mathcal{F}: (например, прямая там, где нужна кривая) — модель будет ошибаться. Это называется недообучением (Underfitting).

  • Слишком сложный \mathcal{F}: (нейросеть с миллиардом параметров на 10 примеров) — модель идеально подстроится под шум. Это переобучение (Overfitting).

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

  1. Данные (Data): Получение, обработка и очистка данных. Качественные данные — половина успеха.

  2. Определение класса (\mathcal{F}): Выбор пространства, в котором ищем решение. Будет это простая линейная модель, дерево решений, или огромная нейросеть?

  3. Выбор функции потерь (L): Определение «санкций». Что хуже: ошибиться на чуть-чуть на многих объектах, или сильно промахнуться на одном?

  4. Выбор метода оптимизации: Сам поиск. Как именно мы будем перебирать функции из \mathcal{F}, чтобы найти среди них ту самую, которая минимизирует L?

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

Эта формула — база, на которой строится всё: от предсказания цены квартиры до современных языковых моделей.

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

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

Сначала поймем, что она из себя представляет.

Представим обычный серый двумерный мир. У нас есть x (например рост человека) и y (размер обуви). Мы хотим понять как по росту человека подбирать ему обувь. В этом контексте линейная регрессия — это просто построение прямой, которая проходит максимально близко ко всем точкам.

пример двумерной линейной регрессии

пример двумерной линейной регрессии

Однако, одним ростом сыт не будешь. В реальном мире признаков обычно много (рост, вес, пол, возраст и так далее), так что признаков обычно у нас много, но идея не сильно сложнее школьной y=kx+b
Теперь, чуть ближе к делу.

Определим линейную регрессию таким образом։ линейная регрессия — это модель, в которой мы предполагаем, что таргет аппроксимируется через линейную комбинацию фич и свободного коэффициента. К слову, свободный коэффициент имеет своё название — смещение (bias)

y_i = \omega_1x_1 + \omega_2x_2 + \dots + \omega_k x_k + \omega_0,

где \omega_i \in \mathbb{R}, i = \overline{0 \dots k} называются весами (weight). И нашей задачей является нахождение таких \omega, при которых ошибка у нас будет минимальна.

Сразу добавлю, что веса и «такие» числа, которые «подберет для нас компьютер» называются параметрами модели. Также, в будущем мы встретим числа, которые инженеры подбирают вручную (грубо говоря, конфигурация модели). Они, в свою очередь, называются гиперпараметрами

Сейчас мы имеем формулу вида \sum_{i=1}^{k}\omega_i x_i + \omega_0. Сделаем один необязательный шаг и немножко улучшим качество нашей жизни.

Дабы избавиться от «бесячего хвостика» \omega_0, скажем что у нас имеется фиктивная фича под названием x_0, которая всегда равна 1и не влияет ни на что. Перепишем формулу таким образом

 \sum_{i=0}^{k}\omega_i x_i \stackrel{\text{def}}{=}  \langle \overline{x}, \overline{\omega} \rangle

для самых маленьких (скалярное произведение)

Выражение \langle \overline{x}, \overline{\omega} \rangle является так называемым скалярным произведением (В n-мерном вещественном евклидовом пространстве)

«Согрешил, батюшка» (о типах данных)

Опытные читатели, возможно, не обратили внимание, но я упустил весьма (не побоюсь этого слова) ключевой момент. В примере выше у нас был рост, вес и пол. Ладно уж рост, это число типа float (так называемый количественный признак), мы его умножим на какое‑то \omega_i и получим число.

Что делать с полом? Достаточно очевидно, что эту фичу можно закодировать бинарно условно (0 — женщина, 1 — мужчина)

А что, если у нас не количественный и даже не бинарный признак, а к примеру номер автомобиля, класс билета в самолете, или кличка кота?

Такие признаки называются категориальными. Они в свою очередь бывают двух типов։ Номинальные и Порядковые.

Порядковые признаки — это те, для которых определены операции сравнения (к примеру одежда размера S меньше одежды размера XL).

А номинальные признаки несравнимы (например, любимые музыкальные группы)

С порядковыми признаками работать относительно легко. В самом простом случае их можно просто нумеровать. А номинальные признаки, зачастую, требуют более хитрых методов (от one hot encoding, до embeddings). Когда как и что обычно делают — Разберемся позже.

Таким образом мы определили класс функций \mathcal{F}(модель), в котором мы ищем подходящую нам функцию.

Настала очередь второго шага — выбора loss функции L. На самом деле, это та часть, по которой будут подобраны наши параметры.

Для задач линейной регрессии, обычно, в качестве функции потерь выбирают так называемую среднеквадратическую ошибку (Mean Square Error / MSE). Выглядит она таким образом

L(X,Y) = \frac{1}{n}\sum_{i=1}^{n}(y_i - \langle \overline{x_i},\overline{\omega} \rangle)^2

И целью становится минимизация функции потерь, то есть нахождение такого \overline{\omega} вида

\overline{\omega} = \arg \min_{\omega} \frac{1}{n} \sum_{i=1}^{n} (y_i - \langle x_i, \omega \rangle)^2

Почему именно MSE
  1. Дифференцируемость (Гладкость)։ имеем возможность посчитать градиенты

  2. Выпуклость: У MSE в линейной регрессии только один минимум (дно чаши). Мы никогда не застрянем в «ложной» яме.

  3. Гауссовое распределение: Если шум в данных распределен нормально (по Гауссу), то минимизация MSE — это то же самое, что метод максимального правдоподобия.

Здесь y_i - \langle \overline{x_i},\overline{\omega} \rangle показывает насколько отличается реальный ответ y_i от «пророчества» нашей модели.

Возведение в квадрат имеет двойной смысл. Во‑первых, мы не попадаем в неприятные ситуации когда из‑за того, что y_i - \langle \overline{x_i},\overline{\omega} \rangle < 0, Loss уменьшается.

Во‑вторых, малые ошибки штрафуются слабо (ответ был 5, модель выдала 4 — квадрат разности всего 1), а большие ошибки штрафуются сильно (ответ был 5, модель выдала 10 — квадрат разности уже 25).

Из‑за этого модель думает։ «бро, я лучше совершу 10 мелких ошибок, чем одну крупную».

Есть и, конечно, альтернативные подходы. К примеру, нашему MSE не уступает по популярности так называемый Mean Absolute Error / (MAE)։

L(X,Y) = \frac{1}{n}\sum_{i=1}^{n}|y_i - \langle \overline{x_i},\overline{\omega} \rangle)|

Почти то же самое, но штраф теперь линейный. В случае MAE модель может подумать «а давай лучше разочек накосячу, зато, в остальных случаях всё будет правильно».

Тут мы введем еще одно модное слово — Robustness (или по‑простому — устойчивость к выбросам). Это «пофигизм» модели к сильным отклонениям в данных (выбросам). Робастная модель не будет пытаться угодить одному странному объекту, если это портит общую картину.

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

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

„Я не боюсь того, кто изучает штрафует 10 000 раз за маленькие ошибки. Я боюсь того, кто штрафует за большую ошибку 10 000 раз.“ — Брюс ИИ.

Я не боюсь того, кто изучает штрафует 10 000 раз за маленькие ошибки. Я боюсь того, кто штрафует за большую ошибку 10 000 раз.“ — Брюс ИИ.

Заключение

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

Подведем краткий итог. В этой статье мы

  • Поняли, что из себя представляет машинное обучение

  • Сформулировали «скелет» задачи в виде четырех шагов

  • Узнали, что такое линейная регрессия

  • Поняли, что такое параметры, веса и смещение

  • Рассмотрели пару функций потерь, и поняли, что её выбор неоднозначен

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

ссылка на оригинал статьи https://habr.com/ru/articles/1036884/