<jupyter_start><jupyter_text>Regressão - Exercício___  6. ExercíciosEsse notebook contém os exercícios da aula de regressão. Siga as instruções para aplicar o que foi aprendido nessa aula para outra base de dados para tentar prever os preços de carros. Essa base de dados foi disponibilizada junto com o notebook.Vamos começasr lendo os dados.<jupyter_code>import pandas as pd
import numpy as np
import math
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
import lightgbm as lgb
# Usando outro caminho para obter os csv do google drive
from google.colab import drive
drive.mount('/content/drive')
!ln -s /content/drive/MyDrive/Data\ Science/Entrega5 /mydrive
!ls /mydrive
cars_df = pd.read_csv("/mydrive/dados/OLX_Car_Data.csv", encoding = 'unicode_escape')

cars_df.describe(include='all')<jupyter_output><empty_output><jupyter_text>Utilizando o método ```describe``` conseguimos ver algumas informações necessárias para fazer uma limpeza básica nos nossos dados. Veja abaixo.<jupyter_code># renomeando as colunas para remover os espaços
cars_df.rename(columns = {'KMs Driven':'KMs_Driven', 
                          'Registered City':'Registered_City', 
                          'Transaction Type':'Transaction_Type'},
               inplace = True)

# Já que a coluna Model tem muitas categorias, vamos nomear todas com menos de 400 observações de 'Outros'
models = ['Alto', 'Corolla GLI', 'Mehran VX', 'Mehran VXR', 'Vitz', 'Bolan', 'Cuore', 'Corolla XLI', 'Mira']
cars_df.loc[~cars_df['Model'].isin(models),'Model'] = 'Outros'

# removendo valores nulos
cars_df.dropna(axis=0, inplace=True)

# removendo outliers
low = 0.05
high = 0.95
quant_df = cars_df.quantile([low, high])
cars_df = cars_df[(cars_df.KMs_Driven < quant_df.loc[high, "KMs_Driven"]) & 
                  (cars_df.KMs_Driven > quant_df.loc[low, "KMs_Driven"]) &
                  (cars_df.Price < quant_df.loc[high, "Price"]) & 
                  (cars_df.Price > quant_df.loc[low, "Price"]) &
                  (cars_df.Year < quant_df.loc[high, "Year"]) & 
                  (cars_df.Year > quant_df.loc[low, "Year"])]

# transformando as variáveis binárias
cars_df['is_new'] = 1
cars_df.loc[cars_df.Condition == 'Used', 'is_new'] = 0
cars_df.drop(['Condition'], axis=1, inplace=True)

cars_df['is_cash'] = 0
cars_df.loc[cars_df.Transaction_Type=='Cash', 'is_cash'] = 1
cars_df.drop('Transaction_Type', axis=1, inplace=True)

# aplicando o One Hot Encoding
cars_df = pd.concat([cars_df.drop("Brand", axis=1), pd.get_dummies(cars_df.Brand, prefix='Brand')], axis=1)
cars_df = pd.concat([cars_df.drop("Fuel", axis=1), pd.get_dummies(cars_df.Fuel, prefix='Fuel')], axis=1)
cars_df = pd.concat([cars_df.drop("Registered_City", axis=1), pd.get_dummies(cars_df.Registered_City, prefix='RCity')], axis=1)
cars_df = pd.concat([cars_df.drop("Model", axis=1), pd.get_dummies(cars_df.Model, prefix='Model')], axis=1)

cars_df.describe(include='all')
y, X = cars_df.Price, cars_df.drop('Price', axis=1)

print("X", X.shape)
print("y", y.shape)
seed = 1

# separando treino e teste
X_training, X_test, y_training, y_test = train_test_split(X, y, random_state=seed, test_size=0.25) #, stratify=y)
print("Test set X", X_test.shape)
print("Test set y", y_test.shape)

# separando treino e validação
X_train, X_val, y_train, y_val = train_test_split(X_training, y_training, random_state=seed,
                                                  test_size=0.33) #, stratify=y_training)

