Численное большинство ошибка

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

Суть понятия – численное большинство в хоккее

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

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

Штрафная система в хоккее подразумевает удаление хоккеиста, нарушившего правила на определенное время. Штраф может длиться от 2-х до 10 минут. Также возможно удаление спортсмена до конца игры, что случается крайне редко.

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

Использовать численное преимущество в хоккее куда важнее и легче, чем в том же футболе, ведь согласитесь, что есть разница между 4-х против 5 и 10 против 11.

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

Как работает стратегия

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

Сама стратегия основана на маркете реализация численного большинства.

ставка на численное большенство

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

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

Раскрытие и описание системы ставок на численное большинство

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

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

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

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

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

Пример ставки

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

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

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

пример ставки на хоккей

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

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

Плюсы и минусы данной стратегии

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

  1. Высокая вероятность прохода при грамотном анализе;
  2. Маркет доступен во всех матчах КХЛ и NHL;
  3. Количество матчей позволяет продуктивно ставить изо дня в день;
  4. Маркет абсолютно не изучается букмекером и у нас появляется возможность делать валуйные ставки;
  5. Неплохие коэффициенты и проходимость.

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

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

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

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

Бонусы и акции

Pin-up: фрибет до 30000 рублей за победные экспрессы

Получить бонус

действителен до 12.12.2021

Pin-up: фрибет до 30000 рублей за победные экспрессы

Получить бонус

действителен до 12.12.20211

Pin-up: фрибет до 30000 рублей за победные экспрессы

Получить бонус

действителен до действителен до 12.12.20211

Словарь плеоназмов для задания 6 ЕГЭ по русскому языку

секунда времени (час времени)

в сентябре месяце

рублей денег

внутренний интерьер

впервые дебютировать (первый дебют)

коренной абориген (местный абориген)

другой альтернативой

мемориальные памятники (памятный мемориал, мемориальный монументы)

ведущий лейтмотив (главный, основной лейтмотив)

прейскурант цен

народный фольклор

более исчерпывающий

памятный сувенир

первая премьера

свободные вакансии

успешной победы

положительный успех

жесты рук

самостоятельная автономия

неожиданные сюрпризы

заранее предопределить

временно приостановить

городской градоначальник

неприкосновенный иммунитет (в значении дипломатическая)

взаимное сотрудничество

передняя авансцена

полностью (окончательно) завершить, закончить

мимика лица

растет вверх

впервые познакомиться

первое «боевое крещение»

свой автопортрет (самого себя)

биография жизни

подниматься вверх

визуальное зрение

снова (вновь) возобновить

необычный феномен

передовой авангард

начальные азы

другая альтернатива

тайный аноним

предварительный анонс

арсенал оружия

беспрецедентный в прошлом

обратный бумеранг

стеклянный витраж

возвратиться обратно

юный вундеркинд

горячие гейзеры

гипотетическое предположение

изысканный деликатес

демобилизовать из армии

дважды дублировать

житница зерна (хлеба)

неизвестный инкогнито

тайная интрига

сатирическая карикатура

коллега по работе

поправки и коррективы

креативное творчество

ладонь руки

первый (ведущий) лидер

мертвый труп

путевой маршрут, маршрут движения, следования

большой массив

огромная, большая, гигантская махина

огромный мегаполис

короткий миг

мизерная мелочь

темный мрак

высотный небоскреб

подлый негодяй

оттенки нюансов

бурные овации

имеющийся опыт (усвоенный)

неповторимая оригинальность

родное Отечество

отступать назад

панацея от всех болезней

лечить болезни

пантеон богов

патриот Родины

будущая перспектива (перспективы на будущее)

бесплатный подарок

истинная подоплека

художественная поэзия

заранее предчувствовать

бумажная пресса

простаивать без дела, зря, без пользы, без работы, бесполезно

аморальный проступок

пернатые птицы

смс сообщение

свой собственный

сосуществовать вместе

специфическая особенность

спуститься вниз

главная суть

толпа людей

уничтожить полностью

денежное финансирование

популярный шлягер

я лично (лично для меня)

пережиток прошлого

информационное сообщение

букет цветов

интерактивное взаимодействие

истинная правда

ответная реакция

установленный факт

поступательное движение

свободная вакансия

наиболее оптимальный

хронометраж времени

смешивать вместе

конечный итог

черная сажа

продолжает оставаться

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

работа по демонтажу

белокурый блондин

сатирический фельетон

библиотека книг

неприятный хмырь

бедная хижина

точно сформулировать

выдающийся деятель

воссоздать заново

заранее спрогнозировать

прогноз на будущее (предварительный прогноз)

по-своему уникален

первейший приоритет

предугадать заранее

неиспользованные резервы

всенародный референдум

перспективы на будущее

планы на будущее

ареал обитания

сервисное обслуживание

полный аншлаг

автоматический рефлекс

рискованная авантюра

смелый риск

сокращенная аббревиатура

самоуправляющая автономия

авторитарный деспот

авторизовать разрешение

распространять агитацию

нападающий агрессор

соответствующий адекватно

азартный запал

приспособиться к акклиматизации

ответная контратака

лучший ас, сильнейший ас

большая армада

полный аншлаг

значимый авторитет

большая половина (исключить большая)

штат США

страсть к графомании

так например

в анфас (так как анфас значит в лицо)

численное большинство (меньшинство)

брак продукции

броский эффект

возрождаться, восстановить заново

вроде бы кажется

внешние габариты

губить (пропадать) зря

отдать дань (должную дань)

определить диагноз

замыслы на будущее

кавалькада всадников

ландшафт местности

длинный марафон

ностальгия по родине

оглядеться вокруг

падать вниз

советоваться вместе

соединить между собой

профессиональный (знающий) специалист

местный старожил

горячая страда

ценное богатство, сокровище

могучий богатырь

чередоваться друг с другом, чередоваться между собой

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

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

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

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

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

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

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

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

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

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

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

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

