Я настоятельно рекомендую вам ознакомиться с веб-приложением Heroku для этого исследования здесь «ASHRAE Great Energy Predictor» и в этом репозитории Github для получения полного кода.

Оглавление

  1. ASHRAE — Great Energy Predictor III — введение в тематическое исследование машинного обучения
  2. Об ASHRAE
  3. Постановка задачи
  4. О наборе данных
  5. Метрика оценки
  6. Проблемы с набором данных
  7. Исследовательский анализ данных
  8. Первый подход
  9. Эксперименты и наблюдения
  10. Предварительная обработка данных
  11. Набор перекрестной проверки, настройка гиперпараметров и моделирование
  12. Результаты отправки
  13. Развертывание приложения Streamlit на Heroku
  14. Дальнейшая работа/Советы по улучшению оценки
  15. КонецПримечания
  16. Ссылки

ASHRAE — Great Energy Predictor III — пример машинного обучения Введение

Знаете ли вы, что здания дышат, чтобы вы могли дышать свежим воздухом? Это может показаться забавным, но они это делают. В здании, в котором вы сейчас находитесь, на рабочем месте или в любом частном/коммерческом здании установлена ​​какая-то система HVAC, которая обеспечивает свежий воздух для дыхания, тепловой комфорт, сбалансированную влажность, которая помогает вам оставаться здоровым ( предотвращать болезни), быть в хорошем настроении (что не дает вам ввязываться в драку ;)) и повышать продуктивность (кто хочет жить/работать в горящем здании или в замерзающем здании (отпустите его :p)?).

Так что же такое «ОВКВ»?

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

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

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

Вентиляция: Системы вентиляции должны направлять наружный воздух внутрь, а воздух в помещении — наружу. Он отвечает за распределение и поток свежего воздуха внутри застроенной среды.

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

О АШРАЭ

На официальном сайте ASHRAE говорится:

«ASHRAE, основанная в 1894 году, представляет собой глобальное общество, повышающее благосостояние людей с помощью устойчивых технологий для искусственной среды. Общество и его члены сосредоточены на строительных системах, энергоэффективности, качестве воздуха в помещениях, охлаждении и устойчивом развитии в отрасли. Благодаря исследованиям, написанию стандартов, публикации и непрерывному обучению ASHRAE уже сегодня формирует среду будущего. ASHRAE была образована как Американское общество инженеров по отоплению, охлаждению и кондиционированию воздуха в результате слияния в 1959 г. Американского общества инженеров по отоплению и кондиционированию воздуха (ASHAE), основанного в 1894 г., и Американского общества инженеров по холодильному оборудованию (ASRE), основанного в 1904 г. .”

Итак, в двух словах, ASHRAE (Американское общество инженеров по отоплению, охлаждению и кондиционированию воздуха) — это американская профессиональная ассоциация, стремящаяся продвигать проектирование и строительство систем отопления, вентиляции, кондиционирования и охлаждения.

Миссия и видение ASHRAE

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

Видение: здоровая и устойчивая искусственная среда для всех.

Как ASHRAE пытается реализовать миссию и концепцию устойчивого развития?

ASHRAE работает следующим образом, чтобы обеспечить устойчивую застроенную среду:

  • Через исследования
  • Написание стандартов
  • Издательский
  • Конференции
  • Непрерывное образование
  • Сертификация

Постановка задачи (проблема регрессии)

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

Вопрос .Сколько стоит охлаждение небоскреба летом?”.

Ответ:"Много! И не только в долларах, но и в воздействии на окружающую среду».

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

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

О наборе данных

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

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

Вы можете скачать данные отсюда: Источник данных

Файлы

train.csv

  • building_id — внешний ключ для метаданных здания.
  • meter - Идентификационный код счетчика. Читать как {0: electricity, 1: chilledwater, 2: steam, 3: hotwater}. Не в каждом здании есть все типы счетчиков.
  • timestamp - Когда было проведено измерение
  • meter_reading - Целевая переменная. Потребление энергии в кВтч (или эквивалент). Обратите внимание, что это реальные данные с ошибкой измерения, которая, как мы ожидаем, будет иметь базовый уровень ошибки моделирования.

building_meta.csv

  • site_id - Внешний ключ для файлов погоды.
  • building_id — внешний ключ для training.csv
  • primary_use - Индикатор основной категории деятельности для здания на основе Определений типа собственности EnergyStar
  • square_feet - Общая площадь здания
  • year_built - Год открытия здания
  • floor_count - Количество этажей здания

погода_[поезд/тест].csv

Данные о погоде с метеостанции как можно ближе к месту.

  • site_id
  • air_temperature - Градусы Цельсия
  • cloud_coverage - Часть неба, покрытая облаками, в октах
  • dew_temperature - Градусы Цельсия
  • precip_depth_1_hr - Миллиметры
  • sea_level_pressure - миллибар/гектопаскаль
  • wind_direction - Направление по компасу (0-360)
  • wind_speed - Метры в секунду

test.csv

Файлы отправки используют номера строк для идентификационных кодов, чтобы сэкономить место при загрузке файлов. test.csv не имеет данных об объектах; он существует, чтобы вы могли расставлять свои прогнозы в правильном порядке.

  • row_id - идентификатор строки для вашего файла отправки
  • building_id - Идентификационный код здания
  • meter - Идентификационный код счетчика
  • timestamp - Временные метки для периода тестовых данных

