<jupyter_start><jupyter_text>EDA<jupyter_code>%%capture
import sys

# If you're on Colab:
if 'google.colab' in sys.modules:
    DATA_PATH = 'https://raw.githubusercontent.com/Air-BnB-2-BW/data-science/master/airbnb_bw.csv'
    !pip install category_encoders==2.*
    !pip install eli5
    !pip install pdpbox
    !pip install shap
import pandas as pd
import plotly 

df = pd.read_csv(DATA_PATH, index_col=0)

print(df.shape)

df
df.info()
# is the target symmetric - it is skewed right
%matplotlib inline
import seaborn as sns
sns.distplot(df['Price']);
pd.options.display.float_format = '{:,.0f}'.format
df['Price'].describe()
fig = px.bar(df, x='Review Scores Rating', y='Price')
fig.show()
df['Amenities'] = df['Free Parking'] + df['Wireless Internet'] + df['Cable TV']
df['sqft/bdrm'] = df['Square Feet']/df['Bedrooms']<jupyter_output><empty_output><jupyter_text>Mean Baseline<jupyter_code>guess = df['Price'].mean()
guess
errors = guess - df['Price']
errors
mean_absolute_error = errors.abs().mean()
print(f'If we just guessed every Airbnb cost ${guess:,.0f},')
print(f'we would be off by ${mean_absolute_error:,.0f} on average.')<jupyter_output>If we just guessed every Airbnb cost $200,
we would be off by $113 on average.<jupyter_text>Set features / target<jupyter_code>from sklearn.model_selection import train_test_split
train, test= train_test_split(df, test_size=0.20)

# Arrange data into X features matrix and y target vector
features = ['Zipcode', 'Square Feet', 'Bedrooms', 'Bathrooms', 'Review Scores Rating', 'Accommodates', 'Cleaning Fee', 'Free Parking', 'Wireless Internet', 'Cable TV', 'Prop_encoded', 'cancel_encoded']
target = 'Price'
X_train = train[features]
y_train = train[target]
X_test = test[features]
y_test = test[target]
row = X_train.iloc[[1]]
row
# What does the model predict for this Airbnb?
model.predict(row)<jupyter_output><empty_output><jupyter_text>Linear Regression<jupyter_code>from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

model = LinearRegression()
model.fit(X_train, y_train)
y_pred_train = model.predict(X_train)
print("MAE(Train):$",mean_absolute_error(y_train, y_pred_train))<jupyter_output>MAE(Train):$ 66.89461855126655<jupyter_text>Random Forest<jupyter_code>from scipy.stats import randint, uniform
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.pipeline import make_pipeline
import category_encoders as ce
from sklearn.preprocessing import StandardScaler

pipeline = make_pipeline(
    ce.TargetEncoder(), 
    SimpleImputer(),
    StandardScaler(), 
    RandomForestRegressor(random_state=42)
)

param_distributions = {
    'targetencoder__min_samples_leaf': randint(1, 1000),     
    'simpleimputer__strategy': ['mean', 'median'], 
    'randomforestregressor__n_estimators': randint(50, 500), 
    'randomforestregressor__max_depth': [5, 10, 15, 20, None], 
    'randomforestregressor__max_features': uniform(0, 1), 
}

# If you're on Colab, decrease n_iter & cv parameters
search = RandomizedSearchCV(
    pipeline, 
    param_distributions=param_distributions, 
    n_iter=100, 
    cv=10, 
    scoring='neg_mean_absolute_error', 
    verbose=10, 
    return_train_score=True, 
    n_jobs=-1
)

search.fit(X_train, y_train);
print('Best hyperparameters', search.best_params_)
print('Cross-validation MAE', -search.best_score_)
model = search.best_estimator_<jupyter_output>Best hyperparameters {'randomforestregressor__max_depth': 15, 'randomforestregressor__max_features': 0.25779212995358014, 'randomforestregressor__n_estimators': 268, 'simpleimputer__strategy': 'median', 'targetencoder__min_samples_leaf': 826}
Cross-validation MAE 62.26442901476558<jupyter_text>XGBoost<jupyter_code>from xgboost import XGBRegressor
pipeline = make_pipeline(
    ce.TargetEncoder(), 
    SimpleImputer(),
    StandardScaler(), 
    XGBRegressor(random_state=42,n_jobs=-1)
)
param_distributions = {
    'targetencoder__min_samples_leaf': randint(1, 1000),     
    'simpleimputer__strategy': ['mean', 'median'],
    'xgbregressor__learning_rate': [.03, 0.05, .07 ,0.13,0.2],
    'xgbregressor__max_depth': [5, 6, 7],}

# If you're on Colab, decrease n_iter & cv parameters
search = RandomizedSearchCV(
    pipeline, 
    param_distributions=param_distributions, 
    n_iter=100, 
    cv=10, 
    scoring='neg_mean_absolute_error', 
    verbose=10, 
    return_train_score=True, 
    n_jobs=-1
)
search.fit(X_train, y_train);
print('XG Boost MAE:', -search.best_score_)<jupyter_output>XG Boost MAE: 60.51901280101125<jupyter_text>Permutation Importances<jupyter_code>from sklearn.ensemble import RandomForestClassifier
from sklearn.impute import SimpleImputer

pipeline = make_pipeline(
    ce.OrdinalEncoder(), 
    SimpleImputer(strategy='median'), 
    RandomForestClassifier(n_estimators=20, 
                           random_state=42, 
                           n_jobs=-1)
)