——

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

Постановка задачи регрессии

Задача регрессии

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

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

Задача регрессии в машинном обучении — это задача предсказания какой-то численной характеристики объекта предметной области по определенному набору его параметров (атрибутов).

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

Во всех таких задачах нам нужно иметь данные, которые позволят осуществить такое предсказание. Да, “предсказание” — это условный термин, не всегда мы говорим о будущих событиях. Зачастую говорят именно о “моделировании” значения целевой переменной. Регрессионные модели используют информацию об объектах в обучающем наборе данных, чтобы сделать вывод о возможном значении целевой переменной. И для этого нужно, чтобы ее значение имело какую-то зависимость от имеющихся у нас атрибутов. Если построить модель предсказания цены акции, но на вход подать информацию о футбольных матчах — ничего не получится. Мы предполагаем, что в наборе данных собраны именно те атрибуты объектов, которые имеют влияние на на значение целевой переменной. И чем больше это предположение выполняется, тем точнее будет потенциально наша модель.

Немного поговорим о терминах. Набор данных который мы используем для обучения модели называют датасетом (dataset) или обучающей выборкой (training set). Объекты, которые описываются в датасете еще называют точками данных (data points). Целевую переменную еще называют на статистический манер зависимой переменной (dependent variable) или результативной, выходной (output), а остальные атрибуты — независимыми переменными (independent variables), или признаками (features), или факторами, или входными переменными (input). Значения одного конкретного атрибута для всех объектов обучающей выборки часто представляют как вектор этого признака (feature vector). А всю таблицу всех атрибутов называют матрицей атрибутов (feature matrix). Соответственно, еще есть вектор целевой переменной, он не входит в матрицу атрибутов.

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

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

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

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

Выводы:

  1. Регрессия — это задача машинного обучения с учителем, которая заключается в предсказании некоторой непрерывной величины.
  2. Для использования регрессионных моделей нужно, чтобы в датасете были характеристики объектов и “правильные” значения целевой переменной.
  3. Примеры регрессионных задач — предсказание цены акции, оценка цены объекта недвижимости.
  4. Задача регрессии основывается на предположении, что значение целевой переменной зависит от значения признаков.
  5. Регрессионная модель принимает набор значений и выдает предсказание значения целевой переменной.
  6. В качестве регрессионных моделей часто берут аналитические функции, например, линейную.

Парная линейная регрессия

Функция гипотезы

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

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

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

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

[hat{y} = h_b (x) = b_0 + b_1 x]

Обратите внимание, что это похоже на уравнение прямой. Эта модель соответствует множеству всех возможных прямых на плоскости. Когда мы конкретизируем модель значениями параметров (в данном случае — $b_0$ и $b_1$), мы получаем конкретную прямую. И наша задача состоит в том, чтобы выбрать такую прямую, которая бы лучше всего “легла” в точки из нашей обучающей выборки.

В данном случае, мы пытаемся подобрать функцию h(x) таким образом, чтобы отобразить данные нам значения x в данные значения y. Допустим, мы имеем следующий обучающий набор данных:

входная переменная x выходная переменная y
0 4
1 7
2 7
3 8

Мы можем составить случайную гипотезу с параметрами $ b_0 = 2, b_1 = 2 $. Тогда для входного значения $ x=1 $ модель выдаст предсказание, что $ y=4 $, что на 3 меньше данного. Значение $y$, которое посчитала модель будем называть теоретическим или предсказанным (predicted), а значение, которое дано в наборе данных — эмпирическим или истинным (true). Задача регрессии состоит в нахождении таких параметров функции гипотезы, чтобы она отображала входные значения в выходные как можно более точно (чтобы теоретические значения были как можно ближе к эмпирическим), или, другими словами, описывала линию, наиболее точно ложащуюся в данные точки на плоскости $(x, y)$.

Выводы:

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

Функция ошибки

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

Разные модели

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

Такая функция называется функцией ошибки (cost function). Она измеряет отклонения теоретических значений (то есть тех, которые предсказывает модель) от эмпирических (то есть тех, которые есть в данных). Чем выше значение функции ошибки, тем хуже модель соответствует имеющимся данным, хуже описывает их. Если модель полностью соответствует данным, то значение функции ошибки будет нулевым.

Отклонения значений

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

[J = sum_{i=1}^{m} (h_b(x_i) — y_i)]

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

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

[J = sum_{i=1}^{m} (h_b(x_i) — y_i)^2]

У этого подхода есть еще одно неочевидное достоинство. Квадратичная функция дополнительно сильно увеличивает размер больших чисел. То есть, если среди наших отклонений будет какое-то очень большое, то после возведения в квадрат оно станет еще непропорционально больше. Таким образом квадратичная функция ошибки как бы сильнее “штрафует” сильные отклонения предсказанных значений от реальных.

Но есть еще одна проблема. Дело в том, что в разных наборах данных может быть разное количество точек. Если мы просто будем считать сумму отклонений, то чем больше точек будем суммировать, тем больше итоговое отклонение будет только из-за количества слагаемых. Поэтому модели, обученные на маленьких объемах данных будут иметь преимущество. Это тоже неправильно и поэтому берут не сумму, а среднее из отклонений. Для этого достаточно лишь поделить эту сумму на количество точек данных:

[J = frac{1}{2m} sum_{i=1}^{m} (h_b(x_i) — y_i)^2]

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

[J(b_0, b_1)
= frac{1}{2m} sum_{i=1}^{m} (hat{y_i} — y_i)^2
= frac{1}{2m} sum_{i=1}^{m} (h_b(x_i) — y_i)^2]

Эту функцию называют «функцией квадрата ошибки» или «среднеквадратичной ошибкой» (mean squared error, MSE). Среднее значение уменьшено вдвое для удобства вычисления градиентного спуска, так как производная квадратичной функции будет отменять множитель 1/2. Вообще, функцию ошибки можно свободно домножить или разделить на любое число (положительное), ведь нам не важна конкретная величина этой функции. Нам важно, что какие-то модели (то есть наборы значений параметров модели) имеют низкую ошибку, они нам подходят больше, а какие-то — высокую ошибку, они подходят нам меньше.

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

