Regressão Linear Simples - Trabalho

Estudo de caso: Seguro de automóvel sueco

Agora, sabemos como implementar um modelo de regressão linear simples. Vamos aplicá-lo ao conjunto de dados do seguro de automóveis sueco. Esta seção assume que você baixou o conjunto de dados para o arquivo insurance.csv, o qual está disponível no notebook respectivo.

O conjunto de dados envolve a previsão do pagamento total de todas as reclamações em milhares de Kronor sueco, dado o número total de reclamações. É um dataset composto por 63 observações com 1 variável de entrada e 1 variável de saída. Os nomes das variáveis são os seguintes:

  1. Número de reivindicações.
  2. Pagamento total para todas as reclamações em milhares de Kronor sueco.

Voce deve adicionar algumas funções acessórias à regressão linear simples. Especificamente, uma função para carregar o arquivo CSV chamado load_csv (), uma função para converter um conjunto de dados carregado para números chamado str_column_to_float (), uma função para avaliar um algoritmo usando um conjunto de treino e teste chamado split_train_split (), a função para calcular RMSE chamado rmse_metric () e uma função para avaliar um algoritmo chamado evaluate_algorithm().

Utilize um conjunto de dados de treinamento de 60% dos dados para preparar o modelo. As previsões devem ser feitas nos restantes 40%.

Compare a performabce do seu algoritmo com o algoritmo baseline, o qual utiliza a média dos pagamentos realizados para realizar a predição ( a média é 72,251 mil Kronor).


In [441]:
#Bibliotecas 
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split

In [442]:
#Carrega os dados
dataset = pd.read_csv('insurance.csv', names=['Reclamações','Kronor'])
dataset.head()


Out[442]:
Reclamações Kronor
0 108 392.5
1 19 46.2
2 13 15.7
3 124 422.2
4 40 119.4

In [443]:
#Classe da regressão linear univariada
class simple_linear_regression(object):
    
    def __init__(self):
        self.b0 = None
        self.b1 = None
    
    def fit(self,train):
        self.b0, self.b1 = self.coefficients(train)
        
    def predict(self, test):
        predictions = []
        for row in test:
            ypred = self.b0 + self.b1 * row
            predictions.append(ypred)
        return predictions
    
    # Calculate coefficients
    def coefficients(self, dataset):
        x = dataset.iloc[:,0]
        y = dataset.iloc[:,1]
        x_mean, y_mean = self.mean(x), self.mean(y)
        b1 = self.covariance(x, x_mean, y, y_mean) / self.variance(x, x_mean)
        b0 = y_mean - b1 * x_mean
        return [b0, b1]
    
    # Calculate covariance between x and y
    def covariance(self, x, mean_x, y, mean_y):
        covar = 0.0
        for i in range(len(x)):
            covar += (x.iloc[i] - mean_x) * (y.iloc[i] - mean_y)
        return covar
    
    # Calculate the variance of a list of numbers
    def variance(self, values, mean):
        return sum([(x-mean)**2 for x in values])

    # Calculate the mean value of a list of numbers
    def mean(self, values):
        return sum(values) / float(len(values))

In [444]:
#Separa o dataset em teste e treino
data_train, data_test = train_test_split(dataset, test_size=0.40)
#Separa os dados de teste em X e y
X_test = data_test.iloc[:,0]
y_test = data_test.iloc[:,1]
y_list = y_test.tolist()

In [445]:
#Executa a regressão linear e prediz os valores para X_test
lr = simple_linear_regression()
lr.fit(data_train)
predict = lr.predict(X_test)

In [446]:
from math import sqrt

# Calculate root mean squared error
def rmse_metric(actual, predicted):
    sum_error = 0.0
    for i in range(len(actual)):
        prediction_error = predicted[i] - actual[i]
        sum_error += (prediction_error ** 2)
        mean_error = sum_error / float(len(actual))
    return sqrt(mean_error)

In [447]:
#Calcula o RMSE para o algoritmo de regressão
rmse_reg = rmse_metric(y_list,predict)

In [448]:
import bisect as bs

#Definição da função smart_mean
#Essa função faz uma aproximação linear entre os dois valores mais próximos, no conjunto de treino, 
#em relação a amostra de teste
def smart_mean(data_train,test):
    data_sort = data_train.sort_values(data_train.columns[0], ascending = True)
    X_train = (data_sort.iloc[:,0]).tolist()
    y_train = (data_sort.iloc[:,1]).tolist()
    predict = []
    for x in test:
        bigger = bs.bisect_right(X_train,x)
        smaller = bs.bisect_left(X_train,x)
        if(bigger > len(X_train)-1):
            valuePredict = (x*y_train[smaller-1])/X_train[smaller-1]
        else:
            dif_x = (X_train[bigger] - X_train[smaller])
            if(dif_x != 0):
                incValue = (y_train[bigger] - y_train[smaller]) / dif_x
                valuePredict = y_train[smaller] + dif_x*incValue
            else:
                valuePredict = y_train[smaller]
        predict.append(valuePredict)
    return predict

