Создание ИТ-сервиса, позволяющего с помощью алгоритмов машинного обучения прогнозировать вероятность возникновения задержек авиарейсов

Сбор и агрегация исторических данных о регулярных рейсах авиакомпаний. Особенность создания модели машинного обучения для предсказания вероятности отмены маршрута. Характеристика формирования ИТ-сервиса для предоставления доступа к предиктивной модели.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 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.2017

  • ERwin как средство разработки структуры базы данных. Внешний вид диалогового окна 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

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.