# Fit on train, score on val
pipeline.fit(X_train, y_train);
# Get feature importances
rf = pipeline.named_steps['randomforestclassifier']
importances = pd.Series(rf.feature_importances_, X_train.columns)

# Plot feature importances
%matplotlib inline
import matplotlib.pyplot as plt

n = 12
plt.figure(figsize=(10,n/2))
plt.title(f'Top {n} features')
importances.sort_values()[-n:].plot.barh(color='grey');<jupyter_output><empty_output><jupyter_text>Partial Dependence Plot 1 feature<jupyter_code>from sklearn.metrics import r2_score
from xgboost import XGBRegressor

gb = make_pipeline(
    ce.OrdinalEncoder(), 
    XGBRegressor(n_estimators=200, objective='reg:squarederror', n_jobs=-1)
)

gb.fit(X_train, y_train)
y_pred = gb.predict(X_test)
print('Gradient Boosting R^2', r2_score(y_test, y_pred))
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 72
from pdpbox.pdp import pdp_isolate, pdp_plot

feature = 'Square Feet'

isolated = pdp_isolate(
      model=gb,
      dataset=X_test,
      model_features=X_test.columns,
      feature=feature
)
pdp_plot(isolated, feature_name=feature)<jupyter_output><empty_output><jupyter_text>Partial Dependence Plot 2 features<jupyter_code>from pdpbox.pdp import pdp_interact, pdp_interact_plot

features = ['Bedrooms', 'Bathrooms']

interaction = pdp_interact(
    model=gb,
    dataset=X_train,
    model_features=X_train.columns,
    features=features
)
pdp_interact_plot
pdp_interact_plot(interaction, plot_type='grid', feature_names=features);<jupyter_output>findfont: Font family ['Arial'] not found. Falling back to DejaVu Sans.<jupyter_text>Shapley Force Plot<jupyter_code>from scipy.stats import randint, uniform
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import RandomizedSearchCV

param_distributions = { 
    'n_estimators': randint(50, 500), 
    'max_depth': [5, 10, 15, 20, None], 
    'max_features': uniform(0, 1), 
}

search = RandomizedSearchCV(
    RandomForestRegressor(random_state=42), 
    param_distributions=param_distributions, 
    n_iter=5, 
    cv=2, 
    scoring='neg_mean_absolute_error', 
    verbose=10, 
    return_train_score=True, 
    n_jobs=6, 
    random_state=42
)

search.fit(X_train, y_train);
print('Best hyperparameters', search.best_params_)
print('Cross-validation MAE', -search.best_score_)
model = search.best_estimator_
# Get an individual observation to explain.
# For example, the 5th row from the test set.
row = X_train.iloc[[5]]
row
# What was the actual price for this Airbnb?
y_test.iloc[[5]]
# What does the model predict for this Airbnb?
model.predict(row)
# Look at a Shapley Values Force Plot
import shap

explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(row)
shap.initjs()
shap.force_plot(
    base_value=explainer.expected_value,
    shap_values=shap_values,
    features=row
)
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
pio.templates.default = 'none'
fig = px.violin(df, y='Price', box=True, points='all')
fig.show()
fig = go.Figure()

fig.add_trace(go.Violin(x=df['Free Parking']==1.0,
                        y=df['Price'][df['Free Parking']==1.0],
                        legendgroup='Yes', scalegroup='Yes', name='Yes',
                        side='negative', line_color='blue')
                    )
fig.update_traces(meanline_visible=True)
fig.update_layout(violingap=0, violinmode='overlay')
fig.show()
fig = px.violin(df, y='Price', color='Free Parking',
                violinmode='overlay', hover_data=df.columns)
fig.show()
fig = px.violin(df, y='Price', color='Cable TV',
                violinmode='overlay', hover_data=df.columns)
fig.show()
df['Bedrooms'].unique()
fig = go.Figure()

accomm = [2.,  8.,  4.,  6.,  5., 10.,  3.,  1., 14.,  7., 16., 13.,  9.,
       12., 15., 11.]

for i in accomm:
    fig.add_trace(go.Violin(x=df['Accommodates'][df['Accommodates'] == i],
                            y=df['Price'][df['Accommodates'] == i],
                            name=i,
                            box_visible=True,
                            meanline_visible=True))

fig.show()
fig = go.Figure()

bdrms = [1., 4., 3., 2., 0., 5., 7., 8., 6.]

for i in bdrms:
    fig.add_trace(go.Violin(x=df['Bedrooms'][df['Bedrooms'] == i],
                            y=df['Price'][df['Bedrooms'] == i],
                            name=i,
                            box_visible=True,
                            meanline_visible=True))

fig.show()
fig = go.Figure()

bdrms = [1., 4., 3., 2., 0., 5., 7., 8., 6.]

for i in bdrms:
    fig.add_trace(go.Violin(x=df['Amenities'][df['Amenities'] == i],
                            y=df['Price'][df['Amenities'] == i],
                            name=i,
                            box_visible=True,
                            meanline_visible=True))

fig.show()
df.head()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12634760705289672, 'fraction_numerical': 0.02468513853904282, 'mean_word_length': 4.24630021141649, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 36, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '274953', 'license': 'MIT', 'n_tokens_mistral': 3701, 'n_tokens_neox': 3453, 'n_words': 701, 'path': 'notebooks/viz_notebook.ipynb', 'repo_name': 'Air-BnB-2-BW/data-science', 'size': '9925'}