#Definição da função baseline, prediz que todos os valores são a média dos dados de treino
def baseline(y_train, test):
    meanValue = np.mean(y_train)
    predictions = [meanValue for i in range(len(test))]
    return predictions

In [449]:
#Calcula o RMSE para o algoritmo de smart_mean
predict_smartmean = smart_mean(data_train,X_test)
rmse_smart = rmse_metric(y_list,predict_smartmean)

In [450]:
#Calcula o RMSE para o algoritmo baseline
predict_base = baseline(y_list,X_test)
rmse_baseline = rmse_metric(y_list,predict_base)

In [451]:
print('Predições')
for i in range(len(y_list)):
    print("valor real: {:.3f}\t|| regressão: {:.3f}\t|| smart_mean: {:.3f}\t|| baseline: {:.3f}".format(y_list[i], predict[i], predict_smartmean[i], predict_base[i]))


Predições
valor real: 38.100	|| regressão: 39.293	|| smart_mean: 40.300	|| baseline: 86.973
valor real: 92.600	|| regressão: 116.396	|| smart_mean: 133.300	|| baseline: 86.973
valor real: 31.900	|| regressão: 69.464	|| smart_mean: 95.500	|| baseline: 86.973
valor real: 21.300	|| regressão: 62.759	|| smart_mean: 58.100	|| baseline: 86.973
valor real: 134.900	|| regressão: 106.339	|| smart_mean: 133.300	|| baseline: 86.973
valor real: 69.200	|| regressão: 109.692	|| smart_mean: 133.300	|| baseline: 86.973
valor real: 187.500	|| regressão: 113.044	|| smart_mean: 133.300	|| baseline: 86.973
valor real: 20.900	|| regressão: 42.645	|| smart_mean: 50.900	|| baseline: 86.973
valor real: 152.800	|| regressão: 149.920	|| smart_mean: 73.400	|| baseline: 86.973
valor real: 113.000	|| regressão: 102.987	|| smart_mean: 137.900	|| baseline: 86.973
valor real: 162.800	|| regressão: 210.261	|| smart_mean: 170.900	|| baseline: 86.973
valor real: 59.600	|| regressão: 79.521	|| smart_mean: 142.100	|| baseline: 86.973
valor real: 39.900	|| regressão: 35.941	|| smart_mean: 11.800	|| baseline: 86.973
valor real: 13.200	|| regressão: 35.941	|| smart_mean: 11.800	|| baseline: 86.973
valor real: 98.100	|| regressão: 92.930	|| smart_mean: 161.500	|| baseline: 86.973
valor real: 103.900	|| regressão: 123.101	|| smart_mean: 194.500	|| baseline: 86.973
valor real: 119.400	|| regressão: 159.977	|| smart_mean: 73.400	|| baseline: 86.973
valor real: 392.500	|| regressão: 387.935	|| smart_mean: 422.200	|| baseline: 86.973
valor real: 15.700	|| regressão: 69.464	|| smart_mean: 95.500	|| baseline: 86.973
valor real: 27.900	|| regressão: 49.350	|| smart_mean: 52.100	|| baseline: 86.973
valor real: 0.000	|| regressão: 25.884	|| smart_mean: 6.600	|| baseline: 86.973
valor real: 181.300	|| regressão: 163.329	|| smart_mean: 214.000	|| baseline: 86.973
valor real: 76.100	|| regressão: 52.702	|| smart_mean: 52.100	|| baseline: 86.973
valor real: 55.600	|| regressão: 52.702	|| smart_mean: 52.100	|| baseline: 86.973
valor real: 4.400	|| regressão: 35.941	|| smart_mean: 11.800	|| baseline: 86.973
valor real: 48.700	|| regressão: 56.055	|| smart_mean: 65.300	|| baseline: 86.973

In [453]:
print('RMSE para regressão linear: {0}'.format(rmse_reg))
print('RMSE para smart_mean: {0}'.format(rmse_smart))
print('RMSE para baseline: {0}'.format(rmse_baseline))


RMSE para regressão linear: 30.045630942473696
RMSE para smart_mean: 45.49237045077745
RMSE para baseline: 82.09841447776755

Criei uma função chamada de smart_mean, para fazer uma aproximação linear entre os valores mais próximos da variável a ser predita, presentes conjunto de treino. Pois o algoritmo de baseline somente tira a média dos valores de treino, dando uma aproximação muito ruim.

Acima é possível ver o RMSE para os três exemplos propostos.

O resultado varia de acordo com a execução, já que o dataset é separado de forma aleátoria, e são poucas amostras de treino. Mas em média a regressão linear deu o melhor resultado, seguido pelo smart_mean e depois pelo baseline