Regression with the California Housing Dataset

Dataset Description¶

The dataset for this competition (both train and test) was generated from a deep learning model trained on the California Housing Dataset. Feature distributions are close to, but not exactly the same, as the original. Feel free to use the original dataset as part of this competition, both to explore differences as well as to see whether incorporating the original in training improves model performance.

Files

  • train.csv - the training dataset; MedHouseVal is the target
  • test.csv - the test dataset; your objective is to predict MedHouseVal
  • sample_submission.csv - a sample submission file in the correct format

Data is synthetic

Features:

  • MedInc, Median Income in block group

House Characteristics

  • HouseAge, median house age in block group
  • AveRooms, average number of rooms per household
  • AveBedrms, average number of bedrooms per household
  • AveOccup, average number of household members

Spatial Features

  • Latitude and Longitude, block group latitude and longitude
  • Population, block group population

Target Feature

  • MedHouseVal, feature to predict, Median House Value

We're also told that the dataset was "derived from the 1990 U.S. census"" and that they define a block to be "the smallest geographical unit for which the U.S. Census Bureau publishes sample data (a block group typically has a population of 600 to 3,000 people).".

Evaluation - Root Mean Squared Error (RMSE)¶

Submissions are scored on the root mean squared error.

Import Libraries

¶

In [1]:
import pandas as pd
import matplotlib.pyplot as plt

import tensorflow as tf
from tensorflow.keras import layers
import seaborn as sns

from sklearn.datasets import fetch_california_housing

Exploratory Data Analysis

¶

In [2]:
data_train = pd.read_csv('/kaggle/input/playground-series-s3e1/train.csv', index_col='id')
data_test = pd.read_csv('/kaggle/input/playground-series-s3e1/test.csv', index_col='id')
features = data_train.columns[:-1]
In [3]:
original_df, original_y = fetch_california_housing(return_X_y=True)
original_df = pd.DataFrame(original_df, columns=features)
original_df['MedHouseVal'] = original_y
In [4]:
data_train.shape[0], data_test.shape[0], original_df.shape[0]
Out[4]:
(37137, 24759, 20640)
In [5]:
data_train.describe()
Out[5]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
count 37137.000000 37137.000000 37137.000000 37137.000000 37137.000000 37137.000000 37137.000000 37137.000000 37137.000000
mean 3.851029 26.057005 5.163124 1.062204 1660.778919 2.831243 35.570030 -119.554329 2.079751
std 1.803167 12.158221 1.206242 0.096490 1302.469608 2.702413 2.083179 1.974028 1.158571
min 0.499900 2.000000 0.851064 0.500000 3.000000 0.950000 32.550000 -124.350000 0.149990
25% 2.602300 17.000000 4.357522 1.020305 952.000000 2.394495 33.930000 -121.800000 1.208000
50% 3.515600 25.000000 5.068611 1.054545 1383.000000 2.744828 34.190000 -118.450000 1.808000
75% 4.699700 35.000000 5.858597 1.088825 1856.000000 3.125313 37.700000 -118.020000 2.660000
max 15.000100 52.000000 28.837607 5.873181 35682.000000 502.990610 41.950000 -114.550000 5.000010
In [6]:
f, ax= plt.subplots(figsize=(16,12), ncols=2, nrows=2)

ax[0,0].scatter(data_train['Latitude'], data_train['Longitude'], s=1)

h = ax[0,1].hist2d(x=data_train['Latitude'], 
              y=data_train['Longitude'], 
              weights=data_train['MedHouseVal'], bins = 500, vmin=0, vmax=100)
plt.colorbar(h[3], ax=ax[0,1])


h = ax[1,0].hist2d(x=data_train['Latitude'], 
              y=data_train['Longitude'], 
              weights=data_train['HouseAge'], bins = 1000, vmin=0, vmax=100)
plt.colorbar(h[3], ax=ax[1,0])


h = ax[1,1].hist2d(x=data_train['Latitude'], 
              y=data_train['Longitude'], 
              weights=data_train['Population'], bins = 1000, vmin=0, vmax=10000)
plt.colorbar(h[3], ax=ax[1,1])

for i in range(2):
    for j in range(2):
        ax[i,j].set_xlabel('Latitude'); ax[i,j].set_ylabel('Longitude')

ax[0,0].set_title('House Distribution', fontsize=15)
ax[0,1].set_title('MedHouseVal Distribution', fontsize=15)
ax[1,0].set_title('HouseAge Distribution', fontsize=15)
ax[1,1].set_title('Population Distribution', fontsize=15)

