Машинное обучение (ML) - это изучение компьютерных алгоритмов, которые улучшаются с опытом и использованием данных. Алгоритмы машинного обучения создают модель на основе выборочных данных (обучающих данных) и делают прогнозы или решения, используя эту модель, не будучи запрограммированными на это.

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

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

Цены на авиабилеты могут быть чем-то трудно угадываемым, сегодня мы можем увидеть цену, узнать цену на тот же рейс завтра, и это будет другая история.

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

Набор данных

Ссылка на набор данных - https://github.com/dsrscientist/Data-Science-ML-Capstone-Projects

У нас есть 2 набора данных - обучающий набор и тестовый набор.

Учебный набор содержит функции, а также цены на авиабилеты. Он содержит 10683 записи, 10 входных характеристик и 1 выходной столбец - «Цена».

Набор тестов содержит 2671 запись и 10 входных характеристик. Выходной столбец «Цена» должен быть предсказан в этом наборе. Здесь мы будем использовать методы регрессии, так как прогнозируемый результат будет непрерывным значением.

Ниже приводится описание функций, доступных в наборе данных.

1. Авиакомпания: название авиакомпании.

2. Date_of_Journey: дата поездки.

3. Источник: источник, с которого начинается обслуживание.

4. Пункт назначения: пункт назначения, в котором заканчивается обслуживание.

5. Маршрут: маршрут, по которому самолет достигает пункта назначения.

6. Dep_Time: время, когда путешествие начинается от источника.

7. Arrival_Time: время прибытия в пункт назначения.

8. Продолжительность: общая продолжительность полета.

9. Total_Stops: общее количество остановок между исходным и конечным пунктами.

10. Additional_Info: дополнительная информация о рейсе.

11. Цена: цена билета.

Содержание статьи

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

1. Исследовательский анализ данных и моделирование данных

2. Обнаружение выбросов и обработка асимметрии

3. Кодирование данных - Label Encoder.

4. Масштабирование данных - стандартный масштабатор.

5. Подгонка моделей машинного обучения

6. Перекрестная проверка выбранной модели.

7. Гипер-тюнинг модели.

8. Сохранение окончательной модели и прогноза с использованием сохраненной модели.

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

Исследовательский анализ данных и моделирование данных

Мы загружаем обучающий набор данных с помощью библиотеки Pandas -

Первый шаг - взглянуть на образец наших данных -

Мы определяем нижеперечисленные моменты на первый взгляд -

1. Столбец «Маршрут» содержит список городов, которые нам нужно будет разделить, поскольку в нашем наборе данных будет несколько комбинаций.

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

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

4. К общему количеству остановок также добавлен текст «остановки» вместе с количеством остановок, а в некоторых столбцах указано «без остановок», которые нам нужно будет преобразовать в целочисленные типы.

Далее мы приступаем к изучению набора данных.

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

Мы заметили, что у нас все столбцы являются типами данных «объект», и только столбец «Цена» (вывод) имеет целочисленный тип. Поскольку мы знаем, что обозначают наши столбцы, мы знаем, какие столбцы нам нужно обработать!

Теперь мы проверяем количество значений NaN (null) в нашем наборе данных, что дает следующий результат:

У нас есть 1 пропущенное значение в столбце Маршрут и 1 пропущенное значение в столбце Всего остановок. В дальнейшем мы будем конструктивно заменять недостающие значения.

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

Мы замечаем, что -

  1. В столбце «Авиакомпания» есть 12 уникальных значений: «IndiGo», «Air India», «Jet Airways», «SpiceJet», «Несколько перевозчиков», «GoAir», «Vistara», «Air Asia», «Vistara Premium Economy», « Jet Airways Business »,« Несколько перевозчиков Премиум-эконом »,« Trujet ».
  2. 2. Исходный столбец имеет 5 уникальных значений: «Бангалор», «Калькутта», «Ченнаи», «Дели» и «Мумбаи».
  3. 3. Столбец назначения имеет 6 уникальных значений - «Нью-Дели», «Банглор», «Кочин», «Калькутта», «Дели», «Хайдарабад».
  4. 4. Столбец дополнительной информации содержит 10 уникальных значений: «Нет информации», «Питание на борту не включено», «Регистрация багажа не включена», «1 короткая пересадка», «Нет информации», «1 длительная пересадка», «Изменить аэропорт», «Бизнес-класс», «Полет с красными глазами», «2 Длительная пересадка».