Давайте проследим формирование функции ошибки на еще более простом примере. Возьмем упрощенную форму линейной модели — прямую пропорциональность. Она выражается формулой:

[hat{y} = h_b (x) = b_1 x]

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

Функция ошибки одной переменной

При значении $b_1 = -1$ линия существенно отклоняется от точек. Отметим уровень ошибки (примерно 10) на правом графике.

Функция ошибки одной переменной

Если взять значение $b_1 = 0$ линия гораздо ближе к точкам, но ошибка все еще есть. Отметим новое значение на правом графике в точке 0.

Функция ошибки одной переменной

При значении $b_1 = 1$ график точно ложится в точки, таким образом ошибка становится равной нулю. Отмечаем ее так же.

Функция ошибки одной переменной

При дальнейшем увеличении $b_1$ линия становится выше точек. Но функция ошибки все равно будет положительной. Теперь она опять станет расти.

Функция ошибки одной переменной

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

Функция ошибки одной переменной

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

Функция ошибки одной переменной

Функция ошибки одной переменной

Функция ошибки одной переменной

Функция ошибки одной переменной

Функция ошибки одной переменной

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

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

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

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

Если мы попытаемся представить это наглядно, наш набор данных обучения будет разбросан по плоскости x-y. Мы пытаемся подобрать прямую линию, которая проходит через этот разбросанный набор данных. Наша цель — получить наилучшую возможную линию. Лучшая линия будет такой, чтобы средние квадраты вертикальных расстояний точек от линии были наименьшими. В лучшем случае линия должна проходить через все точки нашего набора данных обучения. В таком случае значение J будет равно 0.

Ошибка

Ошибка

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

Выводы:

  1. Функция ошибки нужна для того, чтобы отличать хорошие модели от плохих.
  2. Функция ошибки показывает численно, насколько модель хорошо описывает данные.
  3. Аргументами функции ошибки являются параметры модели, ошибка зависит от них.
  4. Само значение функции ошибки не несет никакого смысла, оно используется только в сравнении.
  5. Цель алгоритма машинного обучения — минимизировать функцию ошибки, то есть найти такой набор параметров модели, при которых ошибка минимальна.
  6. Чаще всего используется так называемая L2-ошибка — средний квадрат отклонений теоретических значений от эмпирических (метрика MSE).

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

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

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

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

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

[J(b_0, b_1) = frac{1}{2 m} sum_{i=1}^{m} (h_b(x_i) — y_i)^2]

Частная производная обозначается (frac{partial f}{partial x}) или (frac{partial}{partial x} f) и является обобщением обычной (полной) производной для функций нескольких аргументов. Частая производная показывает наклон функции в направлении изменения определенного аргумента, то есть как бы “в разрезе” этого аргумента. Градиент — это вектор частных производных функции по всем ее аргументам. Вектор градиента показывает направление максимального роста функции.

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

[frac{partial}{partial b_i} J =
frac{1}{2 m} sum_{i=1}^{m} frac{partial}{partial b_i} (h_b(x_i) — y^{(i)})^2]

Теперь самое сложное — производная сложной функции. По правилу она равна производной внешней функции, умноженной на производную внутренней. Внешняя функция — это квадратическая, ее производная равна удвоенному подквадратному выражению ((frac{d}{dt} t^2 = 2 t)). Подставляем (t = h_b(x_i) — y^{(i)}) и получаем:

[frac{partial}{partial b_i} J =
frac{1}{m} sum_{i=1}^{m} (h_b(x_i) — y^{(i)}) cdot frac{partial}{partial b_i} h_b(x_i)]

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

Чтобы продолжить вычисление производной дальше, нужно представить функцию гипотезы как линейную функцию:

[J(b_0, b_1) = frac{1}{2m} sum_{i=1}^{m} (b_0 + b_1 x_i — y_i)^2]

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

[frac{partial J}{partial b_0} =
frac{1}{m} sum (b_0 + b_1 x_i — y_i) =
frac{1}{m} sum (h_b(x_i) — y_i)]

А для коэффициента при $x_i$ производная равна самому значению $x_i$:

[frac{partial J}{partial b_1} =
frac{1}{m} sum (b_0 + b_1 x_i — y_i) cdot x_i =
frac{1}{m} sum (h_b(x_i) — y_i) cdot x_i]

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

[frac{partial J}{partial b_0} =
frac{1}{m} sum (h_b(x_i) — y_i) = 0]

[frac{partial J}{partial b_1} =
frac{1}{m} sum (h_b(x_i) — y_i) cdot x_i = 0]

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

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

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

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

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

Алгоритм градиентного спуска:

повторяйте до сходимости:

[b_j := b_j — alpha frac{partial}{partial b_j} J(b_0, b_1)]

где j=0,1 — представляет собой индекс номера признака.

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

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

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

Алгоритм градиентного спуска для парной линейной регрессии:

повторяйте до сходимости:

[b_0 := b_0 — alpha frac{1}{m} sum_{i=1}^{m} (h_b(x^{(i)} )- y^{(i)})]

[b_1 := b_1 — alpha frac{1}{m} sum_{i=1}^{m} (h_b(x^{(i)}) — y^{(i)}) cdot x^{(i)}]

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

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

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

Выводы:

  1. Метод градиентного спуска нужен, чтобы найти минимум функции, если мы не можем ее вычислить аналитически.
  2. Это численный итеративный алгоритм локальной оптимизации.
  3. Для запуска градиентного спуска нужно знать частную производную функции ошибки.
  4. Для начала мы берем произвольные значения параметров, затем обновляем их по данной формуле.
  5. Доказано, что этот метод сходится к локальному минимуму.
  6. Если функция ошибки достаточно сложная, то разные начальные точки дадут разный результат.
  7. Метод градиентного спуска имеет свой параметр — скорость обучения. Обычно его подстаивают автоматически.
  8. Метод градиентного спуска повторяют много раз до тех пор, пока функция ошибки не перестанет значимо изменяться.