plt.show()
  • MedHouseVal is greated as close as to San Francisco and Los Angeles cities. Similarly, both cities contains a great concentration of population and old houses.

Distributions¶

It's alwas important to check your data distribution, that will give you a sense of which variables behave oddly and may require preprocessing. The following helper function will plot the mean value of the target column with the same scale of the generated histplots. It's a quick a fun way to visualize the relationships between the features and the target.

In [7]:
def add_secondary_plot(
    df, column, target_column, ax, n_bins, color=3,
    show_yticks=False,
):
    secondary_ax = ax.twinx()
    bins = pd.cut(df[column], bins=n_bins)
    bins = pd.IntervalIndex(bins)
    bins = (bins.left + bins.right) / 2
    target = df.groupby(bins)[target_column].mean()
    target.plot(
        ax=secondary_ax, linestyle='',
        marker='.', color=colors[color], label=f'Mean {target_column}'
    )
    secondary_ax.grid(visible=False)
    
    if not show_yticks:
        secondary_ax.get_yaxis().set_ticks([])
        
    return secondary_ax

Train Vs Test¶

Insights:

  • There isn't notable differences between train and test, we probably do not need to do a in-depth adversarial validation.
  • AveOccup, AveBdrms, AveRooms, Population have really skewed distributions, consider using clip function if there isn't a strong impact of outlier values. This may help especially for models that requires feature scaling.
In [8]:
import matplotlib.colors as mpl_colors

def hex_to_rgb(h):
    h = h.lstrip('#')
    return tuple(int(h[i:i+2], 16)/255 for i in (0, 2, 4))

palette = ['#b4d2b1', '#568f8b', '#1d4a60', '#cd7e59', '#ddb247', '#d15252']
palette_rgb = [hex_to_rgb(x) for x in palette]
cmap = mpl_colors.ListedColormap(palette_rgb)
colors = cmap.colors
bg_color= '#fdfcf6'
In [9]:
n_bins = 50
histplot_hyperparams = {
    'kde':True,
    'alpha':0.4,
    'stat':'percent',
    'bins':n_bins
}

columns = features
fig, ax = plt.subplots(2, 4, figsize=(16, 10))
ax = ax.flatten()

for i, column in enumerate(columns):
    plot_axes = [ax[i]]
    
    sns.histplot(data_train[column], label='Train',
                 ax=ax[i], color=colors[0], **histplot_hyperparams)
    
    sns.histplot(data_test[column], label='Test',
                 ax=ax[i], color=colors[1], **histplot_hyperparams)
    
    # Secondary axis to show mean of target
    ax2 = add_secondary_plot(data_train, column, 'MedHouseVal', ax[i], n_bins, color=4)
    
    # titles
    ax[i].set_title(f'{column} Distribution');
    ax[i].set_xlabel(None)
    
    # remove axes to show only one at the end
    plot_axes = [ax[i], ax2]
    handles = []
    labels = []
    for plot_ax in plot_axes:
        handles += plot_ax.get_legend_handles_labels()[0]
        labels += plot_ax.get_legend_handles_labels()[1]
        plot_ax.legend().remove()
    
fig.legend(handles, labels, loc='upper center', bbox_to_anchor=(0.5, 1.04), fontsize=14, ncol=3)
plt.tight_layout()

Correlations¶

In [10]:
data_train.corr()['MedHouseVal'].sort_values(ascending=False)
Out[10]:
MedHouseVal    1.000000
MedInc         0.701925
AveRooms       0.366727
HouseAge       0.103210
Population    -0.038479
AveOccup      -0.048475
Longitude     -0.056742
AveBedrms     -0.067487
Latitude      -0.116499
Name: MedHouseVal, dtype: float64
In [11]:
sns.heatmap(data_train.corr(), cmap='viridis')
Out[11]:
<AxesSubplot:>

Bivariate Distribution with Target¶

Even though correlations will give us a clear picture of linear relationships, it's also important to plot distribution to discover non relationships between variables and the target

Train Dataset¶

Insights:

  • Greater MedInc the greater the MedHouseVal, validated from correlations and from bivariate distribution, a similar effect can be seen on AveRoooms but is less evident.
In [12]:
histplot_hyperparams = {
    'kde':True,
    'alpha':0.4,
    'stat':'percent'
}