sample_submission.csv

Представление действительного образца.

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

Метрика оценки

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

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

Проблемы с набором данных

  • Огромный набор данных. Данные поезда состоят из 20 216 100 строк (20,21 миллиона, 2016 г.), а тестовые данные состоят из более чем 40 миллионов точек данных (2017 и 2018 года вместе взятых). В таких случаях мы не должны хранить нежелательные данные в основной памяти, иначе память взорвется и, следовательно, процесс будет остановлен.
  • Утечки данных. Целевые данные уже доступны в Интернете (ссылки приведены в разделе Ресурсы).

* Примечание: мы не использовали здесь утечку данных

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

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

Загрузка данных, анализ и слияние

Поскольку у нас есть 3 файла данных (train.csv, building_meta.csv, weather_train.csv), мы будем загружать данные в виде фрейма данных pandas, выполнять EDA для каждого фрейма данных и, наконец, объединять все это, чтобы получить один фрейм данных для моделирования.

Загрузить данные

%%time
dir_ = '../input/ashrae-energy-prediction/'
​
# read the data files into memory
train_df = pd.read_csv(dir_ + 'train.csv')
weather_train_df = pd.read_csv(dir_ + 'weather_train.csv')
building_meta_df = pd.read_csv(dir_ + 'building_metadata.csv')

EDA в файле «train.csv»

Получение основной информации о данных: -

# lets see that feature and data type does train set contains
train_df.head()

'''
print the basic information about train data
'''
key_list = ["Min date value in the train set",
            "Max date value in the train set",
            "No of unique buildings",
            "No of rows in the train set",
            "Min date value in the train set",
            "Max date value in the train set",
            "No of unique site id (location)"]
​
value_list = [train_df.timestamp.min(),
              train_df.timestamp.max(),
              train_df.building_id.unique().__len__(),
              train_df.__len__(),
              train_df.meter_reading.min(),
              train_df.meter_reading.max(),
              train_df.site_id.unique().__len__()]
group_list = zip(key_list, value_list)
for group in group_list:
    print(group[0], group[1])

Наблюдение

  • У нас есть подробная информация об идентификаторе здания (число, используемое для идентификации зданий), типе счетчика {0: электричество, 1: охлажденная вода, 2: пар, 3: горячая вода}, отметка времени (было записано время с показаниями) и показания счетчика. (показания счетчика — наша целевая переменная).
  • Нам дана метка времени, здесь мы имеем дело с данными временного ряда
  • Этот набор данных поезда содержит записи показаний счетчиков (4 типа счетчиков) за 2016 год (366 дней) для 1449 уникальных зданий в час (общая строка должна быть 366 * 24 * 4 * 1449) = 50912064.
  • У нас есть 20 216 100 записей показаний счетчиков. Причина, по которой у нас есть 20 миллионов записей, а не 50 миллионов, заключается в том, что не во всех зданиях есть все типы счетчиков.
  • Минимальное показание счетчика равно 0, а максимальное — 21904700,0 (оба значения, вероятно, являются выбросами).
  • Всего 16 различных сайтов.
  • Итак, у нас также есть значение показания счетчика «0», что довольно необычно. Спрашиваю себя, когда у вас показания счетчика 0? Оказывается, причин может быть много.
  • Отключение электроэнергии: это может быть одной из многих причин, по которым мы можем получить показания счетчика, равные 0. Хотя я также считаю, что это может быть помечено как «нан» (отсутствует), потому что нет показаний для чтения.
  • Сезонные причины: у нас есть 4-метровые типы (0: электричество, 1: охлажденная вода, 2: пар, 3: горячая вода). счетчик электроэнергии, потому что будет использоваться общее электричество) это может быть связано с тем, что охлажденная вода не будет использоваться в зимний сезон или устройства с горячей водой или паром вообще не используются в летний сезон.
  • Закрытое здание, в стадии строительства или на обслуживании: это может быть еще одним фактором, когда показания счетчика равны 0.
  • Ошибка в измерительном приборе (ошибка в самом счетчике): Это может быть и другая причина, Здесь сбой или неисправность в самом приборе.

Глядя на здание с показаниями счетчика 21904700,0 (выброс)

# get the building id of building where meter reading is 21904700.0
train_df.building_id[train_df.meter_reading == 21904700.0]

''''
building 1099 has only two meter type, 0 and 2
'''
​
for meter_id in range(0, 3, 2):
  # set the data
  bid = 1099
  d1 = go.Scatter(
      x = train_df.timestamp[(train_df.meter == meter_id) & (train_df.building_id == bid)],
      y = train_df.meter_reading[(train_df.meter == meter_id) & (train_df.building_id == bid)],
      mode= "lines"
  )
# set the appearance
  layout = dict(width = 800,
                height= 400,
                title = f'Distribution of meter {meter_id} reading for Building {bid} over time',
                xaxis= dict(title= 'Date',ticklen= 1,zeroline= False),
                yaxis= dict(title= f'meter {meter_id} reading',ticklen= 1,zeroline= False))
​
  fig = dict(data = d1, layout = layout)
  # plot the data
  iplot(fig)
plotly.offline.init_notebook_mode(connected=True)

Наблюдение

  • По счетчику электроэнергии (счетчик 0) видим нормальную картину подозрений нет.
  • Для счетчика пара (счетчик 2) показания счетчика примерно после марта исчисляются миллионами, что довольно странно. Здесь мы будем рассматривать его как выброс и выполним одну из двух вещей. 1) Удалите его. 2) Winsorize (используя среднее значение или какой-либо другой метод усреднения)

Распределение целевой переменной (показания счетчика электроэнергии) на участке с идентификатором 0 по 20 случайно выбранным зданиям

# sample building id
sample_bid = []
for i in range(20):
    # pick up building id randomly
    bid = train_df.building_id.sample().values[0]
    sample_bid.append(bid)
    d1 = go.Scatter(
        x = train_df.timestamp[(train_df.meter == 0) & (train_df.building_id == bid)],
        y = train_df.meter_reading[(train_df.meter == 0) & (train_df.building_id == bid)],
        mode= "lines"
    )
​
    layout = dict(width = 800,
                  height= 400,
                  title = 'Distribution of electricity meter reading for Building {} over time'.format(bid),
                  xaxis= dict(title= 'Date',ticklen= 1,zeroline= False),
                  yaxis= dict(title= 'meter 0 reading',ticklen= 1,zeroline= False))
​
    fig = dict(data = d1, layout = layout)
    iplot(fig)

* ПРИМЕЧАНИЕ: поскольку было слишком много графиков, которые могли бы занять много места, я решил не показывать вывод/графики для приведенного выше кода, но раздел «наблюдение» должен прояснить это.

Наблюдение

  • В некоторых зданиях показания счетчиков электроэнергии равны нулю в течение нескольких дней подряд (а затем внезапный всплеск).

  • Бывают случаи, когда у нас одно и то же показание несколько дней подряд

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

Нарисуйте тепловую карту (с нулевым счетчиком показаний), чтобы увидеть общую картину

Наблюдение

  • Приведенная выше тепловая карта для всех типов счетчиков показывает следующую картину:
  • Желтый цвет показывает большое количество нулевых показаний счетчика.
  • Вертикальная желтая линия показывает последовательные здания с нулевыми показаниями счетчика (*при условии, что здания расположены близко друг к другу (соседние))
  • Горизонтальная желтая линия показывает, что одно и то же здание имеет нулевые показания счетчика в течение нескольких дней подряд.
  • Здания не желтого цвета не содержат нулевых показаний счетчика.

Для счетчика 0 есть последовательные здания, которые имеют показания счетчика 0 с 1 по 14 день (они также имеют одинаковый идентификатор сайта (расположены в одном и том же месте))

  • Счетчики 1, 2 и 3 (счетчик горячей воды, пара и охлажденной воды) имеют множество горизонтальных желтых линий (нулевые показания счетчика), которые показывают, что какое-либо из устройств не используется. Это нормально, так как мало кто пользуется охлажденной водой зимой или горячей водой летом.
  • Наличие нулевых значений для показаний счетчика (особенно в случае счетчика электроэнергии) может быть проблематичным для модели во время обучения. Мы попытаемся удалить здания из временных рамок, если показания счетчика равны 0 в течение многих дней подряд (рассматривая их как выбросы).

Распределение показаний каждого типа счетчика

fig, axs = plt.subplots(ncols = 2, nrows= 2, figsize=(10, 7), facecolor=’w’, edgecolor=’k’)
# pad each plot
fig.tight_layout(pad=4.0)
row = 0
col = 0
m_type = [“electricity”, “hotwater”, “steam”, “chilled water”]
for i in range(4):
 if i == 2:
 row += 1
 col = 0
 sns.distplot(train_df.target[train_df.meter == i], ax= axs[row][col])
 axs[row][col].title.set_text(f’Distribution of {m_type[i]} meter’)
 col += 1

Наблюдение

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

Давайте посмотрим, есть ли какая-либо связь между идентификатором здания и идентификатором сайта.

# regression plot to capture a relationship (if any exist) between site id and building id
sns.relplot(x= “building_id”, y= “site_id”, hue= “site_id”, data= building_meta_df, legend=”full”)

Наблюдение Существует положительная связь между идентификатором сайта и идентификатором здания. Что это означает?

Это означает, что здания с близким идентификатором на самом деле расположены близко друг к другу (здание с идентификатором 45 намного ближе к зданию 47, чем здание с идентификатором 100 или здание с идентификатором 1). Почему это важно?

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

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

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

Подсчитайте уникальное здание на конкретном участке

fig, ax = plt.subplots()
building_count.plot.bar(x= "site_id", y= "building_id", rot=0, ax= ax)
ax.get_legend().remove()
plt.title("Count of building site wise")

Наблюдение

  • Большая часть здания находится на участке 3, за которым следует участок 13.

Количество типов счетчиков

# count plot of meter types
sns.countplot(train_df.meter)

Медиана показаний счетчиков по неделям на объект

'''
for each site id, compute median of meter reading across week
'''
# dictionary to hold site id and building IDs of corresponding site id
site_id_df = {}
​
# for each site id
for i in range(16):
    # get all the building IDs locate at ith site
    site_id_df["site_id_"+str(i)] = building_meta_df.building_id[building_meta_df.site_id == i]
    
    # get meter reading of all the buildings located at current site (site i)
    site_df = train_df[train_df.building_id.isin(site_id_df["site_id_"+str(i)].values)]
    
    # group data by building id, week and week
    building_week_groupby = site_df[["building_id", "week", "meter", "target"]].groupby(["building_id", "week", "meter"])
    # compute median of meter reading
    building_median_week = building_week_groupby.agg({"target": "median"}).reset_index()
    # update column name
    building_median_week.rename(inplace=True,columns= {"target": "median_week"})
    # create a new plot
    plt.figure()
    sns.pointplot(x= "week", y= "median_week", hue="meter", data= building_median_week).set_title("site id " + str(i))
    plt.ylabel("median of meter reading")
    plt.show()

* ПРИМЕЧАНИЕ. Поскольку все графики занимают много места, мы строим график только для нескольких сайтов.

Наблюдения У нас есть хорошая визуализация того, как ведут себя показания счетчика на разных объектах.

  • Почти всегда существует противоположное соотношение между метрами 1 и метрами 2 и 3 (вместе). Когда 1 увеличивается, другой уменьшается, и наоборот. Это очевидно, т.к. первый счетчик – это счетчик охлажденной воды, а 2 и 3 – стволовой и горячей воды. Поэтому люди обычно используют охлажденную воду летом и горячую/паровую зимой.
  • В зданиях с идентификатором объекта 15 отсутствуют показания счетчиков с 6 по 12 неделю для счетчиков 0, 2 и 3. (в чем может быть причина?)
  • На объекте с идентификатором 0 отсутствуют данные для счетчика 1 (охлажденная вода) и нулевые показания счетчика для счетчика 0 (счетчик электроэнергии). Мы удалим это, поскольку у нас нет предварительных данных об этом типе счетчиков.
  • На большинстве сайтов показания счетчика 0 (электричество) не сильно различаются. За исключением сайтов 3, 4, 5, 8 и 12.

EDA в файле «weather_train.csv»

# looking at data
weather_train_df.head()
# get the count of nan value rows columnwise
weather_null_count = weather_train_df.isna().sum().reset_index()
# alter the column name
weather_null_count.rename(columns={"index": "column_name", 0: "missing_row_count"}, inplace= True)
# compute the percentage and add new percentage column
weather_null_count["missing_row_percentage"] = weather_null_count.missing_row_count/weather_train_df.shape[0]
weather_null_count.plot.bar(x= "column_name", y= "missing_row_percentage")
plt.ylabel("Missing percentage")

Наблюдение Файл погоды содержит информацию о погоде на определенном участке в заданное время.

Всего 139773 записей и 15 функций.

Он содержит пропущенные значения. Вот краткое изложение:

  • В 6 столбцах отсутствуют значения (cloud_coverage dew Temperature, precip_depthbuilding_idhr, sea_level_pressure, wind_direction, wind_speed).
  • cloud_coverage имеет около 50% отсутствующих значений, за ним следует precip_depthbuilding_idhr, что составляет около 0,36% отсутствующих значений. Чтобы решить эту проблему, мы попытаемся удалить эти два столбца и посмотреть, улучшит ли это показатель. На втором этапе мы попытаемся вменить его и проверить, получим ли мы значительный прирост.
  • Для остальных отсутствующих столбцов мы вменим это с помощью моделей ML.

Распределение температуры воздуха, температуры росы, давления на уровне моря, направления ветра и скорости ветра во времени

# Distribution of air temperature day wise
sns.lineplot(x= "dayofyear", y= "air_temperature", sea_level_pressure, data= weather_train_df, hue= "site_id")
​
# Distribution of dew temperature day wise
sns.lineplot(x= "dayofyear", y= "dew_temperature", data= weather_train_df, hue= "site_id")
​
# Distribution of sea level pressure day wise
sns.lineplot(x= "dayofyear", y= "sea_level_pressure", data= weather_train_df, hue= "site_id", legend= "full")
​
# Distribution of wind direction day wise
sns.lineplot(x= "dayofyear", y= "wind_direction", data= weather_train_df, hue= "site_id", legend= "full")
​
# Distribution of cloud coverage day wise
sns.lineplot(x= "dayofyear", y= "cloud_coverage", data= weather_train_df, hue= "site_id")
​
# Distribution of precip_depthbuilding_idhr day wise
sns.lineplot(x= "dayofyear", y= "precip_depthbuilding_idhr", data= weather_train_df, hue= "site_id")

Наблюдение

  • Глядя на графики, кажется, что есть закономерность в температуре воздуха, температуре росы. Он увеличивается к середине, затем начинает уменьшаться к концу (как U-образная форма). Я чувствую, что эта переменная должна быть полезна во время моделирования.
  • wind_direction, sea_level_pressure, cloud_coverage, precip_depthbuilding_idhr и wind_speed, похоже, не имеют закономерностей. Они примерно одинаковы (или имеют некоторые случайные колебания) во времени.

EDA на «building_meta.csv»

Получение сводки данных

# get summary of the data
building_meta_df.describe()
# get the sum of null rows, columns wise
building_meta_df.isna().sum()

Наблюдение

  • Метафайл здания содержит 1449 строк (столько же, сколько уникальных зданий в наборе данных) и 6 столбцов.
  • Самое старое здание было построено в 1900 году, а самое новое — в 2017 году.
  • Минимальная площадь застройки 283, максимальная 875000
  • Минимальное количество этажей — 1, максимальное — 26.
  • Год постройки, кажется, отсутствует для более чем 50% здания, так же как и floor_count. Поэтому мы отбросим эти функции и будем наблюдать за метрикой
  • Также, как видно из блокнота EDA, существует связь между site_id и building_id. Мы обязательно должны включить эти две функции.

Количество значений в столбце основного использования

# count plot 
sns.countplot(building_meta_df.primary_use)
# rotate the labels by 80 degrees
plt.xticks(rotation= 80)

Наблюдение

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

Распределение площади застройки

# distribution plot of area in square feet
sns.distplot(building_meta_df.square_feet)

Наблюдение

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

Фиксация взаимосвязи между показаниями счетчика и площадью в квадратных футах

# compute median of meter reading across buildings
df_median_meter_reading = train_df.groupby("building_id").agg({"target": "median"}).reset_index()
# bringing square_feet area to the same scale
building_meta_df["square_feet"] = np.log1p(building_meta_df["square_feet"])
# merget both the dataframe
df_merged = df_median_meter_reading.reset_index().merge(building_meta_df[["building_id", "square_feet", "primary_use"]], on="building_id", how='left')
# regplot
sns.regplot(x = "target",y= "square_feet" , data= df_merged)

Наблюдение

  • Мы можем ясно видеть положительную связь между медианным показанием счетчика и квадратными футами (в логарифмической шкале). Площадь здания может быть полезна во время моделирования проблемы.

Подход первого разреза

Мой первый подход состоял бы в том, чтобы получить базовый балл для сравнения других сложных идей и моделей. Моим первым подходом будет подход «Просто», когда я буду предварительно обрабатывать данные ровно настолько, чтобы их можно было ввести в модель (например, легкий GBM) и получить метрику оценки. Эта оценка поможет мне сравнить мои сложные идеи (разработка функций) и модель и направит меня в правильном направлении и при принятии решений. Я буду использовать легкий GBM (который используется большинством Kagglers, по крайней мере, для этого соревнования) с данными 2-кратной перекрестной проверки.

Другие передовые идеи моделирования перечислены ниже:

Разделяй и властвуй: мы будем обучать модель для каждого типа счетчика и идентификатора сайта (местоположения) отдельно. Мы будем использовать легкий GBM с 2-кратным разделением перекрестной проверки и будем иметь в общей сложности 16 * 2 = 32 модели (16 моделей (всего 16 сайтов, каждая модель ML на сайт) и 2 перекрестных проверки) . Идея обучения различным режимам машинного обучения для разных объектов проста, потому что погода будет одинаковой для всех зданий, расположенных на одном и том же объекте, и если на объекте произойдет отключение электроэнергии, большинство зданий (если не все ), расположенные на соответствующем сайте, будут затронуты. Таким образом, существует прямая связь между сайтом и зданием, и, следовательно, это можно использовать, обучая разные модели для разных сайтов.

Ансемблирование: здесь мы можем использовать объединение алгоритмов машинного обучения, таких как случайный лес, многоуровневый персептрон (ANN), Light GBM, кошачий буст и XGB. Мы будем использовать максимальное голосование, чтобы получить прогноз (это одна из идей), или попробуем метаклассификатор (суммирование) (это вторая идея), чтобы увидеть, что работает лучше.

Окончательная модель и представление будут выбраны на основе результатов рейтинга лидеров (как общедоступных, так и закрытых)

Эксперименты и наблюдения

Этот раздел должен быть после раздела «Отправка», но, поскольку я просто пишу хорошие вещи (работы, которые сработали) в этом блоге, я чувствую, что мы должны сначала узнать, что не сработало. После множества экспериментов, вот что сработало, а что нет.

  • Вменение на основе модели (с использованием кошачьего повышения) не работало, как и простое вменение на основе среднего или медианы. Я также пытался использовать групповое вменение на основе соответствующих столбцов, например, вменение с использованием среднего значения за день/месяц/site_id и так далее. Наилучший результат я получил, когда позволил алгоритму самостоятельно обрабатывать недостающие данные (здесь мы используем lightGBM).
  • Добавление дополнительных и сложных функций ухудшало оценку таблицы лидеров. Добавление функций временных рядов, таких как скользящее окно, расширяющееся окно, не сработало должным образом. Предоставление целевого значения, вероятно, является плохой идеей (использование целевого значения в качестве функции).
  • Модель разделения и обучения, основанная на типах meter и site_id, тоже не сработала. Моя гипотеза заключалась в том, что обучающие модели для каждой пары (meter, site_id) дадут хорошие результаты, потому что здания, расположенные на участке site_id, будут вести себя одинаково (представьте, что отключение на определенном участке). Обучение одной модели на целом наборе данных работало лучше, чем обучение моделей на основе пары.
  • Прогнозирование преобразования логарифма (1 + meter_reading), нормализованного по площади здания (square_feet), как правило, дает лучший результат, чем сам прогноз meter_reading. Вот цитата из этого обсуждения на Kaggle.

Ближе к концу конкурса мы попытались стандартизировать meter_reading, разделив его на square_feet; т. е. мы предсказали log1p(meter_reading/square_feet). Идея пришла к Исаму после прочтения этого дискуссионного поста от Артема Воробьева. Модели, обученные со стандартизированной целью, добавили разнообразия в наш окончательный ансамбль и улучшили нашу оценку примерно на 0,002. Если бы у нас было больше времени, мы хотели бы продолжить изучение этой идеи; например, мы могли бы попытаться предсказать log1p(meter_reading)/square_feet или создать функции, используя стандартизированные цели.

  • Я также обучал алгоритмы машинного обучения, такие как catboost, XGboost, включая глубокие нейронные сети, такие как CNN-LSTM, MLP. Все они, кажется, либо переоценивают, либо ухудшают оценку.
  • Рассмотрение этого как проблемы временного ряда не сработало для меня. Так что я рассматривал как

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

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

Вы можете взглянуть на мой старый конвейер данных здесь: Предварительная обработка и разработка функций в ASHRAE.

Предварительная обработка данных

Поскольку эталонная модель оказалась победителем, мы анализируем объект DateTime, чтобы получить функцию DateTime, такую ​​как день, выходные, месяц и т. д. Мы добавили is_holiday функцию (американские праздники в 2016, 17, 18), которая помогает нам немного уменьшить переоснащение. . Мы также добавили функцию солнечного горизонтального излучения, описанную в этом обсуждении на Kaggle. Эта функция помогла мне уменьшить переоснащение, а также помогла мне получить лучший личный счет. Мы использовали кодировщик меток для кодирования текстовой категориальной функции primary_use. Мы также удалили floor_count и built_year, потому что в них отсутствовало более 60% значений (и их удаление дает лучшие результаты). Наконец, мы применяем логарифмическое преобразование к целевой переменной, нормализованной по square_feet (площадь здания).

Вот полный код предварительной обработки:

# transform text categorical feature
df.primary_use = le.transform(df.primary_use)
​
# apply log1p to the area (making it more normal and dealing with extreme values)
df.square_feet = np.log1p(df.square_feet)
​
# add dayofyear column
df["dayofyear"] = df.timestamp.dt.dayofyear
# add day column
df["day"] = df.timestamp.dt.day
# add week column
df["weekday"] = df.timestamp.dt.weekday
# add hour column
df["hour"] = df.timestamp.dt.hour
# add month column
df["month"] = df.timestamp.dt.month
# add weekend column
df["weekend"] = df.timestamp.dt.weekday.apply(lambda x: 0 if x <5 else 1)
'''
"It is supposed to calculate the solar horizontal radiation coming into the building". Source:- https://www.kaggle.com/c/ashrae-energy-prediction/discussion/124984
'''
latitude_dict = {0 :28.5383,
                 1 :50.9097,
                 2 :33.4255,
                 3 :38.9072,
                 4 :37.8715,
                 5 :50.9097,
                 6 :40.7128,
                 7 :45.4215,
                 8 :28.5383,
                 9 :30.2672,
                 10 :40.10677,
                 11 :45.4215,
                 12 :53.3498,
                 13 :44.9375,
                 14 :38.0293,
                 15: 40.7128}
​
df['latitude'] = df['site_id'].map(latitude_dict)
df['solarHour'] = (df['hour']-12)*15 # to be removed
df['solarDec'] = -23.45*np.cos(np.deg2rad(360*(df['day']+10)/365)) # to be removed
df['horizsolar'] = np.cos(np.deg2rad(df['solarHour']))*np.cos(np.deg2rad(df['solarDec']))*np.cos(np.deg2rad(df['latitude'])) + np.sin(np.deg2rad(df['solarDec']))*np.sin(np.deg2rad(df['latitude']))
df['horizsolar'] = df['horizsolar'].apply(lambda x: 0 if x <0 else x)
​
# Holiday feature
holidays = ["2016-01-01", "2016-01-18", "2016-02-15", "2016-05-30", "2016-07-04",
            "2016-09-05", "2016-10-10", "2016-11-11", "2016-11-24", "2016-12-26",
            "2017-01-01", "2017-01-16", "2017-02-20", "2017-05-29", "2017-07-04",
            "2017-09-04", "2017-10-09", "2017-11-10", "2017-11-23", "2017-12-25",
            "2018-01-01", "2018-01-15", "2018-02-19", "2018-05-28", "2018-07-04",
            "2018-09-03", "2018-10-08", "2018-11-12", "2018-11-22", "2018-12-25",
            "2019-01-01"]
df["is_holiday"] = df.timestamp.dt.date.astype("str").isin(holidays).astype(int)
​
# Drop the columns which contains lots of missing values and have less or no effect on predicting the target
drop_features = ['floor_count', 'year_built']
df.drop(drop_features, axis=1, inplace=True)

Это все, что касается предварительной обработки.

Набор перекрестной проверки, настройка гиперпараметров и моделирование

Для разделения перекрестной проверки я разделил набор данных на 2 раза (без перетасовки, пополам).