Регрессия с несколькими переменными

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

Множественная регрессия

Парная регрессия, как мы увидели выше, имеет дело с объектами, которые характеризуются одним числовым признаком ($x$). На практике, конечно, объекты характеризуются несколькими признаками, а значит в модели должна быть не одна входящая переменная, а несколько (или, что то же самое, вектор). Линейная регрессия с несколькими переменными также известна как «множественная линейная регрессия». Введем обозначения для уравнений, где мы можем иметь любое количество входных переменных:

$ x^{(i)} $- вектор-столбец всех значений признаков i-го обучающего примера;

$ x_j^{(i)} $ — значение j-го признака i-го обучающего примера;

$ x_j $ — вектор j-го признака всех обучающих примеров;

m — количество примеров в обучающей выборке;

n — количество признаков;

X — матрица признаков;

b — вектор параметров регрессии.

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

Для удобства примем, что $ x_0^{(i)} = 1 $ для всех $i$. Другими словами, мы ведем некий суррогатный признак, для всех объектов равный единице. Это никак не сказывается на самой функции гипотезы, это лишь условность обозначения, но это сильно упростит математические выкладки, особенно в матричной форме.

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

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

Общий вид модели множественной линейной регрессии:

[h_b(x) = b_0 + b_1 x_1 + b_2 x_2 + … + b_n x_n]

Или в матричной форме:

[h_b(x) = X cdot vec{b}]

Используя определение матричного умножения, наша многопараметрическая функция гипотезы может быть кратко представлена в виде: $h(x) = B X$.

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

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

Функция ошибки для множественной линейной регрессии:

[J(b) = frac{1}{2m} sum_{i=1}^{m} (h_b(x^{(i)}) — y^{(i)})^2]

Или в матричной форме:

[J(b) = frac{1}{2m} (X b — vec{y})^T (X b — vec{y})]

Обратите внимание, что мы специально не раскрываем выражение (h_b(x^{(i)})). Это нужно, чтобы подчеркнуть, что форма функции ошибки не зависит от функции гипотезы, она выражается через нее.

Теперь нам нужно взять производную этой функции ошибки. Здесь уже нужно знать производную самой функции гипотезы, так как:

[frac{partial}{partial b_i} J =
frac{1}{m} sum_{i=1}^{m} (h_b(x^{(i)}) — y^{(i)}) cdot frac{partial}{partial b_i} h_b(x^{(i)})]

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

Метод градиентного спуска для множественной регрессии определяется следующими уравнениями:

повторять до сходимости:

[b_0 := b_0 — alpha frac{1}{m} sum_{i=1}^{m} (h_b(x^{(i)}) — y^{(i)}) cdot x_0^{(i)}]

[b_1 := b_1 — alpha frac{1}{m} sum_{i=1}^{m} (h_b(x^{(i)}) — y^{(i)}) cdot x_1^{(i)}]

[b_2 := b_2 — alpha frac{1}{m} sum_{i=1}^{m} (h_b(x^{(i)}) — y^{(i)}) cdot x_2^{(i)}]

[…]

Или в матричной форме:

[b := b — frac{alpha}{m} X^T (X b — vec{y})]

Выводы:

  1. Множественная регрессия очень похожа на парную, но с большим количеством признаков.
  2. Для удобства и однообразия, почти всегда обозначают $x_0 = 1$.
  3. Признаки образуют матрицу, поэтому уравнения множественной регрессии часто приводят в матричной форме, так короче.
  4. Алгоритм градиентного спуска для множественной регрессии точно такой же, как и для парной.

Нормализация признаков

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

В таком случае форма функции ошибки будет очень вытянутой. Это не проблема для математической формализации градиентного спуска — при достаточно малых $alpha$ метод все равно рано или поздно сходится. Проблема в практической реализации. Получается, что если выбрать скорость обучения выше определенного предела по самому компактному признаку, спуск разойдется. Значит, скорость обучения надо делать меньше. Но тогда в направлении второго признака спуск будет проходить слишком медленно. И получается, что градиентный спуск потребует гораздо больше итераций для завершения.

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

Минимаксная нормализация — это изменение входных данных по следующей формуле:

[x’ = frac{x — x_{min}}{x_{max} — x_{min}}]

После преобразования все значения будут лежать в диапазоне $x in [0; 1]$.

Z-оценки или стандартизация производится по формуле:

[x’ = frac{x — M[x]}{sigma_x}]

В таком случае данный признак приводится к стандартному распределению, то есть такому, у которого среднее 0, а дисперсия — 1.

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

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

Целевая переменная не нормируется. Это просто не нужно, а если ее нормировать, это сильно усложнит все математические расчеты и преобразования.

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

Выводы:

  1. Нормализация нужна для ускорения метода градиентного спуска.
  2. Есть два основных метода нормализации — минимаксная и стандартизация.
  3. Параметры нормализации высчитываются по обучающей выборке.
  4. Нормализация встроена в большинство библиотечных методов.
  5. Некоторые методы более чувствительны к нормализации, чем другие.
  6. Нормализацию лучше сделать, чем не делать.

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

Нелинейная регрессия

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

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

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

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

Например, если наша функция гипотезы
$ hat{y} = h_b (x) = b_0 + b_1 x $,
то мы можем добавить еще один признак, основанный на $ x_1 $, получив квадратичную функцию

[hat{y} = h_b (x) = b_0 + b_1 x + b_2 x^2]

или кубическую функцию

[hat{y} = h_b (x) = b_0 + b_1 x + b_2 x^2 + b_3 x^3]