print("Train set X", X_train.shape)
print("Train set y", y_train.shape)
print("Validation set X", X_val.shape)
print("Validation set y", y_val.shape)<jupyter_output>Test set X (3625, 96)
Test set y (3625,)
Train set X (7284, 96)
Train set y (7284,)
Validation set X (3589, 96)
Validation set y (3589,)<jupyter_text>Exercício 1**Substitua as lacunas** para treinar um modelo de *random forest* com validação cruzada e *grid search*. O *grid search* deve variar, pelo menos, os parâmetros *n_estimators* e *max_depth*, mas você pode incluir outros. Após o treino, crie o *dataframe* ```cv_results``` com os resultados de cada iteração e o dicionário ```cv_best_params``` com os valores da melhor combinação de parâmetros.<jupyter_code># Random Forest com validação cruzada e Grid Search

# definindo os valores possíveis dos parâmetros a serem testados
params = {'n_estimators': [5, 50, 100, 500],
          'max_features': [2, 5, 9, 13],
          'max_depth': [2, 5, 10, 50],
          'min_samples_split': [2, 8, 15, 30],}

# criando o objeto do modelo com RandomForestRegressor
rf_model_cv_gs = RandomForestRegressor(random_state = seed)

# criando o objeto do grid search com GridSearchCV
grid_search = GridSearchCV(rf_model_cv_gs, param_grid=params, return_train_score=True, scoring='neg_root_mean_squared_error')

# treinando o modelo com o grid search
grid_search.fit(X_training, y_training)

# pegando os resultados da validação cruzada (cv_results)
cv_results = pd.DataFrame(grid_search.cv_results_)

# pegando e imprimindo a melhor combinação de hiperparâmetros
cv_best_params = grid_search.best_params_
print('\n Best hyperparameters:')
print(cv_best_params)<jupyter_output>Best hyperparameters:
{'max_depth': 50, 'max_features': 13, 'min_samples_split': 8, 'n_estimators': 500}<jupyter_text>Exercício 2**Substitua as lacunas** para treinar o modelo final de *random forest* com os melhores parâmetros obtidos no *grid search* do exercício anterior.<jupyter_code># imprimindo o score médio nas bases de treino
print("Average accuracy on train set: {:.3f} +/- {:.3f}".format(cv_results[cv_results.rank_test_score == 1].mean_train_score.values[0],
                                                                     cv_results[cv_results.rank_test_score == 1].std_train_score.values[0])) 
# imprimindo o score médio nas bases de validação
print("Average accuracy on validation set: {:.3f} +/- {:.3f}".format(cv_results[cv_results.rank_test_score == 1].mean_test_score.values[0],
                                                                     cv_results[cv_results.rank_test_score == 1].std_test_score.values[0])) 

# configurando o modelo com a melhor combinação de hiperparâmetros
rf_model_cv_gs.set_params(n_estimators = grid_search.best_params_['n_estimators'],
                           max_features = grid_search.best_params_['max_features'],
                           max_depth = grid_search.best_params_['max_depth'],
                           min_samples_split = grid_search.best_params_['min_samples_split'])

# treinando um modelo com a melhor combinação de hiperparâmetros
rf_model_cv_gs.fit(X_training, y_training)
best_model_params = rf_model_cv_gs.get_params()<jupyter_output>Average accuracy on train set: -120444.232 +/- 770.748
Average accuracy on validation set: -173288.302 +/- 6005.583<jupyter_text>Exercício 3**Substitua as lacunas** para obter um *dataframe* com a importância de cada variável do modelo de *random forest*.<jupyter_code># desenhando o gráfico de importância de variáveis
features = X_training.columns
importances = rf_model_cv_gs.feature_importances_
indices = np.argsort(importances)

feature_importances_df = pd.DataFrame({'features': features,
                                       'importances': importances})

