Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Um exercício de Machine Learning usando a base "Prudential Life Insurance Assessment" do Kaggle

+2 votos
18 visitas
perguntada Jul 10 em Aprendizagem de Máquinas por Douglas Sad Silveira (111 pontos)  
editado Jul 10 por Douglas Sad Silveira

Em um mundo de compras com um único clique e tudo sob demanda, o processo de inscrição no seguro de vida é antiquado. Os clientes fornecem informações abrangentes para identificar a classificação e elegibilidade de risco, incluindo o agendamento de exames médicos, um processo que leva em média 30 dias.

O resultado? As pessoas estão desligadas. É por isso que apenas 40% dos lares americanos possuem seguro de vida individual. A Prudential quer tornar mais rápida e menos trabalhosa para clientes novos e existentes obterem uma cotação, mantendo os limites de privacidade.

Ao desenvolver um modelo preditivo que classifica com precisão os riscos usando uma abordagem mais automatizada, você pode impactar significativamente a percepção pública do setor.

Os resultados ajudarão a Prudential a entender melhor o poder preditivo dos pontos de dados na avaliação existente, permitindo-nos simplificar significativamente o processo.

acesse o link do kaggle aqui

Compartilhe

4 Respostas

+2 votos
respondida Jul 10 por Stuart Mill (1,079 pontos)  
editado Jul 10 por Stuart Mill

Parte III - Rodando os modelos com as variáveis selecionadas
Com isso em mãos, rodo os modelos para cada seleção de variáveis:
[Tentei fazer com um loop, para ficar mais elegante, mas não consegui. Se alguém conseguir, deixaria o código mais conciso. No entanto, executar cada parte em separado permite ter mais controle do que está acontecendo.]

  lasso_alfa1 = lista_lasso[0]
    lasso_alfa01 = lista_lasso[1]
    lasso_alfa001 = lista_lasso[2]
    lasso_alfa0001 = lista_lasso[3]
    lasso_alfa00001 = lista_lasso[4]
    lasso_alfa000001 = lista_lasso[5]

    #Baseline:
    X_train_lasso = X_train.copy()
    y_train_lasso = y_train.copy()
    X_test_lasso = X_test.copy()
    y_test_lasso = y_test.copy()

    X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                          y_train_lasso,
                                                          test_size = 0.25,
                                                          random_state = 201)
    print("Testando Baseline (sem LASSO):")
    bateria_testes()
    sep()

    # Alfa = 1
    X_train_lasso = X_train.copy()
    y_train_lasso = y_train.copy()
    X_test_lasso = X_test.copy()
    y_test_lasso = y_test.copy()
    X_train_lasso = X_train_lasso[lasso_alfa1]
    X_test_lasso = X_test_lasso[lasso_alfa1]
    X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                          y_train_lasso,
                                                          test_size = 0.25,
                                                          random_state = 201)
    print("alfa=1")
    bateria_testes()
    sep()

    # Alfa = 0.1
    X_train_lasso = X_train.copy()
    y_train_lasso = y_train.copy()
    X_test_lasso = X_test.copy()
    y_test_lasso = y_test.copy()
    X_train_lasso = X_train_lasso[lasso_alfa01]
    X_test_lasso = X_test_lasso[lasso_alfa01]
    X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                          y_train_lasso,
                                                          test_size = 0.25,
                                                          random_state = 201)
    print("alfa=0.1")
    bateria_testes()
    sep()

    # Alfa = 0.01
    X_train_lasso = X_train.copy()
    y_train_lasso = y_train.copy()
    X_test_lasso = X_test.copy()
    y_test_lasso = y_test.copy()
    X_train_lasso = X_train_lasso[lasso_alfa001]
    X_test_lasso = X_test_lasso[lasso_alfa001]
    X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                          y_train_lasso,
                                                          test_size = 0.25,
                                                          random_state = 201)
    print("alfa=0.01")
    bateria_testes()
    sep()

    # Alfa = 0.001
    X_train_lasso = X_train.copy()
    y_train_lasso = y_train.copy()
    X_test_lasso = X_test.copy()
    y_test_lasso = y_test.copy()
    X_train_lasso = X_train_lasso[lasso_alfa0001]
    X_test_lasso = X_test_lasso[lasso_alfa0001]
    X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                          y_train_lasso,
                                                          test_size = 0.25,
                                                          random_state = 201)
    print("alfa=0.001")
    bateria_testes()
    sep()

    # Alfa = 0.0001
    X_train_lasso = X_train.copy()
    y_train_lasso = y_train.copy()
    X_test_lasso = X_test.copy()
    y_test_lasso = y_test.copy()
    X_train_lasso = X_train_lasso[lasso_alfa00001]
    X_test_lasso = X_test_lasso[lasso_alfa00001]
    X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                          y_train_lasso,
                                                          test_size = 0.25,
                                                          random_state = 201)
    print("alfa=0.0001")
    bateria_testes()
    sep()

    # Alfa = 0.00001
    X_train_lasso = X_train.copy()
    y_train_lasso = y_train.copy()
    X_test_lasso = X_test.copy()
    y_test_lasso = y_test.copy()
    X_train_lasso = X_train_lasso[lasso_alfa000001]
    X_test_lasso = X_test_lasso[lasso_alfa000001]
    X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                          y_train_lasso,
                                                          test_size = 0.25,
                                                          random_state = 201)
    print("alfa=0.00001")
    bateria_testes()
    sep()

Pelo critério da parcimônia, selecionamos as variáveis associadas ao alfa=0.01, que seleciona algumas variáveis (evitando overfitting no futuro), e tem uma performance superior aos alfas maiores e parecida com os menores.

+1 voto
respondida Jul 10 por Douglas Sad Silveira (111 pontos)  
editado Jul 10 por Douglas Sad Silveira

[Parte I - Buscando o Melhor Score]

A variável "Response" é a que queremos prever. Ela é dividida em 8 categorias (1 a 8), isto é, y = 1,2,3,4,5,6,7,8.