В кубической функции мы по сути ввели два новых признака:
$ x_2 = x^2, x_3 = x^3 $.
Точно таким же образом, мы можем создать, например, такую функцию:

[hat{y} = h_b (x) = b_0 + b_1 x + b_2 sqrt{x}]

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

И вот такое представление нелинейной функции как множественной линейной позволяет нам без изменений воспользоваться алгоритмом градиентного спуска для множественной линейной регрессии. Только вместо $ x_2, x_3, … , x_n $ нам нужно будет подставить соответствующие функции от $ x_1 $.

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

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

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

Для регрессии с двумя признаками.

Линейная модель (полином степени 1):

[h_b (x) = b_0 + b_1 x_1 + b_2 x_2]

Квадратичная модель (полином степени 2):

[h_b (x) = b_0 + b_1 x + b_2 x_2 + b_3 x_1^2 + b_4 x_2^2 + b_5 x_1 x_2]

Кубическая модель (полином степени 3):

[hat{y} = h_b (x) = b_0 + b_1 x_1 + b_2 x_2 + b_3 x_1^2 + b_4 x_2^2 + b_5 x_1 x_2 + b_6 x_1^3 + b_7 x_2^3 + b_7 x_1^2 x_2 + b_8 x_1 x_2^2]

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

Выводы:

  1. Данные в датасете не всегда располагаются так, что их хорошо может описывать линейная функция.
  2. Для описания нелинейных зависимостей нужна более сложная, нелинейная модель.
  3. Чтобы не изобретать алгоритм обучения заново, можно просто ввести в модель суррогатные признаки.
  4. Суррогатный признак — это новый признак, который считается из существующих атрибутов.
  5. Чаще всего используют полиномиальную регрессию — это когда в модель вводят полиномиальные признаки — степени существующих атрибутов.
  6. Обычно берут все комбинации факторов до какой-то определенной степени полинома.
  7. Полиномиальная регрессия может аппроксимировать любую функцию, нужно только подобрать степень полинома.
  8. Чем больше степень полиномиальной регрессии, тем она сложнее и универсальнее, но вычислительно сложнее (экспоненциально).

Практическое построение регрессии

В данной главе мы посмотрим, как можно реализовать методы линейной регрессии на практике. Сначала мы попробуем создать алгоритм регрессии с нуля, а затем воспользуемся библиотечной функцией. Это поможет нам более полно понять, как работают модели машинного обучения в целом и в библиотеке sckikit-learn (самом популярном инструменте для создания и обучения моделей на языке программирования Python) в частности.

Для понимания данной главы предполагаем, что читатель знаком с основами языка программирования Python. Нам понадобится знание его базового синтаксиса, немного — объектно-ориентированного программирования, немного — использования стандартных библиотек и модулей. Никаких продвинутых возможностей языка (типа метапрограммирования или декораторов) мы использовать не будем.

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

Применение любых моделей машинного обучения начинается с подготовки данных в необходимом формате. Для этого очень удобными для нас будут библиотеки numpy и pandas. Они практически всегда используются совместно с библиотекой sckikit-learn и другими инструментами машинного обучения. В первую очередь мы будем использовать numpy для создания массивов и операций с векторами и матрицами. Pandas нам понадобится для работы с табличными структурами — датасетами.

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

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

x = np.array([1.46, 1.13, -2.30, 1.74, 0.04, 
    -0.61, 0.32, -0.76, 0.58, -1.10, 
     0.87, 1.62, -0.53, -0.25, -1.07, 
    -0.38, -0.17, -0.32, -2.06, -0.88, ])

y = np.array([101.16, 78.44, -159.24, 120.72, 2.92, 
    -42.33, 22.07, -52.67, 40.32, -76.10, 
     59.88, 112.38, -36.54, -17.25, -74.24, 
    -26.57, -11.93, -22.31, -142.54, -60.74,])

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

1
2
3
4
5
x = np.array([
  [0, 1, 2, 3, 4],
  [5, 4, 9, 6, 3],
  [7.8, -0.1, 0.0, -2.14, 10.7],
  ])

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

Но чаще всего вы не будете задавать исходные данные явно. Практически всегда их приходится читать из каких-либо входных файлов. Удобнее всего это сделать при помощи библиотеки pandas вот так:

1
2
3
4
import pandas as pd

x = pd.read_csv('x.csv', index_col=0)
y = pd.read_csv('y.csv', index_col=0)

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

1
2
3
4
5
6
7
8
import pandas as pd

data = pd.read_csv('data.csv', index_col=0)

y = data.Y
y = data["Y"]

x = data.drop(["Y"])

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

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

1
2
3
4
5
import maiplotlib.pyplot as plt

plt.figure()
plt.scatter(x, y)
plt.show()

Конечно, такая визуализация будет работать только в случае задачи парной регрессии. Если x многомерно, то простой график использовать не получится.

Давайте соберем весь наш код вместе:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import numpy as np
import pandas as pd
import maiplotlib.pyplot as plt

# x = pd.read_csv('x.csv', index_col=0)
x = np.array([1.46, 1.13, -2.30, 1.74, 0.04, 
    -0.61, 0.32, -0.76, 0.58, -1.10, 
     0.87, 1.62, -0.53, -0.25, -1.07, 
    -0.38, -0.17, -0.32, -2.06, -0.88, ])

# y = pd.read_csv('y.csv', index_col=0)
y = np.array([101.16, 78.44, -159.24, 120.72, 2.92, 
    -42.33, 22.07, -52.67, 40.32, -76.10, 
     59.88, 112.38, -36.54, -17.25, -74.24, 
    -26.57, -11.93, -22.31, -142.54, -60.74,])

plt.figure()
plt.scatter(x, y)
plt.show()

Это код генерирует вот такой вот график:

Данные для регрессии

Как работает метод машинного обучения “на пальцах”?

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

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

1
2
3
4
5
class hypothesis(object):
    """Модель парной линейной регрессии"""
    def __init__(self):
        self.b0 = 0
        self.b1 = 0

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