Теперь мы разделим столбец «Дата», чтобы извлечь значения «Дата», «Месяц» и «Год» и сохранить их в новых столбцах нашего фрейма данных.

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

Поскольку максимальное количество остановок - 4, на каждом конкретном маршруте должно быть максимум 6 городов. Мы разделяем данные в столбце маршрута и сохраняем все названия городов в отдельных столбцах -

Аналогичным образом мы разделяем столбец Dep_time и создаем отдельные столбцы для часов и минут отправления -

Далее, для разделения даты прибытия и времени прибытия, мы разделяем столбец «Arrival_Time» и создаем столбец «Arrival_date». Мы также разбиваем время и делим его на «Arrival_time_hours» и «Arrival_time_minutes», аналогично тому, что мы делали со столбцом «Dep_time» -

Затем мы делим столбец «Продолжительность» на «Время в пути» и «Время в пути».

Мы также обрабатываем столбец «Total_stops» и заменяем беспосадочные рейсы значением 0 и извлекаем целую часть столбца «Total_Stops» -

Далее мы переходим к столбцу «Дополнительная_информация», где мы замечаем, что есть 2 категории, обозначающие «Нет информации», которые делятся на 2 категории, поскольку «I» в «Нет информации» является заглавной. Мы заменяем «Нет информации» на «Нет информации», чтобы объединить ее в единую категорию -

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

Замена недостающих значений

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

Мы решили опустить столбец «City4», поскольку 9117 значений из 10683 строк содержат значения NaN. Затем мы распечатываем строку с отсутствующими данными City1.

Мы обнаруживаем, что это та же строка, в которой отсутствовал «Маршрут». В этой строке также указано «Total_stops» как NaN. Мы заменяем City 1 в этой строке на «DEL» и «City2» на COK. Мы заменяем "Total_stops" на 0.

Далее мы заменяем значения «NaN» в «City3» на «None», поскольку в строках, в которых отсутствует «City3», не было никакой остановки, только источник и пункт назначения.

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

Мы также заменяем отсутствующие значения в поле «Travel_mins» на 0, поскольку отсутствующие значения означают, что время в пути указано только в часах, а не в дополнительных минутах.

Используя вышеуказанные шаги, мы успешно смогли обработать все недостающие значения из наших данных. Мы снова проверяем информацию в наших данных и обнаруживаем, что в наборе данных все еще есть типы данных для нескольких столбцов как «объект», где он должен быть «int» -

Следовательно, мы пытаемся изменить тип данных необходимых столбцов -

На этом этапе мы сталкиваемся с проблемой преобразования столбца «Travel_hours», в котором говорится, что в столбце есть данные как «5m», что не позволяет преобразовать его в «int».

Мы печатаем эту строку, чтобы один раз проверить данные -

Данные показывают, что время полета составляет «5 минут», что явно неверно, поскольку самолет не может вылететь из БОМБАЯ- ›ГОА-› ПУНЕ- ›ХАЙДАРАБАД за 5 минут! (Для этого рейса "Total_stops" равно 2)

Мы решили удалить эту строку из-за неправильных данных в строке.

Затем мы преобразуем столбец «Travel_hours» в тип данных «int», и операция выполняется успешно.

Теперь у нас есть обработанный набор данных с 10682 строками и 19 столбцами (18 независимых и 1 зависимая переменная).

Мы создаем отдельные списки категориальных столбцов и числовых столбцов для построения и анализа данных -

Продолжение построения и анализа данных с использованием библиотек seaborn, matplotlib -

Построение графиков для категориальных данных -

Мы делаем указанные ниже наблюдения, используя графики выше -

