{"cells":[{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport gc, math\n\nfrom pandas.tseries.holiday import USFederalHolidayCalendar as calendar\nfrom sklearn.metrics import mean_squared_error\nimport lightgbm as lgb\nfrom sklearn.model_selection import KFold, StratifiedKFold, GroupKFold\nfrom tqdm import tqdm\nfrom sklearn.preprocessing import LabelEncoder","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### Set the size and styles of graphs"},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set(rc={'figure.figsize':(11,8)})\nsns.set(style=\"whitegrid\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Read the dataset\nData is given in different CSV files which we will need to merge afterwards. \n\n`train.csv` only contains the ID of the building and meter related information including our target variable to be predicted (`meter_reading`). This `building_id` is foreign key in `building_metadata.csv`. All the information related to the buildings are given in this file. \n\n\nSame goes for `weather_train.csv` and `building_metadata.csv` files with common column (foreign key) `site_id`. So all three files are related and we will have to join these tables later"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nmetadata_df = pd.read_csv('/kaggle/input/ashrae-energy-prediction/building_metadata.csv')\ntrain_df = pd.read_csv('/kaggle/input/ashrae-energy-prediction/train.csv', parse_dates=['timestamp'])\ntest_df = pd.read_csv('/kaggle/input/ashrae-energy-prediction/test.csv', parse_dates=['timestamp'])\nweather_train_df = pd.read_csv('/kaggle/input/ashrae-energy-prediction/weather_train.csv', parse_dates=['timestamp'])\nweather_test_df = pd.read_csv('/kaggle/input/ashrae-energy-prediction/weather_test.csv', parse_dates=['timestamp'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Align timestamps\nTimestap data is not in their local time. As energy consumptions are related to the local time, an alighment is nescessary before using timestamp. \n\nThe credit goes to [this kernel](https://www.kaggle.com/nz0722/aligned-timestamp-lgbm-by-meter-type) for the idea. Refer it for more details and explanation about below code."},{"metadata":{"trusted":true},"cell_type":"code","source":"weather = pd.concat([weather_train_df,weather_test_df],ignore_index=True)\nweather_key = ['site_id', 'timestamp']\n\ntemp_skeleton = weather[weather_key + ['air_temperature']].drop_duplicates(subset=weather_key).sort_values(by=weather_key).copy()\n\n# calculate ranks of hourly temperatures within date/site_id chunks\ntemp_skeleton['temp_rank'] = temp_skeleton.groupby(['site_id', temp_skeleton.timestamp.dt.date])['air_temperature'].rank('average')\n\n# create a dataframe of site_ids (0-16) x mean hour rank of temperature within day (0-23)\ndf_2d = temp_skeleton.groupby(['site_id', temp_skeleton.timestamp.dt.hour])['temp_rank'].mean().unstack(level=1)\n\n# Subtract the columnID of temperature peak by 14, getting the timestamp alignment gap.\nsite_ids_offsets = pd.Series(df_2d.values.argmax(axis=1) - 14)\nsite_ids_offsets.index.name = 'site_id'\n\ndef timestamp_align(df):\n    df['offset'] = df.site_id.map(site_ids_offsets)\n    df['timestamp_aligned'] = (df.timestamp - pd.to_timedelta(df.offset, unit='H'))\n    df['timestamp'] = df['timestamp_aligned']\n    del df['timestamp_aligned']\n    return df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df.tail()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df = timestamp_align(weather_train_df)\nweather_test_df = timestamp_align(weather_test_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del weather \ndel df_2d\ndel temp_skeleton\ndel site_ids_offsets","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df.tail()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Fill NaNs in weather data by interpolation"},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df.isna().sum()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_test_df.isna().sum()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df = weather_train_df.groupby('site_id').apply(lambda group: group.interpolate(limit_direction='both'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_test_df = weather_test_df.groupby('site_id').apply(lambda group: group.interpolate(limit_direction='both'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df.isna().sum()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_test_df.isna().sum()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['meter_reading'] = np.log1p(train_df['meter_reading'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Function to reduce the memory usage\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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"le = LabelEncoder()\nmetadata_df['primary_use'] = le.fit_transform(metadata_df['primary_use'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"metadata_df = reduce_mem_usage(metadata_df)\ntrain_df = reduce_mem_usage(train_df)\ntest_df = reduce_mem_usage(test_df)\nweather_train_df = reduce_mem_usage(weather_train_df)\nweather_test_df = reduce_mem_usage(weather_test_df)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Get insights of shapes and first few data rows of all the files"},{"metadata":{"trusted":true},"cell_type":"code","source":"print (f'Training data shape: {train_df.shape}')\nprint (f'Weather training shape: {weather_train_df.shape}')\nprint (f'Weather training shape: {weather_test_df.shape}')\nprint (f'Weather testing shape: {metadata_df.shape}')\nprint (f'Test data shape: {test_df.shape}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"metadata_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Merge necessary files\nAs mentioned previously, to get a single dataframe for training and a single data frame for testing with all the feature included, we need to join the tables/files which are related by foreign keys. Let's first merge/join training data."},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nfull_train_df = train_df.merge(metadata_df, on='building_id', how='left')\nfull_train_df = full_train_df.merge(weather_train_df, on=['site_id', 'timestamp'], how='left')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Drop all NaN rows which are generated by timestamp alignment"},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df = full_train_df.loc[~(full_train_df['air_temperature'].isnull() & full_train_df['cloud_coverage'].isnull() & full_train_df['dew_temperature'].isnull() & full_train_df['precip_depth_1_hr'].isnull() & full_train_df['sea_level_pressure'].isnull() & full_train_df['wind_direction'].isnull() & full_train_df['wind_speed'].isnull() & full_train_df['offset'].isnull())]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Reducing the memory usage\nLet's delete unnecessary dataframes from memory to lower the memory usage"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Delete unnecessary dataframes to decrease memory usage\ndel train_df\ndel weather_train_df\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now let's change the data types of necessary feature columns based on the range of the data values. This will lower the data usage. But **how**? Let's see. For example the datatype of feature `building_id` is `int64` but based on the range of this feature, it can be accomodated in lower range i.e. `int16`. So this will decrease the memory usage."},{"metadata":{},"cell_type":"markdown","source":"#### Let's do the same for test data"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nfull_test_df = test_df.merge(metadata_df, on='building_id', how='left')\nfull_test_df = full_test_df.merge(weather_test_df, on=['site_id', 'timestamp'], how='left')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_test_df.shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Reducing the memory usage\nLet's delete unnecessary dataframes from memory to lower the memory usage"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Delete unnecessary dataframes to decrease memory usage\ndel metadata_df\ndel weather_test_df\ndel test_df\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now let's change the data types of necessary feature columns based on the range of the data values. This will lower the data usage. But **how**? Let's see. For example the datatype of feature `building_id` is `int64` but based on the range of this feature, it can be accomodated in lower range i.e. `int16`. So this will decrease the memory usage."},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Distribition of primary usage of buildings"},{"metadata":{"trusted":true},"cell_type":"code","source":"ax = sns.barplot(le.inverse_transform(full_train_df.groupby(['primary_use']).size().reset_index(name='counts')['primary_use']), full_train_df.groupby(['primary_use']).size().reset_index(name='counts')['counts'])\nax.set(xlabel='Primary Usage', ylabel='# of records', title='Primary Usage vs. # of records')\nax.set_xticklabels(ax.get_xticklabels(), rotation=50, ha=\"right\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Distribution of meter types"},{"metadata":{"trusted":true},"cell_type":"code","source":"meter_types = {0: 'electricity', 1: 'chilledwater', 2: 'steam', 3: 'hotwater'}\nax = sns.barplot(np.vectorize(meter_types.get)(pd.unique(full_train_df['meter'])), full_train_df['meter'].value_counts())\nax.set(xlabel='Meter Type', ylabel='# of records', title='Meter type vs. # of records')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Average meter reading for training dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Average meter reading\nprint (f'Average meter reading: {full_train_df.meter_reading.mean()} kWh')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Distribution of meter readings for each meter type"},{"metadata":{"trusted":true},"cell_type":"code","source":"ax = sns.barplot(np.vectorize(meter_types.get)(full_train_df.groupby(['meter'])['meter_reading'].mean().keys()), full_train_df.groupby(['meter'])['meter_reading'].mean())\nax.set(xlabel='Meter Type', ylabel='Meter reading', title='Meter type vs. Meter Reading')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Distribution of buildings built in each year for both training and test datasets"},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1,1,figsize=(14, 6))\nax.set(xlabel='Year Built', ylabel='# Of Buildings', title='Buildings built in each year')\nfull_train_df['year_built'].value_counts(dropna=False).sort_index().plot(ax=ax)\nfull_test_df['year_built'].value_counts(dropna=False).sort_index().plot(ax=ax)\nax.legend(['Train', 'Test']);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Distribution of square feet area of buildings"},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1,1,figsize=(15, 7))\nfull_train_df.groupby(['building_id'])['square_feet'].mean().plot(ax=ax)\nax.set(xlabel='Building ID', ylabel='Area in Square Feet', title='Square Feet area of buildings')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Feature Engineering\nThe joined dataframe (full_train_df) now has 20,216,100 rows, and 16 features in training dataset."},{"metadata":{},"cell_type":"markdown","source":"### Analysing missing data\nFirst let's count and fill missing data in training datasets"},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.DataFrame(full_train_df.isna().sum().sort_values(ascending=False), columns=['NaN Count'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Missing data can be filled in many ways. Here are few techniques to fill missing values: \n\n* Ignore the data row\n* Back-fill or forward-fill to propagate next or previous values respectively\n* Replace with some constant value outside fixed value range-999,-1 etc.\n* Replace with mean, median value\n\nFor now, we will go with last method. So let's fill all the missing data with it's average(mean) values of corresponding columns."},{"metadata":{"trusted":true},"cell_type":"code","source":"def mean_without_overflow_fast(col):\n    col /= len(col)\n    return col.mean() * len(col)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"missing_values = (100-full_train_df.count() / len(full_train_df) * 100).sort_values(ascending=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nmissing_features = full_train_df.loc[:, missing_values > 0.0]\nmissing_features = missing_features.apply(mean_without_overflow_fast)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for key in full_train_df.loc[:, missing_values > 0.0].keys():\n    if key == 'year_built' or key == 'floor_count':\n        full_train_df[key].fillna(math.floor(missing_features[key]), inplace=True)\n        full_test_df[key].fillna(math.floor(missing_features[key]), inplace=True)\n    else:\n        full_train_df[key].fillna(missing_features[key], inplace=True)\n        full_test_df[key].fillna(missing_features[key], inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.tail()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_test_df.tail()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So all the missing values for training and testing data is now filled with the mean of corresponding feature columns."},{"metadata":{},"cell_type":"markdown","source":"### Adding few more features"},{"metadata":{},"cell_type":"markdown","source":"First let's expand timestamp to multiple components"},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df['timestamp'].dtype","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df[\"timestamp\"] = pd.to_datetime(full_train_df[\"timestamp\"])\nfull_test_df[\"timestamp\"] = pd.to_datetime(full_test_df[\"timestamp\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def transform(df):\n    df['hour'] = np.uint8(df['timestamp'].dt.hour)\n    df['day'] = np.uint8(df['timestamp'].dt.day)\n    df['weekday'] = np.uint8(df['timestamp'].dt.weekday)\n    df['month'] = np.uint8(df['timestamp'].dt.month)\n    df['year'] = np.uint8(df['timestamp'].dt.year-1900)\n    \n    df['square_feet'] = np.log(df['square_feet'])\n    \n    return df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df = transform(full_train_df)\nfull_test_df = transform(full_test_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def encode_cyclic_feature(df, col, max_vals):\n    df[col + '_sin'] = np.sin(2 * np.pi * df[col]/max_vals)\n#     df[col + '_cos'] = np.cos(2 * np.pi * df[col]/max_vals)\n    del df[col]\n    return df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dates_range = pd.date_range(start='2015-12-31', end='2019-01-01')\nus_holidays = calendar().holidays(start=dates_range.min(), end=dates_range.max())\nfull_train_df['is_holiday'] = (full_train_df['timestamp'].dt.date.astype('datetime64').isin(us_holidays)).astype(np.int8)\nfull_test_df['is_holiday'] = (full_test_df['timestamp'].dt.date.astype('datetime64').isin(us_holidays)).astype(np.int8)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Assuming 5 days a week for all the given buildings\nfull_train_df.loc[(full_train_df['weekday'] == 5) | (full_train_df['weekday'] == 6) , 'is_holiday'] = 1\nfull_test_df.loc[(full_test_df['weekday']) == 5 | (full_test_df['weekday'] == 6) , 'is_holiday'] = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# full_train_df.loc[(full_train_df['primary_use'] == le.transform(['Education'])[0]) & (full_train_df['month'] >= 6) & (full_train_df['month'] <= 8), 'is_vacation_month'] = np.int8(1)\n# full_train_df.loc[full_train_df['is_vacation_month']!=1, 'is_vacation_month'] = np.int8(0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Removing weired data on site_id 0\nAs you can see above, this data looks weired until May 20. It is reported in this discussion by @barnwellguy that All electricity meter is 0 until May 20 for site_id == 0. Let's remove these data from training data."},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df = full_train_df.query('not (building_id <= 104 & meter == 0 & timestamp <= \"2016-05-20\")')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_test_df = full_test_df.drop(['timestamp'], axis=1)\nfull_train_df = full_train_df.drop(['timestamp'], axis=1)\nprint (f'Shape of training dataset: {full_train_df.shape}')\nprint (f'Shape of testing dataset: {full_test_df.shape}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.tail()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.tail()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## Reducing memory\nfull_train_df = reduce_mem_usage(full_train_df)\nfull_test_df = reduce_mem_usage(full_test_df)\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"beaufort = [(0, 0, 0.3), (1, 0.3, 1.6), (2, 1.6, 3.4), (3, 3.4, 5.5), (4, 5.5, 8), (5, 8, 10.8), (6, 10.8, 13.9), \n          (7, 13.9, 17.2), (8, 17.2, 20.8), (9, 20.8, 24.5), (10, 24.5, 28.5), (11, 28.5, 33), (12, 33, 200)]\n\nfor item in beaufort:\n    full_train_df.loc[(full_train_df['wind_speed']>=item[1]) & (full_train_df['wind_speed']<item[2]), 'beaufort_scale'] = item[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df['group'] = full_train_df['month']\nfull_train_df['group'].replace((1,2,3,4,5,6), 1,inplace=True)\nfull_train_df['group'].replace((7,8,9,10,11,12), 2, inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df = encode_cyclic_feature(full_train_df, 'weekday', 7)\nfull_train_df = encode_cyclic_feature(full_train_df, 'hour', 24)\nfull_train_df = encode_cyclic_feature(full_train_df, 'day', 31)\nfull_train_df = encode_cyclic_feature(full_train_df, 'month', 12)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df = reduce_mem_usage(full_train_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"categoricals = ['site_id', 'building_id', 'primary_use', 'meter',  'wind_direction', 'is_holiday']\ndrop_cols = ['sea_level_pressure', 'wind_speed']\nnumericals = ['square_feet', 'year_built', 'air_temperature', 'cloud_coverage',\n              'dew_temperature', 'precip_depth_1_hr', 'floor_count', 'beaufort_scale', 'weekday_sin', 'day_sin', 'hour_sin', 'month_sin']\n\nfeat_cols = categoricals + numericals","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.tail()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df = reduce_mem_usage(full_train_df)\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"target = full_train_df[\"meter_reading\"]\ndel full_train_df[\"meter_reading\"]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.drop(drop_cols, axis=1)\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save the testing dataset to freeup the RAM. We'll read after training\n# full_test_df.to_pickle('full_test_df.pkl')\n# del full_test_df\n# gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"params = {\n            'boosting_type': 'gbdt',\n            'objective': 'regression',\n            'metric': {'rmse'},\n            'subsample': 0.4,\n            'subsample_freq': 1,\n            'learning_rate': 0.25,\n            'num_leaves': 31,\n            'feature_fraction': 0.8,\n            'lambda_l1': 1,\n            'lambda_l2': 1\n            }\n\nfolds = 2\nseed = 666\n\n# kf = StratifiedKFold(n_splits=folds, shuffle=False, random_state=seed)\n\n# models = []\n# for train_index, val_index in kf.split(full_train_df, full_train_df['building_id']):\n#     train_X = full_train_df[feat_cols].iloc[train_index]\n#     val_X = full_train_df[feat_cols].iloc[val_index]\n#     train_y = target.iloc[train_index]\n#     val_y = target.iloc[val_index]\n#     lgb_train = lgb.Dataset(train_X, train_y, categorical_feature=categoricals)\n#     lgb_eval = lgb.Dataset(val_X, val_y, categorical_feature=categoricals)\n#     gbm = lgb.train(params,\n#                 lgb_train,\n#                 num_boost_round=500,\n#                 valid_sets=(lgb_train, lgb_eval),\n#                 early_stopping_rounds=100,\n#                 verbose_eval = 100)\n#     models.append(gbm)\nkf = GroupKFold(n_splits=folds)\n\nmodels = []\nfor train_index, val_index in kf.split(full_train_df, full_train_df['building_id'], groups=full_train_df['group']):\n#     train_X, train_y = full_train_df[feat_cols].loc[train_index], full_train_df['meter_reading'][train_index]\n#     val_X, val_y = full_train_df[feat_cols].loc[val_index], full_train_df['meter_reading'][val_index]\n    train_X = full_train_df[feat_cols].iloc[train_index]\n    val_X = full_train_df[feat_cols].iloc[val_index]\n    train_y = target.iloc[train_index]\n    val_y = target.iloc[val_index]\n    lgb_train = lgb.Dataset(train_X, train_y, categorical_feature=categoricals)\n    lgb_eval = lgb.Dataset(val_X, val_y, categorical_feature=categoricals)\n    gbm = lgb.train(params,\n                lgb_train,\n                num_boost_round=500,\n                valid_sets=(lgb_train, lgb_eval),\n                early_stopping_rounds=100,\n                verbose_eval = 100)\n    models.append(gbm)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del full_train_df, train_X, val_X, lgb_train, lgb_eval, train_y, val_y, target\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# full_test_df = pd.read_pickle('full_test_df.pkl')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# full_test_df.loc[(full_test_df['primary_use'] == le.transform(['Education'])[0]) & (full_test_df['month'] >= 6) & (full_test_df['month'] <= 8), 'is_vacation_month'] = np.int8(1)\n# full_test_df.loc[full_test_df['is_vacation_month']!=1, 'is_vacation_month'] = np.int8(0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for item in beaufort:\n    full_test_df.loc[(full_test_df['wind_speed']>=item[1]) & (full_test_df['wind_speed']<item[2]), 'beaufort_scale'] = item[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_test_df = encode_cyclic_feature(full_test_df, 'weekday', 7)\nfull_test_df = encode_cyclic_feature(full_test_df, 'hour', 24)\nfull_test_df = encode_cyclic_feature(full_test_df, 'day', 31)\nfull_test_df = encode_cyclic_feature(full_test_df, 'month', 12)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_test_df = full_test_df[feat_cols]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"full_test_df = reduce_mem_usage(full_test_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"i=0\nres=[]\nstep_size = 50000\nfor j in tqdm(range(int(np.ceil(full_test_df.shape[0]/50000)))):\n    res.append(np.expm1(sum([model.predict(full_test_df.iloc[i:i+step_size]) for model in models])/folds))\n    i+=step_size","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"res = np.concatenate(res)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.read_csv('/kaggle/input/ashrae-energy-prediction/sample_submission.csv')\nsubmission['meter_reading'] = res\nsubmission.loc[submission['meter_reading']<0, 'meter_reading'] = 0\nsubmission.to_csv('submission_fe_lgbm.csv', index=False)\nsubmission","execution_count":null,"outputs":[]}],"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.6"}},"nbformat":4,"nbformat_minor":1}