{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# Import Statements\n\nimport datetime\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport pickle\nfrom lightgbm import LGBMRegressor, plot_importance\nfrom sklearn.metrics import mean_squared_log_error as msle, mean_squared_error as mse\nfrom sklearn.model_selection import KFold, train_test_split\nfrom sklearn.preprocessing import OneHotEncoder\nfrom sklearn.linear_model import LinearRegression\nfrom tqdm import tqdm\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# # Any results you write to the current directory are saved as output.\npd.set_option('display.max_columns', 100)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Code from https://www.kaggle.com/caesarlupum/ashrae-start-here-a-gentle-introduction \n# Function to reduce the DF size\ndef reduce_mem_usage(df, verbose=True):\n    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']\n    start_mem = df.memory_usage().sum() / 1024**2    \n    for col in df.columns:\n        col_type = df[col].dtypes\n        if col_type in numerics:\n            c_min = df[col].min()\n            c_max = df[col].max()\n            if str(col_type)[:3] == 'int':\n                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                    df[col] = df[col].astype(np.int8)\n                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                    df[col] = df[col].astype(np.int16)\n                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                    df[col] = df[col].astype(np.int32)\n                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                    df[col] = df[col].astype(np.int64)  \n            else:\n                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                    df[col] = df[col].astype(np.float16)\n                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                    df[col] = df[col].astype(np.float32)\n                else:\n                    df[col] = df[col].astype(np.float64)    \n    end_mem = df.memory_usage().sum() / 1024**2\n    if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))\n    return df\n\n# function to calculate evaluation metric\ndef rmsle(y_true: pd.Series, y_predict: pd.Series) -> float:\n    \"\"\"\n    Evaluate root mean squared log error\n    :param y_true:\n    :param y_predict:\n    :return:\n    \"\"\"\n    return np.sqrt(msle(y_true, y_predict))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Import data\nINPUT = \"../input/ashrae-energy-prediction/\"\n\ndf_train = pd.read_csv(f\"{INPUT}train.csv\")\ndf_test = pd.read_csv(f\"{INPUT}test.csv\")\nbldg_metadata = pd.read_csv(f\"{INPUT}building_metadata.csv\")\nweather_train = pd.read_csv(f\"{INPUT}weather_train.csv\")\nweather_test = pd.read_csv(f\"{INPUT}weather_test.csv\")\nsample = pd.read_csv(f\"{INPUT}sample_submission.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test = df_test.drop(columns=['row_id'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = reduce_mem_usage(df=df_train)\ndf_test = reduce_mem_usage(df=df_test)\nweather_train = reduce_mem_usage(df=weather_train)\nweather_test = reduce_mem_usage(df=weather_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = df_train.merge(bldg_metadata, on='building_id', how='left')\ndf_test = df_test.merge(bldg_metadata, on='building_id', how='left')\ndf_train = df_train.merge(weather_train, on=['site_id', 'timestamp'], how='left')\ndf_test = df_test.merge(weather_test, on=['site_id', 'timestamp'], how='left')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import gc\ndel weather_train, weather_test, bldg_metadata\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train['timestamp'] = pd.to_datetime(arg=df_train['timestamp'])\ndf_test['timestamp'] = pd.to_datetime(arg=df_test['timestamp'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Feature Engineering"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Extracting date features from timestamp\ndf_train['year'] = df_train['timestamp'].dt.year\ndf_train['month'] = df_train['timestamp'].dt.month\ndf_train['day'] = df_train['timestamp'].dt.day\ndf_train['hour'] = df_train['timestamp'].dt.hour\ndf_test['year'] = df_test['timestamp'].dt.year\ndf_test['month'] = df_test['timestamp'].dt.month\ndf_test['day'] = df_test['timestamp'].dt.day\ndf_test['hour'] = df_test['timestamp'].dt.hour\ndf_train['dayofweek'] = df_train['timestamp'].dt.dayofweek\ndf_test['dayofweek'] = df_test['timestamp'].dt.dayofweek","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Making age feature\ndf_train['age'] = df_train['year'] - df_train['year_built']\ndf_test['age'] = df_test['year'] - df_test['year_built']\n\n# Making number of hours passed from start\nnew_df = df_train.groupby(by=['building_id'], as_index=False)['timestamp'].min()\nnew_df = new_df.rename(columns = {'timestamp': 'start_ts'})\n\ndf_train = df_train.merge(new_df, on = 'building_id', how='left')\ndf_test = df_test.merge(new_df, on = 'building_id', how='left')\n\ndf_train['hours_passed'] = (df_train['timestamp'] - df_train['start_ts']).dt.total_seconds()/3600\ndf_test['hours_passed'] = (df_test['timestamp'] - df_test['start_ts']).dt.total_seconds()/3600","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data Cleaning"},{"metadata":{"trusted":true},"cell_type":"code","source":"# site_id =0 has some building where meter readings before May 21, 2016 are not reliable so dropping those records \ndf_train = df_train.query('not(site_id==0 & timestamp<\"2016-05-21 00:00:00\")')\n\n# Missing value handling\ncols = ['floor_count', 'air_temperature', 'cloud_coverage', 'dew_temperature', 'precip_depth_1_hr', 'sea_level_pressure', \n        'wind_direction', 'wind_speed']\ndf_train.loc[:, cols] = df_train.loc[:, cols].interpolate(axis=0)\ndf_test.loc[:, cols] = df_test.loc[:, cols].interpolate(axis=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class NewFeatures:\n    \"\"\"This class constructs features of min, max, median, mean, std_dev based on grouping columns\"\"\"\n    \n    def __init__(self, feature, grouping_cols):\n        self.feature = feature\n        self.grouping_cols = grouping_cols\n        self.features = None\n        self.feature_mean = None\n        self.feature_median = None\n        self.feature_std_dev = None\n        self.feature_min = None\n        self.feature_max = None\n        \n    def fetch_values(self, df):\n        self.feature_mean = df.groupby(by=self.grouping_cols, as_index=False)[self.feature].mean().rename(columns={self.feature: f'{self.feature}_mean'})\n        self.feature_median = df.groupby(by=self.grouping_cols, as_index=False)[self.feature].median().rename(columns={self.feature: f'{self.feature}_median'})\n        self.feature_std_dev = df.groupby(by=self.grouping_cols, as_index=False)[self.feature].std().rename(columns={self.feature: f'{self.feature}_std_dev'})\n        self.feature_min = df.groupby(by=self.grouping_cols, as_index=False)[self.feature].min().rename(columns={self.feature: f'{self.feature}_min'})\n        self.feature_max = df.groupby(by=self.grouping_cols, as_index=False)[self.feature].max().rename(columns={self.feature: f'{self.feature}_max'})\n        self.features = self.feature_mean\n        self.features[f'{self.feature}_median'] = self.feature_median[f'{self.feature}_median']\n        self.features[f'{self.feature}_std_dev'] = self.feature_std_dev[f'{self.feature}_std_dev']\n        self.features[f'{self.feature}_min'] = self.feature_min[f'{self.feature}_min']\n        self.features[f'{self.feature}_max'] = self.feature_max[f'{self.feature}_max']\n    \n    def predict(self, df):\n        STEP = 10000\n        for i in tqdm(range(0, df.shape[0], STEP)):\n            df.loc[i:i+STEP-1,:] = df.loc[i:i+STEP-1,:].merge(self.features, on = self.grouping_cols)\n        return df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Convert to categorical datatype\ncat_cols = ['meter', 'primary_use', 'site_id', 'building_id', 'year', 'month', 'day', 'hour', 'dayofweek']\nfor col in cat_cols:\n    df_train[col] = df_train[col].astype('category')\n    df_test[col] = df_test[col].astype('category')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Modelling"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Make validation set based on time split\ndf_val = df_train.loc[df_train['timestamp'] >= '2016-11-01 00:00:00']\ndf_train = df_train.loc[df_train['timestamp'] < '2016-11-01 00:00:00']\ny_train = df_train['meter_reading']\ny_val = df_val['meter_reading']\n\ny_train = np.log1p(y_train)\ny_val = np.log1p(y_val)\ndf_train = df_train.drop(columns=['meter_reading'])\ndf_val = df_val.drop(columns=['meter_reading'])\n\n# # Create input and target\n# y_train = df_train['meter_reading']\n# y_train = np.log1p(y_train)\n# df_train = df_train.drop(columns=['meter_reading'])\n\n# # Make validation set based on train_test_split\n# df_train, df_val, y_train, y_val = train_test_split(df_train, y_train, test_size=0.2, random_state=42)\n\n# Drop timestamp because model does not accept\ndf_train = df_train.drop(columns=['timestamp', 'start_ts'])\ndf_val = df_val.drop(columns=['timestamp', 'start_ts'])\ndf_test = df_test.drop(columns=['timestamp', 'start_ts'])\n\n# Model\nlgbmr = LGBMRegressor(random_state=10)\nlgbmr.fit(df_train, y_train)\ny_predict = lgbmr.predict(df_val)\nscore = np.sqrt(mse(y_val, y_predict))\n# score = rmsle(y_val, y_predict)\nprint(f\"score: {score}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # Model\nmodel = []\nmeter_types = list(df_train['meter'].unique().astype('int'))\nmeter_types.sort()\nfor meter_type in meter_types:\n     print(meter_type)\n     model.append(LGBMRegressor(random_state=10))\n     X = df_train.loc[df_train['meter']==meter_type, :].reset_index(drop=True)\n     y = y_train[df_train['meter']==meter_type].reset_index(drop=True)\n     X_validation = df_val.loc[df_val['meter']==meter_type, :].reset_index(drop=True)\n     y_validation = y_val[df_val['meter']==meter_type].reset_index(drop=True)\n     model[meter_type].fit(X, y)\n     y_predict = model[meter_type].predict(X_validation)\n     score = np.sqrt(mse(y_validation, y_predict))\n     print(f\"score: {score}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Ensemble Modelling"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Half and half learning\nX_1st_half = df_train[:int(df_train.shape[0]/2)]\ny_1st_half = y_train[:int(df_train.shape[0]/2)]\nX_2nd_half = df_train[int(df_train.shape[0]/2):]\ny_2nd_half = y_train[int(df_train.shape[0]/2):]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lgbmr_1st_half = LGBMRegressor(random_state=10)\nlgbmr_2nd_half = LGBMRegressor(random_state=10)\nlgbmr_1st_half.fit(X_1st_half, y_1st_half)\nlgbmr_2nd_half.fit(X_2nd_half, y_2nd_half)\ny_predict_1 = lgbmr_1st_half.predict(df_val)\ny_predict_2 = lgbmr_2nd_half.predict(df_val)\ny_predict_1_2 = (pd.Series(data=y_predict_1, name='prediction_1') + pd.Series(data=y_predict_2, name='prediction_2'))/2\nscore = np.sqrt(mse(y_val, y_predict_1_2))\nprint(f\"score: {score}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Saving model\nfilename = 'lgbm_model1.pickle'\npickle.dump(lgbmr, open(filename, 'wb'))\n# load the model from disk\nloaded_model = pickle.load(open(filename, 'rb'))\n\nfilename = 'lgbmr_1st_half.pickle'\npickle.dump(lgbmr, open(filename, 'wb'))\n# load the model from disk\nlgbmr_1st_half = pickle.load(open(filename, 'rb'))\nfilename = 'lgbmr_2nd_half.pickle'\npickle.dump(lgbmr, open(filename, 'wb'))\n# load the model from disk\nlgbmr_2nd_half = pickle.load(open(filename, 'rb'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # Important features\nfig, ax = plt.subplots(figsize=(12, 9))\nplot_importance(lgbmr, ax=ax)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 9))\nplot_importance(lgbmr_1st_half, ax=ax)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 9))\nplot_importance(lgbmr_2nd_half, ax=ax)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del df_train, df_val, y_train, y_val, lgbmr\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nSTEP = 1000000\ny_test_predict = []\nfor i in range(0, df_test.shape[0], STEP):\n    batch_prediction = loaded_model.predict(df_test.loc[i:i+STEP-1,:])\n    y_test_predict.append(list(batch_prediction))\ny_test_1st_half = []\nfor predictions in y_test_predict:\n    y_test_1st_half = y_test_1st_half + predictions\n    \nSTEP = 1000000\ny_test_predict = []\nfor i in range(0, df_test.shape[0], STEP):\n    batch_prediction = loaded_model.predict(df_test.loc[i:i+STEP-1,:])\n    y_test_predict.append(list(batch_prediction))\ny_test_2nd_half = []\nfor predictions in y_test_predict:\n    y_test_2nd_half = y_test_2nd_half + predictions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# sample['meter_reading'] = y_test\nsample['meter_reading'] = (pd.Series(data=y_test_1st_half, name='pred_1st_half') + \n                           pd.Series(data=y_test_2nd_half, name='pred_2nd_half'))/2 ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from math import e\n# sample['meter_reading'] = e**sample['meter_reading'] - 1\nsample['meter_reading'] = np.expm1(sample['meter_reading'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Submittion file"},{"metadata":{"trusted":true},"cell_type":"code","source":"sample.to_csv(\"submission.csv\", index=False, float_format='%.4f')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":1}