Skip to content

Instantly share code, notes, and snippets.

@alllexx88
Created March 25, 2019 16:23
Show Gist options
  • Save alllexx88/3dc2c54320e9f0a70151056efe0e831a to your computer and use it in GitHub Desktop.
Save alllexx88/3dc2c54320e9f0a70151056efe0e831a to your computer and use it in GitHub Desktop.
Created on Cognitive Class Labs
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Using TensorFlow backend.\n"
]
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"from math import sqrt\n",
"from numpy import split\n",
"from numpy import array\n",
"from sklearn.metrics import mean_squared_error\n",
"from sklearn.preprocessing import StandardScaler\n",
"from matplotlib import pyplot\n",
"pd.plotting.register_matplotlib_converters()\n",
"from keras.models import Sequential\n",
"from keras.layers import Dense\n",
"from keras.layers import Flatten\n",
"from keras.layers import LSTM\n",
"from keras.layers import RepeatVector\n",
"from keras.layers import TimeDistributed\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Загрузим датасет"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"timeStamp object\n",
"month int64\n",
"dayofweek int64\n",
"precip float64\n",
"demand float64\n",
"temp float64\n",
"is_workday float64\n",
"dtype: object"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"electricity_data = pd.read_csv ('Electricity_D.csv')\n",
"electricity_data.dtypes"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>timeStamp</th>\n",
" <th>month</th>\n",
" <th>dayofweek</th>\n",
" <th>precip</th>\n",
" <th>demand</th>\n",
" <th>temp</th>\n",
" <th>is_workday</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2012-01-01</td>\n",
" <td>0</td>\n",
" <td>6</td>\n",
" <td>0.0033</td>\n",
" <td>91775.9</td>\n",
" <td>47.3622</td>\n",
" <td>0.5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2012-01-02</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0.0000</td>\n",
" <td>127270.9</td>\n",
" <td>40.4967</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2012-01-03</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0.0000</td>\n",
" <td>146292.3</td>\n",
" <td>26.6725</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2012-01-04</td>\n",
" <td>0</td>\n",
" <td>2</td>\n",
" <td>0.0000</td>\n",
" <td>152070.4</td>\n",
" <td>20.5850</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2012-01-05</td>\n",
" <td>0</td>\n",
" <td>3</td>\n",
" <td>0.0000</td>\n",
" <td>147125.9</td>\n",
" <td>33.5775</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" timeStamp month dayofweek precip demand temp is_workday\n",
"0 2012-01-01 0 6 0.0033 91775.9 47.3622 0.5\n",
"1 2012-01-02 0 0 0.0000 127270.9 40.4967 0.0\n",
"2 2012-01-03 0 1 0.0000 146292.3 26.6725 0.0\n",
"3 2012-01-04 0 2 0.0000 152070.4 20.5850 0.0\n",
"4 2012-01-05 0 3 0.0000 147125.9 33.5775 0.0"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"electricity_data.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Преобразуем колонку 'timeStamp' в datetime"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"timeStamp datetime64[ns]\n",
"month int64\n",
"dayofweek int64\n",
"precip float64\n",
"demand float64\n",
"temp float64\n",
"is_workday float64\n",
"dtype: object"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"electricity_data['timeStamp'] = pd.to_datetime(electricity_data['timeStamp'])\n",
"electricity_data.dtypes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Делаем колонку 'timeStamp' индексом"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>month</th>\n",
" <th>dayofweek</th>\n",
" <th>precip</th>\n",
" <th>demand</th>\n",
" <th>temp</th>\n",
" <th>is_workday</th>\n",
" </tr>\n",
" <tr>\n",
" <th>timeStamp</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2012-01-01</th>\n",
" <td>0</td>\n",
" <td>6</td>\n",
" <td>0.0033</td>\n",
" <td>91775.9</td>\n",
" <td>47.3622</td>\n",
" <td>0.5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-02</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0.0000</td>\n",
" <td>127270.9</td>\n",
" <td>40.4967</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-03</th>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0.0000</td>\n",
" <td>146292.3</td>\n",
" <td>26.6725</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-04</th>\n",
" <td>0</td>\n",
" <td>2</td>\n",
" <td>0.0000</td>\n",
" <td>152070.4</td>\n",
" <td>20.5850</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-05</th>\n",
" <td>0</td>\n",
" <td>3</td>\n",
" <td>0.0000</td>\n",
" <td>147125.9</td>\n",
" <td>33.5775</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" month dayofweek precip demand temp is_workday\n",
"timeStamp \n",
"2012-01-01 0 6 0.0033 91775.9 47.3622 0.5\n",
"2012-01-02 0 0 0.0000 127270.9 40.4967 0.0\n",
"2012-01-03 0 1 0.0000 146292.3 26.6725 0.0\n",
"2012-01-04 0 2 0.0000 152070.4 20.5850 0.0\n",
"2012-01-05 0 3 0.0000 147125.9 33.5775 0.0"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"electricity_data.set_index('timeStamp', inplace=True)\n",
"electricity_data.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Кодируем категориальные данные в onehot представление"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>precip</th>\n",
" <th>demand</th>\n",
" <th>temp</th>\n",
" <th>workday</th>\n",
" <th>weekend</th>\n",
" <th>celebration</th>\n",
" <th>Mn</th>\n",
" <th>Tue</th>\n",
" <th>Wd</th>\n",
" <th>Thr</th>\n",
" <th>...</th>\n",
" <th>Mr</th>\n",
" <th>Ap</th>\n",
" <th>May</th>\n",
" <th>Jn</th>\n",
" <th>Jl</th>\n",
" <th>Ag</th>\n",
" <th>Sp</th>\n",
" <th>Oct</th>\n",
" <th>Nv</th>\n",
" <th>Dc</th>\n",
" </tr>\n",
" <tr>\n",
" <th>timeStamp</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2012-01-01</th>\n",
" <td>0.0033</td>\n",
" <td>91775.9</td>\n",
" <td>47.3622</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-02</th>\n",
" <td>0.0000</td>\n",
" <td>127270.9</td>\n",
" <td>40.4967</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-03</th>\n",
" <td>0.0000</td>\n",
" <td>146292.3</td>\n",
" <td>26.6725</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-04</th>\n",
" <td>0.0000</td>\n",
" <td>152070.4</td>\n",
" <td>20.5850</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-05</th>\n",
" <td>0.0000</td>\n",
" <td>147125.9</td>\n",
" <td>33.5775</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-06</th>\n",
" <td>0.0000</td>\n",
" <td>140820.9</td>\n",
" <td>43.4008</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-07</th>\n",
" <td>0.0000</td>\n",
" <td>124258.6</td>\n",
" <td>51.4979</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-08</th>\n",
" <td>0.0000</td>\n",
" <td>122893.0</td>\n",
" <td>41.4671</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-09</th>\n",
" <td>0.0000</td>\n",
" <td>141379.7</td>\n",
" <td>35.3600</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2012-01-10</th>\n",
" <td>0.0000</td>\n",
" <td>140910.3</td>\n",
" <td>40.5033</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>10 rows × 24 columns</p>\n",
"</div>"
],
"text/plain": [
" precip demand temp workday weekend celebration Mn \\\n",
"timeStamp \n",
"2012-01-01 0.0033 91775.9 47.3622 0.0 0.0 1.0 0.0 \n",
"2012-01-02 0.0000 127270.9 40.4967 1.0 0.0 0.0 1.0 \n",
"2012-01-03 0.0000 146292.3 26.6725 1.0 0.0 0.0 0.0 \n",
"2012-01-04 0.0000 152070.4 20.5850 1.0 0.0 0.0 0.0 \n",
"2012-01-05 0.0000 147125.9 33.5775 1.0 0.0 0.0 0.0 \n",
"2012-01-06 0.0000 140820.9 43.4008 1.0 0.0 0.0 0.0 \n",
"2012-01-07 0.0000 124258.6 51.4979 0.0 1.0 0.0 0.0 \n",
"2012-01-08 0.0000 122893.0 41.4671 0.0 1.0 0.0 0.0 \n",
"2012-01-09 0.0000 141379.7 35.3600 1.0 0.0 0.0 1.0 \n",
"2012-01-10 0.0000 140910.3 40.5033 1.0 0.0 0.0 0.0 \n",
"\n",
" Tue Wd Thr ... Mr Ap May Jn Jl Ag Sp Oct Nv \\\n",
"timeStamp ... \n",
"2012-01-01 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-02 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-03 1.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-04 0.0 1.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-05 0.0 0.0 1.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-06 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-07 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-08 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-09 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"2012-01-10 1.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"\n",
" Dc \n",
"timeStamp \n",
"2012-01-01 0.0 \n",
"2012-01-02 0.0 \n",
"2012-01-03 0.0 \n",
"2012-01-04 0.0 \n",
"2012-01-05 0.0 \n",
"2012-01-06 0.0 \n",
"2012-01-07 0.0 \n",
"2012-01-08 0.0 \n",
"2012-01-09 0.0 \n",
"2012-01-10 0.0 \n",
"\n",
"[10 rows x 24 columns]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"electricity_data_onehot = electricity_data.copy()\n",
"\n",
"for (n, is_workday) in zip([0, 1, 0.5], ['workday', 'weekend', 'celebration']):\n",
" electricity_data_onehot[is_workday] = (electricity_data_onehot['is_workday'] == n).astype(float)\n",
"\n",
"for (n, dayofweek) in zip(range(7), ['Mn', 'Tue', 'Wd', 'Thr', 'Fr', 'St', 'Sn']):\n",
" electricity_data_onehot[dayofweek] = (electricity_data_onehot['dayofweek'] == n).astype(float)\n",
"\n",
"for (n, month) in zip(range(12), ['Jr', 'Fr', 'Mr', 'Ap', 'May', 'Jn', 'Jl', 'Ag', 'Sp',\n",
" 'Oct', 'Nv', 'Dc']):\n",
" electricity_data_onehot[month] = (electricity_data_onehot['month'] == n).astype(float)\n",
"\n",
"electricity_data_onehot.drop(columns = ['is_workday', 'dayofweek', 'month'], inplace = True)\n",
"\n",
"electricity_data_onehot.head(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Датасет для ML"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" demand\n",
"2014-05-04 114339.3\n",
"2014-05-05 129762.3\n",
"2014-05-06 129834.0\n",
"2014-05-07 129842.7\n",
"2014-05-08 131727.8\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>temp</th>\n",
" <th>precip</th>\n",
" <th>workday</th>\n",
" <th>weekend</th>\n",
" <th>celebration</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2014-05-04</th>\n",
" <td>58.0013</td>\n",
" <td>0.0000</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2014-05-05</th>\n",
" <td>58.1371</td>\n",
" <td>0.0000</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2014-05-06</th>\n",
" <td>59.1088</td>\n",
" <td>0.0000</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2014-05-07</th>\n",
" <td>57.7008</td>\n",
" <td>0.0000</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2014-05-08</th>\n",
" <td>54.8892</td>\n",
" <td>0.0146</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" temp precip workday weekend celebration\n",
"2014-05-04 58.0013 0.0000 0.0 1.0 0.0\n",
"2014-05-05 58.1371 0.0000 1.0 0.0 0.0\n",
"2014-05-06 59.1088 0.0000 1.0 0.0 0.0\n",
"2014-05-07 57.7008 0.0000 1.0 0.0 0.0\n",
"2014-05-08 54.8892 0.0146 1.0 0.0 0.0"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# переменная, определяющая прогнозируемый интервал\n",
"X_date = pd.to_datetime('2016-05-01')\n",
"# наша неделя, дни недели\n",
"X_week = pd.date_range(X_date, X_date + pd.DateOffset(days=7), closed='left')\n",
"days_dict = {0:'Пн',1:'Вт',2:'Ср',3:'Чт',4:'Пт',5:'Сб',6:'Вс'}\n",
"X_weekdays = [days_dict[d.dayofweek] for d in X_week]\n",
"# реальные данные за нашу неделю\n",
"y_real = electricity_data_onehot.loc[X_week, ['demand']].values\n",
"\n",
"# ~2 года по X_date, не включая X_date:\n",
"dates_range = pd.date_range(X_date - pd.DateOffset(weeks=104), X_date, closed='left')\n",
"\n",
"ml_X = electricity_data_onehot.loc[dates_range,\n",
" ['temp', 'precip', 'workday', 'weekend', 'celebration']]\n",
"ml_Y = electricity_data_onehot.loc[dates_range, ['demand']]\n",
"\n",
"print(ml_Y.head())\n",
"ml_X.head()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# использована часть кода отсюда:\n",
"# https://machinelearningmastery.com/how-to-develop-lstm-models-for-multi-step-time-series-forecasting-of-household-power-consumption\n",
"\n",
"# evaluate one or more weekly forecasts against expected values\n",
"def evaluate_forecasts(actual, predicted):\n",
" scores = list()\n",
" # calculate an RMSE score for each day\n",
" for i in range(actual.shape[1]):\n",
" # calculate mse\n",
" mse = mean_squared_error(actual[:, i], predicted[:, i])\n",
" # calculate rmse\n",
" rmse = sqrt(mse)\n",
" # store\n",
" scores.append(rmse)\n",
" # calculate overall RMSE\n",
" s = 0\n",
" for row in range(actual.shape[0]):\n",
" for col in range(actual.shape[1]):\n",
" s += (actual[row, col] - predicted[row, col])**2\n",
" score = sqrt(s / (actual.shape[0] * actual.shape[1]))\n",
" return score, scores\n",
"\n",
"# summarize scores\n",
"def summarize_scores(name, score, scores):\n",
" s_scores = ', '.join(['%.1f' % s for s in scores])\n",
" print('%s: [%.3f] %s' % (name, score, s_scores))\n",
"\n",
"# convert history into inputs and outputs\n",
"def to_supervised(train, n_input, n_out=7):\n",
" # flatten data\n",
" data = train.reshape((train.shape[0]*train.shape[1], train.shape[2]))\n",
" X, y = list(), list()\n",
" in_start = 0\n",
" # step over the entire history one time step at a time\n",
" for _ in range(len(data)):\n",
" # define the end of the input sequence\n",
" in_end = in_start + n_input\n",
" out_end = in_end + n_out\n",
" # ensure we have enough data for this instance\n",
" if out_end < len(data):\n",
" X.append(data[in_start:in_end, :])\n",
" y.append(data[in_end:out_end, 0])\n",
" # move along one time step\n",
" in_start += 1\n",
" return array(X), array(y)\n",
"\n",
"# train the model\n",
"def build_model(train, n_input):\n",
" # prepare data\n",
" train_x, train_y = to_supervised(train, n_input)\n",
" # define parameters\n",
" verbose, epochs, batch_size = 0, 100, 32\n",
" n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1]\n",
" # reshape output into [samples, timesteps, features]\n",
" train_y = train_y.reshape((train_y.shape[0], train_y.shape[1], 1))\n",
" # define model\n",
" model = Sequential()\n",
" model.add(LSTM(200, activation='relu', input_shape=(n_timesteps, n_features)))\n",
" model.add(RepeatVector(n_outputs))\n",
" model.add(LSTM(200, activation='relu', return_sequences=True))\n",
" model.add(TimeDistributed(Dense(100, activation='relu')))\n",
" model.add(TimeDistributed(Dense(1)))\n",
" model.compile(loss='mse', optimizer='adam')\n",
" # fit network\n",
" model.fit(train_x, train_y, epochs=epochs, batch_size=batch_size, verbose=verbose)\n",
" return model\n",
"\n",
"# make a forecast\n",
"def forecast(model, history, n_input):\n",
" # flatten data\n",
" data = array(history)\n",
" data = data.reshape((data.shape[0]*data.shape[1], data.shape[2]))\n",
" # retrieve last observations for input data\n",
" input_x = data[-n_input:, :]\n",
" # reshape into [1, n_input, n]\n",
" input_x = input_x.reshape((1, input_x.shape[0], input_x.shape[1]))\n",
" # forecast the next week\n",
" yhat = model.predict(input_x, verbose=0)\n",
" # we only want the vector forecast\n",
" yhat = yhat[0]\n",
" return yhat"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### LSTM модель для составления недельного прогноза\n",
"\n",
"Согласно информации в сети (например, [блогпост на volohai.com](https://blog.valohai.com/smart-grids-use-machine-learning-to-forecast-load)), хороший результат при построении прогнозов загруженности сети дает использование LSTM моделей. Для тренировки модели мы используем данные ~ за два года (104 недели) до прогнозируемого интервала, далее, при прогнозе используются данные за последние две недели."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Эксперементальным путем установлено, что в нашем случае масштабирование входных данных несколько ухудшает качество прогноза: точность сильнее \"прыгает\" в зависимости от инициализации модели, хотя в среднем (по результатам ~30 запусков) результаты сопоставимы"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"scale_input = False\n",
"\n",
"dataset_X = ml_X.values\n",
"dataset_Y = ml_Y.values\n",
"if scale_input:\n",
" scaler = StandardScaler()\n",
" dataset_X = scaler.fit_transform(dataset_X)\n",
"dataset = np.concatenate((dataset_Y, dataset_X), axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Тренировка модели"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"n_input = 14\n",
"\n",
"train_final = array(split(dataset, len(dataset)/7))\n",
"model_final = build_model(train_final, n_input)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"RMSE: [6725.887] 11017.0, 5024.1, 6181.4, 4436.1, 2839.5, 4950.4, 8921.3\n"
]
},
{
"data": {
"image/png": "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XZ1/PqxeHXdUlWf8+PBFQdeu8MQTULt23BFJhlECLSIiIiIiqdt5Z3j6afjtb2HkSDj0UFi4MO6ott/EidCnD3ToEPpXr17cEUkGUhGxCqxdu5bFixezOknfqsWoTp06NGvWjJoaBiMiIiKS3apXD0s65efD2WeHedGPPBKuTGej116DE06AvfYK6183aBB3RJKhlEBXYPHixey44460atUKU9W97eLuLFu2jMWLF7PHHnvEHY6IiIiIVIbjj4e334aTTw5zhv/8Z7j66uyqWD1tGhxzDDRrBi+8EK6wi5RDQ7grsHr1aho3bqzkuRKYGY0bN9bVfBEREZGk2WuvUJX71FPhmmvCMOhvvok7qtTMnAlHHRWS5kmTcmN5LtkuSqC3QMlz5dHPUkRERCSh6tcPQ7hvvRWefBIOOghmz447qop9+in06gV16oTkuVmzuCOSLKAEOsNVr16dvLw89ttvP/r06cOqVaviDklEREREZHNm8Otfh2HQX30FnTuHStaZaMGCMF97w4aQPLduHXdEkiWUQFeioiJo1QqqVQv3RUXbf8y6desyY8YMZs6cSa1atRg2bNj2H1REREREJF26d4fp02GffcLc6Ouug/Xr447qR198EZLnb76Bf/87xCmSIiXQlaSoCAYODF9muYf7gQMrJ4ku1q1bN+bMmQPAQw89ROfOncnLy+MXv/gF66NfShdddBH5+fm0a9eOG264YZP9W7VqRfv27Wnbti377bcfAL///e+59dZbN3uv/v37M3bs2I3P99tvP+bPnw/AiSeeSMeOHWnXrh3Dhw/fuM19993HPvvsQ15eHg0bNmTKlCmV13kRERERyR7Nm8PLL8MFF4TCYkcfDcuWxR1VuDLeqxcsWQITJoR1rUW2gqpwp+iKK2DGjPJfnzoV1qzZtG3VKhgwAAoLy94nLw/uuCO191+3bh0TJkygd+/ezJo1izFjxvDaa69Rs2ZNLr74YoqKijjnnHMYMmQIO++8M+vXr6dnz568//777L///gCsX7+el156iZUrV3Lcccel9sZlGDlyJDvvvDPff/89nTp14pRTTqFx48YMGjSIDz/8kKZNm27X8UVEREQkAerUgeHDw1DuSy4JS109/jgceGA88Xz9dagUPm9eSJ67dIknDslqugJdSUonz1tqT9X3339PXl4e+fn5tGjRggEDBjBp0iSmT59Op06dyMvLY9KkScybNw+ARx99lAMPPJAOHTrw4Ycf8tFHH21yrDp16mz2Hrfffjt5eXl07dqVqVOnbmy/+uqrycvLIy8vj7lz525sv/POOznggAPo0qULixYt4tNPPwWgWrVqfJMtFRdFREREpGqcfz688koYxt21K4weXfUxfPstHHtsqLr9+ONwxBFVH4Mkgq5Ap2hLV4pbtQrDtktr2RK2ZyRz8Rzoktydfv368ec//3mT9s8++4xbb72Vt99+m5122on+/ftvXDZq9erVbNiwgXr16m32Hr/61a+46qqrmDhxIldeeSWvv/46ALfccgunnnoqwMYh31OmTGHixIm88cYb1KtXjyOOOGLjewwdOpRDDjmEJk2asGjRIq666qpt77iIiIiIJEfnzmFe9OmnQ//+8NZbcPvtUKtW+t979Wo44QR480149NEwnFxkG+kKdCUZMgRK56b16oX2ytazZ0/Gjh3Ll19+CcDy5ctZsGABK1euZIcddqBhw4YsWbKECRMmbNxn7NixHHzwwRUet3Hjxvzwww8VbrNixQp22mkn6tWrx+zZsze5Yv1///d/HHDAAbz33nt069ZtO3ooIiIiIonTtGko2nX11XDvveEq8Oefp/c9f/ghrE89eTKMGhWKmolsB12BriR9+4b7wYNh4UJo0SIkz8Xtlalt27bcdNNNHHnkkWzYsIGaNWtyzz330KVLFzp06EC7du1o3bo1Xbt2BeCJJ55g6NChjBo1qszj3XPPPTz55JOsWrVqs6vapfXu3Zthw4ax//77s/fee9MlmjuybNkyLrvsMp566imqV69eqf0VERERkYSoUQP++lfo1AnOPTfMh37sMUjHxZf16+Gss+CZZ2DYsPBYZDuZu8cdQ0bIz8/3adOmbdI2a9Ys9t1335giSib9TEUkV5jZdHfPjzuObFbWuVlEEuTDD8MV4Xnz4G9/g1/+MqwlXRk2bAjVfEeNCse+8srKOa5ktco4N2sIt4iIiIiIVL127cJc6GOPhcsvD1eIV63a/uO6w2WXheT5D39Q8iyVSgm0iIiIiIjEo2HDUBX7ppvg4Yfh4IOhxOovW80dBg2Ce+4Jc61/+9vKi1UEJdAiIiIiIhKnatVCIaEJE2DRIsjPh2ef3bZjDRkS5lhfdBH85S+VNyRcJKIEWkRERERE4nfUUWGpq1at4Ljj4MYbw1zmVN1+e7ji3K8f3H23kmdJCyXQIiIiIiKSGfbYA157LcyHvuGGsH7z119veb/hw8Nc5z59YMSIcFVbJA30L0tERERERDJHvXowejTcdRc891xY8mrmzPK3f+ghuPDCUIzsoYfCUlkiaaIEOsNVr16dvLy8jbcWLVpw6aWXxh2WiIiIiEj6mMGll8KUKfDtt3DQQTBmzObbPf449O8P3buH9aRr1arqSCXHKIGuREUfFNHqjlZU+0M1Wt3RiqIPirb7mHXr1mXGjBkbbzfeeGMlRCoiIiIikgW6doV33oEOHeD00+GYY6BlyzBEe5ddwpDtzp1h3DioWzfuaCUHKIGuJEUfFDFw/EAWrFiA4yxYsYCB4wdWShJdnv79+3PhhRfSrVs39tprL55++mkAVq9ezbnnnkv79u3p0KEDkydPBmDUqFE0adJk49XsO++8k/nz57PffvttPObYsWPp378/AAsWLKBnz57sv//+9OzZk4ULFwLwpz/9iY4dO7Lvvvty/vnns2FrijuIiIiIiGyN3XaDF1+EI48MlboXLgzLVX35Zbg/91yoXz/uKCVHaIJAiq547gpm/HdGua9PXTyVNevXbNK2au0qBowbQOH0wjL3yds1jzt637Fdcc2fP5+XXnqJuXPn0r17d+bMmcM999wDwAcffMDs2bM58sgj+eSTTwD4+c9/zt13373J/uW59NJLOeecc+jXrx8jR47ksssu48knn+S6667juuuuY82aNeyzzz58+umn7L333tvVDxERERGRctWqBR9/vHm7e1i66oILqj4myUm6Al1JSifPW2qvLKeddhrVqlWjTZs2tG7dmtmzZ/Pqq69y9tlnA7DPPvvQsmXLjQl0WebOnbvxqvTVV1+9sf2NN97gzDPPBODss8/m1Vdf3fjahRdeSNOmTTniiCNo06ZNmnonIiIiIhKJRkOm3C6SBroCnaItXSludUcrFqxYsFl7y4YtmdJ/SpqiAiu1vp2Z4e5bdYyf/vSnzJgRrq6PHTt241Dwit5r2LBh3HbbbRx99NHMnz+f1q1bb2XkIiIiIiJboUULWLD539u0aFH1sUjO0hXoSjKk5xDq1ay3SVu9mvUY0nNIWt/3scceY8OGDcydO5d58+ax9957c9hhh1FUFOZef/LJJyxcuHCbhlgfcsghPPLIIwAUFRVx6KGH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\n",
"text/plain": [
"<Figure size 1152x432 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"y_hat = forecast(model_final, train_final, n_input)\n",
"score, scores = evaluate_forecasts(array([y_real]), array([y_hat]))\n",
"\n",
"summarize_scores('RMSE', score, scores)\n",
"\n",
"# график\n",
"pyplot.figure(num=None, figsize=(16, 6))\n",
"\n",
"pyplot.subplot(122)\n",
"pyplot.plot(X_week.to_series().dt.date, [100 * np.fabs((y_real[i] - y_hat[i]) / y_real[i]) for i in range(len(y_real))],\n",
" color=\"red\", marker='o', label='Относительная ошибка (MAPE)')\n",
"pyplot.xlabel(\"День, YYYY-MM-DD\")\n",
"pyplot.ylabel(\"Ошибка, %\")\n",
"pyplot.title(\"Ошибка прогнозирования\")\n",
"pyplot.legend()\n",
"\n",
"pyplot.subplot(121)\n",
"pyplot.plot(X_week.to_series().dt.date, y_real, label='Реальная', color=\"blue\", marker='o')\n",
"pyplot.plot(X_week.to_series().dt.date, y_hat, label='Прогноз', color=\"green\", marker='o')\n",
"pyplot.ylim(bottom=100000)\n",
"pyplot.xlabel(\"День, YYYY-MM-DD\")\n",
"pyplot.ylabel(\"Нагрузка\")\n",
"pyplot.title(\"Реальная нагрузка сети Vs Прогнозированная\")\n",
"pyplot.legend()\n",
"pyplot.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Построение и оценка прогноза"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Вывод\n",
"\n",
"Точность прогноза на 2016-05-02 (прогноз через день), основываясь на информации по 2016-05-01 (не включительно) по результатом 30+ запусков являет собой величину порядка 94%-98%."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment