Prevendo a qualidade do vinho com técnicas de Classificação

Um passo a passo de um projeto de ciência de dados aplicando: Árvores de Decisão, Florestas Aletórias, AdaBoost, Gradient Boosting e XGBoost

Recentemente, adquiri um gosto por vinhos, embora eu realmente não sei o que faz um bom vinho. Por isso, decidi aplicar alguns modelos de aprendizado de máquina para descobrir o que faz um vinho de boa qualidade.

Para este projeto, usei o conjunto de dados da Qualidade do Vinho Tinto para construir vários modelos de classificação para prevermos se um determinado vinho tinto é de “boa qualidade” ou não.

Cada vinho neste conjunto de dados recebe uma pontuação de “qualidade” entre 0 e 10. Para efeitos deste projeto, converti a saída em uma produção binária onde cada vinho é de “boa qualidade” (uma pontuação de 7 ou mais) ou não (uma pontuação abaixo de 7). A qualidade de um vinho é determinada por 11 variáveis de entrada:

  1. Acidez fixa
  2. Acidez volátil
  3. Ácido cítrico
  4. Açúcar residual
  5. Cloretos
  6. Dióxido de enxofre grátis
  7. Dióxido de enxofre total
  8. Densidade
  9. Ph
  10. Sulfatos
  11. Álcool

Os objetivos deste projeto são os seguintes

  1. Para experimentar diferentes métodos de classificação para ver qual gera a maior precisão.
  2. Para determinar quais características são as mais relevantes de um vinho de boa qualidade.
  1. Configuração
  2. Explorando variáveis
  3. Converter para um problema de classificação
  4. Preparando dados para modelagem
  5. Modelagem
  6. Importância do recurso

Primeiramente, importar todas as bibliotecas relevantes que usaremos, bem como os dados em si.

import numpy as np
import pandas as pd
import matplotlib as plt
import seaborn as sns
import plotly.express as px
df = pd.read_csv("winequality-red.csv")
# Número de linhas e colunas
df.shape
1599 linhas, 12 colunas
df.head()
DataFrame de Vinhos

São 1599 linhas e 12 colunas. Os dados parecem limpos olhando para as cinco primeiras linhas, mas ainda desejo ter certeza de que não há valores ausentes.

# Missing Values
df.isna().sum())

Este é um conjunto de dados muito amigável para iniciantes. Eu não tive que lidar com nenhum valor ausente, e não há muita flexibilidade para conduzir alguma engenharia de recursos dadas essas variáveis. Em seguida, vamos explorar um pouco mais os dados

Primeiro, vamos ver a distribuição da variável de qualidade. Gostaríamos de ter certeza de que temos vinhos de “boa qualidade” suficientes no conjunto de dados .

fig = px.histogram(df,x='quality')
fig.show()

Em seguida, veremos as correlações entre as variáveis com as quais trabalhamos. Isso permite entender muito melhor as relações das variáveis em um vislumbre rápido.

Imediatamente, podemos ver que existem algumas variáveis que estão fortemente correlacionadas com qualidade. É provável que essas variáveis também sejam as características mais importantes em nosso modelo de aprendizado de máquina, mas vamos dar uma olhada nisso mais tarde.

corr = df.corr()
matplotlib.pyplot.subplots(figsize=(15,10))
sns.heatmap(
corr,
xticklabels=corr.columns,
yticklabels=corr.columns,
annot=True,
cmap=sns.diverging_palette(220, 20, as_cmap=True))
Mapa de calor

Gostaríamos de comparar a eficácia de diferentes técnicas de classificação, então precisamos mudar a variável de saída para uma saída binária.

Para este problema, foi definido que uma garrafa de vinho de “boa qualidade” é que tenha uma pontuação de qualidade de 7 ou mais, e se tivesse uma pontuação inferior a 7, é considerada de “má qualidade”.

Uma vez convertida a variável de saída em uma saída binária, separamos as variáveis de preditoras (X) e a variável alvo (y) em dataframes separados.

# Criar uma classificação para a variável alvo
df['goodquality'] = [1 if x >= 7 else 0 for x in df['quality']]

# Separarar variáveis preditoras e variável alvo
X = df.drop(['quality','goodquality'], axis = 1)
y = df['goodquality']
Definindo o critério de classificação binária

Gostaria de certeza de que há um número razoável de vinhos de boa qualidade. Com base nos resultados abaixo, parece um número justo o suficiente. Em alguns aplicativos, a reamostragem pode ser necessária se os dados foram extremamente desequilibrados, mas assumimos aqui que estava de acordo para nossos fins.

# Proporção da classificaçãp
df['goodquality'].value_counts()

A primeira coisa que a se fazer aqui, é padronizar os dados. Padronizar os dados significa que ele transformará os dados para que sua distribuição tenha uma média igual 0 e um desvio padrão de 1. É importante padronizar os dados para equalizar o alcance dos dados.

Por exemplo, imagine um conjunto de dados com duas características de entrada: altura em milímetros e peso em libras. Como os valores de ‘altura’ são muito mais elevados devido à sua medição, uma maior ênfase será automaticamente colocada na altura do que no peso, criando um viés.

