{"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 numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport gc\n\n# matplotlib and seaborn for plotting\nimport matplotlib.pyplot as plt\n\nimport seaborn as sns\nimport matplotlib.patches as patches\n\nfrom plotly import tools, subplots\nimport plotly.offline as py\npy.init_notebook_mode(connected=True)\nimport plotly.graph_objs as go\nimport plotly.express as px\npd.set_option('max_columns', 150)\n\npy.init_notebook_mode(connected=True)\nfrom plotly.offline import init_notebook_mode, iplot\ninit_notebook_mode(connected=True)\nimport plotly.graph_objs as go\n\nimport os\nimport random\nimport math\nimport psutil\nimport pickle\n\nfrom sklearn.model_selection import train_test_split,KFold\nfrom sklearn.preprocessing import LabelEncoder","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"metadata_dtype = {'site_id':\"uint8\",'building_id':'uint16','square_feet':'float32','year_built':'float32','floor_count':\"float16\"}\nweather_dtype = {\"site_id\":\"uint8\",'air_temperature':\"float16\",'cloud_coverage':\"float16\",'dew_temperature':\"float16\",'precip_depth_1_hr':\"float16\",\n                 'sea_level_pressure':\"float32\",'wind_direction':\"float16\",'wind_speed':\"float16\"}\ntrain_dtype = {'meter':\"uint8\",'building_id':'uint16'}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n\nweather_train = pd.read_csv(\"../input/ashrae-energy-prediction/weather_train.csv\", parse_dates=['timestamp'], dtype=weather_dtype)\nweather_test = pd.read_csv(\"../input/ashrae-energy-prediction/weather_test.csv\", parse_dates=['timestamp'], dtype=weather_dtype)\n\nmetadata = pd.read_csv(\"../input/ashrae-energy-prediction/building_metadata.csv\", dtype=metadata_dtype)\n\ntrain = pd.read_csv(\"../input/ashrae-energy-prediction/train.csv\", parse_dates=['timestamp'], dtype=train_dtype)\ntest = pd.read_csv(\"../input/ashrae-energy-prediction/test.csv\", parse_dates=['timestamp'], usecols=['building_id','meter','timestamp'], dtype=train_dtype)\n\nprint('Size of train_df data', train.shape)\nprint('Size of weather_train_df data', weather_train.shape)\nprint('Size of weather_test_df data', weather_test.shape)\nprint('Size of building_meta_df data', metadata.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train['meter'].replace({0:\"Electricity\",1:\"ChilledWater\",2:\"Steam\",3:\"HotWater\"},inplace=True)\ntest['meter'].replace({0:\"Electricity\",1:\"ChilledWater\",2:\"Steam\",3:\"HotWater\"},inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"weather_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Dropping floor_count variable as it has 75% missing values\nmetadata.drop('floor_count',axis=1,inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for df in [train, test]:\n    df['Month'] = df['timestamp'].dt.month.astype(\"uint8\")\n    df['DayOfMonth'] = df['timestamp'].dt.day.astype(\"uint8\")\n    df['DayOfWeek'] = df['timestamp'].dt.dayofweek.astype(\"uint8\")\n    df['Hour'] = df['timestamp'].dt.hour.astype(\"uint8\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train['meter_reading'] = np.log1p(train['meter_reading'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"metadata['primary_use'].replace({\"Healthcare\":\"Other\",\"Parking\":\"Other\",\"Warehouse/storage\":\"Other\",\"Manufacturing/industrial\":\"Other\",\n                                \"Retail\":\"Other\",\"Services\":\"Other\",\"Technology/science\":\"Other\",\"Food sales and service\":\"Other\",\n                                \"Utility\":\"Other\",\"Religious worship\":\"Other\"},inplace=True)\nmetadata['square_feet'] = np.log1p(metadata['square_feet'])\nmetadata.drop('year_built',axis=1,inplace=True) # delete instead of fill in gaps","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntrain = pd.merge(train,metadata,on='building_id',how='left')\ntest  = pd.merge(test,metadata,on='building_id',how='left')\nprint (\"Training Data+Metadata Shape {}\".format(train.shape))\nprint (\"Testing Data+Metadata Shape {}\".format(test.shape))\ngc.collect()\ntrain = pd.merge(train,weather_train,on=['site_id','timestamp'],how='left')\ntest  = pd.merge(test,weather_test,on=['site_id','timestamp'],how='left')\nprint (\"Training Data+Metadata+Weather Shape {}\".format(train.shape))\nprint (\"Testing Data+Metadata+Weather Shape {}\".format(test.shape))\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save space\nfor df in [train,test]:\n    df['square_feet'] = df['square_feet'].astype('float16')\n    \n# Fill NA\ncols = ['air_temperature','cloud_coverage','dew_temperature','precip_depth_1_hr','sea_level_pressure','wind_direction','wind_speed']\nfor col in cols:\n    train[col].fillna(np.nanmean(train[col].tolist()),inplace=True)\n    test[col].fillna(np.nanmean(test[col].tolist()),inplace=True)\n    \n# Drop nonsense entries\n# As per the discussion in the following thread, https://www.kaggle.com/c/ashrae-energy-prediction/discussion/117083, there is some discrepancy in the meter_readings for different ste_id's and buildings. It makes sense to delete them\nidx_to_drop = list((train[(train['site_id'] == 0) & (train['timestamp'] < \"2016-05-21 00:00:00\")]).index)\nprint (len(idx_to_drop))\ntrain.drop(idx_to_drop,axis='rows',inplace=True)\n\n# dropping all the electricity meter readings that are 0, after considering them as anomalies.\nidx_to_drop = list(train[(train['meter'] == \"Electricity\") & (train['meter_reading'] == 0)].index)\nprint(len(idx_to_drop))\ntrain.drop(idx_to_drop,axis='rows',inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Not using constructed features, not dropping correlated ones","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.drop('timestamp',axis=1,inplace=True)\ntest.drop('timestamp',axis=1,inplace=True)\n\nle = LabelEncoder()\n\ntrain['meter']= le.fit_transform(train['meter']).astype(\"uint8\")\ntest['meter']= le.fit_transform(test['meter']).astype(\"uint8\")\ntrain['primary_use']= le.fit_transform(train['primary_use']).astype(\"uint8\")\ntest['primary_use']= le.fit_transform(test['primary_use']).astype(\"uint8\")\n\nprint (train.shape, test.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"categorical_cols = ['building_id','Month','meter','Hour','primary_use','DayOfWeek','DayOfMonth']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.ensemble import RandomForestRegressor as RF\nimport lightgbm as lgb\n\ndef train_site_model(train, site):\n    print(\"Training model for site\", site)\n    \n    train = train.loc[site]\n    y = train['meter_reading']\n    train.drop('meter_reading',axis=1,inplace=True)\n    \n    # 0 has too much missing data in certain months, so will throw away the month value to force it to consider temperature and the like for detecting winter times instead of using the month value\n    if site == 0:\n        train[\"Month\"] = 0\n    \n    x_train,x_test,y_train,y_test = train_test_split(train,y,test_size=0.1,random_state=42)\n    print (x_train.shape)\n    print (y_train.shape)\n    print (x_test.shape)\n    print (y_test.shape)\n    \n    lgb_train = lgb.Dataset(x_train, y_train, categorical_feature=categorical_cols)\n    lgb_test = lgb.Dataset(x_test, y_test, categorical_feature=categorical_cols)\n    del x_train, x_test , y_train, y_test\n\n    params = {'feature_fraction': 0.85, # 0.75\n              'bagging_fraction': 0.75,\n              'objective': 'regression',\n               \"num_leaves\": 40, # New\n              'max_depth': -1,\n              'learning_rate': 0.15,\n              \"boosting_type\": \"gbdt\",\n              \"bagging_seed\": 11,\n              \"metric\": 'rmse',\n              \"verbosity\": -1,\n              'reg_alpha': 0.5,\n              'reg_lambda': 0.5,\n              'random_state': 47\n             }\n\n    reg = lgb.train(params, lgb_train, num_boost_round=3000, valid_sets=[lgb_train, lgb_test], early_stopping_rounds=100, verbose_eval=100)\n    del lgb_train,lgb_test\n    ser = pd.DataFrame(reg.feature_importance(),train.columns,columns=['Importance']).sort_values(by='Importance')\n    ser['Importance'].plot(kind='bar',figsize=(10,6))\n    return reg","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"indexed_train = train.set_index([\"site_id\"])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"models = []\n\nfor i in range(16):\n    models.append(train_site_model(indexed_train, i))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Submission = pd.DataFrame(test.index, columns=['row_id'])\nSubmission['site_id'] = test['site_id']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test.set_index(['site_id'], inplace = True)\nSubmission.set_index(['site_id'], inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n# Couldn't just set them directly to the Submission dataframe because it complains about unmatching lengths, even though they are totally the same length grrr\nPredictions = pd.Series(np.zeros(test.shape[0]), test.index)\nfor i in range(16):\n    print(\"Predicting for site\", i)\n    Predictions.loc[i] = np.expm1(models[i].predict(test.loc[i]))\nSubmission['meter_reading'] = Predictions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Submission.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Submission['meter_reading'].clip(lower=0,upper=None,inplace=True)\nSubmission.to_csv(\"model_per_site.csv\",index=None)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from IPython.display import FileLink\nFileLink('model_per_site.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Submission.shape","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}