Реализуем метод, который принимает значение входной переменной и возвращает теоретическое значение выходной — это прямое действие нашей регрессии — метод предсказания результата по факторам (в случае парной регрессии — по одному фактору):

1
2
    def predict(self, x):
        return self.b0 + self.b1 * x

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

Теперь зададим функцию ошибки:

1
2
    def error(self, X, Y):    
        return sum((self.predict(X) - Y)**2) / (2 * len(X)) 

В данном случае мы используем простую функцию ошибки — среднеквадратическое отклонение (mean squared error, MSE). Можно использовать и другие функции ошибки. Именно вид функции ошибки будет определять то, какой вид регрессии мы реализуем. Существует много разных вариаций простого алгоритма регрессии. О большинстве распространенных методах регрессии можно почитать в официальной документации sklearn.

Теперь реализуем метод градиентного спуска. Он должен принимать массив X и массив Y и обновлять параметры регрессии в соответствии в формулами градиентного спуска:

1
2
3
4
5
6
    def BGD(self, X, Y):  
        alpha = 0.5
        dJ0 = sum(self.predict(X) - Y) /len(X)
        dJ1 = sum((self.predict(X) - Y) * X) /len(X)
        self.b0 -= alpha * dJ0
        self.b1 -= alpha * dJ1

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

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

1
2
3
4
5
6
7
8
hyp = hypothesis()
print(hyp.predict(0))
print(hyp.predict(100))
J = hyp.error(x, y)
print("initial error:", J)
0 
0 
initial error: 36271.58344889084

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

Теперь все готово к запуску градиентного спуска.

1
2
3
4
5
6
7
8
9
10
hyp.BGD(x, y)
J = hyp.error(x, y)
print("error after gradient descent:", J)
error after gradient descent: 6734.135540194945
X0 = np.linspace(60, 180, 100)
Y0 = hyp.predict(X0)
plt.figure()
plt.scatter(x, y)
plt.plot(X0, Y0, 'r')
plt.show()

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

1
2
3
4
5
6
7
8
9
10
11
12
13
    def BGD(self, X, Y, alpha=0.5, accuracy=0.01, max_steps=5000):
        step = 0        
        old_err = hyp.error(X, Y)
        new_err = hyp.error(X, Y)
        dJ = 1
        while (dJ > accuracy) and (step < max_steps):
            dJ0 = sum(self.predict(X) - Y) /len(X)
            dJ1 = sum((self.predict(X) - Y) * X) /len(X)
            self.b0 -= alpha * dJ0
            self.b1 -= alpha * dJ1            
            old_err = new_err
            new_err = hyp.error(X, Y)
            dJ = abs(old_err - new_err) 

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

Запустим наш градиентный спуск:

1
2
3
4
5
hyp = hypothesis()
hyp.BGD(x, y)
J = hyp.error(x, y)
print("error after gradient descent:", J)
error after gradient descent: 298.76881676471504

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

Посмотрим, как теперь наша регрессия выглядит на графике:

1
2
3
4
5
6
X0 = np.linspace(60, 180, 100)
Y0 = hyp.predict(X0)
plt.figure()
plt.scatter(x, y)
plt.plot(X0, Y0, 'r')
plt.show()

Обученная регрессия

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

Как оценить качество регрессионной модели?

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    def BGD(self, X, Y, alpha=0.1, accuracy=0.01, max_steps=1000):
        steps, errors = [], []
        step = 0        
        old_err = hyp.error(X, Y)
        new_err = hyp.error(X, Y) - 1
        dJ = 1
        while (dJ > accuracy) and (step < max_steps):
            dJ0 = sum(self.predict(X) - Y) /len(X)
            dJ1 = sum((self.predict(X) - Y) * X) /len(X)
            self.b0 -= alpha * dJ0
            self.b1 -= alpha * dJ1            
            old_err = new_err
            new_err = hyp.error(X, Y)
            dJ = abs(old_err - new_err) 
            step += 1            
            steps.append(step)
            errors.append(new_err)
        return steps, errors

Мы просто запоминаем в массивах на номер шаа и ошибку на каждом шаге. Получив эти данные можно легко построить их на графике:

1
2
3
4
5
6
hyp = hypothesis()
steps, errors = hyp.BGD(x, y)

plt.figure()
plt.plot(steps, errors, 'g')
plt.show()

Прогресс обучения

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

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

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

Как подбирать скорость обучения?

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

На самом деле подобрать скорость обучения гораздо легче. Нужно использовать тот факт, что при превышении определенного порогового значения ошибка начинает возрастать. Кроме того, мы знаем, что скорость обучения должна быть положительна, но меньше единицы. Вся проблема в этом пороговом значении, которое сильно зависит от размерности задачи. При одних данных хорошо работает $ alpha = 0.5 $, а при каких-то приходится уменьшать ее на несколько порядков, например, $ alpha = 0.00000001 $.

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

Подбирать скорость обучения можно по следующему алгоритму. Сначала мы выбираем $ alpha $ близкое к 1, скажем, $ alpha = 0.7 $. Производим одну итерацию градиентного спуска и оцениваем, как изменилась ошибка. Если она уменьшилась, то ничего не надо менять, продолжаем спуск как обычно. Если же ошибка увеличилась, то скорость обучения нужно уменьшить. Например, раа в два. После чего мы повторяем первый шаг градиентного спуска. Таким образом мы не начинаем спуск, пока скорость обучения не снизится настолько, чтобы он начал сходиться.

Как применять регрессию с использованием scikit-learn?

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

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

1
from sklearn import linear_model

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

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

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

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

1
2
3
4
5
6
reg = linear_model.LinearRegression()
reg.fit(x, y)
y_pred = reg.predict(x)

print(reg.score(x, y))
print("Коэффициенты: n", reg.coef_)

