import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import scipy.stats as stats
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import cross_val_predict
from sklearn.linear_model import Ridge
from sklearn.model_selection import GridSearchCV
# Importando os dados de veículos de 1985 como dataset de estudo
file = "dados/imports-85.data"
df = pd.read_csv(file, header = None)
df.head(5)
# O CSV está sem os valores de coluna, ou seja, sem cabeçalhos (headers), estes serão definidos abaixo pela seguinte lista:
headers = [
"symboling",
"normalized-losses",
"make",
"fuel-type",
"aspiration",
"num-of-doors",
"body-style",
"drive-wheels",
"engine-location",
"wheel-base",
"length",
"width",
"height",
"curb-weight",
"engine-type",
"num-of-cylinders",
"engine-size",
"fuel-system",
"bore",
"stroke",
"compression-ratio",
"horsepower",
"peak-rpm",
"city-mpg",
"highway-mpg",
"price"
]
# Definindo a lista de headers como a lista de cabeçalho do DataFrame
df.columns = headers
df.head(5)
df.describe()
df.info()
df.dtypes
df.describe(include = "all")
# Trabalhando com missing data, ou valores nulos, NaN, entre outros
df = df.replace('NaN', '')
df = df.replace("?", "0")
df = df.fillna(0)
# Criando uma nova coluna para converter a coluna city-mpg para city-L/100km
df["city-L/100km"] = 235 / df["city-mpg"]
df.head()
# Convertendo o tipo de uma coluna em outro
df["price"] = df["price"].astype("int")
df
# Aplicando o método de simplificação no campo length (data / data.max)
df["length"] = df["length"] / df["length"].max()
df["length"].head(5)
# Aplicando o método de min-max na coluna length (data - data.min / data.max - data.min)
df["length"] = (df["length"] - df["length"].min()) / (df["length"].max() - df["length"].min())
df["length"].head(5)
# Aplicando o método de Z-Score na coluna length (data - data.media / data.std)
df["length"] = (df["length"] - df["length"].mean()) / (df["length"].std())
df["length"].head(5)
# Trabalhando com Data Binning (categorização de dados)]
groups = ["Low", "Medium", "High"]
bins = np.linspace(min(df["price"]), max(df["price"]), 4)
print(bins)
for bin_item in bins:
print('Bin: {}'.format(bin_item))
# Convertendo dados em dados categóricos usando dummy data
# O método get_dummies recebe uma coluna e cria um DataFrame contendo valores 0 (false) e 1 (true) para dados
# da coluna com objetivo em categorizá-los
categorical = pd.get_dummies(df["fuel-type"])
categorical.tail(15)
drive_wheels_count = df["drive-wheels"].value_counts()
drive_wheels_count.head(5)
# Plotando a distribuição da coluna drive-wheels pela coluna price em um boxplot usando a biblioteca Seaborn
x = "drive-wheels"
y = "price"
sns.boxplot(x = x, y = y, data = df)
# Plotando a distribuição da coluna engine-size pela coluna price em um scatterplot usando a biblioteca Matplotlib
x = df["engine-size"]
y = df["price"]
# Configurações de exibições do gráfico
plt.xlabel("Engine Size")
plt.ylabel("Price")
plt.title("Distribution of Engine Size by Pricing")
plt.scatter(x, y)
# Agrupando dados utilizando a função groupby
group = df[["drive-wheels", "body-style", "price"]]
group = group.groupby(["drive-wheels", "body-style"], as_index = False).mean()
group
drive_wheels = group["drive-wheels"]
price = group["price"]
plt.xlabel("Drive Wheels")
plt.title("Drive Wheels by Pricing")
plt.bar(drive_wheels, price)
body_style = group["body-style"]
plt.xlabel("Body Style")
plt.ylabel("Price")
plt.title("Body Style by Pricing")
plt.bar(body_style, price)
# Criando uma tabela pivô (semelhante à tabela dinâmica do Excel)
pivot_group = group.pivot(index = "drive-wheels", columns = "body-style")
# Criando um mapa de calor (HeatMap) com os dados do DataFrame pivô criado anteriormente
plt.pcolor(pivot_group, cmap = "RdBu")
plt.colorbar()
plt.show()
# Utilizando análise ANOVA (Análise de Variância)
anova_df = df[["make", "price"]]
anova_df.head()
# Teste ANOVA entre os preços de Honda e Subaru no DataFrame agrupando marca e preço
group_anova = anova_df.groupby(["make"])
anova_resultados = stats.f_oneway(group_anova.get_group("honda")["price"], group_anova.get_group("subaru")["price"])
anova_resultados
# É possível verificar que não há tanta diferença na variância, levando em consideração que F-Score < 1 e p > 0.05
# Teste ANOVA entre os preços de Honda e Jaguar no DataFrame agrupando marca e preço
group_anova = anova_df.groupby(["make"])
anova_resultados = stats.f_oneway(group_anova.get_group("honda")["price"], group_anova.get_group("jaguar")["price"])
anova_resultados
# É possível verificar que há diferença na variância, levando em consideração que F-Score > 1 e p > 0.05
# Trabalhando com correlação entre variáveis
# O gráfico regplot irá traçar uma linha em um scatter plot para indicar a correlação entre as variáveis
x = df["engine-size"]
y = df["price"]
sns.regplot(x, y, df)
plt.ylim(0, )
# É possível analisar que há uma correlação positiva entre engine-size e price, sendo uma correlação forte,
# pois, aumentando o engine-size, aumenta-se o preço
# Verificando agora a correlação existente entre highway-mpg e price
x = df["highway-mpg"]
sns.regplot(x, y, df)
plt.ylim(0, ) # Essa propriedade irá setar um limite de 0 para o eixo Y
# É possível analisar que há uma correlação positiva entre engine-size e price, sendo uma correlação forte,
# pois, reduzindo highway-mpg, reduz-se o preço
# Verificando agora a correlação existente entre peak-rpm e price
x = df["peak-rpm"].astype("int")
sns.regplot(x, y, df)
plt.ylim(0, )
# É possível analisar que há uma correlação negativa entre peak-rpm e price, sendo uma correlação fraca,
# pois, há valores altos e baixos em peak-rpm, e o preço mantém-se quase sempre constante
# Utilizando o método de correlação de Pearson
# Coeficiente de correlação
# Valor p
# Valores de Referência:
# Coeficiente de correlação:
# +1: correlação forte
# -1: correlação fraca
# 0: não há correlação
# Valores de p:
# p < 0.001 - Resultado altamente confiável
# p < 0.05 - Resultado moderadamente confiável
# p < 0.1 - Resultado baixamente confiável
# p > 0.1 - Resultado nada confiável
# Verificando a correlação entre as variáveis horsepower e price
df["horsepower"] = df["horsepower"].astype("int")
correlacao_df = df[["horsepower", "price"]]
coeficiente, p = stats.pearsonr(correlacao_df["horsepower"], correlacao_df["price"])
print("Coeficiente: {}".format(str(coeficiente)))
print("Valor de p: {}".format(str(p)))
# É possível verificar que p é muito menor que 0.001 e F é próximo de 1, então há uma forte correlação
# Regressão Linear Simples (SLR)
# Utilizando a classe LinearRegression da biblioteca Scikit-Learn para determinar os arrays de b0 e b1
# e criar um modelo de previsã utilizando regressão linear simples
lm = LinearRegression()
x = df[["highway-mpg"]]
y = df["price"]
lm.fit(x, y)
previsao = lm.predict(x)
print(previsao)
# Interceptando o valor de b0
b0 = lm.intercept_
print(b0)
# Interceptando o valor de b1
b1 = lm.coef_
print(b1)
# A relação entre o preço será: preco = 37758.50562969372 - 806.76723574 * highway-mpg
preco_previsao = b0 - b1 * x
print(preco_previsao)
# Regressão Linear Múltipla (MLR)
# Podemos ter b0, o alvo, b1, b2, b3... bn
horsepower = df["horsepower"]
curb_weight = df["curb-weight"]
engine_size = df["engine-size"]
highway_mpg = df["highway-mpg"]
z = df[["horsepower", "curb-weight", "engine-size", "highway-mpg"]]
lm.fit(z, y)
previsao = lm.predict(z)
previsao
b0 = lm.intercept_
bn = lm.coef_
print(b0)
print(bn)
preco_previsao_multipla = b0 + bn[0] * horsepower + bn[1] * curb_weight + bn[2] * engine_size + bn[3] * highway_mpg
preco_previsao_multipla
# Plotando um gráfico de regressão com a biblioteca Seabonr
x = "highway-mpg" # Variável dependente
y = "price" # Variável target
sns.regplot(x, y, df)
plt.ylim(0,)
# Criando um gráfico residual
sns.residplot(x, y, df)
# Gráficos de distribuição apenas de price por highway-mpg
y = df["price"]
grafico_1 = sns.distplot(y, hist = False, color = "r", label = "Valores Atuais")
# Agora, vamos comprar os valores previstos com os valores atuais
grafico_1 = sns.distplot(y, hist = False, color = "r", label = "Valores Atuais")
sns.distplot(preco_previsao_multipla, hist = False, color = "b", label = "Valores de Previsão", ax = grafico_1)
# Regressões polinomiais
x = df["highway-mpg"]
y = df["price"]
# Calculando polinômio de 3º grau com os campos highway-mpg e price
f = np.polyfit(x, y, 3)
f
p = np.poly1d(f)
p
# Criando polinômios multidimensionais com ScikitLearn
pr = PolynomialFeatures(degree = 2, include_bias = False)
x_polly = pr.fit_transform(df[["horsepower", "curb-weight"]])
x_polly
# Normalizar cada feature
scale = StandardScaler()
scale.fit(df[["horsepower", "curb-weight"]])
scale.transform(df[["horsepower", "curb-weight"]])
# Utilizando Pipeline para fazer todo o processo de regressão linear, features polinomiais e normalização
pipeline = [
('scale', StandardScaler()),
('polynomial', PolynomialFeatures(degree = 2)),
('model', LinearRegression())
]
pipe = Pipeline(pipeline)
print(pipe)
# É possível perceber que, no campo steps, o Pipeline irá executar cada um dos passos definidos para conseguir realizar
# operações de previsões, treinamentos, entre outras operações
# Medidas amostrais de avaliação e Erro Quadrático Médio (MSE)
# O método mean_squared_error recebe a variável target e a variável que foi prevista para
# encontrar o erro quadrático médio
# O fator R^2 (Coeficiente de Determinação) determina o quão próximo o dado está da linha de regressão
mean_squared_error(df["price"], preco_previsao_multipla)
# Geralmente, o MSE fica entre 0 e 1, é possível calcular o valor do MSE da seguinte maneira:
x = df[["highway-mpg"]]
y = df["price"]
lm.fit(x, y)
lm.score(x, y)
# Tomada de Decisão: verificando se seu modelo é aceitável
nova_entrada = np.arange(1, 101, 1).reshape(-1, 1)
nova_entrada
nova_entrada_previsao = lm.predict(nova_entrada)
nova_entrada_previsao
sns.regplot(nova_entrada, nova_entrada_previsao)
# Criando um modelo de testes e treinamentos com train_test_split da biblioteca Scikit-Learn
x = df[["highway-mpg", "curb-weight"]]
y = df["price"]
# Define-se que 30% dos dados serão para testes e 70% para os modelos de teste
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)
print("Treinamento das variáveis independentes: {}".format(x_train))
print("Teste das variáveis independentes: {}".format(x_test))
print("Treinamento das variáveis target: {}".format(y_train))
print("Teste das variáveis target: {}".format(y_test))
# Realizando a distribuição comparando os valores atuais de price com os valores treinados de price (70% dos dados)
grafico_1 = sns.distplot(y, hist = False, color = "r", label = "Valores Atuais")
sns.distplot(y_train, hist = False, color = "b", label = "Valores de Previsão", ax = grafico_1)
# Realizando a distribuição comparando os valores atuais de price com os valores de teste de price (30% dos dados)
grafico_1 = sns.distplot(y, hist = False, color = "r", label = "Valores Atuais")
sns.distplot(y_test, hist = False, color = "b", label = "Valores de Previsão", ax = grafico_1)
# Utilizando modelo Cross Value Score - Particionar o DataFrame em 4 para dividir o modelo em modelos de
# testes e de treinamento, 3 para treinamento e 1 para testes
lm = LinearRegression()
scores = cross_val_score(lm, x, y, cv = 3)
scores
# Verificando a média dos scores definidos
np.mean(scores)
# O método cross_val_predict é bastante parecido com cross_val_scores, a diferença é
# que o resultado é um conjunto de valores de predição
lm_2 = LinearRegression()
previsoes = cross_val_predict(lm, x, y, cv = 3)
previsoes
# Valor médio das previsões
np.mean(previsoes)
# Sobreajuste e Sub-Ajuste e Seleção de Modelo
# Primeiro, iremos definir os modelos x e y de treino e teste
x_train, x_test, y_train, y_test = train_test_split(df[["horsepower"]], df[["price"]], test_size = 0.3, random_state = 0)
# Será necessário instanciar uma regressão linear e uma lista vazia, que conterá os valores R Quadráticos de teste
lm_3 = LinearRegression()
r_quad_test = []
# Será necessário criar uma lista de 4 posições para definirmos os 4 graus de teste
order = [1, 2, 3, 4]
# Primeiramente, iremos instanciar uma PolynomialFeature, e então, iremos realizar um fit_transform com
# os valores de treino e teste de x
# Por fim, iremos utilizar a regressão linear para realizar um fit do valor de treino de X e de Y
# Ao realizar o score entre x_test com PolynomialFeature e o teste y, iremos incrementar este valor à lista de R Quadrático
# para obter os valroes para cada grau
for n in order:
pr = PolynomialFeatures(degree = n)
x_train_pr = pr.fit_transform(x_train)
x_test_pr = pr.fit_transform(x_test)
lm_3.fit(x_train_pr, y_train)
r_quad_test.append(lm_3.score(x_test_pr, y_test))
r_quad_test
# Regressão de Ridge - previne sobreajuste
# Utiliza um valor alpha para controlar os coeficientes dos graus no polinômio
x = df[["horsepower"]]
y = df[["price"]]
ridge_model = Ridge(alpha = 0.1)
ridge_model.fit(x, y)
previsao = ridge_model.predict(x)
previsao
# Utilizando método de Busca por Grid - valores como o alpha na regressão de Ridge são Hiperparâmetros, e o
# método de Busca por Grid nos permite iterar sobre esses hiperparâmetros
parametros = [
{
'alpha': [0.001, 0.1, 1, 10, 100, 1000, 10000, 100000, 1000000]
}
]
x = df[["horsepower", "curb-weight", "engine-size", "highway-mpg"]]
y = df[["price"]]
ridge = Ridge()
grid = GridSearchCV(ridge, parametros, cv = 4)
grid.fit(x, y)
melhor_estimador = grid.best_estimator_
resultados = grid.cv_results_
print("Melhor estimador: {}\n".format(melhor_estimador))
print("Teste médio dos scores: {}\n".format(resultados["mean_test_score"]))
# Utilizando os parametros passando atributo de normalização
parametros = [
{
'alpha': [1, 10, 100, 1000],
'normalize': [True, False]
}
]
ridge = Ridge()
grid = GridSearchCV(ridge, parametros, cv = 4)
grid.fit(x, y)
melhor_estimador = grid.best_estimator_
resultados = grid.cv_results_
print("Melhor estimador: {}\n".format(melhor_estimador))
print("Scores: {}\n".format(resultados["params"]))