Tipicamente, inicia-se a avaliação da base de dados a partir de uma análise descritiva do conjunto de variáveis que a compõe. Desta forma, temos:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import style
import seaborn as sns

train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')

df=train_df.copy()

train_df.info() # para saber se as características são object, int ou float

A imagem será apresentada aqui.

A base possui um total de 128 variáveis, sendo "Response" a que queremos prever. O próximo passo é avaliar a existência de missing data.

Tratamento de Missing Values

# GRÁFICO PARA VISUALIZAR A % DE MISSING VALUES (features) NOS DADOS DE TREINO
missing= df.isnull().sum()[df.isnull().sum() !=0]
missing=pd.DataFrame(missing.reset_index())
missing.rename(columns={'index':'features',0:'missing_count'},inplace=True)
missing['missing_count_percentage']=((missing['missing_count'])/59381)*100
plt.figure(figsize=(7,3))
sns.barplot(y=missing['features'],x=missing['missing_count_percentage'])

A imagem será apresentada aqui.

Variáveis Contínuas: EmploymentInfo146
InsuranceHistory5
FamilyHist2-3-4-5

Variáveis discretas: MedicalHistory1,
MedicalHistory10,
MedicalHistory15,
MedicalHistory24,
MedicalHistory32

A estratégia adotada será remover linhas com missing values e ver como o
modelo performa. Podemos escolher a forma de substituir os missing values com:

(a) média;
(b) mediana;
(c) moda.

Antes de decidir sobre isso, vamos ver a distribuição dos dados pelo respectivo
boxplot.

Tratamento dos Outliers

plt.plot(figsize=(15,10))
sns.boxplot(df['Employment_Info_1'])

A imagem será apresentada aqui.

EmploymentInfo1 parece ter muitos outliers - talvez o mais adequado seja
utilizar a mediana para substituir os NA tanto na amostra de treino quanto
de teste.

train_df['Employment_Info_1'].isna().sum()
test_df['Employment_Info_1'].isna().sum()

train_df['Employment_Info_1'].fillna(train_df['Employment_Info_1'].median(),inplace=True) 

test_df['Employment_Info_1'].fillna(test_df['Employment_Info_1'].median(),inplace=True) 

## PARA CONFERIR SE NÃO HÁ NENHUM N/A ##

train_df['Employment_Info_1'].isna().sum()

test_df['Employment_Info_1'].isna().sum()

train_df['Employment_Info_1'].describe()

A imagem será apresentada aqui.

sns.boxplot(train_df['Employment_Info_4'])

A imagem será apresentada aqui.

EmploymentInfo4 é centrada em zero, mas tem muitos outliers.

train_df['Employment_Info_4'].fillna(train_df['Employment_Info_4'].median(),inplace=True)
test_df['Employment_Info_4'].fillna(test_df['Employment_Info_4'].median(),inplace=True) 

sns.boxplot(traindf['EmploymentInfo_6'])
A imagem será apresentada aqui.

Como não há outliers em 'EmploymentInfo6' , a média pode ser uma proxy para os N/A:

train_df['Employment_Info_6'].fillna(train_df['Employment_Info_6'].mean(),inplace=True)
test_df['Employment_Info_6'].fillna(test_df['Employment_Info_6'].mean(),inplace=True)

sns.boxplot(y=train_df['Medical_History_1'])

A imagem será apresentada aqui.

train_df['Medical_History_1'].fillna(train_df['Medical_History_1'].median(),inplace=True)
test_df['Medical_History_1'].fillna(test_df['Medical_History_1'].median(),inplace=True)

Fazendo o drop das variáveis com muitos missing values

train_df.drop(['Medical_History_10','Medical_History_15','Medical_History_24','Medical_History_32','Family_Hist_3','Family_Hist_5','Family_Hist_2','Family_Hist_4'],axis=1,inplace=True)
test_df.drop(['Medical_History_10','Medical_History_15','Medical_History_24','Medical_History_32','Family_Hist_3','Family_Hist_5','Family_Hist_2','Family_Hist_4'],axis=1,inplace=True)
train_df.isnull().sum()[train_df.isnull().sum()!=0]


 sns.boxplot(y=train_df['Insurance_History_5'])

A imagem será apresentada aqui.

Substituindo pela mediana

train_df['Insurance_History_5'].fillna(train_df['Insurance_History_5'].median(),inplace=True)
test_df['Insurance_History_5'].fillna(test_df['Insurance_History_5'].median(),inplace=True)

train_df.isnull().sum()

Todos os missing NA values foram devidamente tratados. Agora, podemos iniciar o próximo passo, que é converter as características do tipo string em valores (dados) numéricos. É o caso de 'ProductInfo2':

train_df.info(object)
train_df['Product_Info_2'].unique()

A imagem será apresentada aqui.

Utiliza-se o LabelEncoder para a conversão:

from sklearn.preprocessing import LabelEncoder
le=LabelEncoder()
train_df['Product_Info_2']=le.fit_transform(train_df['Product_Info_2'])
test_df['Product_Info_2']=le.transform(test_df['Product_Info_2'])

train_df['Product_Info_2'].unique()

Que transforma a variável em:

A imagem será apresentada aqui.

O próximo passo foi fazer a separação das variáveis independentes e a dependente ('Response'). Também optou-se por fazer o drop de "Id"

X_train=train_df.iloc[:,0:-1]
y_train=train_df['Response']
X_train.drop('Id',axis=1,inplace=True)

X_train.head()

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X_train,y_train)

y_train.unique()

from sklearn.metrics import accuracy_score,confusion_matrix
from sklearn.model_selection import cross_val_score,GridSearchCV
from sklearn.multiclass import OneVsRestClassifier

Feito isso, podemos começar a estimar o score de alguns modelos. A ver:

Árvore de Decisão