plt.title('Feature Importances')
plt.barh(range(len(importances[indices][-15:])), importances[indices][-15:], color='b', align='center')
plt.yticks(range(len(importances[indices][-15:])), [features[i] for i in indices[-15:]])
plt.xlabel('Relative Importance')
plt.show()<jupyter_output><empty_output><jupyter_text>Exercício 4**Substitua as lacunas** para calcular o RMSE do modelo de *random forest* final na base de teste.<jupyter_code>y_test_pred_rf = rf_model_cv_gs.predict(X_test)
rmse_test_rf = math.sqrt(mean_squared_error(y_test, y_test_pred_rf))
print(rmse_test_rf)<jupyter_output>166742.34632465875<jupyter_text>Exercício 5**Substitua as lacunas** para treinar um modelo de *Light GBM* com validação cruzada e *grid search*. O *grid search* deve variar, pelo menos, os parâmetros *learning_rate* e *n_estimators*, mas você pode incluir outros. Após o treino, crie o *dataframe* ```cv_results``` com os resultados de cada iteração e o dicionário ```cv_best_params``` com os valores da melhor combinação de parâmetros.<jupyter_code>import warnings
warnings.filterwarnings('ignore')
# Light GBM com validação cruzada e Grid Search

# definindo os valores possíveis dos parâmetros a serem testados
# params = {'max_depth': [10, 50, 100],
#           'learning_rate': [0.01, 0.03, 0.1, 0.5],
#           'num_iterations': [100, 200, 500],
#           'min_data_in_leaf': [20, 50],
#           'min_gain_to_split': [0., 1, 5]}

params = {'max_depth': [10, 50, 100],
          'learning_rate': [0.01, 0.03, 0.1, 0.5],
          'num_iterations': [100, 200, 500],
          'min_data_in_leaf': [20, 50],
          'min_gain_to_split': [0., 1, 5]}

# criando o objeto do modelo com XGBClassifier
lgb_model_cv_gs = lgb.LGBMRegressor(random_state = seed)

# criando o objeto do grid search com GridSearchCV
grid_search = GridSearchCV(lgb_model_cv_gs, param_grid=params, return_train_score=True, scoring='neg_root_mean_squared_error')

# treinando o modelo com o grid search
grid_search.fit(X_training, y_training)

# pegando os resultados da validação cruzada (cv_results)
cv_results = pd.DataFrame(grid_search.cv_results_)

# pegando e imprimindo a melhor combinação de hiperparâmetros
cv_best_params = grid_search.best_params_
print('\n Best hyperparameters:')
print(cv_best_params)<jupyter_output>Best hyperparameters:
{'learning_rate': 0.03, 'max_depth': 10, 'min_data_in_leaf': 20, 'min_gain_to_split': 5, 'num_iterations': 500}<jupyter_text>Exercício 6**Substitua as lacunas** para treinar o modelo final de *light GBM* com os melhores parâmetros obtidos no *grid search* do exercício anterior.<jupyter_code># imprimindo o score médio nas bases de treino
print("Average accuracy on train set: {:.3f} +/- {:.3f}".format(cv_results[cv_results.rank_test_score == 1].mean_train_score.values[0],
                                                                     cv_results[cv_results.rank_test_score == 1].std_train_score.values[0]))

# imprimindo o score médio nas bases de validação
print("Average accuracy on validation set: {:.3f} +/- {:.3f}".format(cv_results[cv_results.rank_test_score == 1].mean_test_score.values[0],
                                                                     cv_results[cv_results.rank_test_score == 1].std_test_score.values[0]))

# configurando o modelo com a melhor combinação de hiperparâmetros
lgb_model_cv_gs.set_params(max_depth = grid_search.best_params_['max_depth'],
                           learning_rate = grid_search.best_params_['learning_rate'],
                           min_data_in_leaf = grid_search.best_params_['min_data_in_leaf'],
                           min_gain_to_split = grid_search.best_params_['min_gain_to_split'])

# treinando um modelo com a melhor combinação de hiperparâmetros
lgb_model_cv_gs.fit(X_training, y_training)
best_model_params = lgb_model_cv_gs.get_params()<jupyter_output>Average accuracy on train set: -148863.359 +/- 1120.330
Average accuracy on validation set: -171900.130 +/- 4856.291<jupyter_text>Exercício 7**Substitua as lacunas** para obter um *dataframe* com a importância de cada variável do modelo de *light GBM*.<jupyter_code># desenhando o gráfico de impoartância de variáveis
features = X_training.columns
importances = lgb_model_cv_gs.feature_importances_
indices = np.argsort(importances)