columns = features
fig, ax = plt.subplots(2, 4, figsize=(16, 10), sharey=True)
ax = ax.flatten()

for i, column in enumerate(columns):
    sns.histplot(x=data_train[column], 
                 y=data_train['MedHouseVal'], label='Train', ax=ax[i], color=colors[0], **histplot_hyperparams)
    
    ax[i].set_title(f'{column} Distribution vs MedHouseVal', fontsize=10);
    ax[i].set_xlabel(None)
    ax[i].legend()

plt.tight_layout()

Latitude And Longitude¶

Insights

  • Data is distributed across the entire california state
  • We can consider using socieconomic external data to have additional insights about geographic location
  • Lots of properties in Los Angeles
  • Train and test follow the same distribution of latitud-longitude pairs. random KFold Is enough
In [13]:
import folium
from folium import plugins
from folium.plugins import HeatMap

heat_map = folium.Map(data_train[['Latitude', 'Longitude']].mean(axis=0), zoom_start = 6) 

lat_long_list = [[row['Latitude'],row['Longitude']] for index, row in data_train.iterrows()]
HeatMap(lat_long_list, radius=10).add_to(heat_map)
heat_map
Out[13]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Model Development

¶

Catboost+XGBoost+LGBM

In [14]:
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_california_housing
In [15]:
!pip install reverse_geocoder
Collecting reverse_geocoder
  Downloading reverse_geocoder-1.5.1.tar.gz (2.2 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.2/2.2 MB 4.0 MB/s eta 0:00:00a 0:00:01
  Preparing metadata (setup.py) ... done
Requirement already satisfied: numpy>=1.11.0 in /opt/conda/lib/python3.7/site-packages (from reverse_geocoder) (1.21.6)
Requirement already satisfied: scipy>=0.17.1 in /opt/conda/lib/python3.7/site-packages (from reverse_geocoder) (1.7.3)
Building wheels for collected packages: reverse_geocoder
  Building wheel for reverse_geocoder (setup.py) ... done
  Created wheel for reverse_geocoder: filename=reverse_geocoder-1.5.1-py3-none-any.whl size=2268088 sha256=b0e3bf17d86323672d8f67ba9a7a9f983ed468b8d18140daae75869e63bb79d9
  Stored in directory: /root/.cache/pip/wheels/34/6e/70/5423639428a2cac8ea7eb467214a4254b549b381f306a9c790
Successfully built reverse_geocoder
Installing collected packages: reverse_geocoder
Successfully installed reverse_geocoder-1.5.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
In [16]:
train_df = pd.read_csv('/kaggle/input/playground-series-s3e1/train.csv')
test_df = pd.read_csv('/kaggle/input/playground-series-s3e1/test.csv')
submission = pd.read_csv('/kaggle/input/playground-series-s3e1/sample_submission.csv')
train_df = train_df.drop('id', axis=1)
In [17]:
extra_data = fetch_california_housing()

train_data2 = pd.DataFrame(extra_data['data'])
train_data2['MedHouseVal'] = extra_data['target']
train_data2.columns = train_df.columns

train_df['generated'] = 1
test_df['generated'] = 1
train_data2['generated'] = 0

# train_df = pd.concat([train_df, train_data2],axis=0).drop_duplicates()
train_df = pd.concat([train_df, train_data2],axis=0, ignore_index=True)

train_df.loc[33228,['Latitude','Longitude']] = [32.74, -117]
train_df.loc[34363,['Latitude','Longitude']] = [32.71, -117]
train_df.loc[20991,['Latitude','Longitude']] = [34.2, -119]

print(train_df.shape)
train_df.head()
(57777, 10)
Out[17]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal generated
0 2.3859 15.0 3.827160 1.112100 1280.0 2.486989 34.60 -120.12 0.980 1
1 3.7188 17.0 6.013373 1.054217 1504.0 3.813084 38.69 -121.22 0.946 1
2 4.7750 27.0 6.535604 1.103175 1061.0 2.464602 34.71 -120.45 1.576 1
3 2.4138 16.0 3.350203 0.965432 1255.0 2.089286 32.66 -117.09 1.336 1
4 3.7500 52.0 4.284404 1.069246 1793.0 1.604790 37.80 -122.41 4.500 1

Features¶

In [18]:
train_df['r'] = np.sqrt(train_df['Latitude']**2 + train_df['Longitude']**2)
train_df['theta'] = np.arctan2(train_df['Latitude'], train_df['Longitude'])

test_df['r'] = np.sqrt(test_df['Latitude']**2 + test_df['Longitude']**2)
test_df['theta'] = np.arctan2(test_df['Latitude'], test_df['Longitude'])
In [19]:
df = pd.concat([train_df, test_df], axis=0, ignore_index=True)

Encoding trick (see here: https://www.kaggle.com/competitions/playground-series-s3e1/discussion/376210)

In [20]:
emb_size = 20
precision = 1e6 

latlon = np.expand_dims(df[['Latitude', 'Longitude']].values, axis=-1) 

m = np.exp(np.log(precision) / emb_size) 
angle_freq = m ** np.arange(emb_size) 
angle_freq = angle_freq.reshape(1, 1, emb_size) 

latlon = latlon * angle_freq 
latlon[..., 0::2] = np.cos(latlon[..., 0::2]) 
latlon[..., 1::2] = np.sin(latlon[..., 1::2]) 
latlon = latlon.reshape(-1, 2 * emb_size) 

df['exp_latlon1'] = [lat[0] for lat in latlon]
df['exp_latlon2'] = [lat[1] for lat in latlon]

Using feature engineering ideas with coordinates suggested here: https://www.kaggle.com/code/dmitryuarov/ps-s3e1-coordinates-key-to-victory

In [21]:
from sklearn.decomposition import PCA

def pca(data):
    '''
    input: dataframe containing Latitude(x) and Longitude(y)
    '''
    coordinates = data[['Latitude','Latitude']].values
    pca_obj = PCA().fit(coordinates)
    pca_x = pca_obj.transform(data[['Latitude', 'Longitude']].values)[:,0]
    pca_y = pca_obj.transform(data[['Latitude', 'Longitude']].values)[:,1]
    return pca_x, pca_y

# train_df['pca_x'], train_df['pca_y'] = pca(train_df)
# test_df['pca_x'], test_df['pca_y'] = pca(test_df)
df['pca_x'], df['pca_y'] = pca(df)
In [22]:
from umap import UMAP

# UMAP: Uniform Manifold Approximation and Projection for Dimension Reduction
coordinates = df[['Latitude', 'Longitude']].values
umap = UMAP(n_components=2, n_neighbors=50, random_state=228).fit(coordinates)
df['umap_lat'] = umap.transform(coordinates)[:,0]
df['umap_lon'] = umap.transform(coordinates)[:,1]
In [23]:
def crt_crds(df):
    df['rot_15_x'] = (np.cos(np.radians(15)) * df['Longitude']) + \
                      (np.sin(np.radians(15)) * df['Latitude'])
    
    df['rot_15_y'] = (np.cos(np.radians(15)) * df['Latitude']) + \
                      (np.sin(np.radians(15)) * df['Longitude'])
    
    df['rot_30_x'] = (np.cos(np.radians(30)) * df['Longitude']) + \
                      (np.sin(np.radians(30)) * df['Latitude'])
    
    df['rot_30_y'] = (np.cos(np.radians(30)) * df['Latitude']) + \
                      (np.sin(np.radians(30)) * df['Longitude'])
    
    df['rot_45_x'] = (np.cos(np.radians(45)) * df['Longitude']) + \
                      (np.sin(np.radians(45)) * df['Latitude'])
    return df

# train_df = crt_crds(train_df)
# test_df = crt_crds(test_df)
df = crt_crds(df)
In [24]:
import reverse_geocoder as rg
from sklearn.preprocessing import LabelEncoder

def geocoder(df):
    coordinates = list(zip(df['Latitude'], df['Longitude']))
    results = rg.search(coordinates)
    return results

# results = geocoder(train_df)
# train_df['place'] = [x['admin2'] for x in results]
# results = geocoder(test_df)
# test_df['place'] = [x['admin2'] for x in results]

results = geocoder(df)
df['place'] = [x['admin2'] for x in results]

places = ['Los Angeles County', 'Orange County', 'Kern County',
          'Alameda County', 'San Francisco County', 'Ventura County',
          'Santa Clara County', 'Fresno County', 'Santa Barbara County',
          'Contra Costa County', 'Yolo County', 'Monterey County',
          'Riverside County', 'Napa County']

def replace(x):
    if x in places:
        return x
    else:
        return 'Other'
    
# train_df['place'] = train_df['place'].apply(lambda x: replace(x))
# test_df['place'] = test_df['place'].apply(lambda x: replace(x))

df['place'] = df['place'].apply(lambda x: replace(x))

# le = LabelEncoder()
# train_df['place'] = le.fit_transform(train_df['place'])
# test_df['place'] = le.transform(test_df['place'])

# test_df = pd.get_dummies(test_df)
# train_df = pd.get_dummies(train_df)

df = pd.get_dummies(df)
Loading formatted geocoded file...

Distances to cities and coast points

In [25]:
from haversine import haversine

Sac = (38.576931, -121.494949)
SF = (37.780080, -122.420160)
SJ = (37.334789, -121.888138)
LA = (34.052235, -118.243683)
SD = (32.715759, -117.163818)

df['dist_Sac'] = df.apply(lambda x: haversine((x['Latitude'], x['Longitude']), Sac, unit='ft'), axis=1)
df['dist_SF'] = df.apply(lambda x: haversine((x['Latitude'], x['Longitude']), SF, unit='ft'), axis=1)
df['dist_SJ'] = df.apply(lambda x: haversine((x['Latitude'], x['Longitude']), SJ, unit='ft'), axis=1)
df['dist_LA'] = df.apply(lambda x: haversine((x['Latitude'], x['Longitude']), LA, unit='ft'), axis=1)
df['dist_SD'] = df.apply(lambda x: haversine((x['Latitude'], x['Longitude']), SD, unit='ft'), axis=1)
df['dist_nearest_city'] = df[['dist_Sac', 'dist_SF', 'dist_SJ', 
                              'dist_LA', 'dist_SD']].min(axis=1)
In [26]:
from shapely.geometry import LineString, Point

coast_points = LineString([(32.6644, -117.1613), (33.2064, -117.3831),
                           (33.7772, -118.2024), (34.4634, -120.0144),
                           (35.4273, -120.8819), (35.9284, -121.4892),
                           (36.9827, -122.0289), (37.6114, -122.4916),
                           (38.3556, -123.0603), (39.7926, -123.8217),
                           (40.7997, -124.1881), (41.7558, -124.1976)])

df['dist_to_coast'] = df.apply(lambda x: Point(x['Latitude'], x['Longitude']).distance(coast_points), axis=1)
In [27]:
# combine latitude and longitude
# codes from 
# https://datascience.stackexchange.com/questions/49553/combining-latitude-longitude-position-into-single-feature
from math import radians, cos, sin, asin, sqrt

def single_pt_haversine(lat, lng, degrees=True):
    """
    'Single-point' Haversine: Calculates the great circle distance
    between a point on Earth and the (0, 0) lat-long coordinate
    """
    r = 6371 # Earth's radius (km). Have r = 3956 if you want miles

    # Convert decimal degrees to radians
    if degrees:
        lat, lng = map(radians, [lat, lng])

    # 'Single-point' Haversine formula
    a = sin(lat/2)**2 + cos(lat) * sin(lng/2)**2
    d = 2 * r * asin(sqrt(a)) 

    return d
# add more metric 
# referred to this discussion
# https://www.kaggle.com/competitions/playground-series-s3e1/discussion/376210

def manhattan(lat,lng):
    return np.abs(lat) + np.abs(lng)
def euclidean(lat,lng):
    return (lat**2 + lng**2) **0.5

def add_combine(df):      
    df['haversine'] = [single_pt_haversine(x, y) for x, y in zip(df.Latitude, df.Longitude)]
    df['manhattan'] = [manhattan(x,y) for x,y in zip(df.Latitude, df.Longitude)]
    df['euclidean'] = [euclidean(x,y) for x,y in zip(df.Latitude,df.Longitude)]
    return df

df = add_combine(df)
In [28]:
train_df = df.iloc[:-len(test_df),:]
test_df = df.iloc[-len(test_df):,:].drop('MedHouseVal', axis=1).reset_index(drop=True)

X = train_df.drop(['MedHouseVal', 'id'], axis=1)
y = train_df.MedHouseVal
X_test = test_df.drop('id', axis=1)

Catboost model¶

In [ ]:
import catboost
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error

n_folds = 15

MAX_ITER = 15000
PATIENCE = 1000
DISPLAY_FREQ = 100

eval_predsCB = []
predsCB = []

k_fold = KFold(n_splits=n_folds, random_state=42, shuffle=True)

MODEL_PARAMS = {
                'random_seed': 1234,    
#                 'learning_rate': 0.1,   # 0.15: 0.5678, 0.12: 0.5685, 0.1: 0.56757, 0.05: 0.57, 0.01, 0.57             
                'iterations': MAX_ITER,
                'early_stopping_rounds': PATIENCE,
#                 'metric_period': DISPLAY_FREQ,
                'use_best_model': True,
                'eval_metric': 'RMSE',
                'verbose': 1000,
#                 'task_type': 'GPU'
               }


for train_index, test_index in k_fold.split(X, y):
    X_train, X_valid = X.iloc[train_index], X.iloc[test_index]
    y_train, y_valid = y.iloc[train_index], y.iloc[test_index]
    
    model = catboost.CatBoostRegressor(**MODEL_PARAMS)
    
    model.fit(X=X_train, y=y_train,
          eval_set=[(X_valid, y_valid)],
          early_stopping_rounds = PATIENCE,
#           metric_period = DISPLAY_FREQ
         )
    predsCB.append(model.predict(X_test))
#     eval_predsCB.append(model.predict(X))
#     print("RMSE valid = {}".format(mean_squared_error(y_valid, model.predict(X_valid))))
#     print("RMSE full = {}".format(mean_squared_error(y, model.predict(X))))

XGBoost model¶

In [ ]:
from xgboost import XGBRegressor

# n_folds = 20
k_fold = KFold(n_splits=n_folds, random_state=42, shuffle=True)

eval_predsXB = []
predsXB = []

PATIENCE = 200

MODEL_PARAMS = {       'n_estimators': 1000, #1000, 5000
#                        'learning_rate': 0.05,
                       'max_depth': 4, # 3
                       'colsample_bytree': 0.9, # 0.95
                       'subsample': 1,
                       'reg_lambda': 20,
                       'early_stopping_rounds': PATIENCE,
#                        'tree_method': 'gpu_hist',
                       'seed': 1
}

for train_index, test_index in k_fold.split(X, y):
    X_train, X_valid = X.iloc[train_index], X.iloc[test_index]
    y_train, y_valid = y.iloc[train_index], y.iloc[test_index]
    
    model = XGBRegressor(**MODEL_PARAMS)
    
    model.fit(X=X_train, y=y_train,
          eval_set=[(X_valid, y_valid)],
#           early_stopping_rounds = PATIENCE,
          verbose = 100
         )
    predsXB.append(model.predict(X_test))
#     eval_predsXB.append(model.predict(X))

LGBM model¶

In [ ]:
import lightgbm as lgbm
from lightgbm.sklearn import LGBMRegressor

# n_folds = 20
k_fold = KFold(n_splits=n_folds, random_state=42, shuffle=True)

eval_predsLB = []
predsLB = []

MODEL_PARAMS = {
                       'learning_rate': 0.01,
                       'max_depth': 9,
                       'num_leaves': 90,
                       'colsample_bytree': 0.8,
                       'subsample': 0.9,
                       'subsample_freq': 5,
                       'min_child_samples': 36,
                       'reg_lambda': 28,
                       'n_estimators': 20000,
                       'metric': 'rmse',
                       'random_state': 1
}

callbacks = [lgbm.early_stopping(30, verbose=1), lgbm.log_evaluation(period=0)]

for train_index, test_index in k_fold.split(X, y):
    X_train, X_valid = X.iloc[train_index], X.iloc[test_index]
    y_train, y_valid = y.iloc[train_index], y.iloc[test_index]
    
    model = lgbm.LGBMRegressor(**MODEL_PARAMS)
    
    model.fit(X=X_train, y=y_train,
          eval_set=[(X_valid, y_valid)],
#           early_stopping_rounds = PATIENCE,
          callbacks=callbacks
         )
    predsLB.append(model.predict(X_test))
#     eval_predsLB.append(model.predict(X))

Making prediction¶

In [ ]:
a = 0.4
b = 0.2
c = 0.4

predCB = np.average(np.array(predsCB),axis=0)
predXB = np.average(np.array(predsXB),axis=0)
predLB = np.average(np.array(predsLB),axis=0)
pred = predCB * a + predXB * b + predLB * c

Making submission¶

In [ ]:
submission['MedHouseVal'] = pred
submission
In [ ]:
vals = train_df['MedHouseVal'].unique().tolist()
submission['MedHouseVal'] = submission['MedHouseVal'].apply(lambda x: min(vals, key=lambda v: abs(v - x)))
submission.MedHouseVal.clip(0, 5, inplace=True)
In [ ]:
submission.to_csv('submission_v3.1.4.csv', index=False)