# Normalizando as variáveis preditorasfrom sklearn.preprocessing import StandardScaler
X_features = X
X = StandardScaler().fit_transform(X)

Em seguida, dividimos os dados em um conjunto de treinamento e teste para que pudéssemos validar os modelos e determinar sua eficácia.

# Separando dados de treino e testfrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.25, random_state=0)
train_test_splt( ) divisão de 25%

Para este projeto, vamos comparar cinco modelos diferentes de aprendizado de máquina:

  1. árvores de decisão,
  2. florestas aleatórias,
  3. AdaBoost,
  4. Gradient Boost
  5. XGBoost.

Modelo 1: Árvores de Decisão

As árvores de decisão são um modelo popular, usado em pesquisa de operações, planejamento estratégico e machine learning.

Cada retângulo acima é chamado de nó, e quanto mais nódulos tiver, mais precisa será aárvore de decisão (geralmente).

Os últimos nós da árvore de decisão, onde uma decisão é tomada, são chamados de folhas da árvore. As árvores de decisão são intuitivas e fáceis de construir, mas ficam aquém quando se trata de precisão.

from sklearn.metrics import classification_report
from sklearn.tree import DecisionTreeClassifier
model1 = DecisionTreeClassifier(random_state=1)model1.fit(X_train, y_train)
y_pred1 = model1.predict(X_test)
print(classification_report(y_test, y_pred1))

Florestas aleatórias são uma técnica de aprendizado ensemble que se constrói a partir de árvores de decisão.

Florestas aleatórias envolvem a criação de múltiplas árvores de decisão usando conjuntos de dados bootstrap dos dados originais e selecionando aleatoriamente um subconjunto de variáveis em cada etapa da árvore de decisão.

O modelo então seleciona o modo de todas as previsões de cada árvore de decisão. Qual é o objetivo disso? Ao confiar em um modelo de que “maioria ganha”, reduz o risco de erro de uma árvore individual de decisão.

Por exemplo, se criássemos uma árvore de decisão, a terceira, ela preveria 0. Mas se dependêssemos do modo de todas as 4 árvores de decisão, o valor previsto seria 1. Este é o poder das florestas aleatórias.

from sklearn.ensemble import RandomForestClassifier
model2 = RandomForestClassifier(random_state=1)
model2.fit(X_train, y_train)
y_pred2 = model2.predict(X_test)
print(classification_report(y_test, y_pred2))
RandomForestClassifier

Modelo 3: AdaBoost

Os próximos três modelos são algoritmos de “boosting”, que pegam alunos fracos e os transformam em fortes. Vou deixar alguns recursos onde podemos aprender sobre AdaBoost, Gradient Boosting e XGBoosting.

from sklearn.ensemble import AdaBoostClassifier
model3 = AdaBoostClassifier(random_state=1)
model3.fit(X_train, y_train)
y_pred3 = model3.predict(X_test)
print(classification_report(y_test, y_pred3))
AdaBoostClassifier

Modelo 4: Gradient Boosting

from sklearn.ensemble import GradientBoostingClassifiermodel4 = GradientBoostingClassifier(random_state=1)
model4.fit(X_train, y_train)
y_pred4 = model4.predict(X_test)
print(classification_report(y_test, y_pred4))
GradientBoostingClassifier

Modelo 5: XGBoost

import xgboost as xgbmodel5 = xgb.XGBClassifier(random_state=1)
model5.fit(X_train, y_train)
y_pred5 = model5.predict(X_test)
print(classification_report(y_test, y_pred5))

Comparando os cinco modelos, a floresta aleatória e o XGBoost parecem produzir o mais alto nível de precisão. No entanto, como o XGBoost tem uma pontuação F1 melhor para prever vinhos de boa qualidade (1), podemos assumir que o XGBoost é o vencedor dos cinco modelos.

Abaixo, grafamos a importância do recurso com base no modelo Random Forest e no modelo XGBoost. Embora variem ligeiramente, as características tops 3 são as mesmas: álcool, acidez volátil e sulfatos. Se você olhar abaixo dos gráficos, divido o conjunto de dados em boa qualidade e má qualidade para comparar essas variáveis com mais detalhes.

feat_importances = pd.Series(model2.feature_importances_, index=X_features.columns)
feat_importances.nlargest(25).plot(kind='barh',figsize=(10,10))
feat_importances = pd.Series(model5.feature_importances_, index=X_features.columns)
feat_importances.nlargest(25).plot(kind='barh',figsize=(10,10))
# Filtrando df para vinhos de boa qualidade
df_temp = df[df['goodquality']==1]
df_temp.describe()
Boa Qualidade
# Filtrando df para vinhos de má qualidade
df_temp2 = df[df['goodquality']==0]
df_temp2.describe()
Má Qualidade

Olhando para os detalhes, podemos ver que vinhos de boa qualidade têm em média:

- níveis mais elevados de álcool,

- acidez volátil menor,

- níveis mais altos de sulfatos,

- níveis mais altos de açúcar residual.

Obrigado.

Composing a repository of books (i bought), authors (i follow) & blogs (direct ones) for my own understanding.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store