feature_importances_df = pd.DataFrame({'features': features,
                                       'importances': importances})

plt.title('Feature Importances')
plt.barh(range(len(importances[indices][-15:])), importances[indices][-15:], color='b', align='center')
plt.yticks(range(len(importances[indices][-15:])), [features[i] for i in indices[-15:]])
plt.xlabel('Relative Importance')
plt.show()<jupyter_output><empty_output><jupyter_text>Exercício 8**Substitua as lacunas** para calcular o RMSE do modelo de *light GBM* final na base de teste.<jupyter_code>y_test_pred_lgb = lgb_model_cv_gs.predict(X_test)
rmse_test_lgb = math.sqrt(mean_squared_error(y_test, y_test_pred_lgb))
print(rmse_test_lgb)<jupyter_output>174500.91971972145<jupyter_text>Os resultados dos modelos criados até aqui fazem sentido para você?Vamos desenhar gráficos para comparar as duas previsões como fizamos com os dados de **boston**, e usá-los para responder as demais perguntas:<jupyter_code># Desenhando o gráfico de valores previstos por valores reais para ambos os modelos

plt.figure(figsize=(16,10))
plt.title('Pakistan car prices - Predicted vs Real',fontsize=20)
df = pd.DataFrame({'real':y_val,'Random Forest':rf_model_cv_gs.predict(X_val),
                   'LGBM':lgb_model_cv_gs.predict(X_val)})
df = df.sample(200)
df.sort_values(by=['real'],ascending=True,inplace=True)
df = df.reset_index(drop=True)
plt.plot(df)
plt.legend(['Real price','Predicted RF price','Predicted LGBM price'],fontsize=20)
plt.ylabel('$ Price',fontsize=20)
plt.xlabel('Observations ordered by price',fontsize=20)
plt.show()

plt.figure(figsize=(16,10))
plt.title('Pakistan car prices - Predicted vs Real',fontsize=20)
plt.scatter(x=df['real'],y=df['Random Forest'],c='y')
plt.scatter(x=df['real'],y=df['LGBM'],c='g')
plt.plot([0,1750000],[0,1750000],'k--')
# plt.axis([0,1750000,0,1750000])
plt.legend(['Real price','Predicted RF price','Predicted LGBM price'],fontsize=20)
plt.xlabel('Real price',fontsize=20)
plt.ylabel('Predicted price',fontsize=20)
plt.show()<jupyter_output><empty_output><jupyter_text>Exercício 9*(Resposta aberta, não contabilizara pontos, o objetivo é refletir sobre a questão/tópico)*Qual modelo parece ter menos *over-fitting*? Explique<jupyter_code># suas respostas
LGBM, por possuirem picos mais acentuados<jupyter_output><empty_output><jupyter_text>Exercício 10*(Resposta aberta, não contabilizara pontos, o objetivo é refletir sobre a questão/tópico)*Qual modelo faz a melhor previsão dos preços dos carros em cada faixa de preço?<jupyter_code># suas respostas
O modelo de random florest<jupyter_output><empty_output><jupyter_text>Exercício 11*(Resposta aberta, não contabilizara pontos, o objetivo é refletir sobre a questão/tópico)*Qual modelo vocês utilizaria afinal? Explique<jupyter_code># suas respostas
Provavelmente o modelo RF, por se adequar mais aos resultados obtidos<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11559268643429432, 'fraction_numerical': 0.026295966582209136, 'mean_word_length': 4.813694267515924, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '48831', 'license': 'MIT', 'n_tokens_mistral': 5504, 'n_tokens_neox': 5071, 'n_words': 1227, 'path': 'Regressao_Exercicio.ipynb', 'repo_name': 'Bruno-Messias/data_science_visagio', 'size': '14603'}