Авиакомпании

  • Jet Airways - самая предпочтительная авиакомпания с наибольшим количеством строк, за ней следуют Indigo и AirIndia.
  • Рассчитывайте на Vistara Premium Economy, Trujet, Multiple предлагает премиум-эконом и Jet airways.

Источник

  • Большинство рейсов вылетают из Дели.
  • В Ченнаи минимальное количество взлетов рейсов

Место назначения

  • Максимальное количество рейсов приземляется в Коччи
  • У Калькутты самое низкое количество принимающих рейсов

Дополнительная информация

  • Максимальное количество строк имеет значение Нет информации.
  • Нам нужно проверить, как этот столбец влияет на цены.

City1

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

City2

  • Большинство рейсов совершают остановки в Бомбее.
  • Во многих городах очень мало остановок. Мы проверим, как рейсы с 1-й вершиной влияют на стоимость полетов, и есть ли какая-либо связь с местом остановки.

City3

  • У большинства рейсов нет второй остановки
  • Если есть вторая остановка, высоки шансы, что это место находится в Коччи.

Теперь мы построим графики распределения, чтобы проверить распределение в числовых данных -

Мы делаем следующие наблюдения из числовых данных -

Всего остановок

  • Большинство рейсов имеют остановки как 1, рейсы с 3 и 4 остановками довольно низкие.

Дата

  • Нет конкретных дат, когда рейсы прибывают; распределение практически одинаково для всех дат

Месяц

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

Год

  • В этом столбце указано значение только 2019, и его можно опустить.

Dep_Time_Hour

  • Большинство рейсов совершаются рано утром.
  • Количество рейсов, вылетающих с 16:00 до 23:00, также велико. Дневных рейсов меньше.

Dep_Time_Min

  • Большинство рейсов вылетают в полные часы (мин как 00)

Дата прибытия

  • В большинстве случаев рейсы вылетают и приземляются в один и тот же день.

Время прибытия, час

  • Большинство рейсов прибывают в пункт назначения в вечернее время около 18: 00-19: 00.
  • Похоже, это связано с тем, что большинство рейсов вылетают утром и, следовательно, приземляются вечером.

Время прибытия мин.

  • Этот дистрибутив похож и не выдает никакой специальной информации.

Часы в пути

  • На большинство рейсов время в пути составляет около 2-3 часов, что кажется нормальным, поскольку это внутренние рейсы.
  • У некоторых рейсов есть время около 30 часов, это может быть из-за количества промежуточных остановок.

Минуты в пути

- Данные разделены и не указывают на какие-либо конкретные точки

Распределение столбца "Цена"

Столбец цен содержит минимальное значение 1759 и максимальное значение 79512. Большинство рейсов имеют диапазон цен от 1759 до 20 тысяч, а количество рейсов с ценой выше 20 тысяч значительно меньше. Ценовой диапазон смещен вправо.

Теперь мы сравним независимые характеристики со столбцом «Цена», чтобы проверить влияние на «Цена».

Мы делаем следующие наблюдения -

- Бизнес-класс Jet Airways имеет самые высокие цены от 50 до 80 тысяч.

- Все высокобюджетные рейсы отправляются из Бангалора, остальные рейсы имеют цены от 3 до 50 тысяч.

- Все высокобюджетные рейсы выполняются в Дели, остальные рейсы имеют цены от 3 до 50 тысяч.

- Если рейс бизнес-класса, его цена будет высокой.

- Рейсы по высокой цене с 1 пересадкой, с пересадкой в ​​Бомбее.

- Рейсы с 2 пересадками, имеющие более высокую цену, имеют остановку в Дели.

У нас гораздо меньше данных там, где цены выше 50к. Проверяем эти строки один раз -

Мы делаем следующие наблюдения -

- Мы наблюдаем, что рейсов с высокой ценой всего 8.

- Большинство этих рейсов выполняются по одному маршруту - BLR- ›BOM-› DEL.

- Большинство рейсов относятся к бизнес-классу.

