Использование машинного обучения для прогнозирования погоды Часть 1

Почему сложно предсказать погоду со 100% точностью форекс.

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

Сбор и обработка данных (эта статья) Модели линейной регрессии (статья 2) Модели нейронных сетей (статья 3)

Данные, используемые в этой серии, будут собраны из веб-службы API уровня бесплатного пользования Weather Underground. Я буду использовать библиотеку запросов для взаимодействия с API, чтобы получать данные о погоде с 2015 года для города Линкольн, штат Небраска. После сбора данные необходимо будет обработать и объединить в формат, подходящий для анализа данных, а затем очистить..

Вторая статья будет посвящена анализу тенденций в данных с целью выбора подходящих функций для построения модели линейной регрессии с использованием библиотек Python statsmodels и scikit-learn. Я расскажу о важности понимания допущений, необходимых для использования модели линейной регрессии, и продемонстрирую, как оценивать функции для построения надежной модели. Эта статья завершится обсуждением тестирования и проверки модели линейной регрессии..

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

Знакомство с Weather Underground.

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

Если вы хотите следовать руководству, вам нужно будет зарегистрировать их бесплатную учетную запись разработчика здесь. Эта учетная запись предоставляет ключ API для доступа к веб-службе со скоростью 10 запросов в минуту и ​​до 500 запросов в день..

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

Формат запроса ресурса API истории следующий:

API_KEY: API_KEY, который Weather Underground предоставляет вашей учетной записи. ГГГГММДД: строка, представляющая целевую дату вашего запроса. СОСТОЯНИЕ: двухбуквенное сокращение штата в США. CITY: название города, связанного с запрашиваемым государством..

Отправка запросов к API.

Чтобы делать запросы к API истории Weather Underground и обрабатывать возвращенные данные, я буду использовать несколько стандартных библиотек, а также некоторые популярные сторонние библиотеки. Ниже приводится таблица библиотек, которые я буду использовать, и их описание. Инструкции по установке см. В указанной документации..

Библиотека Описание использования Источник datetime Используется для увеличения количества наших запросов по дням Стандартное время библиотеки Используется для задержки запросов, чтобы оставаться ниже 10 в минуту Коллекции стандартной библиотеки Используйте именованные кортежи для структурированного сбора данных Стандартные библиотеки pandas Используются для обработки, организации и очистки данных Третья сторона Запросы библиотеки Используется для выполнения сетевых запросов к API Сторонней библиотеки matplotlib Используется для графического анализа Сторонняя библиотека.

Давайте начнем с импорта этих библиотек:

Теперь я определю пару констант, представляющих мой API_KEY и BASE_URL конечной точки API, которую я буду запрашивать. Обратите внимание, что вам нужно будет зарегистрировать учетную запись в Weather Underground и получить собственный API_KEY. К тому времени, когда эта статья будет опубликована, я отключу эту.

BASE_URL — это строка с двумя заполнителями, представленными фигурными скобками. Первое <> будет заполнен API_KEY, а второй <> будет заменен датой в строковом формате. Оба значения будут интерполированы в строку BASE_URL с помощью функции str.format (.).

Затем я инициализирую целевую дату на первый день года в 2015 году. Затем я укажу функции, которые я хотел бы проанализировать, на основе ответов, возвращаемых API. Функции — это просто ключи, присутствующие в истории -> dailсводная часть ответа JSON. Эти функции используются для определения именованного кортежа DailySummary, который я буду использовать для организации данных отдельного запроса в списке кортежей DailySummary..

В этом разделе я буду делать фактические запросы к API и собирать успешные ответы, используя функцию, определенную ниже. Эта функция принимает параметры url, api_key, target_date и days. .

Я начинаю с определения списка, называемого записями, который будет содержать проанализированные данные как DailySummary namedtuple s. Цикл for определен таким образом, что он выполняет итерацию цикла в течение количества дней, переданных функции..

Затем запрос форматируется с использованием функции str.format () для интерполяции API_KEY и строкового объекта target_date. После форматирования переменная запроса передается методу get () объекта запросов, а ответ присваивается переменной с именем response. .

Получив ответ, я хочу убедиться, что запрос был успешным, оценив, что код состояния HTTP равен 200. Если он успешен, я анализирую тело ответа в JSON, используя метод json () возвращенного объекта ответа. Привязанный к одному и тому же вызову метода json (), я выбираю индексы структур истории и суточной сводки, затем беру первый элемент в списке сводок дня и назначаю его переменной с именем data .

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

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

Затем target_date увеличивается на 1 день с использованием объекта timedelta модуля datetime, поэтому следующая итерация цикла извлекает ежедневную сводку на следующий день..

Первый пакет запросов.

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

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

Завершение получения данных.

Хорошо, теперь, когда наступил новый день, у нас есть чистый лист и до 500 запросов, которые могут быть сделаны в API истории Weather Underground. Наш пакет из 500 запросов, отправленных вчера, начался 1 января 2015 г. и закончился 15 мая 2016 г. (при условии, что у вас не было ни одного неудавшегося запроса). Еще раз позвольте нам начать еще один пакет из 500 запросов, но на этот раз не оставляйте меня на один день, потому что после того, как этот последний фрагмент данных будет собран, мы начнем форматировать его в Pandas DataFrame и получить потенциально полезные функции.

Настройка нашего Pandas DataFrame.

Теперь, когда у меня есть хороший и внушительный список записей с именованными кортежами DailySummary, я буду использовать его для построения Pandas DataFrame. Pandas DataFrame — это очень полезная структура данных для многих задач программирования, которые наиболее известны для очистки и обработки данных, которые будут использоваться в проектах машинного обучения (или экспериментах)..

