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:
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]:
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]))
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))
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