from sklearn.tree import DecisionTreeClassifier
param_grid={'max_depth':range(1,20,2)}
DT=DecisionTreeClassifier()
clf_DT=GridSearchCV(DT,param_grid,cv=10,scoring='accuracy',n_jobs=-1).fit(X_train,y_train)
y_pred=clf_DT.predict(X_test)
print(accuracy_score(y_test,y_pred))

Que nos retorna um score de 0.5189950154923885.

Random Forest

from sklearn.ensemble import RandomForestClassifier
param_grid={'max_depth':range(1,20,2)}
RF=RandomForestClassifier()
clf_rf=GridSearchCV(RF,param_grid,cv=10,scoring='accuracy',n_jobs=-1).fit(X_train,y_train)
y_pred=clf_rf.predict(X_test)
accuracy_score(y_test,y_pred)

cujo score é 0.5041762090798868

Ridge Regression

Para avaliar a performance da Ridge Regression, podemos partir pra uma modelagem distinta da apresentada anteriormente.

from collections import Counter
import numpy as np
from scipy import stats
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import Ridge

Leitura dos Dados

Dividir os dados do input em 4 classes distintas de variáveis, dado que as
formas de tratamento é diferente pra cada uma:
i) categórica
ii) Contínua
iii)discreta
iv) dummy

train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')

TRAIN_DATA=train_df.copy()
TEST_DATA=test_df.copy()


CATEGORICAL_COLUMNS = ["Product_Info_1", "Product_Info_2", "Product_Info_3", "Product_Info_5", "Product_Info_6",\
                       "Product_Info_7", "Employment_Info_2", "Employment_Info_3", "Employment_Info_5", "InsuredInfo_1",\
                       "InsuredInfo_2", "InsuredInfo_3", "InsuredInfo_4", "InsuredInfo_5", "InsuredInfo_6", "InsuredInfo_7",\
                       "Insurance_History_1", "Insurance_History_2", "Insurance_History_3", "Insurance_History_4", "Insurance_History_7",\
                       "Insurance_History_8", "Insurance_History_9", "Family_Hist_1", "Medical_History_2", "Medical_History_3",\
                       "Medical_History_4", "Medical_History_5", "Medical_History_6", "Medical_History_7", "Medical_History_8",\
                       "Medical_History_9", "Medical_History_11", "Medical_History_12", "Medical_History_13", "Medical_History_14",\
                       "Medical_History_16", "Medical_History_17", "Medical_History_18", "Medical_History_19", "Medical_History_20",\
                       "Medical_History_21", "Medical_History_22", "Medical_History_23", "Medical_History_25", "Medical_History_26",\
                       "Medical_History_27", "Medical_History_28", "Medical_History_29", "Medical_History_30", "Medical_History_31",\
                       "Medical_History_33", "Medical_History_34", "Medical_History_35", "Medical_History_36", "Medical_History_37",\
                       "Medical_History_38", "Medical_History_39", "Medical_History_40", "Medical_History_41"]

CONTINUOUS_COLUMNS = ["Product_Info_4", "Ins_Age", "Ht", "Wt", "BMI",
                      "Employment_Info_1", "Employment_Info_4", "Employment_Info_6",
                      "Insurance_History_5", "Family_Hist_2", "Family_Hist_3", "Family_Hist_4", "Family_Hist_5"]
DISCRETE_COLUMNS = ["Medical_History_1", "Medical_History_10", "Medical_History_15", "Medical_History_24", "Medical_History_32"]
DUMMY_COLUMNS = ["Medical_Keyword_{}".format(i) for i in range(1, 48)]

categorical_data = pd.concat([TRAIN_DATA[CATEGORICAL_COLUMNS], TEST_DATA[CATEGORICAL_COLUMNS]])
continuous_data = pd.concat([TRAIN_DATA[CONTINUOUS_COLUMNS], TEST_DATA[CONTINUOUS_COLUMNS]])
discrete_data = pd.concat([TRAIN_DATA[DISCRETE_COLUMNS], TEST_DATA[DISCRETE_COLUMNS]])
dummy_data = pd.concat([TRAIN_DATA[DUMMY_COLUMNS], TEST_DATA[DUMMY_COLUMNS]])

Tratamento dos Dados

Variáveis Categóricas

Do total de 128 colunas, 60 representam variáveis categóricas:

ProductInfo1, ProductInfo2, ProductInfo3, ProductInfo5,
ProductInfo6, ProductInfo7,

EmploymentInfo2, EmploymentInfo3, EmploymentInfo5,

InsuredInfo1, InsuredInfo2, InsuredInfo3, InsuredInfo4, InsuredInfo5,
InsuredInfo
6, InsuredInfo_7,

InsuranceHistory1, InsuranceHistory2, InsuranceHistory3,
InsuranceHistory4, InsuranceHistory7, InsuranceHistory8,
InsuranceHistory9,

FamilyHist1, MedicalHistory2, MedicalHistory3, MedicalHistory4,
MedicalHistory5, MedicalHistory6, MedicalHistory7, MedicalHistory8,
MedicalHistory9, MedicalHistory11, MedicalHistory12, MedicalHistory13,
MedicalHistory14, MedicalHistory16, MedicalHistory17, MedicalHistory18,
MedicalHistory19, MedicalHistory20, MedicalHistory21, MedicalHistory22,
MedicalHistory23, MedicalHistory25, MedicalHistory26, MedicalHistory27,
MedicalHistory28, MedicalHistory29, MedicalHistory30, MedicalHistory31,
MedicalHistory33, MedicalHistory34, MedicalHistory35, MedicalHistory36,
MedicalHistory37, MedicalHistory38, MedicalHistory39, MedicalHistory40,
MedicalHistory41

