import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_log_error
import pandas as pd
import numpy as np
import xgboost as xgb
from sklearn.model_selection import GridSearchCV


train_data = pd.read_csv('data/regression_train.csv', index_col=0)
test_data = pd.read_csv('data/regression_test.csv', index_col=0)
solution = pd.read_csv('data/regression_solution.csv')

# I'll ignore the categorical features for now and just focus on the numberical features
X_train = train_data.select_dtypes(include=['number']).copy()
X_train = X_train.drop(['SalePrice'], axis=1)
y_train = train_data["SalePrice"]
X_test = test_data.select_dtypes(include=['number']).copy()
y_test = solution["SalePrice"]

# bit of feature engineering
for df in (X_train, X_test):
    df["n_bathrooms"] = df["BsmtFullBath"] + \
        (df["BsmtHalfBath"]*0.5) + df["FullBath"] + (df["HalfBath"]*0.5)
    df["area_with_basement"] = df["GrLivArea"] + df["TotalBsmtSF"]

# regression
model = xgb.XGBRegressor(eval_metric='rmsle')

# first using Gridsearch to find optimal parameters
param_grid = {"max_depth":    [4, 5],  # max depth of trees, increasing often leads to overfitting
              "n_estimators": [500, 600, 700],  # number of boosting rounds
              "learning_rate": [0.01, 0.015]  # aka "eta"
              }

# try out every combination of the above values
search = GridSearchCV(model, param_grid, cv=5).fit(X_train, y_train)
print("The best hyperparameters are ", search.best_params_)


# then run again to fit a model using those values
model = xgb.XGBRegressor(learning_rate=search.best_params_["learning_rate"],
                         n_estimators=search.best_params_["n_estimators"],
                         max_depth=search.best_params_["max_depth"],
                         eval_metric='rmsle')

model.fit(X_train, y_train)


# and use the trained model against the test data
predictions = model.predict(X_test)


# and evaluate
RMSLE = np.sqrt(mean_squared_log_error(y_test, predictions))
print("The score is %.5f" % RMSLE)


output = pd.DataFrame({"Id": test_data.index, "SalePrice": predictions})


# Feature importance
plt.style.use('fivethirtyeight')
#plt.rcParams.update({'font.size': 16})

fig, ax = plt.subplots(figsize=(12, 6))
xgb.plot_importance(model, max_num_features=8, ax=ax)
plt.show()


def RSLE(y_hat, y):
    return np.sqrt((np.log1p(y_hat) - np.log1p(y))**2)


print("The RMSLE score is %.3f" % RSLE(400, 1000))
print("The RMSLE score is %.3f" % RSLE(1600, 1000))


plt.rcParams["figure.figsize"] = (7, 4)
x = np.linspace(5, 4000, 100)
plt.plot(x, RSLE(x, 1000))
plt.xlabel('prediction')
plt.ylabel('RMSLE')
plt.show()