Для задачи регрессии я использовал повышающий алгоритм, который быстрее обучается (по сравнению с ИНС) и может обрабатывать нелинейные данные (в отличие от линейной регрессии, которая работает быстро, но фиксирует только линейный паттерн). Мы будем обучать 2 модели lightGBM, каждая из которых обучена на 1 сгибе и проверена на другом, поэтому у каждого сгиба будет только один шанс рассматриваться как набор перекрестной проверки. Таким образом, мы предоставляем модели весь набор данных. Чтобы получить окончательный прогноз, мы просто возьмем среднее значение, предсказанное этими двумя моделями.

Я искал сетку вручную, чтобы получить лучшие значения гиперпараметров. Вот список имен гиперпараметров, которые я искал:

num_leaves, feature_fraction, learning_rate,reg_lambda

Лучший найденный гиперпараметр:

{'num_leaves': 90,
 'feature_fraction': 0.85,
 'learning_rate': 0.05,
 'reg_lambda': 10}

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

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

*ВНИМАНИЕ: у нас на диске уже сохранена 38-я модель. Мы замариновали его, чтобы мы могли загружать и повторно использовать его при необходимости, то есть во время создания модели (см. раздел Развертывание приложения Streamlit на Heroku).

Полный код находится здесь: ASHRAE_Great_Energy_Predictor_III(Modeling).ipynb

Результаты отправки

Вот оценка таблицы лидеров Kaggle.

Здесь мы получаем частную оценку 1,322 и общедоступную оценку 1,137, что, на мой взгляд, является достойным показателем, учитывая проблемы в конкурсе, такие как «огромный набор данных» и «утечка данных» (мы не использовали утечки данных здесь, может быть одна из причин, почему мы получили вышеуказанный балл).

Развертывание приложения Streamlit на Heroku

В этом разделе мы развернем нашу лучшую модель на Heroku. Чтобы сделать приложение машинного обучения интерактивным и предоставить пользователям свободу ввода данных, я использовал простую в использовании «streamlit» (библиотека Python для создания веб-приложения для машинного обучения).

Heroku — это платформа как услуга (PaaS), которая предоставляет платформу для быстрого и простого запуска нашего приложения. В отличие от службы AWS, такой как «EC2», которая представляет собой инфраструктуру как услугу (IaaS), которую нам необходимо настроить, чтобы предоставить среду выполнения (или платформу) для запуска нашего приложения.

Чтобы развернуть приложение Python на Heroku, выполните следующие действия:

  1. Зарегистрируйте учетную запись Heroku здесь
  2. После того, как вы настроите свою учетную запись, перейдите в панель управления или просто перейдите по ссылке эта.
  3. Нажмите «новый»-> «создать новое приложение». Введите здесь название приложения и регион и нажмите «Создать приложение».

4. Сначала давайте посмотрим, какие файлы нам потребуются, кроме файлов/папок проекта, для запуска нашего потокового приложения на Heroku. Вот список файлов, которые потребуются Heroku для запуска вашего приложения: * ПРИМЕЧАНИЕ. Все эти файлы должны находиться в локальной рабочей области, мы еще не загружали файлы на Heroku.

  • requirement.txt: этот файл содержит все модули, необходимые вашему приложению Python. Вот как это может выглядеть:
seaborn
matplotlib
streamlit
….

* ПРИМЕЧАНИЕ: вы можете указать версию, например seaborn==0.11.1

Чтобы получить зависимости вашего текущего проекта, вы можете использовать pipreqs, библиотеку Python. Он создаст файл requires.txt для вашего проекта.

  • Procfile: содержит команду, которую приложение Heroku будет использовать в порядке запуска для запуска вашего приложения на своей платформе. Вот как может выглядеть «procfile»:
web: sh setup.sh && streamlit run Final.py

В нем говорится: это тип веб-процесса (разрешите приложению Heroku получать HTTP-запрос), запустите файл setup.sh в оболочке sh и запустите потоковый сервер Потоковод запуска Final.py. Чтобы узнать больше об Procfile, используемом Heroku, прочитайте это.

  • setup.sh: этот файл используется исключительно для настройки Streamlit. По этой причине мы сначала запускаем «setup.sh», а затем запускаем сервер потоковой передачи «streamlit run Final.py». Конфигурация будет выглядеть так:
mkdir -p ~/.streamlit/
echo “\
[general]\n\
email = \”youremail@domainName”\n\
“ > ~/.streamlit/credentials.toml
echo “\
[server]\n\
headless = true\n\
enableCORS=false\n\
port = $PORT\n\
“ > ~/.streamlit/config.toml

Этот сценарий создаст папку "streamlit" в домашнем каталоге и добавит два подфайла: "credentials.toml" и "config.toml". который сообщает streamlit, какой порт использовать, запускать ли безголовый и хотим ли мы разрешить CORS.

Просто скопируйте и вставьте приведенный выше код в файл «setup.sh», и он должен работать.

Вот как будет выглядеть папка вашего проекта:

5. После создания нового приложения Heroku попросит вас выбрать один из трех методов развертывания и предоставит вам шаги, которые необходимо выполнить для развертывания вашего приложения.

Здесь мы просто сосредоточимся на "Heroku Git". Чтобы использовать Heroku git, вам необходимо скачать Heroku CLI, скачать его можно здесь