def plot_categoricals(data):
    ncols = len(data.columns)
    fig = plt.figure(figsize=(5 * 5, 5 * (ncols // 5 + 1)))
    for i, col in enumerate(data.columns):
        cnt = Counter(data[col])
        keys = list(cnt.keys())
        vals = list(cnt.values())
        plt.subplot(ncols // 5 + 1, 5, i + 1)
        plt.bar(range(len(keys)), vals, align="center")
        plt.xticks(range(len(keys)), keys)
        plt.xlabel(col, fontsize=10)
        plt.ylabel("frequência", fontsize=10)
    fig.tight_layout()
    plt.show()

plot_categoricals(categorical_data)

O comando acima plota todas as variáveis categóricas. Aqui, para fins de ilustração, apresentaremos apenas duas:

A imagem será apresentada aqui.
Para manipular as variáveis categóricas com as scikit-learn built in functions
foi necessário transformar elas em dummy usando o 'pandas.get_dummies'. Ai,
podemos notar também que não há missing values nos dados categóricos.

# pra usar o get_dummies é preciso converter para string

categorical_data = categorical_data.applymap(str)  

categorical_data = pd.get_dummies(categorical_data, drop_first=True)

Variáveis Contínuas

Correspondem às seguintes 13 colunas:

ProductInfo4, InsAge, Ht, Wt, BMI, EmploymentInfo1, EmploymentInfo4,
Employment
Info6, InsuranceHistory5, FamilyHist2, FamilyHist3,
Family
Hist4, FamilyHist_5

# Plotando as variáveis contínuas

def plot_histgrams(data):
    ncols = len(data.columns)
    fig = plt.figure(figsize=(4 * 4, 5 * (ncols // 5 + 1)))
    for i, col in enumerate(data.columns):
        X = data[col].dropna()
        plt.subplot(ncols // 5 + 1, 5, i + 1)
        plt.hist(X, bins=20, alpha=0.5, \
                 edgecolor="black", linewidth=1)
        plt.xlabel(col, fontsize=12)
        plt.ylabel("frequência", fontsize=12)
    fig.tight_layout()
    plt.show()

plot_histgrams(continuous_data)    

O comando acima plota todas as contínuas. Aqui apresentaremos apenas duas, em função de sua assimetria:

A imagem será apresentada aqui.

Como algumas variáveis são distribuídas de forma bastante assimétrica, será
aplicada a transformação de Box-Cox. Assim, cada coluna é normalizada, com
cada missing value assumindo valor igual a zero...depois podemos testar outras
formas de substituir os missing values.

Transformação Box-Cox nas variáveis contínuas

def preproc_quantitatives(X):

    Y = X.copy()

    # transformaçao Box-Cox nos non-missing values
    not_missing = Y[~Y.isnull()].copy()
    not_missing = not_missing - np.min(not_missing) + 1e-10  # para evitar erros com valores não positivos
    res = stats.boxcox(not_missing)
    Y[~Y.isnull()] = res[0]

Variáveis discretas

Foram tratadas da mesma forma que as variáveis continuas (por simplicidade)
Correspondem às seguintes colunas (5):

MedicalHistory1, MedicalHistory10, MedicalHistory15, MedicalHistory24,
MedicalHistory32

# transformação  das variáveis discretas
for col in discrete_data.columns:
    discrete_data[col] = preproc_quantitatives(discrete_data[col])

# plotando as variáveis discretas
plot_histgrams(discrete_data)    

Ridge Regression

Como exemplo, vou começar com a para prever a nossa variável
de interesse. Antes da previsão, será feita uma bateria de experimentos para
decidir qual das características devem ser utilizadas ou não, bem como para
"setar" o valor de alpha

# normalizando os non-missing values
    mu = np.mean(Y[~Y.isnull()])
    sigma = Y[~Y.isnull()].std()
    Y = (Y - mu) / sigma

    # Substituindo os missing values (aqui, depois podemos testar a média pra ver como fica)
    Y[Y.isnull()] = 0.0

    return Y

# Pre processando os dados continuos
for col in continuous_data.columns:
    continuous_data[col] = preproc_quantitatives(continuous_data[col])

plot_histgrams(continuous_data)

Desta forma, do conjunto dos dados, foram utilizadas 40000 observações (linhas)
para o treino e 10000 obs para o teste (train, test) = (0.8, 0.2), retiradas
da variável TRAIN_DATA

# Habilitando teste de vários alphas para a Ridge Regression
# rodar todo o bloco abaixo para gerar o grafico corretamente

configs = {'var. quantitativas' : pd.concat([continuous_data, discrete_data], axis = 1),
           'var. qualitativas' : pd.concat([categorical_data, dummy_data], axis = 1),
           'todas as características' : pd.concat([continuous_data, discrete_data, categorical_data, dummy_data], axis = 1)}

errors_dict = {}

y = TRAIN_DATA['Response']
for title, X in configs.items():
    X_train = X[:40000]
    X_test = X[40000:50000]
    y_train = y[:40000]
    y_test = y[40000:50000]
    alphas = [0.1, 1.0, 10.0, 100.0, 1000.0]
    errors = []

    for alpha in alphas:
        model = Ridge(alpha=alpha)
        model.fit(X_train, y_train)
        z = model.predict(X_test)
        error = np.sqrt(np.sum((y_test - z) * (y_test - z)) / (1.0 * len(y_test)))
        errors.append(error)
    errors_dict[title] = errors

errors_dict = pd.DataFrame(data=errors_dict)


plt.plot(alphas, errors_dict)
plt.xlabel("alpha", fontsize=12)
plt.ylabel("(MSE)^1/2", fontsize=12)
plt.title('Experimentos - Ridge Regression', fontsize=12)
plt.legend(errors_dict.columns)
plt.xscale('log')
plt.show()

A imagem será apresentada aqui.

A partir dos experimentos com a Ridge Regression, que mostra que o MSE para
várias combinações possíveis, foi possível notar que o menor MSE é aquele em
que se utiliza todas as características, considerando alpha = 10.0

Previsão

o código a seguir prevê a variável de interesse para a base de dados reservadas
para o teste e gera o arquivo de submissão ao kaggle no formato (csv).

# Previsão para o "test set" e submissão ao kaggle

X = pd.concat([continuous_data, discrete_data, categorical_data, dummy_data], axis = 1)
X_train = X[:len(y)]
X_test = X[len(y):]

model = Ridge(alpha=10.0)
model.fit(X_train, y)
z = model.predict(X_test)
z

z = np.round(z)
z[z < 1] = 1
z[z > 8] = 8
z = z.astype(np.int64)


df = pd.DataFrame(data={'Id' : TEST_DATA['Id'], 'Response' : z})
df.to_csv('submit_ridge_1.csv', index=False)


# plot histgram of scores in leaderboard

data = pd.read_csv("/Users/Douglas/Desktop/MCE - UnB/Seguro//prudential-life-insurance-assessment-publicleaderboard.csv")

plt.hist(data["Score"], bins=20, alpha=0.5, color="green", \
         edgecolor="black", linewidth=2.0)
plt.xlabel('Score', fontsize=18)
plt.ylabel('Frequência', fontsize=18)
plt.title('Score Geral em 04/07/2019', fontsize=16)
plt.xlim([-0.5, 0.8])
plt.axvline(0.55443, color='b', linestyle='dashed', linewidth=2)
plt.show()

A imagem será apresentada aqui.

Note que a Ridge Regression apresentou o melhor score = 0.55443.

+1 voto
respondida Jul 10 por Stuart Mill (1,079 pontos)  
editado Jul 10 por Stuart Mill

[ Parte II - Seleção de Variáveis]

Após os tratamentos dos dados realizados na seção anterior, procedemos a uma seleção de variáveis utilizando o LASSO. Criamos uma função que recebe um grid de valores para o parâmetro \( \alpha \) do LASSO e cria um dicionário com as features selecionadas e seus coeficientes (necessariamente não nulos) e uma lista contendo as listas desses coeficientes (para serem usados depois nos modelos).

 #LASSO com vários alfas
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import Lasso
import xgboost as xgb
from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LinearRegression,Ridge,Lasso,RidgeCV

lista_lasso = []
#coef_dict_baseline = {}
#Grid pro LASSO
def gridlasso(lista):
    for i in lista:
        print("Resultados para alfa= " + str(i))# + ". Contador = " + str(counter))
        lasso = Lasso(alpha=i, max_iter = 10e5) #, normalize = True)
        lasso.fit(X_train,y_train)
        train_score=lasso.score(X_train,y_train)
        test_score=lasso.score(X_test,y_test)
        coeff_used = np.sum(lasso.coef_!=0)
        print("training score:", train_score)
        print("test score: ", test_score)
        print("number of features used: ", coeff_used)
        coef_dict_baseline = {}
        # Criando um dicionário com as features e coeficientes nao nulos
        for coef, feat in zip(lasso.coef_,X_train.columns):
           if not(coef==0):
               coef_dict_baseline[feat] = coef
        # Criando uma lista com as variáveis selecionadas em cada 
        #iteração do grid e adicionando à lista global do grid.
        listavars = [k for k in coef_dict_baseline.keys()]
        lista_lasso.append(listavars)

        print(coef_dict_baseline)



#        for i in coef_dict_baseline:
#            if not i==0:
#                print(coef_dict_baseline)
        print("----------------------------------------------------------------")

Em seguida, definimos a variável do grid, inserindo-a na função gridlasso( ), para em seguida observar os resultados (variáveis selecionadas) para cada \(\alpha\):

grid = [1,0.1,0.01,0.001,0.0001,0.00001]
gridlasso(grid)
counter = 1
for i in lista_lasso:
    print("----------------------------------------------------")
    print("Variáveis selecionadas para a iteração do grid número:  " + str(counter))
    print(i) # Ou seja, lista_lasso[0] está associada a alfa=1 e assim por diante, de acordo com a variável grid
    counter = counter + 1
    print("----------------------------------------------------")

O resultado do último loop é o mais relevante, e será mostrado abaixo:

----------------------------------------------------
Variáveis selecionadas para a iteração do grid número:  1
['Medical_History_2', 'Medical_History_1']
----------------------------------------------------
----------------------------------------------------
Variáveis selecionadas para a iteração do grid número:  2
['Medical_History_16', 'Medical_History_33', 'Product_Info_3', 'Product_Info_2', 'Medical_History_1', 'Medical_History_23', 'Medical_History_4', 'Product_Info_4', 'InsuredInfo_6', 'Medical_History_39', 'Medical_History_13', 'Medical_History_2', 'Employment_Info_2', 'Medical_History_6']
----------------------------------------------------
----------------------------------------------------
Variáveis selecionadas para a iteração do grid número:  3
['InsuredInfo_3', 'Medical_History_16', 'Medical_History_5', 'Medical_History_20', 'Insurance_History_2', 'Medical_History_31', 'Medical_History_28', 'InsuredInfo_7', 'Product_Info_2', 'Medical_History_23', 'Medical_Keyword_37', 'Ins_Age', 'Medical_History_27', 'InsuredInfo_6', 'Medical_History_30', 'Insurance_History_3', 'Medical_History_13', 'InsuredInfo_1', 'Product_Info_4', 'BMI', 'Employment_Info_2', 'Medical_History_4', 'Insurance_History_1', 'Product_Info_3', 'Medical_History_19', 'Product_Info_6', 'Medical_History_33', 'Medical_History_18', 'Employment_Info_3', 'Medical_History_1', 'Medical_History_6', 'Medical_Keyword_3', 'Medical_History_3', 'InsuredInfo_5', 'Medical_History_40', 'Medical_Keyword_25', 'Medical_History_39', 'Medical_History_2', 'Medical_History_41', 'Family_Hist_1']
----------------------------------------------------
----------------------------------------------------
Variáveis selecionadas para a iteração do grid número:  4
['Medical_History_5', 'Medical_History_28', 'Insurance_History_4', 'Medical_History_29', 'Medical_Keyword_12', 'Medical_History_21', 'Ins_Age', 'InsuredInfo_6', 'Insurance_History_2', 'BMI', 'Medical_History_12', 'Medical_History_4', 'Medical_Keyword_22', 'Medical_Keyword_14', 'Product_Info_6', 'Medical_Keyword_38', 'Medical_Keyword_6', 'Employment_Info_2', 'Product_Info_7', 'Medical_History_20', 'Medical_History_38', 'Medical_History_3', 'Medical_Keyword_10', 'Employment_Info_5', 'Medical_History_18', 'Medical_Keyword_25', 'Medical_Keyword_33', 'Medical_History_16', 'Medical_Keyword_9', 'Medical_History_36', 'Medical_Keyword_45', 'Product_Info_5', 'InsuredInfo_4', 'Medical_Keyword_40', 'Insurance_History_1', 'Medical_History_23', 'InsuredInfo_2', 'Medical_Keyword_2', 'Medical_Keyword_47', 'Medical_History_37', 'Employment_Info_6', 'Medical_History_33', 'Medical_Keyword_28', 'Medical_Keyword_3', 'Wt', 'Medical_History_35', 'Medical_Keyword_37', 'Medical_Keyword_41', 'Medical_History_2', 'Medical_History_17', 'Medical_Keyword_19', 'Medical_Keyword_7', 'Medical_History_14', 'Product_Info_2', 'Product_Info_1', 'Medical_Keyword_15', 'Medical_History_30', 'InsuredInfo_1', 'Medical_Keyword_18', 'Medical_Keyword_46', 'Product_Info_3', 'Medical_History_19', 'Insurance_History_8', 'Medical_Keyword_27', 'Medical_History_6', 'Medical_History_7', 'Medical_Keyword_34', 'Insurance_History_9', 'Medical_History_22', 'Medical_History_31', 'InsuredInfo_7', 'Medical_Keyword_4', 'Medical_Keyword_39', 'Medical_Keyword_31', 'Medical_History_34', 'InsuredInfo_5', 'Medical_Keyword_24', 'Insurance_History_3', 'Medical_History_39', 'Medical_History_13', 'Medical_History_40', 'Medical_History_27', 'Medical_History_8', 'Medical_Keyword_17', 'Medical_History_41', 'Employment_Info_3', 'Medical_History_1', 'Product_Info_4', 'Medical_History_11', 'Insurance_History_7', 'Medical_Keyword_20', 'InsuredInfo_3', 'Medical_Keyword_26', 'Medical_Keyword_29', 'Family_Hist_1']
----------------------------------------------------
----------------------------------------------------
Variáveis selecionadas para a iteração do grid número:  5
['Medical_History_25', 'Medical_History_5', 'Medical_History_28', 'Insurance_History_3', 'Insurance_History_4', 'Medical_History_38', 'Medical_Keyword_12', 'Medical_History_21', 'Ins_Age', 'InsuredInfo_6', 'Insurance_History_2', 'Medical_Keyword_30', 'BMI', 'Medical_History_12', 'Medical_History_4', 'Medical_Keyword_19', 'Medical_Keyword_22', 'Medical_History_26', 'Medical_Keyword_14', 'Product_Info_6', 'Medical_Keyword_38', 'Medical_Keyword_6', 'Employment_Info_2', 'Product_Info_7', 'Medical_History_20', 'Medical_History_29', 'Medical_History_3', 'Medical_Keyword_10', 'Employment_Info_5', 'Medical_History_18', 'Medical_Keyword_25', 'Medical_Keyword_33', 'Medical_History_16', 'Medical_History_9', 'Medical_Keyword_9', 'Medical_History_36', 'Medical_Keyword_45', 'Product_Info_5', 'InsuredInfo_4', 'Medical_Keyword_40', 'Insurance_History_1', 'Medical_History_23', 'Ht', 'InsuredInfo_2', 'Medical_Keyword_2', 'Medical_Keyword_47', 'Medical_History_37', 'Employment_Info_6', 'Medical_History_33', 'Medical_Keyword_28', 'Medical_Keyword_3', 'Wt', 'Medical_History_35', 'Medical_Keyword_37', 'Medical_Keyword_41', 'Medical_History_2', 'Medical_Keyword_1', 'Medical_History_17', 'InsuredInfo_3', 'Medical_Keyword_7', 'Medical_Keyword_35', 'Medical_History_14', 'Product_Info_2', 'Product_Info_1', 'Medical_Keyword_13', 'Medical_Keyword_21', 'Medical_History_30', 'InsuredInfo_1', 'Medical_Keyword_43', 'Medical_Keyword_18', 'Medical_Keyword_46', 'Product_Info_3', 'Medical_History_19', 'Insurance_History_8', 'Medical_Keyword_27', 'Medical_History_6', 'Medical_History_7', 'Medical_Keyword_34', 'Insurance_History_9', 'Medical_Keyword_15', 'Medical_History_22', 'Medical_History_31', 'Medical_History_8', 'Employment_Info_4', 'InsuredInfo_7', 'Medical_Keyword_4', 'Medical_Keyword_39', 'Medical_Keyword_31', 'InsuredInfo_5', 'Medical_Keyword_24', 'Medical_Keyword_16', 'Medical_Keyword_26', 'Medical_History_13', 'Medical_Keyword_42', 'Medical_History_40', 'Medical_History_27', 'Medical_Keyword_11', 'Medical_Keyword_5', 'Medical_Keyword_17', 'Medical_History_41', 'Employment_Info_3', 'Medical_History_1', 'Product_Info_4', 'Medical_History_11', 'Insurance_History_7', 'Medical_Keyword_32', 'Medical_Keyword_20', 'Medical_History_34', 'Medical_History_39', 'Family_Hist_1', 'Medical_Keyword_29', 'Employment_Info_1']
----------------------------------------------------
----------------------------------------------------
Variáveis selecionadas para a iteração do grid número:  6
['Medical_History_25', 'Medical_History_5', 'Medical_History_28', 'Insurance_History_3', 'Insurance_History_4', 'Medical_History_38', 'Medical_Keyword_12', 'Medical_History_21', 'Ins_Age', 'InsuredInfo_6', 'Insurance_History_2', 'Medical_Keyword_30', 'BMI', 'Medical_History_12', 'Medical_History_6', 'Medical_Keyword_19', 'Medical_Keyword_22', 'Medical_History_26', 'Medical_Keyword_14', 'Product_Info_6', 'Medical_Keyword_38', 'Medical_Keyword_6', 'Employment_Info_2', 'Product_Info_7', 'Medical_History_20', 'Medical_History_29', 'Medical_History_3', 'Medical_Keyword_48', 'Medical_Keyword_47', 'Medical_Keyword_10', 'Medical_Keyword_23', 'Employment_Info_5', 'Medical_History_18', 'Medical_Keyword_25', 'Medical_Keyword_33', 'Medical_History_16', 'Medical_History_9', 'Medical_Keyword_9', 'Medical_History_36', 'Medical_Keyword_45', 'Product_Info_5', 'InsuredInfo_4', 'Medical_Keyword_40', 'Insurance_History_1', 'Medical_History_23', 'Ht', 'Medical_Keyword_17', 'Medical_Keyword_2', 'Insurance_History_5', 'Medical_History_37', 'Employment_Info_6', 'Medical_History_33', 'Medical_Keyword_28', 'Medical_Keyword_3', 'Wt', 'Medical_History_35', 'Medical_Keyword_37', 'Medical_Keyword_41', 'Medical_History_2', 'Medical_Keyword_1', 'Medical_History_17', 'InsuredInfo_3', 'Medical_Keyword_7', 'Medical_Keyword_35', 'Medical_History_14', 'Product_Info_2', 'Product_Info_1', 'Medical_Keyword_13', 'Medical_Keyword_21', 'Medical_Keyword_36', 'Medical_History_30', 'InsuredInfo_1', 'Medical_Keyword_43', 'Medical_Keyword_18', 'Medical_Keyword_46', 'Product_Info_3', 'Medical_History_19', 'Insurance_History_8', 'Medical_Keyword_27', 'Medical_History_4', 'Medical_History_7', 'Medical_Keyword_34', 'Insurance_History_9', 'Medical_Keyword_15', 'Medical_History_22', 'Medical_History_31', 'Medical_History_8', 'Medical_Keyword_44', 'Employment_Info_4', 'InsuredInfo_7', 'Medical_Keyword_4', 'Medical_Keyword_39', 'Medical_Keyword_31', 'InsuredInfo_5', 'Medical_Keyword_24', 'Medical_Keyword_16', 'Medical_Keyword_26', 'Medical_History_13', 'Medical_Keyword_42', 'Medical_History_40', 'Medical_History_27', 'Medical_Keyword_11', 'Medical_Keyword_5', 'InsuredInfo_2', 'Medical_History_41', 'Employment_Info_3', 'Medical_History_1', 'Product_Info_4', 'Medical_History_11', 'Insurance_History_7', 'Medical_Keyword_32', 'Medical_Keyword_20', 'Medical_History_34', 'Medical_History_39', 'Family_Hist_1', 'Medical_Keyword_29', 'Employment_Info_1']
----------------------------------------------------

Note que conforme \(\alpha \) tende a 0, o LASSO tende a incluir todas as variáveis.

Para a avaliação dos modelos e melhor visualização, importamos mais alguns pacotes e definimos funções auxiliares, fazendo também cópias dos dataframes que serão usados para testar os modelos com cada lista de variáveis selecionada pelo LASSO.

#Outros modelos:
#regression
from sklearn.linear_model import LinearRegression,Ridge,Lasso,RidgeCV
from sklearn.ensemble import RandomForestRegressor,BaggingRegressor,GradientBoostingRegressor,AdaBoostRegressor
from sklearn.svm import SVR
from sklearn.neighbors import KNeighborsRegressor

#model selection
from sklearn.model_selection import train_test_split,cross_validate
from sklearn.model_selection import KFold
from sklearn.model_selection import GridSearchCV

#evaluation metrics
from sklearn.metrics import mean_squared_log_error,mean_squared_error, r2_score,mean_absolute_error # for regression
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score  # for classification

def RMSLE(predictions, realizations):
    predictions_use = predictions.clip(0)
    rmsle = np.sqrt(np.mean(np.array(np.log(predictions_use + 1) - 
                                     np.log(realizations + 1))**2))
    return rmsle
def outros_modelos():
    models=[RandomForestRegressor(),AdaBoostRegressor(),BaggingRegressor(),SVR(),KNeighborsRegressor()]
    model_names=['RandomForestRegressor','AdaBoostRegressor','BaggingRegressor','SVR','KNeighborsRegressor']
    rmsle=[]
    d={}
    for model in range (len(models)):
        clf=models[model]
        clf.fit(X_train_lasso,y_train_lasso)
        test_pred=clf.predict(X_test_lasso)
        rmsle.append(np.sqrt(RMSLE(test_pred,y_test_lasso)))
    d={'Modelling Algo':model_names,'RMSLE':rmsle}   
    print(d)
#outros_modelos()

X_train_lasso = X_train.copy()
y_train_lasso = y_train.copy()
X_test_lasso = X_test.copy()
y_test_lasso = y_test.copy()

X_train_lasso, X_valid, y_train_lasso, y_valid = train_test_split (X_train_lasso,
                                                      y_train_lasso,
                                                      test_size = 0.25,
                                                      random_state = 201) 
def sep():
    print("------------------------------------------------")

Agora, defino uma função que realiza os testes de Random Forest, Decision Tree, Boosted Tre e Regression Tree.

def bateria_testes():
    sep()
    #Random Forest
    # from sklearn.ensemble import RandomForestClassifier
    param_grid={'max_depth':range(1,20,2)}
    RF=RandomForestClassifier()
    clf_rf=GridSearchCV(RF,param_grid,cv=10,scoring='accuracy',n_jobs=-1).fit(X_train_lasso,y_train_lasso)
    y_pred=clf_rf.predict(X_test_lasso)
    print("Acurácia do Random Forest:")
    print(accuracy_score(y_test_lasso,y_pred))   
    # Arvore de Decisão 
    # from sklearn.tree import DecisionTreeClassifier
    param_grid={'max_depth':range(1,20,2)}
    DT=DecisionTreeClassifier()
    clf_DT=GridSearchCV(DT,param_grid,cv=10,scoring='accuracy',n_jobs=-1).fit(X_train_lasso,y_train_lasso)
    y_pred=clf_DT.predict(X_test_lasso)
    print("Acurácia Árvore de Decisão:")
    print(accuracy_score(y_test_lasso,y_pred))

    # Boosted Tree
    xgb_train = xgb.DMatrix(X_train_lasso, label = y_train_lasso)
    xgb_valid = xgb.DMatrix(X_valid)

    num_round_for_cv = 500
    param = {'max_depth':6, 'eta':0.1, 'seed':201, 'objective':'reg:linear'}

    xgb.cv(param,
           xgb_train,
           num_round_for_cv,
           nfold = 5,
           show_stdv = False,
           verbose_eval = False,
           as_pandas = False)

    num_round = 400
    xgb_model = xgb.train(param, xgb_train, num_round)
    xgb_pred  = xgb_model.predict(xgb_valid)
    print("RMSLE Boosted Tree:")
    print(RMSLE(xgb_pred, y_valid))
    plt.figure(figsize=(6,6))
    plt.scatter(xgb_pred, y_valid, s = 0.2)
    plt.xlim(-1,10)
    plt.ylim(-1, 10)
    plt.plot([-1, 10], [-1, 10], color='r', linestyle='-', linewidth=3)
    plt.suptitle('Dados - Previsão x Observados', fontsize=18)
    plt.xlabel('Previsão - Boosted Tree', fontsize = 16)
    plt.ylabel('y_valid', fontsize=16)
    #xgb_model.get_fscore

#    #Outros Modelos
#    print("Outros modelos:")
#    outros_modelos()

    ## Ajustando Regression Tree

    rt = DecisionTreeRegressor(min_samples_split=25, random_state=201)
    rt_model = rt.fit(X_train_lasso, y_train_lasso)
    rt_pred = rt_model.predict(X_valid)

#    pd.DataFrame(rt_model.feature_importances_, index=ind_variables_selected)
#
#    plt.figure(figsize=(6,6))
#    plt.scatter(rt_pred, y_valid, s = 0.2)
#    plt.xlim(-1,10)
#    plt.ylim(-1, 10)
#    plt.plot([-1, 10], [-1, 10], color='red', linestyle='-', linewidth=3)
#    plt.suptitle('Dados - Previsão x Observados', fontsize=18)
#    plt.xlabel('Previsão - Random Tree', fontsize = 16)
#    plt.ylabel('y_valid', fontsize=16)
#    plt.show()
    print("RMSLE Regression Tree:")
    print(RMSLE(rt_pred, y_valid))

    sep()

#def data_frames_set():
#    X_train_lasso = X_train.copy()
#    y_train_lasso = y_train.copy()
#    X_test_lasso = X_test.copy()
#    y_test_lasso = y_test.copy()
#    X_train_lasso, X_valid_lasso, y_train_lasso, y_valid_lasso = train_test_split (X_train_lasso,
#                                                      y_train_lasso,
#                                                      test_size = 0.25,
#                                                      random_state = 201)
0 votos
respondida Jul 10 por Douglas Sad Silveira (111 pontos)  

[ Parte IV - Testando outros critérios de Modelagem]

Ainda sobre a discussão envolvendo a questão da parcimônia/menor erro de previsão, também seria possível implementar:

train_df.head()
train_df.columns.to_series().groupby(train_df.dtypes).groups

    x_train,x_test,y_train,y_test=train_test_split(train_df.drop('Response',axis=1),train_df['Response'],test_size=0.25,random_state=42)
    models=[RandomForestRegressor(),AdaBoostRegressor(),BaggingRegressor(),SVR(),KNeighborsRegressor()]
    model_names=['RandomForestRegressor','AdaBoostRegressor','BaggingRegressor','SVR','KNeighborsRegressor']
    rmsle=[]
    d={}
    for model in range (len(models)):
        clf=models[model]
        clf.fit(x_train,y_train)
        test_pred=clf.predict(x_test)
        rmsle.append(np.sqrt(mean_squared_log_error(test_pred,y_test)))
    d={'Modelling Algo':model_names,'RMSLE':rmsle}   
    print(d)

    rmsle_frame=pd.DataFrame(d)
    rmsle_frame

    sns.factorplot(y='Modelling Algo',x='RMSLE',data=rmsle_frame,kind='bar',size=5,aspect=2)

    sns.factorplot(x='Modelling Algo',y='RMSLE',data=rmsle_frame,kind='point',size=5,aspect=2)

Note que a proporção da amostra de treino/teste foi dada como (0,75, 0.25). Como a base de dados é relativamente extensa e com muitas características a se considerar no critério de seleção (e o código acima não está lá grandes coisas em termos de eficiência!), foi preciso um tempo considerável pra gerar os outputs (em torno de 20 minutos) que apresento a seguir:
A imagem será apresentada aqui.
A imagem será apresentada aqui.

RandomForestRegressor: 0.4384457465703512

AdaBoostRegressor: 0.46118021019209143

BaggingRegressor: 0.43666164150466363

SVR: 0.5501137403743809

KNeighborsRegressor: 0.539663284380064

Os que tiveram menor RMSLE: (i) Bagging (ii) Random Forest

...