Машинное обучение (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 пропущенное значение в столбце Всего остановок. В дальнейшем мы будем конструктивно заменять недостающие значения.
Теперь мы начинаем изучать столбцы, доступные в нашем наборе данных. Первое, что мы делаем, это создаем список категориальных столбцов и проверяем уникальные значения, присутствующие в этих столбцах -
Мы замечаем, что -
- В столбце «Авиакомпания» есть 12 уникальных значений: «IndiGo», «Air India», «Jet Airways», «SpiceJet», «Несколько перевозчиков», «GoAir», «Vistara», «Air Asia», «Vistara Premium Economy», « Jet Airways Business »,« Несколько перевозчиков Премиум-эконом »,« Trujet ».
- 2. Исходный столбец имеет 5 уникальных значений: «Бангалор», «Калькутта», «Ченнаи», «Дели» и «Мумбаи».
- 3. Столбец назначения имеет 6 уникальных значений - «Нью-Дели», «Банглор», «Кочин», «Калькутта», «Дели», «Хайдарабад».
- 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% и успешно выполнили требуемую задачу.