- Все рейсы имеют Airlines как Jet airways.

- Все эти рейсы вылетели в марте.

Теперь перейдем к проверке связи столбца «Цена» с числовыми данными -

Мы замечаем, что -

- По мере увеличения количества стопов диапазон цен сокращается до меньшего ценового окна (10–22 000).

- Полеты с высокими ценами меньше в конце месяца

- Цены выше в марте месяце

- С увеличением времени в пути цена увеличивается, а количество рейсов уменьшается.

После проведенного выше анализа мы отбрасываем ненужные столбцы, которые, по нашему мнению, не влияют на цены на авиабилеты. Эти столбцы включают Dep_Time_Min, Arrival_Time_Min, Travel_mins, Year, City1.

Теперь у нас есть окончательный набор данных с 10682 строками и 14 столбцами (включая столбец «Цена»).

Обнаружение выбросов

Теперь мы построим коробчатые диаграммы, чтобы проверить наличие выбросов в наших данных -

Делаем следующие выводы -

- Выбросы присутствуют в Общих часах, Общих остановках и цене.

- Мы не будем удалять выбросы из общего количества остановок, так как на цену влияет количество остановок.

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

Лечение асимметрии

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

Нам нужно обработать асимметрию для столбца «Travel_hours», учитывая пороговое значение для асимметрии как +/- 0,5 (мы не будем преобразовывать столбец «Price», поскольку это наша целевая переменная).

Мы используем метод преобразования журнала, чтобы удалить перекос -

Мы успешно устранили асимметрию наших данных. Теперь перейдем к шагу «Кодирование».

Кодирование категориальных данных

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

Наши преобразованные данные выглядят примерно так -

Масштабирование данных

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

Мы используем стандартный скейлер для этого процесса -

StandardScaler следует за стандартным нормальным распределением (SND). Следовательно, он принимает среднее значение = 0 и масштабирует данные до единичной дисперсии

Наши масштабированные данные выглядят так, как показано ниже -

Подбор регрессионных моделей

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

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

Мы достигли наилучшего результата с помощью регрессора K-Neighbours с r2_score, равным 81%. Мы также получаем минимальные значения для mean_absolute_error, mean_squared_error и root_mean_squared_error (показатели регрессии) с этой моделью.

Мы пытаемся использовать ансамблевые модели, чтобы проверить, улучшается ли наша производительность, используя ансамблевые модели -

Мы делаем следующие наблюдения -

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

Мы постараемся настроить эту модель, чтобы проверить, удастся ли убрать переоснащение.

Средняя абсолютная ошибка для этой модели составляет ~ 723 и RMSE ~ 1607.

Повышение градиента также дает оценку 84%, что лучше, чем у K-Neighbours, и модель также не переоснащается.

Модель имеет среднюю абсолютную ошибку ~ 1234 и RMSE ~ 1753 (рядом со случайным лесом).

Перекрестная проверка

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

Регрессор случайного леса дает нам оценку перекрестной проверки 86%, а регрессор с градиентным бустом дает оценку 82%. Мы настроим обе модели, чтобы проверить, улучшилась ли наша точность.

Гипертюнинг модели

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

R2_score, полученный для Регрессора с усилением градиента, оказывается лучше после гипертюнинга, который составляет 86%, по сравнению с регрессором случайного леса, дающим точность 82%. Значение MAE также уменьшается, что означает, что мы смогли настроить нашу модель.

Следовательно, мы выбираем Gradient Boosting Regressor в качестве нашей окончательной модели, сохраняем модель с использованием лучших параметров и создаем объект модели с помощью joblib.

Заключение

Далее мы приступаем к тестированию объекта, который мы сохранили с помощью joblib, и создаем фрейм данных с предсказанными значениями -

В качестве окончательных показателей мы получаем следующие показатели -

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

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

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

Следовательно, в конце мы смогли успешно обучить нашу регрессионную модель «Gradient Boosting Regressor» для прогнозирования колебаний цен с r2_score 87% и успешно выполнили требуемую задачу.