В этом классе кроме уже упомянутых методов fit() и predict(), которые есть в любой модели, есть большое количество методов и полей для получения дополнительной информации о моделях. Так, практически в каждой модели есть встроенный метод score(), который оценивает качество полученной модели. А поле coef_ содержит коэффициенты модели.

Обратите внимание, что в большинстве моделей коэффициентами считаются именно параметры при входящих переменных, то есть $ b_1, b_2, …, b_n $. Коэффициент $b_0$ считается особым и хранится отдельно в поле intercept_

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

1
2
3
4
plt.figure(figsize=(12, 9))
plt.scatter(x, y, color="black")
plt.plot(x, y_pred, color="blue", linewidth=3)
plt.show()

Как мы видим, результат ничем не отличается от модели, которую мы обучили сами, вручную:

Библиотечная регрессия

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from sklearn.linear_model import LinearRegression

x = x.reshape((-1, 1))

reg = LinearRegression()
reg.fit(x, y)
print(reg.score(x, y))

from sklearn.metrics import mean_squared_error, r2_score

y_pred = reg.predict(x)
print("Коэффициенты: n", reg.coef_)
print("Среднеквадратичная ошибка: %.2f" % mean_squared_error(y, y_pred))
print("Коэффициент детерминации: %.2f" % r2_score(y, y_pred))

plt.figure(figsize=(12, 9))
plt.scatter(x, y, color="black")
plt.plot(x, y_pred, color="blue", linewidth=3)
plt.show()

Удаление. Командный штраф (Металлург Мг) оштрафованы за численное большинство

21 Октябрь 2022

00:42

26

логотип-команды

Барыс

Астана


0




5

логотип-команды

Металлург Мг

Магнитогорск

comments

Комментаторы:

Антон Васятин, Анна Пругова

stadium

Стадион:

«Барыс Арена» г Астана

time

Графика:

С графикой (счёт), без таймера

judge

Судьи:

Кулаков Сергей, Юдаков Сергей, Антонов Евгений, Кучава Торнике

  • Барыс — Металлург Мг

  • Condensed game Барыс — Металлург Мг

  • Барыс — Металлург Мг | 21.10.2022 | Обзор матча КХЛ

  • Барыс — Металлург Мг. Лучшие моменты первого периода
    0:01:34

  • Барыс — Металлург Мг. Лучшие моменты второго периода
    0:00:50

  • Барыс — Металлург Мг. Лучшие моменты матча
    0:02:40

  • Интервью. Илья Воробьев (Металлург Мг)
    0:00:45

  • Интервью. Андрей Скабелка (Барыс)
    0:00:59

  • Интервью. Павел Акользин (Металлург Мг)
    0:00:35

  • Интервью. Андрей Скабелка (Барыс)
    0:00:46

  • Раздевалка команды Металлург Мг
    0:00:40

  • Гол. 0:1. Кошелев Семён (Металлург Мг) открывает счёт
    0:00:55

  • Гол. 0:2. Голдобин Николай (Металлург Мг) выводит команду вперед
    0:00:48

  • Гол. 0:3. Никонцев Анатолий (Металлург Мг) становится автором заброшенной шайбы
    0:00:45

  • Гол. 0:4. Лайпсик Брендэн (Металлург Мг) прошивает вратаря
    0:00:47

  • Гол. 0:5. Кошелев Семён (Металлург Мг) не оставляет шансов вратарю
    0:00:53

  • Удаление. Сагадеев Антон (Барыс) зарабатывает штрафное время
    0:00:47

  • Удаление. Яковлев Егор К. (Металлург Мг) наказан за подножку
    0:00:41

  • Удаление. Мищенко Иван (Барыс) 2 мин. Игра высоко поднятой клюшкой.
    0:00:44

  • Удаление. Командный штраф (Барыс) за нарушение численного состава
    0:00:55

  • Удаление. Командный штраф (Металлург Мг) оштрафованы за численное большинство
    0:00:42

  • Удаление. Сагадеев Антон (Барыс) оштрафован за блокировку
    0:00:40

  • Удаление. Дронов Григорий (Металлург Мг) получает две штрафных минуты
    0:00:48

  • Удаление. Биграс Кристофер (Барыс) оштрафован за задержку
    0:01:27

  • Удаление. Яковлев Егор К. (Металлург Мг) отправляется в штрафной бокс
    0:00:50

  • Удаление. Земчёнок Артём (Металлург Мг) 2 мин. Толчок на борт.
    0:00:47

  • Коростелёв Никита (Металлург Мг) бросил по воротам
    0:00:40

  • Вей Линден (Барыс) наносит опасный бросок
    0:00:40

  • Майе Филипп (Металлург Мг) попытался подправить шайбу в ворота соперника
    0:00:42

  • Ножье Нельсон (Барыс) мощно бросил по воротам
    0:00:45

  • Сергиенко Юрий (Барыс) набрасывает по воротам соперника
    0:00:42

  • Луис Энтони (Барыс) бросает по воротам с разворота
    0:00:46

  • Кошечкин Василий (Металлург Мг) защитил свои ворота
    0:00:42

  • Кошечкин Василий (Металлург Мг) спас свою команду
    0:00:41

  • Кошечкин Василий (Металлург Мг) не дал сопернику забросить шайбу
    0:00:41

  • Гудачек Юлиус (Барыс) не даёт сопернику забросить шайбу
    0:00:41

Поиск видео

Подписка на трансляции

Подписка

Игроки


Фильтр задан некорректно!

Клуб А


Фильтр задан некорректно!

Клуб В


Фильтр задан некорректно!

Тип


Фильтр задан некорректно!

Даты


Фильтр задан некорректно!


Фильтр задан некорректно!

Этапы, кубки


Фильтр задан некорректно!

Сбросить

Похожие видео

0:02:16

13

Интервью. Никишин Александр

18 мая 2023

0:01:59

6

Интервью. Ерёменко Александр.

18 мая 2023

0:01:31