Вот инструкции, которые Heroku предоставит, если вы хотите развернуть через «Развертывание с помощью Heroku Git».

Откройте приглашение cmd или терминал и выполните следующие действия:

5.1) Войдите в Heroku, набрав:

heroku login

Откроется вкладка в веб-браузере для аутентификации.

5.2) Найдите корневую папку вашего проекта и введите:

git init

Это создаст локальный репозиторий git и позволит вам поддерживать версии приложения python. Нам нужно выбрать приложение, а затем отправить все основные файлы в Heroku.

5.3) Вам нужно выбрать приложение Heroku, в которое вы хотите загрузить приложение Python и другие дополнительные файлы (поскольку у вас может быть несколько приложений Heroku, вам нужно указать Heroku, куда вы хотите загрузить файлы), чтобы сделать это следующим образом:

heroku git: remote — app “app_name”

«app_name» — это имя приложения Heroku, которое вы создали на шаге 3.

5.4) Теперь добавьте и зафиксируйте все файлы в локальном репозитории, набрав:

git add .
git commit -am “my first commit”

5.5) Наконец, загрузите весь проект на сервер Heroku.

git push

6. После загрузки всех необходимых файлов на сервер Heroku нам просто нужно сделать последний шаг, а именно запустить dynos. Dynos — это сердце Heroku. Они представляют собой легкий виртуализированный контейнер Linux, который запускает код (наше потоковое приложение). Вы можете узнать больше о dynos Heroku здесь. Если вы посмотрите на вкладку Ресурсы в своем приложении Heroku, вы увидите что-то вроде:

Это означает, что нет Dynos (контейнера), на котором выполняется наш код (и, следовательно, нет процесса). Чтобы запустить dynos, введите:

heroku ps:scale web=1

Эта команда указывает Heroku получить 1'web” динамометр, который будет запускать весь наш проталкиваемый код. Чтобы узнать, какие еще конфигурации динамометров доступны, читайте это.

После выполнения этой команды вы должны увидеть на вкладке «Ресурсы» примерно следующее:

Итак, наше приложение теперь работает на веб-динамиках Heroku, вы можете просто зайти на «yourappname.herokuapp.com» и посмотреть, все ли работает нормально.

Проверьте веб-приложение Heroku ASHRAE Great Energy Predictor, чтобы увидеть, как будет выглядеть ваше приложение с потоковым освещением.

Будущая работа / советы по улучшению оценки

  • Использование методов ансамбля. Здесь мы создаем модели множественной регрессии, которые отличаются друг от друга (идея, стоящая за этим, заключается в том, что каждая модель будет изучать разные аспекты данных, и, следовательно, общий прогноз будет хорошим), т.е. гетерогенные в природе. Это может включать в себя обучение различных моделей, таких как древовидная, искусственная нейронная сеть, SVM и т. д., и агрегирование их результатов.
  • Использование утечек данных. Данные для этого соревнования общедоступны. Чтобы узнать больше об утечках данных, прочитайте ядро ​​Это. Использование цели утечек для направления нашей модели в правильном направлении, несомненно, поможет нам улучшить оценку.
  • Разработка функций: поскольку набор данных огромен, разработка новых функций и процесс выбора функций сложны, трудны и не экономят память, но это может помочь нам подняться в таблице лидеров.
  • Использование автоматизированного инструмента машинного обучения. Использование библиотек автоматического машинного обучения, таких как auto-sklearn, TPOT, h20 и т. д., может помочь нам получить более высокие оценки или даже помочь нам в процессе сборки, но одно большое узкое место может быть связано с размером набора данных.
  • Экспериментирование с различным разделением перекрестной проверки. Здесь мы использовали 2-кратное разделение CV, выбирая такие разделения, как 4 разделения (для каждого квартала) или 8–4 месяца и т. д., что может помочь зафиксировать шаблоны лучше, что может привести к лучшему счету.
  • Использование подмножества данных: мы можем поэкспериментировать с несколькими миллионами строк для обучения моделей. Поскольку у нас есть 20,21 миллиона обучающих строк, которые также могут содержать нерелевантные (зашумленные) данные.

EndNote

Это был удивительный опыт участия в конкурсе Kaggle «ASHRAE Great Energy Predictor III». Я многому научился по таким темам, как обработка больших данных с ограниченными ресурсами, проектирование функций, выбор и удаление функций. коллинеарных признаков, важность настройки гиперпараметров, предсказание временных рядов и многое другое в процессе.

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

Спасибо за чтение!

О! Кроме того, вы можете связаться со мной в Linkedin для любых вопросов, запросов или предложений.

использованная литература

Курс прикладного AI

АШРАЭ

Миссия и видение ASHRAE

Описание конкурса

Простой исследовательский блокнот — ASHRAE

Разработка признаков для временных рядов

ASHRAE — UCF Spider и EDA (полные тестовые этикетки)

UCL: утечка данных (Эпизод 2)

Все счетчики электроэнергии обнулены до 20 мая

ASHRAE-нули

Разделяй и властвуй

Простой исследовательский блокнот — ASHRAE

Отсутствующие данные и нули отображаются

Как развернуть Streamlit на Heroku