Создание ИТ-сервиса, позволяющего с помощью алгоритмов машинного обучения прогнозировать вероятность возникновения задержек авиарейсов
Сбор и агрегация исторических данных о регулярных рейсах авиакомпаний. Особенность создания модели машинного обучения для предсказания вероятности отмены маршрута. Характеристика формирования ИТ-сервиса для предоставления доступа к предиктивной модели.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 09.08.2018 |
Размер файла | 948,2 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
* snowfall - количество миллиметров снега, выпавших в конкретный день;
* snow_depth - количество миллиметров снега, оставшихся на поверхности;
* thunder - был ли в выбранный день сильный ветер;
* dust - ветер с пылью в конкретный день;
* haze - легкий туман;
* snow - наличие снежного покрова;
* fog - густой туман;
* hail - наличие града;
* damaging_wind - наличие ветра разрушительной силы.
Наконец, в ходе анализа ряда гипотез и более детального рассмотрения имеющихся данных, были созданы новые переменные, позволяющие улучшить общее качество работы алгоритмов. Так, к информации о каждом рейсе были добавлены следующие переменные:
* airline_delay_index - рассчитанный ранее индекс задержек авиакомпании;
* airline_avg_delay - величина средней задержки у авиакомпании;
* day_of_year - текущий день года;
* weekend - является ли день вылета выходным или праздником;
* previous_flight_delay - был ли задержан предыдущий рейс для самолета, осуществляющего текущий рейс.
3.3 Обучение моделей машинного обучения
Закончив предварительную обработку данных, было начато обучение различных моделей классификаторов с целью нахождения наиболее качественной модели машинного обучения (Приложение 2).
Так как количество данных, доступных для задачи, очень велико, а сами данные достаточно различны, было принято решение не создавать одну общую модель, описывающую перелеты из любого города, а обучать модели для каждого из городов отдельно. Благодаря такому методу обучения финальной модели, не только уменьшились общие требования к вычислительным мощностям, но и существенно выросла будущая мобильность решения, позволяющая заменять классификаторы постепенно для каждого из городов.
Для обучения моделей использовался модуль GridSearchCV , позволяющий не только обучить модель классификатора, но и подобрать наиболее оптимальные параметры. В качестве тестового города, на котором происходил поиск наиболее оптимальной модели был выбран город Алабама, так как количество вылетов из него соответствует среднему количеству по стране, а сами данные достаточно качественные. Данный набор данных был разделен на тестовую и обучающую выборки в соотношении 20 к 80. Таким образом было получено две выборки, одна - для обучения, вторая - для проверки полученной модели. Также для обучения классификаторов использовался подход фолдирования выборки с помощью методов библиотеки StratifiedKFold , дополнительно разбивающий обучающую выборку на меньшие выборки с целью уменьшения степени переобучения.
В рамках выбора наиболее качественной модели классификации было произведено обучение следующих моделей:
* Random Forest;
* AdaBoost Classifier;
* Decision Tree Classifier;
* K-Neighbors Classifier;
* Gradient Boosting Classifier.
В качестве оценки качества обучения была использована метрика для оценки мульти классовой классификации - взвешенная вариация F-меры (f1-weighted) .
Для каждой из модели был представлен набор возможных параметров, влияющих на процесс обучения. Каждый из возможных наборов был использован для создания классификатора, а затем, оценен с помощью используемой метрики с целью нахождения наиболее качественного классификатора для каждой из моделей.
В итоге, результаты, полученные после выполненной оценки качества обучения всех моделей, представлены на рис. 15.
Исходя из полученных выше результатов, наиболее высокую точность предсказания показал классификатор Gradient Boosting Classifier, однако, при более детальной оценке классификаторов с использованием других метрик для оценки качества предсказания, наиболее оптимальным был выбран Random Forest Classifier, так как он более качественно предсказывал задержки рейсов.
Сводная таблица точности каждого из классификаторов при обучении с наиболее оптимальными параметрами
Завершив работу по выбору наиболее оптимального классификатора, на базе полученной модели для каждого из доступных городов США была построена выборка, содержащая данные о совершенных регулярных рейсах из данного аэропорта. Для каждой из полученных выборок был построен собственный классификатор, позволяющий производить предсказание рейсов из указанного аэропорта. Среднее значение взвешенной F-метрики для всех городов выборки составила 0.93, что является очень хорошим показателем. Значения взвешенной F-метрики для первых 20 городов выборки представлены в таблице 1.
Таблица 1
Значения F-метрики на тестовых значениях для первых 20 городов выборки
Код аэропорта Город Значение взвешенной F-метрики
ABE Аллентаун 0,937067
ABI Абилин 0,928000
ABQ Альбукерке 0,950335
ABR Абердин 0,958602
ABY Олбани 0,915504
ACK Нантакет 0,887218
ACT Вако 0,949776
ACV McKinleyville 0,888557
ACY Атлантик-Сити 0,900806
ADK Адак 0,855182
ADQ Аплтон 0,938117
AEX Александрия 0,922271
AGS Огаста 0,942828
AKN Кинг-Салмон 0,916667
ALB Олбани 0,944369
ALO Ватерлоо 0,965220
AMA Ама 0,945055
ANC Анкоридж 0,965773
APN Альпена 0,924694
ASE Аспен 0,874242
Глава 4. Формирование ИТ-сервиса для предоставления доступа сторонним программным решениям с использование программного интерфейса API к построенной модели предсказания статуса рейсов
В данном разделе рассмотрены вопросы создания финального веб-сервиса, позволяющего посредствам HTTP API предоставлять сторонним приложениям доступ к построенной ранее модели. А также приведены возможные варианты минимизации и сокращения затрат международных компаний от внедрения данного сервиса в собственные программные решения.
4.1 Формирование ИТ-сервиса для предоставления доступа к предиктивной модели
Осуществив выбор и построение классификаторов для каждого из городов выборки, было начато построение веб-сервиса для предоставления общего доступа к построенной аналитической модели. Для построения данного сервиса был выбран фреймворк для веб-разработки на Python - Flask. Данный выбор был обусловлен как исключительной простотой данного фреймворка, так и совпадением платформ - анализ и построение аналитических моделей было произведено с использованием языка Python. Таким образом, использование фреймворка для того же языка программирования упрощает взаимную интеграцию и ускоряет общее время разработки. В общем же разработка веб-сервиса была разбита на три этапа:
* Перенос моделей классификаторов.
* Написание методов API для доступа к построенным моделям.
* Проверка и тестирование полученного веб-сервиса.
Для переноса моделей была использована популярная библиотека Pickle, позволяющая производить бинарную сериализацию Python-объектов. Благодаря применению данного решения, все классификаторы для 235 городов США были сохранены в отдельные бинарные файлы, представляющие собой обученные модели классификации. Также, для дальнейших целей обработки поступающих данных, была сериализована информация о рейтингах задержек авиакомпаний, а также прочие статистические сведения, сформированные ранее. Данный подход к решению переноса моделей не только предельно прост, но и позволяет в дальнейшем использовать сериализованные модели на различных платформах с использованием отличных от Python, языков программирования.
Далее, завершив перенос данных, было начато построение методов API для организации доступа к модели. Исходя из поставленных задач, а также текущих возможностей построенных моделей классификации для формирования базового функционала ИТ сервиса (Приложение 3), были реализованы следующие методы API:
* HTTP GET /api/flights/predict - метод, для предсказания статуса рейса. Метод принимает следующие параметры:
? origin - IATA код аэропорта отправления;
? dest - IATA код аэропорта прибытия;
? carrier - IATA код авиакомпании;
? fl_num - номер рейса авиакомпании;
? flight_date - дата вылета.
* HTTP GET /api/airlines/ - метод, для получения списка всех авиакомпаний, присутствующих в базе приложения.
* HTTP GET /api/airlines/flights/ - метод, для получения списка всех авиарейсов авиакомпании, присутствующих в базе приложения. Метод принимает следующие параметры:
? сarrier - IATA код авиакомпании.
* HTTP GET /api/airlines/delay_rating - метод, для получения рейтинга задержек авиакомпаний.
* HTTP GET /api/last_update/ - метод, для получения даты последнего обновления предиктивных моделей.
Ввиду высокой ресурсоемкости предсказания статусов рейсов, а также для уменьшения времени ответа сервиса, для всех методов приложения было реализовано кэширование с использованием библиотеки Memcached.
Рассмотрим более подробно работу веб-приложения, а также наиболее интересный и сложный метод сервиса - метод предсказания статуса рейса. Итак, при запуске приложения, для инициализации всех модулей, данные классификаторов, а также дополнительные сведения, необходимые для обработки данных, загружаются в оперативную память веб-сервера. Таким образом, при использовании In-Memory подхода для хранения данных, обеспечивается не только высокая скорость работы приложения, но и исключаются многие из возможных проблем, связанных с высокими нагрузками на дисковое хранилище.
Переходя к рассмотрению алгоритма работы метода API построенного ИТ сервиса для предсказания статуса рейса, следует рассмотреть общую последовательность действий, выполняемых при запросе статуса рейса. Так, последовательность выглядит следующим образом:
1. Получение начальных параметров.
После получения запроса на предсказание статуса рейса, входные проверяются на корректность, а также наличие исторических сведений о данном перелете в базе приложения.
Выполняется валидация входных данных с целью проверки корректности входных параметров запросов. В случае передачи ошибочных данных, либо использования некорректного обращения методу веб-сервиса, пользователю выводится информационный ответ, указывающий на наличие ошибок в сформированном запросе.
2. Предобработка данных с учетом аэропорта вылета.
При корректно введенных данных и аэропорта вылета, происходит поиск данных, необходимых для предобработки входных данных, а также происходит запрос к сервису погодных данных - OpenWeather для определения текущей погоды в аэропорту вылета. Так как доступ к погодным данным ограничен, погодные данные также кэшируются. Далее, получив набор необходимых сведений, происходит обработка данных к необходимому для предиктивной модели виду.
3. Предобработка данных с учетом аэропорта вылета.
Завершив предобработку данных, классификатор, соответствующий аэропорту вылета рейса, производит предсказание статуса рейса на базе предобработанных данных.
4. Финальная обработка данных и формирование выходного ответа в формате JSON .
По окончанию работы классификатора, полученный результат, содержащий вероятности для каждого из возможных статусов рейса (вовремя, задержан, отменен), кэшируется, а сформированный ответ в формате JSON отправляется на клиентскую сторону. Выполнение запроса окончено.
Таким образом, в результате выполнения указанных действий, был получен отказоустойчивый веб-сервис, способный с высокой скоростью генерировать наиболее вероятный статус рейса для любого из актуальных регулярных рейсов внутри США.
4.2 Проверка качества работы сформированного ИТ-сервиса
Завершив построение архитектуры ИТ-сервиса по предсказанию статуса регулярных рейсов, было начато финальное развертывание построенного веб-ресурса на облачную платформу Amazon AWS для организации отказоустойчивого и масштабируемого доступа к построенной системе. Ввиду отсутствия высокого уровня нагрузки на ранних этапах существования проекта, а также низкой цены размещения, для первоначального развертывания сервиса был выбран VPS начального уровня - t2.small.
После завершения развертывания сервиса, осуществив запросы к описанным ранее методам ИТ-сервиса, была выполнена проверка работоспособности каждого из методов HTTP API.
В первую очередь была выполнена проверка работы методов, не связанных напрямую с аналитической моделью:
* Метод получения списка поддерживаемых авиакомпаний
GET /api/airlines/
Результат выполнения работы данного метода представлен на рисунке 16.
Результат выполнения метода получения списка авиакомпаний
* Метод получения списка всех рейсов авиакомпании
GET /api/airlines/flights/
с параметром: carrier - UA
Результат выполнения метода по формированию списка всех рейсов авиакомпании представлен на рисунке 17.
Результат выполнения метода получения списка рейсов авиакомпании (UA)
* Метод получения общего рейтинга задержек авиакомпаний
GET /api/airlines/delay_rating
Результат выполнения метода получения общего рейтинга задержек авиакомпаний изображен на рисунке 18.
Результат выполнения метода получения рейтинга задержек авиакомпаний
* Метод получения даты последнего обновления предиктивных моделей
GET /api/last_update
Результат выполнения метода получения даты последнего обновления предиктивных моделей представлен на рисунке 19.
Результат выполнения метода получения даты последнего обновления моделей классификации
Далее была проверена работа и основного метода API.
* Метод предсказания задержек рейсов.
HTTP GET /api/flights/predict
cо следующими параметрами:
origin - ABR;
dest - MSP;
carrier - OO;
fl_num - 7363;
flight_date - 2018-2-3.
Результат выполнения метода предсказания задержек рейсов представлен на рисунке 20.
Результат выполнения метода предсказания статуса рейса
В результате выполнения запроса был предсказан статус рейса № 7363 авиакомпании SkyWest из аэропорта города Абердин (ABR) в город Миннеаполис (MSP) на 13 мая 2018 года. Ответ сервиса содержит технические данные, а также вероятности для каждого из возможных классов модели: машинный обучение предиктивный сервис
* cancelled_flight (рейс отменен) - 2.5%;
* delay (рейс задержан более, чем на 30 минут) - 0%;
* no_delay (рейс выполняется без задержек) - 97.5%.
Таким образом, в завершении данной работы, был получен масштабируемый отказоустойчивый веб-сервис, способный на базе погодных и исторических данных с высокой точностью (средняя точность предсказания более 80%) предсказывать статус регулярных рейсов внутри США и предоставлять полученный результат для взаимодействия и интеграции с другими программными решениями.
4.3 Оценка возможных выгод для бизнеса от внедрения предиктивной модели
Переходя к вопросу оценки возможных выгод от внедрения подобной предиктивной модели, в первую очередь, следует отметить размеры финансовых потерь, получаемых как авиакомпаниями, бизнесом так и частными пассажирами. Так, согласно коллективному исследованию «Total Delay Impact Study» (2010), в общемировой экономике общая стоимость задержек рейсов составляет 32.9 млрд. долл., что представляет собой исключительно высокий уровень расходов. Согласно исследованию, более половины всех затрат, связанных с задержками, несут сами пассажиры, в то время, как финансовые потери авиакомпаний и прочих агентов существенно ниже. Так, согласно еще одному исследованию Грэма Таннера и Эндрю Кука, «European airline delay cost reference values» (Graham Tanner, Andrew Cook, 2011), стоимость задержки рейса для пассажиров может достигать величины 150 долларов в час, что, естественно, является существенной статьей расходов, в частности, в случае групповых поездок, и сильно увеличивает общую стоимость поездок. Издержки же для бизнеса представляют еще большие значения, так как отсутствие ключевых сотрудников может приводить как к срыву встреч, так и к задержкам по ключевым задачам бизнеса, что в ряде случаев может приводить к издержкам существенного более высокого уровня.
Для уменьшения возможности происшествий, компании диверсифицируют свои риски, отправляя своих сотрудников заранее, либо, в случае возникновения чрезвычайных ситуаций, организовывают другие, более дорогие стыковки авиарейсов. Использование данного подхода влечет за собой существенные излишне высокие финансовые затраты. Так, при средней стоимости одного дня поездки в 321 доллар на одного сотрудника (Business Travel News Corporate Travel Index, 2017), и наличии не менее 10 сотрудников, находящихся в командировках, выходит, что раннее прибытие сотрудников может быть оценено не меньше, чем в 3500 долларов в сутки без учета необходимости изменения билетов на другой рейс в случае возникновения чрезвычайных происшествий. В случае нечастых поездок (3 раза в год для 1 сотрудника), потери компании составят уже 10000 долларов - существенная сумма, оптимизация которой может существенно снизить стоимость организации командировок для компании. В случае более крупных компании, возможные финансовые выгоды будут еще выше.
Исходя из этого, внедрение предиктивной системы, описанной в данной работе позволит не только снизить операционные расходы на организацию командировок за счет исключения дополнительного времени, заложенного на случай задержки, но и существенно повысить качество и скорость перевозок сотрудников в рамках рабочих поездок.
Данный сервис будет полезен и для частных пассажиров, планирующих свои путешествия.
Заключение
В ходе выполнения данной работы было достигнуто решение ряда целей и задач, поставленных при формировании изначальной идеи проекта.
В первую очередь, был проведен анализ рынка авиационной статистики, а также моделей предоставления статистических данных. В результате чего был выбран источник статистических данных - Bureau of Transportation Statistics и целевой регион для первоначального тестирования предиктивных моделей - США.
Затем, на базе имеющихся интерфейсов для сбора данных, был создан модуль для организации сбора и агрегации больших массивов исторических данных по осуществленным перелетам и сопутствующим погодным условиям. Результатом решения данной задачи стало создание массивного банка данных, насчитывающего в себе более 8 миллионов записей, и содержащего информацию о перелетах всех регулярных рейсов внутри США за период между 1 декабря 2016 года и 1 декабря 2018 года.
На базе собранных данных был проведен первоначальный анализ ситуации на рынке авиационных услуг США, а также построен ряд моделей машинного обучения для предсказания статуса новых рейсов. Таким образом, по завершению построения и оценивания моделей классификации, была создана финальная комплексная модель для предсказания статуса новых рейсов с точностью более 80%. Созданная модель далее была использована в качестве центрального модуля создаваемого ИТ-сервиса для предсказания статуса рейсов c возможностью интеграции в сторонние информационные решения.
Результатом выполнения поставленных целей и задач стало создание качественно нового облачного ИТ-сервиса, предоставляющего B2B услуги по предсказанию статуса рейса с высоким уровнем точности на базе исторических и погодных данных. Использование сторонними организациями подобного рода ИТ-сервиса позволит не только существенно снизить операционные расходы на организацию командировок для своих сотрудников, но и ощутимо улучшить качество организации трансферов для своих сотрудников. Также подобный сервис может быть интересен и частным путешественникам, организующим свое путешествие с использованием стыковок большого количества рейсов. Таким образом было построено решение, потенциально интересное большому количеству потенциальных клиентов и открытое для расширения на другие рынки.
Список использованной литературы
1. Hastie T., Tibshirani R., and Friedman H. The elements of statistical learning: data mining, inference, and prediction // Springler. (2001)
2. James G., Witten D., Hastie T. An introduction to statistical learning: with applications in R // Springer. 2017.
3. Kuhn M., Johnso, K. Applied Predictive Modeling // Springer. 2013.
4. Kumar V., Minz S. Feature Selection: A Literature Review // Smart Computing Review. 2014.
5. Leskovec J., Rajaraman A., Ullman J. Mining of Massive Datasets // Stanford. 2014.
6. Lutz M. Learning Python // O'Reilly Media. 2013.
7. Martinez V. Flight Delay Prediction // ETH Zьrich. 2012.
8. McKinney W. Python for data analysis // OReilly. 2014.
9. Mullin M., Sukthankar R. Complete cross-validation for nearest neighbor classifiers // Proceedings of International Conference on Machine Learning. 2000.
10. Tanner G., Cook A. European airline delay cost reference values // University of Westminster. 2011.
11. Tibshirani R. Regression shrinkage and selection via the lasso // Journal of the Royal Statistical Society. 1996.
12. Viola P., Jones J. Fast and Robust Classification Using Asymmetric Adaboost and a Detecton Cascade // NIPS. 2002.
13. Zaki M. J., Meira W. Data mining and analysis: fundamental concepts and algorithms // Cambridge University Press. 2014.
14. А Wu, T.F., Lin, C.J., Weng, R.C. Probability estimates for multi-class classification by pairwise coupling // J. Mach. Learn. Res. 5 (2004)
Приложение
Исходный код модуля сбора и агрегации статистических и погодных данных
In [1]: import pandas as pd
import numpy as np
import glob
import requests
import json
import gc
import pickle
import concurrent.futures
RND_STATE = 100412
In [2]: def log_progress(sequence, every=None, size=None, name='Items'):
from ipywidgets import IntProgress, HTML, VBox
from IPython.display import display
is_iterator = False
if size is None:
try:
size = len(sequence)
except TypeError:
is_iterator = True
if size is not None:
if every is None:
if size <= 200:
every = 1
else:
every = int(size / 200) # every 0.5%
else:
assert every is not None, 'sequence is iterator, set every'
if is_iterator:
progress = IntProgress(min=0, max=1, value=1)
progress.bar_style = 'info'
else:
progress = IntProgress(min=0, max=size, value=0)
label = HTML()
box = VBox(children=[label, progress])
display(box)
index = 0
try:
for index, record in enumerate(sequence, 1):
if index == 1 or index % every == 0:
if is_iterator:
label.value = '{name}: {index} / ?'.format( name=name,
index=index
)
else:
progress.value = index
label.value = u'{name}: {index} / {size}'.format(
name=name,
index=index,
size=size
)
yield record
except:
progress.bar_style = 'danger'
raise
else:
progress.bar_style = 'success'
progress.value = index
label.value = "{name}: {index}".format(
name=name,
index=str(index or '?')
)
Configuration
In [3]: # weather links
In [4]: WEATHER_API_KEY = ''
In [5]: STARTING_DATE = '2017-03-01'
END_DATE = '2018-03-01'
In [6]: DATA_FOLDER = '../data/historical_data'
DICT_FOLDER = '../data/dictionaries'
WEATHER_FOLDER = '../data/weather_data'
In [20]: DATA_FILE = '/Users/bulhakovdmytro/Desktop/merged_data.csv'
Merging and loading data
Loading flights data
In [9]: def get_file_list(folder_name, prefix=''):
return glob.glob(folder_name + '/*' + prefix + '.csv')
In [10]: def read_csv(file_name):
file_data = pd.read_csv(file_name, dtype={'CANCELLATION_CODE':
str}, parse_dates=True)
file_data['FL_DATE'] = pd.to_datetime(file_data.FL_DATE)
return file_data
In [11]: def read_csv_backup(file_name):
file_data = pd.read_csv(file_name, dtype={'cancellation_code':
str}, parse_dates=True)
file_data['fl_date'] = pd.to_datetime(file_data.fl_date) file_data = file_data.drop(['Unnamed: 0'], axis = 1) return file_data
In [12]: def gather_data(folder_name):
file_list = get_file_list(folder_name)
files_data = read_csv(file_list[0])
for file in log_progress(file_list[1:], every=1):
tmp = read_csv(file)
files_data = pd.concat([files_data, tmp])
del tmp
files_data = files_data.reindex()
files_data.columns = map(str.lower, files_data.columns)
return files_data
In [13]: def append_city_names(files_data, dict_folder_name):
files_data_df = files_data.copy()
city_info = pd.read_csv(dict_folder_name + '/city_codes_info.csv')
city_info['Description'] = city_info['Description'].str.replace
(',.*|\/.*| City', '')
city_info.columns = ['origin_city_market_id', 'origin_city_name']
files_data_df = pd.merge(files_data_df, city_info, on=
'origin_city_market_id')
city_info.columns = ['dest_city_market_id', 'dest_city_name']
files_data_df = pd.merge(files_data_df, city_info, on=
'dest_city_market_id')
del city_info
return files_data_df
In [14]: def load_data(folder_name, dict_folder_name):
files_data = gather_data(folder_name)
files_data = files_data.sort_values(by='fl_date')
files_data = files_data.dropna(thresh=9)
files_data = append_city_names(files_data, dict_folder_name)
return files_data.reindex()
In [15]: data = load_data(DATA_FOLDER, DICT_FOLDER)
In [22]: data.to_csv(DATA_FILE)
Loading weather data
In [23]: def get_data_city_names(data_df):
return list(set(list(data['origin_city_name'].values) +
list(da ta['dest_city_name'].values)))
In [24]: def load_city_codes(dict_folder_name):
tmp = pd.read_csv(dict_folder_name + '/weather_city_codes_info. csv')
tmp['name'] = tmp['name'].str.lower()
tmp['name'] = tmp['name'].str.replace(',.*|\/.*| city', '')
tmp['name'] = tmp['name'].str.strip()
return tmp
In [25]: def get_weather_city_codes(data_df, dict_folder_name):
weather_cities_codes = load_city_codes(dict_folder_name) data_city_names = get_data_city_names(data_df)
processed_cities = []
failed_cities = []
for city in data_city_names:
city_data = weather_cities_codes[weather_cities_codes
['name '].str.contains(city.lower())]
if len(city_data) == 0:
failed_cities.append(city)
else:
processed_cities.append({'name': city, 'weather_id':
city_data['id'].values[0]})
return processed_cities, failed_cities
In [26]: def get_weather_for_city(city_info, start_date, end_date, api_key, limit=1000, offset=0):
offset= {4}'
req_url = req_url.format(city_info['weather_id'],
start_date, e nd_date, limit, offset)
result_json = requests.get(req_url, headers={'token': api_key},
timeout=20)
result_json = json.loads(result_json.content)
result_data = pd.DataFrame(result_json['results'])
if result_json['metadata']['resultset']['count'] > offset + limit:
return pd.concat([result_data, get_weather_for_city(city_info,
start_date, end_date, api_key, limit, offset + limit)])
else:
return result_data
In [27]: def save_weather_data(data_df, dict_folder_name, save_folder,
start _date, end_date, api_key):
weather_city_codes, error_cities = get_weather_city_codes(data_ df,
dict_folder_name)
for city in log_progress(weather_city_codes, every=1):
try:
city_weather = get_weather_for_city(city, start_date, end_date, api_key)
city_weather.to_csv(save_folder + '/' + city['name'] +'.csv')
except Exception as e:
error_cities.append(city)
print(e)
return weather_city_codes, error_cities
In [ ]: ok, err = save_weather_data(data, DICT_FOLDER, WEATHER_FOLDER, STAR TING_DATE, END_DATE, WEATHER_API_KEY)
In [28]: def filter_data_by_available_weather(data_df, weather_data_folder, prefix=''):
city_list = get_file_list(weather_data_folder, prefix)
fixed_city_list = []
for city in city_list:
fixed_city_list.append(city.replace(weather_data_folder + '
/', '').replace('.csv', '').replace(prefix, ''))
tmp_df = data_df[(data_df['origin_city_name'].
isin(fixed_city_l ist)) | (data_df['dest_city_name'].isin(fixed_city_list))]
return tmp_df, city_list
In [29]: def read_weather_file(weather_data_folder, weather_file_path,
prefi x=''):
weather_data = pd.read_csv(weather_file_path)
weather_data['date'] = pd.to_datetime(weather_data.date)
weather_data = weather_data.drop(['Unnamed: 0', 'attributes', '
station'], axis=1)
weather_data = weather_data.rename(columns={'date': 'fl_date'})
weather_data = weather_data.drop_duplicates(["fl_date", "datatype"])
weather_data = weather_data.pivot_table(weather_data,
index='fl _date', columns='datatype', aggfunc=sum, fill_value=0)
weather_data = weather_data.reset_index()
weather_data_value = weather_data['value'].copy() weather_data_value['fl_date'] = weather_data['fl_date'] del weather_data
selected_cols = ['fl_date', 'AWND', 'SNOW',
'SNWD', 'WT01', 'WT 02', 'WT03', 'WT04', 'WT05', 'WT06',
'WT07', 'WT08', 'WT09', 'WT10' , 'WT11']
available_cols =
list(set(weather_data_value.columns).
intersect ion(selected_cols))
na_cols = list(set(selected_cols) - set(available_cols))
weather_data_value = weather_data_value[available_cols]
for na_col in na_cols:
weather_data_value[na_col] = None
weather_data_value = weather_data_value.rename({'SNOW':
'snowfall_mm', 'SNWD': 'snow_depth_mm',
'AWND': 'avg_wind_ms', 'WT08': 'smoke', 'WT01': 'fog',
'WT03': 'thunder'})
weather_data_value['city_name'] =
weather_file_path.replace(wea ther_data_folder
+ '/', '').replace('.csv', '').replace(prefix, '')
return weather_data_value
In [30]: def merge_data_with_weather(data_df, weather_data_folder, prefix='' ):
filtered_df, city_list = filter_data_by_available_weather(data_ df, weather_data_folder, prefix=prefix)
dfs = []
for city in log_progress(city_list, every=1):
tmp = read_weather_file(weather_data_folder, city, prefix=prefix)
tmp = tmp.rename(columns={'city_name': 'origin_city_name'}) dfs.append(pd.merge(filtered_df, tmp, on=['fl_date',
'origin_city_name']))
tmp = tmp.rename(columns={'origin_city_name': 'dest_city_name'})
dfs.append(pd.merge(filtered_df, tmp, on=['fl_date', 'dest_ city_name']))
del tmp
gc.collect()
final_df = pd.concat(dfs)
final_df = final_df.sort_values(by=['fl_date', 'origin_city_name', 'dest_city_name'])
return final_df
In [31]: data2016 = merge_data_with_weather(data, WEATHER_FOLDER, prefix='20 16')
In [32]: data2017 = merge_data_with_weather(data, WEATHER_FOLDER,
prefix='20 17')
In [33]: data_merged = pd.concat([data2016, data2017])
In [34]: data_merged = data_merged.sort_values(by=['fl_date',
'origin_city_name', 'dest_city_name'])
In [35]: data = data_merged
In [36]: data = data.drop_duplicates(subset=['origin', 'dest', 'fl_num',
'carrier', 'year', 'day_of_month', 'day_of_week', 'month'])
In [37]: len(data)
Out[37]: 8807371
In [38]: data.to_csv(DATA_FILE)
Preprocessing data
In [39]: data = read_csv_backup(DATA_FILE)
In [40]: def get_dependent_variable_value(cancelled, cancelled_code,
dep_del ay_new):
if cancelled == 1:
return 'cancelled_flight'
if dep_delay_new > 30:
return 'delay'
return 'no_delay'
In [41]: def preprocess_data(file_data):
data_df = file_data.copy()
data_df[['WT01', 'WT02', 'WT04', 'WT05', 'WT10', 'WT11']] =
dat a_df[['WT01', 'WT02', 'WT04', 'WT05', 'WT10',
'WT11']].fillna(value =0)
data_df = data_df.drop(['origin_airport_id',
'origin_airport_se q_id', 'origin_city_market_id',
'dest_airport_id', 'dest_airport_se q_id',
'dest_city_market_id', 'year', 'unnamed: 28',
'unnamed: 29', 'dep_time'], axis=1)
data_df = data_df.fillna(value={'cancellation_code': 'E'})
data_df['fog'] = list(map(int , (data_df['WT01'] +
data_df['WT0 2']).values > 0))
data_df['hail'] = list(map(int , (data_df['WT04'] +
data_df['WT 05']).values > 0))
data_df['damaging_wind'] = list(map(int ,
(data_df['WT10'] + da ta_df['WT11']).values > 0))
data_df = data_df.drop(['WT01', 'WT02', 'WT04', 'WT05',
'WT06', 'WT10', 'WT11'], axis=1)
data_df = data_df.rename(columns={'SNOW': 'snowfall', 'SNWD': '
snow_depth', 'AWND': 'average_wind_speed','WT03': 'thunder', 'WT07'
: 'dust', 'WT08': 'haze', 'WT09': 'snow'})
data_df['cancellation_code'] = list(map(str,
data_df['cancellat ion_code']))
data_df['carrier'] = list(map(str, data_df['carrier']))
data_df['dest'] = list(map(str, data_df['dest']))
data_df['dest_city_name'] = list(map(str, data_df['dest_city_name']))
data_df['origin'] = list(map(str, data_df['origin']))
data_df['origin_city_name'] = list(map(str, data_df['origin_city_name']))
data_df['cancelled'] = list(map(int, data_df['cancelled']))
data_df['diverted'] = list(map(int, data_df['diverted']))
with concurrent.futures.ProcessPoolExecutor(16) as pool:
data_df['status'] = list(pool.map(get_dependent_variable_va
lue, data_df['cancelled'], data_df['cancellation_code'],
data_df['d ep_delay_new'], chunksize=1_000))
return data_df
In [42]: def save_file(file_name, data_to_save):
n_bytes = 2**31
max_bytes = 2**31 - 1
bytes_out = pickle.dumps(data_to_save)
with open(file_name, 'w+b') as f_out:
for idx in range(0, n_bytes, max_bytes):
f_out.write(bytes_out[idx:idx+max_bytes])
In [43]: data = preprocess_data(data)
In [44]: save_file(DATA_PICKLE, data)
Исходный код модуля обучения моделей классификации
In [1]: import pandas as pd
import numpy as np
import pickle
import concurrent.futures
import warnings
import sklearn.exceptions
warnings.filterwarnings("ignore", category=sklearn.exceptions.Undef inedMetricWarning)
import os.path
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import f1_score
from imblearn.under_sampling import TomekLinks
from sklearn.svm import SVC
from sklearn.ensemble import AdaBoostClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import LogisticRegression from sklearn.linear_model import SGDClassifier
RND_STATE = 100412
In [2]: def log_progress(sequence, every=None, size=None, name='Items'):
from ipywidgets import IntProgress, HTML, VBox
from IPython.display import display
is_iterator = False
if size is None:
try:
size = len(sequence)
except TypeError:
is_iterator = True
if size is not None:
if every is None:
if size <= 200:
every = 1
else:
every = int(size / 200) # every 0.5%
else:
assert every is not None, 'sequence is iterator, set every'
if is_iterator:
progress = IntProgress(min=0, max=1, value=1)
progress.bar_style = 'info'
else:
progress = IntProgress(min=0, max=size, value=0)
label = HTML()
box = VBox(children=[label, progress])
display(box)
index = 0
try:
for index, record in enumerate(sequence, 1):
if index == 1 or index % every == 0:
if is_iterator:
label.value = '{name}: {index} / ?'.format( name=name,
index=index)
else:
progress.value = index
label.value = u'{name}: {index} / {size}'.format(
name=name,
index=index,
size=size
)
yield record
except:
progress.bar_style = 'danger'
raise
else:
progress.bar_style = 'success'
progress.value = index
label.value = "{name}: {index}".format(
name=name,
index=str(index or '?') )
In [3]: def load_file(file_name):
max_bytes = 2**31 - 1
bytes_in = bytearray(0)
input_size = os.path.getsize(file_name)
with open(file_name, 'rb') as f_in:
for _ in range(0, input_size, max_bytes):
bytes_in += f_in.read(max_bytes)
return pickle.loads(bytes_in)
In [32]: def save_file(file_name, data_to_save):
n_bytes = 2**31
max_bytes = 2**31 - 1
bytes_out = pickle.dumps(data_to_save)
with open(file_name, 'w+b') as f_out:
for idx in range(0, n_bytes, max_bytes):
f_out.write(bytes_out[idx:idx+max_bytes])
Configuration
In [4]: DICT_FOLDER = '../data/dictionaries'
In [5]: DATA_PICKLE = '../data/merged_data.data'
In [6]: BEST_CLF = '../data/best_clf.data'
In [7]: data = load_file(DATA_PICKLE)
Additional preprocessing
In [8]: data2 = data[data['origin'] == 'ALB']
In [9]: data2['average_wind_speed'].fillna((data2['average_wind_speed'].mean()),
inplace=True)
/Users/bulhakovdmytro/anaconda3/lib/python3.6/site-packages/pandas /core/generic.py:4355: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pan
das-docs/stable/indexing.html#indexing-view-versus-copy
self._update_inplace(new_data)
In [10]: working_df = data2
In [11]: def additional_preprocessing(data_df):
data_info = data_df.copy()
data_info = data_info.drop(['cancellation_code', 'cancelled', ' carrier_delay', 'dep_delay_new', 'late_aircraft_delay', 'nas_delay',
'security_delay', 'weather_delay', 'diverted', 'origin_city_name',
'dest_city_name'], axis = 1)
data_info = data_info.drop(['snowfall', 'snow_depth', 'thunder',
'dust', 'haze', 'snow', 'fog', 'hail', 'damaging_wind'], axis = 1)
data_info['crs_dep_time'] = list(map(int, working_df['crs_dep_t ime'].
values / 100))
return data_info
In [12]: working_df = additional_preprocessing(working_df)
Processing
In [13]: airlines_group = data[['status', 'carrier']]
airlines_group_num = airlines_group.groupby(['carrier']).size()
airlines_group = data[['status', 'carrier']]
airlines_group = airlines_group[(airlines_group['status'] != 'no_de lay')]
airlines_group_delays_num = airlines_group.groupby(['carrier']).siz e()
delay_info = pd.DataFrame({'Carrier': np.unique(airlines_
group.carrier.values), 'Number of flights': airlines_group_num.values,
'Number of delays': airlines_group_delays_num.values})
delay_info['Delay index'] = delay_info['Number of delays'] / delay_
info['Number of flights']
In [14]: def add_airline_delay_index(carrier):
return delay_info[delay_info['Carrier'] ==
carrier]['Delay index'].values[0]
In [15]: def process_data(data_df):
data_info = data_df.copy()
with concurrent.futures.ProcessPoolExecutor(16) as pool:
data_info['airline_delay_index'] =
list(pool.map(add_airline_delay_index, data_info['carrier'],
chunksize=1_000))
data_info = pd.get_dummies(data_info, columns=['dest'])
data_info['day_of_year'] = (data_info['fl_date'] -
data_info['f l_date'].min()) / np.timedelta64(1,'D')
# data_info['crs_dep_time_time_sin'] = np.sin(2*np.pi*data_info
.crs_dep_time/24.)
# data_info['crs_dep_time_time_cos'] = np.cos(2*np.pi*
# data_info
.crs_dep_time/24.)
data_info['weekend'] = np.where(data_info['day_of_week'] >=
6, 1, 0)
data_info = data_info.drop(['fl_date', 'fl_num', 'origin',
'tail_num', 'carrier'], axis=1)
return data_info, data_info.columns
In [16]: working_df, tmp = process_data(working_df)
Train test split
In [17]: X_train, X_test, y_train, y_test = train_test_split
(working_df.loc[ :, working_df.columns != 'status'],
working_df['status'], test_size = 0.2, random_state = RND_STATE)
Predictions
In [18]: classifiers = []
In [19]: class ModelTester():
def __init__(self, parameters, model, scoring='f1_macro',
njobs =-1, cv=3):
self.cv = GridSearchCV(model, param_grid=parameters, scorin g =
scoring, n_jobs = njobs, cv = cv, verbose = 1)
def test_model(self, Xtrain, ytrain, Xtest, ytest):
self.cv.fit(Xtrain, ytrain);
print('Best score cv: ', self.cv.best_score_)
print('Params: ', self.cv.best_params_)
y_predicted = self.cv.predict(Xtest)
print('F1 (micro) score on test sample:', f1_score(ytest,
y_predicted, average='micro'))
print('F1 (weighted) score on test sample:', f1_score(ytest ,
y_predicted, average='weighted'))
def best_estimator(self):
return self.cv.best_estimator_
Random Forest
In [20]: param = {'criterion':['gini', 'entropy'],
'max_features':[1, 2, 3, 4, 5, 6, 7, 'log2', 'auto'],
'max_depth':[2, 4, 8, 16, 32, 64],
'class_weight':['balanced', None], 'n_estimators':
[30, 40, 50, 60], 'bootstrap': [True, F alse]}
mt = ModelTester(parameters = param, model = RandomForestClassifier (random_state=RND_STATE))
mt.test_model(X_train, y_train, X_test, y_test)
rf_clf = mt.best_estimator()
classifiers.append({'name': 'Random Forest Classifier', 'clf': rf_c lf})
Fitting 3 folds for each of 1728 candidates, totalling 5184 fits
[Parallel(n_jobs=-1)]: Done 42 tasks | elapsed: 9.3s
[Parallel(n_jobs=-1)]: Done 192 tasks | elapsed: 53.4s
[Parallel(n_jobs=-1)]: Done 442 tasks | elapsed: 3.2min
[Parallel(n_jobs=-1)]: Done 792 tasks | elapsed: 5.8min
[Parallel(n_jobs=-1)]: Done 1242 tasks | elapsed: 9.9min
[Parallel(n_jobs=-1)]: Done 1792 tasks | elapsed: 12.9min
[Parallel(n_jobs=-1)]: Done 2442 tasks | elapsed: 15.9min
[Parallel(n_jobs=-1)]: Done 3192 tasks | elapsed: 19.5min
[Parallel(n_jobs=-1)]: Done 4042 tasks | elapsed: 24.6min
[Parallel(n_jobs=-1)]: Done 4992 tasks | elapsed: 29.4min
[Parallel(n_jobs=-1)]: Done 5184 out of 5184 | elapsed: 30.9min fi
nished
Best score cv: 0.4866038733729732
Params: {'bootstrap': False, 'class_weight': 'balanced',
'criteri on': 'gini', 'max_depth': 16, 'max_features': 7,
'n_estimators': 6 0}
F1 (micro) score on test sample: 0.8760162601626016
F1 (weighted) score on test sample: 0.8663217975054347
In [21]: y_predicted = rf_clf.predict(X_test)
print('F1 (macro) score on test sample:', f1_score(y_test,
y_predic ted, average='macro'))
print('F1 (macro) score on test sample:', f1_score(y_test,
y_predic ted, average=None))
F1 (micro) score on test sample: 0.5362536052155895
F1 (macro) score on test sample: [0.46153846 0.21259843 0.93462393]
SVC
In [22]: param = {'C': np.linspace(0.01, 0.03, num=2),
'class_weight':['balanced', None], 'kernel':['linear'],
'decision_function_shape' : ['ovo', 'ovr', None]}
mt = ModelTester(parameters = param, model =
SVC(random_state=RND_S TATE, cache_size=2048))
# mt.test_model(X_train, y_train, X_test, y_test)
# svc_clf = mt.best_estimator()
# classifiers.append({'name': 'SVC', 'clf': svc_clf})
AdaBoostClassifier
In [23]: param = {'algorithm': ['SAMME.R', 'SAMME'], 'learning_rate':
[0.1, 0.3, 0.6, 0.8, 1.0]}
mt = ModelTester(parameters = param, model = AdaBoostClassifier
(ran dom_state=RND_STATE))
mt.test_model(X_train, y_train, X_test, y_test)
adc_clf = mt.best_estimator()
classifiers.append({'name': 'AdaBoost Classifier', 'clf': adc_clf})
Fitting 3 folds for each of 10 candidates, totalling 30 fits
[Parallel(n_jobs=-1)]: Done 30 out of 30 | elapsed: 23.7s finished
Best score cv: 0.3467505236915829
Params: {'algorithm': 'SAMME.R', 'learning_rate': 1.0}
F1 (micro) score on test sample: 0.9009872241579558
F1 (weighted) score on test sample: 0.85489123183182
Decision Tree Classifier
In [24]: param = {'criterion': ['gini', 'entropy'], 'splitter': ['best',
'ra ndom'], 'max_features':[1, 2, 3, 4, 5, 'log2', 'auto'],
'class_weight' : ['balanced'], 'random_state':[RND_STATE], 'presort':[True, False]}
mt = ModelTester(parameters = param, model =
DecisionTreeClassifier (random_state=RND_STATE))
mt.test_model(X_train, y_train, X_test, y_test)
dtc_clf = mt.best_estimator()
classifiers.append({'name': 'Decision Tree Classifier',
'clf': dtc_ clf})
Fitting 3 folds for each of 56 candidates, totalling 168 fits
[Parallel(n_jobs=-1)]: Done 42 tasks | elapsed: 3.9s
[Parallel(n_jobs=-1)]: Done 168 out of 168 | elapsed: 16.9s fini
shed
Best score cv: 0.44622380964057645
Params: {'class_weight': 'balanced', 'criterion': 'entropy',
'max_features': 5, 'presort': False, 'random_state': 100412,
'splitter': 'best'}
F1 (micro) score on test sample: 0.8426248548199767
F1 (weighted) score on test sample: 0.8437562066173171
K-Neighbors Classifier
In [25]: param = {'n_neighbors': [30, 50, 65, 70], 'weights':
['uniform', 'd istance'], 'algorithm':['auto', 'ball_tree',
'kd_tree', 'brute'],'leaf_size' : [10, 15, 20], 'p':[1, 2]}
mt = ModelTester(parameters = param, model =
KNeighborsClassifier())
mt.test_model(X_train, y_train, X_test, y_test)
knn_clf = mt.best_estimator()
classifiers.append({'name': 'K-Neighbors Classifier',
'clf': knn_cl f})
Fitting 3 folds for each of 192 candidates, totalling 576 fits
[Parallel(n_jobs=-1)]: Done 42 tasks | elapsed: 29.5s
[Parallel(n_jobs=-1)]: Done 192 tasks | elapsed: 2.1min
[Parallel(n_jobs=-1)]: Done 442 tasks | elapsed: 5.8min
[Parallel(n_jobs=-1)]: Done 576 out of 576 | elapsed: 25.4min fini
shed
Best score cv: 0.3468096104253847
Params: {'algorithm': 'auto', 'leaf_size': 10, 'n_neighbors': 30,
'p': 1, 'weights': 'distance'}
F1 (micro) score on test sample: 0.9027293844367015
F1 (weighted) score on test sample: 0.8595549073713904
Gradient Boosting Classifier
In [26]: param = {'loss': ['deviance'], 'max_features':[1, 2, 3, 4, 5, 'log2 ',
'auto'], 'presort':[True, False], 'n_estimators':[200, 300],
'min_samples_leaf' : [3]}
mt = ModelTester(parameters = param, model = GradientBoostingClassi fier(random_state=RND_STATE))
mt.test_model(X_train, y_train, X_test, y_test)
gbc_clf = mt.best_estimator()
classifiers.append({'name': 'Gradient Boosting Classifier', 'clf':
gbc_clf})
Fitting 3 folds for each of 28 candidates, totalling 84 fits
[Parallel(n_jobs=-1)]: Done 42 tasks | elapsed: 1.7min
[Parallel(n_jobs=-1)]: Done 84 out of 84 | elapsed: 4.0min fini
shed
Best score cv: 0.44898212892711603
Params: {'loss': 'deviance', 'max_features': 'auto', 'min_samples
_leaf': 3, 'n_estimators': 300, 'presort': True}
F1 (micro) score on test sample: 0.9044715447154471
F1 (weighted) score on test sample: 0.867061334328921
Results per classifier:
In [27]: def print_importances_internal(data_df, imp_list):
print('Top 10 features:')
val_zip = zip(data_df.columns, imp_list)
for a, b, in sorted(val_zip, key = lambda zp_gb: zp_gb[1],
reve rse = True)[:10]:
print("{0}: {1}".format(a, b))
In [30]: def print_importances(data_df, model):
if hasattr(model, 'feature_importances_'):
print_importances_internal(data_df,
model.feature_importances_)
elif hasattr(model, 'coef_'):
print_importances_internal(data_df, model.coef_.flatten())
In [31]: results_data = []
for clf in log_progress(classifiers, every = 1):
print('\n' + clf['name'])
score = f1_score(clf['clf'].predict(X_test), y_test,
average='w eighted')
print('F1 score: ', score)
results_data.append({'Classifier': clf['name'], 'F1 Score':
score})
print_importances(working_df.loc[:, working_df.columns !=
'stat us'], clf['clf'])
Random Forest Classifier
F1 score: 0.8857107228197686
Top 10 features:
day_of_year: 0.1906763850269155
average_wind_speed: 0.16357845145130895
day_of_month: 0.1450401775580273
crs_elapsed_time: 0.10335953052856928
crs_dep_time: 0.09999126640853984
day_of_week: 0.06748131863980306
month: 0.0662450973889621
airline_delay_index: 0.040061246723587365
quarter: 0.02713779858633902
weekend: 0.012999320626495524
AdaBoost Classifier
F1 score: 0.9470832164840918
Top 10 features:
day_of_year: 0.36
crs_elapsed_time: 0.12
crs_dep_time: 0.1
day_of_month: 0.1
average_wind_speed: 0.08
month: 0.08
airline_delay_index: 0.04
quarter: 0.02
dest_CLT: 0.02
dest_DTW: 0.02
Decision Tree Classifier
F1 score: 0.8414935030226363
Top 10 features:
day_of_year: 0.1623640684932886
average_wind_speed: 0.15944477768928256
day_of_month: 0.12274598903177944
crs_elapsed_time: 0.11171249419092372
crs_dep_time: 0.10660056628939428
day_of_week: 0.08027070950606444
month: 0.066253338149032
airline_delay_index: 0.03919742600882441
quarter: 0.03605067823701363
weekend: 0.02159372545942422
K-Neighbors Classifier
F1 score: 0.9459038615020126
Gradient Boosting Classifier
F1 score: 0.9418817551019735
Top 10 features:
day_of_year: 0.27932825290658797
average_wind_speed: 0.16313032703232058
crs_elapsed_time: 0.135415574104321
crs_dep_time: 0.10347341223388402
day_of_month: 0.10296924690261106
month: 0.044741366846506085
airline_delay_index: 0.03927415917370957
day_of_week: 0.03267084404401242
dest_ORD: 0.01287510196344979
dest_BWI: 0.012269863993930222
In [33]: save_file(BEST_CLF, rf_clf)
Исходный код модуля ИТ-сервиса
from datetime import datetime
from flask import Flask, request, jsonify
import pandas as pd
import glob
import pickle
import requests
import json
from werkzeug.contrib.cache import SimpleCache
WEATHER_API_KEY = ''
FL_INFO_FOLDER = '../data/flight_info.data'
DELAYS_INFO_FOLDER = '../data/delays.data'
AVG_DELAYS_INFO_FOLDER = '../data/avg_delays.data'
CLFS_INFO_FOLDER = '../data/clfs'
COLS_FOLDER = '../data/values_dicts'
INFO_DATA = {}
CACHE_TIMEOUT = 100
cache = SimpleCache()
app = Flask(__name__)
@app.before_request
def before_request():
global INFO_DATA
if len(INFO_DATA) == 0:
INFO_DATA = load_initial_data()
response = cache.get(request.path)
if response:
return response
@app.after_request
def cache_response(response):
cache.set(request.path, response, CACHE_TIMEOUT)
return response
@app.route('/')
def main_route():
return 'Web service is up and running'
@app.route('/api/last_update')
def last_update():
data = {'last_update': '08-05-2018'}
return jsonify(get_formatted_json(data))
@app.route("/api/flights/predict", methods=['GET'])
def predict_flight():
try:
origin = request.args.get('origin', default='', type=str)
dest = request.args.get('dest', default='', type=str)
carrier = request.args.get('carrier', default='', type=str)
fl_num = request.args.get('fl_num', default='', type=str)
flight_date = datetime.strptime(request.args.get('flight_date'),
"%Y-%m-%d").date()
features = get_features(INFO_DATA, WEATHER_API_KEY, origin, dest,
carrier, int(fl_num), flight_date)
result = INFO_DATA['clfs'][origin]['clf'].predict_proba(features).
tolist()[0]
result = [{'cancelled_flight': result[0], 'delay': result[1],
'no_delay': result[2]}]
return jsonify(get_formatted_json(result))
except:
return jsonify(get_formatted_json([], 'Could not check flight status.
Please, check input params.'))
@app.route("/api/airlines", methods=['GET'])
def get_airlines_list():
data = {'airlines': INFO_DATA['delays']['Carrier'].to_dict()}
return jsonify(get_formatted_json(data))
@app.route("/api/airlines/flights", methods=['GET'])
def get_airlines_flights():
try:
carrier = request.args.get('carrier', default='', type=str)
data = {'flights': INFO_DATA['fl_info'][INFO_DATA['fl_info']['carrier']
== carrier][['origin', 'dest', 'fl_num']].to_dict('index')}
if len(data) == 0:
raise ValueError('Incorrect carrier code')
return jsonify(get_formatted_json(data))
except:
return jsonify(get_formatted_json([], 'Could not find selected
airline. Please, check your request.'))
@app.route("/api/airlines/delay_rating", methods=['GET'])
def get_airlines_delay_ratings():
data = {'airlines': INFO_DATA['delays'][['Carrier', 'Delay index']].
to_dict('index')}
return jsonify(get_formatted_json(data))
def load_initial_data():
flight_info = load_file(FL_INFO_FOLDER)
delays = load_file(DELAYS_INFO_FOLDER)
avg_delays = load_file(AVG_DELAYS_INFO_FOLDER)
files_list = get_file_list(CLFS_INFO_FOLDER)
clfs = {}
for file in files_list:
airport = file.replace(CLFS_INFO_FOLDER + '/', '').replace('.data', '')
clfs[airport] = {'clf': load_file(file), 'cols':
load_file(COLS_FOLDER + '/' + airport + '.data')}
return {'clfs': clfs, 'fl_info': flight_info, 'delays': delays,
'avg_delays': avg_delays}
def get_features(data, weather_api_key, origin, dest, carrier, flight, date):
fl_info = data['fl_info'][(data['fl_info']['fl_num'] == flight) & (data['fl_info']['carrier'] == carrier)
& (data['fl_info']['origin'] == origin)]
df = pd.DataFrame(columns=data['clfs'][origin]['cols'])
df = df.append({'average_wind_speed': get_wind_speed_for_city(get_series_value(fl_info['origin_city_name']),
weather_api_key),
'crs_dep_time': get_series_value(fl_info['crs_dep_time']),
'crs_elapsed_time': get_series_value(fl_info['crs_elapsed_time']),
'day_of_month': date.day,
'day_of_week': date.weekday(),
'month': date.month,
'quarter': date.month // 4,
'previous_flight_delay': 0,
'airline_delay_index': get_series_value(data['delays']
[data['delays']['Carrier'] == carrier]['Delay index']),
'airline_avg_delay': get_series_value(data['avg_delays']
[data['avg_delays']['carrier'] == carrier]['carrier_delay']),
'dest_' + dest: 1,
'day_of_year': int(date.strftime("%j"))}, ignore_index=True)
df = df.drop('status', axis=1)
df = df.fillna(0)
return df
def get_wind_speed_for_city(city_name, api_key):
try:
r = requests.get(url=api_url, params=dict(q=city_name, APPID=api_key))
result_json = json.loads(r.text)
return result_json['wind']['speed'] * 10
except Exception as e:
print(e)
return 0
def get_series_value(series):
return series.values[0]
...Подобные документы
Использование классификаторов машинного обучения для анализа данных. Создание модели, которая на основании параметров, влияющих на течение диабета, выявляет показатель возвращения больного в ухудшенное состояния после оказанного лечения (реадмиссию).
дипломная работа [625,2 K], добавлен 10.06.2017Популярность алгоритмов машинного обучения для компьютерных игр. Основные техники обучения с подкреплением в динамической среде (компьютерная игра "Snake") с экспериментальным сравнением алгоритмов. Обучение с подкреплением как тип обучения без учителя.
курсовая работа [1020,6 K], добавлен 30.11.2016Создание системы предобработки данных; разработка системы классификации на базе методов и алгоритмов машинного обучения, их реализация в программной системе. Предобработка информации, инструкция пользователя, система классификации, машинный эксперимент.
дипломная работа [917,1 K], добавлен 31.01.2015Описание создаваемого сервиса. Разработка и реализация серверной части сервиса и клиентской части сервиса, которая будет предоставлять пользователям возможность создания и редактирования генеалогических деревьев, возможность импорта и экспорта данных.
курсовая работа [116,9 K], добавлен 20.07.2012Разработка модели и создание структуры реляционной базы данных. Организация данных в таблицах для предоставления оперативного доступа к данным. Основные структурные единицы базы данных Access: таблицы, запросы, формы, отчеты, страницы, макросы и модули.
реферат [4,0 M], добавлен 03.02.2013Анализ проблем, возникающих при применении методов и алгоритмов кластеризации. Основные алгоритмы разбиения на кластеры. Программа RapidMiner как среда для машинного обучения и анализа данных. Оценка качества кластеризации с помощью методов Data Mining.
курсовая работа [3,9 M], добавлен 22.10.2012Проведение исследования опыта взаимодействия в сети. Методы улучшения согласования с пользователем web-сервиса. Особенность проектирования онлайн-приложения. Изучение разработки контроллеров и моделей. Характеристика создания интерфейса программы.
дипломная работа [1,3 M], добавлен 11.08.2017Анализ информационных потоков, связанных с деятельностью шиномонтажной мастерской. Разработка информационной модели данных. Описание технического задания на разработку web-сервиса. Составление планов управления конфигурациями и контроля качества.
курсовая работа [3,7 M], добавлен 25.12.2014Искусственные нейронные сети как одна из широко известных и используемых моделей машинного обучения. Знакомство с особенностями разработки системы распознавания изображений на основе аппарата искусственных нейронных сетей. Анализ типов машинного обучения.
дипломная работа [1,8 M], добавлен 08.02.2017Представление данных в памяти компьютера. Обобщенные структуры и модели данных. Методы доступа к информации. Физическая организация системы управления базами данных, структура сервера. Архитектура "клиент-сервер". Создание базы данных с помощью "Денвер".
курсовая работа [770,3 K], добавлен 17.11.2014Организация проверки результатов обучения и оценки знаний, использование систем тестирования, основные требования к ним. Создание современной модели WEB-сервиса тестирования знаний; программная реализация; защита от копирования информации и списывания.
курсовая работа [24,1 K], добавлен 11.05.2012Описание сервиса электронного кафе и определение основных требований к системе. Модели вариантов использования, состояний, последовательности, классов, компонентов и развертывания. Описание алгоритмов, реализующих бизнес-логику серверной части.
курсовая работа [3,3 M], добавлен 23.12.2014Психолого-педагогические основы формирования системно-деятельностного подхода обучения. Обзор существующих конструкторов сайтов, обоснование выбора сервиса Wix. Ознакомление обучающихся с правилами безопасности в сети Интернет. Технологии создания сайтов.
дипломная работа [428,9 K], добавлен 07.09.2017Історія машинного перекладу як науково-прикладного напряму. Теорія машинного перекладу. Особливості використання систем, орієнтованих на персональні комп’ютери. Напрямки розвитку та застосування машинного перекладу. Приклади систем машинного перекладу.
реферат [21,5 K], добавлен 19.02.2011Роль и возможности адаптивной модели в организации образовательного процесса. Структура и механизм навигации в адаптивной модели обучения АЯП Prolog. Программная реализация адаптивной модели обучения. Демонстрация созданного программного продукта.
курсовая работа [1,6 M], добавлен 19.06.2015Проектирование Web-сервиса учебного процесса кафедры физкультуры. Анализ существующих решений и построение моделей предметной области. Разработка базы данных Web-сервиса для обеспечения функциональности работы. Архитектура, интерфейс, взаимодействие с БД.
дипломная работа [1,9 M], добавлен 05.04.2017ERwin как средство разработки структуры базы данных. Внешний вид диалогового окна Entity Edition. Общий вид модели после создания сущностей. Вид логической модели после создания связей. Диалоговое окно New Key Group, окончательный вид логической модели.
лабораторная работа [559,0 K], добавлен 16.07.2013Характеристика работы сервиса технического обслуживания автомобилей и основные составляющие процесса. Структурная схема модели, временная диаграмма, Q-схема системы и их описание. Сравнение результатов моделирования и машинная программа работы сервиса.
дипломная работа [140,2 K], добавлен 18.06.2011Моделирование системы массового обслуживания. Анализ зависимости влияния экзогенных переменных модели однофазной одноканальной СМО на эндогенные переменные. План машинного эксперимента множественного регрессионного анализа и метода наименьших квадратов.
лабораторная работа [107,5 K], добавлен 15.06.2010Учет книжного фонда библиотеки. Разработка концептуальной модели данных. Составление спецификации атрибутов и связей, генерация в системе PowerDesigner физической модели по концептуальной модели. Создание скрипта создания базы данных для СУБД FireBird.
контрольная работа [784,2 K], добавлен 10.04.2014