9

Интервью. Мозякин Сергей

18 мая 2023

0:01:57

4

Интервью. Гребёнкин Никита

18 мая 2023

0:01:20

10

Церемония закрытия сезона 2022/2023. Лучшие моменты Церемонии закрытия сезона 2022/2023

18 мая 2023

0:15:40

15

Золотой состав 15 лет КХЛ

18 мая 2023

0:10:12

3

Лучший тренер

18 мая 2023

0:04:10

11

Золотой шлем. Символическая сборная сезона.

18 мая 2023

0:07:18

5

«Золотая клюшка». Cамый ценный игрок регулярного сезона

18 мая 2023

0:06:58

6

Лучший вратарь

18 мая 2023

Прошедшие матчи

Скрыть счет

показать счет

запись матча

Хайлайтс

Condensed game

Ак Барс

Ак Барс

Казань

29 Апрель 2023, Сб

Графика

Комментарии

HD-качество

29 Апрель 2023, Сб

2
3

1:0

1:3

0:0

ЦСКА

ЦСКА

Москва

запись матча

Хайлайтс

Condensed game

ЦСКА

ЦСКА

Москва

27 Апрель 2023, Чт

Графика

Комментарии

HD-качество

27 Апрель 2023, Чт

0
3

0:1

0:1

0:1

Ак Барс

Ак Барс

Казань

запись матча

Хайлайтс

Condensed game

Ак Барс

Ак Барс

Казань

25 Апрель 2023, Вт

Графика

Комментарии

HD-качество

25 Апрель 2023, Вт

2
1

0:1

1:0

1:0

ЦСКА

ЦСКА

Москва

запись матча

ЦСКА

ЦСКА

Москва

23 Апрель 2023, Вс

Графика

Комментарии

HD-качество

23 Апрель 2023, Вс

2
1

1:1

0:0

1:0

Ак Барс

Ак Барс

Казань

запись матча

Хайлайтс

Condensed game

ЦСКА

ЦСКА

Москва

21 Апрель 2023, Пт

Графика

Комментарии

HD-качество

21 Апрель 2023, Пт

3
2

0:0

3:1

0:1

Ак Барс

Ак Барс

Казань

запись матча

Хайлайтс

Condensed game

Ак Барс

Ак Барс

Казань

19 Апрель 2023, Ср

Графика

Комментарии

HD-качество

19 Апрель 2023, Ср

0
3

0:1

0:1

0:1

ЦСКА

ЦСКА

Москва

Выбор болельщиков

сегодня

7 дней

30 дней

за все время

06 октября 2012

0:00:51

772

2

Гол. Жафяров (Металлург Нк) сравнивает счёт, без оплошности Ари Ахонена (Металлург Нк) не обошлось (1:1).

18 мая 2023

0:03:08

255

1

Никита Гребёнкин получает приз имени Черепанова

18 мая 2023

0:06:00

418

1

Никита Серебряков — лучший вратарь сезона Фонбет КХЛ

24 февраля 2023

0:01:19

2 491

1

Гол. 3:6. Юров Данила (Металлург Мг) засчитанная шайба после броска по пустым воротам

24 февраля 2023

0:01:09

2 834

1

Гол. 0:1. Коростелёв Никита (Металлург Мг) наказал за ошибку

22 ноября 2022

0:01:27

12 491

1

Гол. 1:0. Венгрыжановский Денис (Торпедо). Открывает счет в матче

15 октября 2021

0:01:17

3 635

1

Гол. 4:4. Шрёдер Джордан (Йокерит) делает счёт равным

Моменты

Рекомендуемые

Популярные

18 мая 2023

0:05:13

81

Василий Кошечкин получает Приз имени Сергея Гимаева

18 мая 2023

0:08:09

129

Белов и Шелянин получают приз лучшим арбитрам сезона

18 мая 2023

0:03:12

46

Александр Никишин — самый результативный защитник сезона

17 мая 2023

0:04:06

553

Самые сильные броски сезона Фонбет КХЛ 2022/2023

11 мая 2023

0:09:06

701

Золотые голы в истории КХЛ

10 мая 2023

0:05:25

482

Лучшие передачи сезона КХЛ 2022-2023

09 мая 2023

0:04:00

706

Самые сильные броски Плей-офф Кубка Гагарина 2023

04 мая 2023

0:02:48

482

Лучшие передачи Финала Кубка Гагарина 2023

Топ-10

Голы

Сейвы

Самые сильные броски

Выбор болельщиков

Подписка на трансляции

Подписка

16 мая 2023

0:03:39

930

Лучшие голы Финала Кубка Гагарина 2023

09 мая 2023

0:04:00

706

Самые сильные броски Плей-офф Кубка Гагарина 2023

03 мая 2023

0:02:21

424

Самые сильные броски Финала Кубка Гагарина 2023

17 апреля 2023

0:03:43

911

Лучшие голы финалов конференций Кубка Гагарина 2023

04 апреля 2023

0:03:48

1 084

Лучшие голы второго раунда плей-офф Кубка Гагарина 2023

17 марта 2023

0:03:50

2 399

Лучшие голы первого раунда плей-офф Кубка Гагарина 2023

15 марта 2023

0:03:56

781

Самые сильные броски первого раунда плей-офф Кубка Гагарина 2023

02 марта 2023

0:07:04

2 377

Лучшие снайперы в истории КХЛ

02 марта 2023

0:04:06

1 326

Самые сильные броски регулярного сезона Фонбет Чемпионата КХЛ 22/23

01 марта 2023

0:04:27

2 366

Лучшие голы регулярного сезона Фонбет Чемпионата КХЛ 22/23

Понравилась статья? Поделить с друзьями:
  • Числа от 1 до 20 найти ошибку
  • Читать ошибки на авто как называется
  • Чипсет amd lpc filter ошибка установки
  • Читать ошибки ваз 2110
  • Чиплоадер ошибка открытия порта