Я буду использовать конструктор класса Pandas.DataFrame (.) Для создания экземпляра объекта DataFrame. Параметры, передаваемые конструктору, представляют собой записи, которые представляют данные для DataFrame, список функций, который я также использовал для определения именованных кортежей DailySummary, которые будут определять столбцы DataFrame. Метод set_index () связан с экземпляром DataFrame, чтобы указать дату в качестве индекса..

Получение функций.

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

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

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

Сейчас я не могу сказать, что обладаю значительными знаниями в области метеорологии или моделей прогнозирования погоды, но я провел минимальный поиск в предыдущих работах по использованию машинного обучения для прогнозирования погодных температур. Оказывается, есть довольно много исследовательских статей по этой теме, и в 2016 году Холмстрем, Лю и Во описывают использование линейной регрессии для этого. В своей статье Машинное обучение применительно к прогнозированию погоды они использовали данные о погоде за предыдущие два дня для следующих измерений..

макс. температура мин. температура средняя влажность среднее атмосферное давление.

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

средняя температура средняя точка росы среднее давление макс. влажность мин. влажность макс. точка росы мин. точка росы макс. давление мин. давление осадки.

Итак, дальше нужно выяснить, как включить эти новые функции в качестве столбцов в наш DataFrame. Для этого я сделаю меньшее подмножество текущего DataFrame, чтобы упростить работу при разработке алгоритма для создания этих функций. Я сделаю tmp DataFrame, состоящий всего из 10 записей и функций meantempm и meandewptm. .

date meantempm meandewptm 2015-01-01-6-12 2015-01-02-6-9 2015-01-03-4-11 2015-01-04-14-19 2015-01-05-9-14 2015- 01-06-10-15 2015-01-07-16-22 2015-01-08-7-12 2015-01-09-11-19 2015-01-10-6-12.

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

date meantempm meandewptm meantempm_1 2015-01-01-6-12 Нет 2015-01-02-6-9-6 2015-01-03-4-11-6 2015-01-04-14-19-4 2015-01 -05-9-14-14 2015-01-06-10-15-9 2015-01-07-16-22-10 2015-01-08-7-12-16 2015-01-09-11-19 -7 10.01.2015-6-12-11.

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

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

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

Превосходно! Похоже, у нас есть то, что нам нужно. Следующее, что я хочу сделать, это оценить качество данных и при необходимости очистить их..

Очистка данных — самая важная часть.

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

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

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

Обратите внимание, что тип данных каждого столбца имеет тип "объект". Нам нужно преобразовать все эти столбцы функций в числа с плавающей запятой для того типа численного анализа, который мы надеемся выполнить. Для этого я буду использовать метод DataFrame apply (), чтобы применить метод Pandas to_numeric ко всем значениям DataFrame. Параметр error = ‘coerce’ заполняет любые текстовые значения до NaN. Обычно текстовые значения находятся в данных из дикой природы, которые обычно исходят от сборщика данных, где данные отсутствуют или недействительны..

Теперь, когда все наши данные имеют тот тип данных, который мне нужен, я хотел бы взглянуть на некоторую сводную статистику функций и использовать статистическое правило большого пальца для проверки существования экстремальных выбросов. Метод DataFrame describe () создаст DataFrame, содержащий подсчет, среднее значение, стандартное отклонение, мин., 25-й процентиль, 50-й процентиль (или медиану), 75-й процентиль и максимальное значение. Это может быть очень полезной информацией для оценки распределения данных функции..

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

подсчитать среднее значение std min 25% 50% 75% max выбросы maxhumidity_1 999.0 88.107107 9.273053 47,0 83.0 90.0 93.00 100.00 True maxhumidity_2 998.0 88.102204 9.276407 47,0 83.0 90.0 93.00 100.00 True maxhumidity_3 997.0 88.09xpress3280 9.276775 47.0 10024 9.0 ma 1055,00 Правда maxpressurem_2 998,0 +1019,922846 7,755482 993,0 1015,0 1019,0 1024,00 1055,00 Правда maxpressurem_3 997,0 +1019,927783 7,757805 993,0 1015,0 1019,0 1024,00 1055,00 Правда minpressurem_1 999,0 +1012,329329 7,882062 956,0 1008,0 1012,0 1017,00 1035,00 Правда minpressurem_2 998,0 +1012,326653 7,885560 956,0 1008,0 1012,0 1017,00 1035,00 Правда minpressurem_3 997,0 1012,326981 7,889511 956,0 1008,0 1012,0 1017,00 1035,00 Истинные осадки_1 889,0 2.908211 8,874345 0,0 0,0 0,0 0,51 95,76 Истинные осадки_2 889,0 2.908211 8.874345 0,0 0,0 0,0 0,51 95,76 Истинные осадки_3 888,0 2.888885 8,860608 0,0 0,0 0,0 0,51 95,76 Истинные.

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

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

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

Далее я рассмотрю распределение характеристик минимального давления..

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

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

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

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

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

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

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

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

Теперь, когда я заполнил все возможные недостающие значения, стараясь не повлиять на качество отрицательно, мне было бы удобно просто удалить оставшиеся записи, содержащие недостающие значения из набора данных. Достаточно легко удалить строки из DataFrame, содержащие NaN. Все, что мне нужно сделать, это вызвать метод dropna (), и Pandas сделает всю работу за меня..

Ресурсы.

Хотите изучить инструменты, машинное обучение и анализ данных, используемые в этом руководстве? Вот несколько отличных ресурсов для начала:

Заключение.

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

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

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

Ищете части 2 и 3 этой серии? Вот и все:

Похожие статьи