Módulos Essenciais de Python
A ciência de dados abrange um conjunto diversificado de técnicas e ferramentas que permitem a extração de conhecimento e insights valiosos a partir de dados. Python, com sua vasta coleção de bibliotecas, é uma escolha popular para cientistas de dados. Além dos módulos comuns como NumPy, Pandas, Matplotlib e Scikit-learn, existem outros módulos que podem ser utilizados para análises mais avançadas e específicas.
Neste artigo apresento alguns módulos adicionais para ciência de dados utilizando o conjunto de dados House Prices do Kaggle. Esses módulos incluem:
Dask: Para manipulação e análise de dados em grande escala.
XGBoost: Para modelos de gradient boosting.
SHAP: Para interpretar modelos de machine learning.
Plotly: Para visualizações interativas.
TensorFlow: Para deep learning.
# suprimir avisos (warnings)
import warnings
warnings.filterwarnings("ignore")
1. Dask: Manipulação e Análise de Dados em Grande Escala
Quando lidamos com grandes volumes de dados, o Pandas pode não dar conta do recado, especialmente quando a memória é limitada. É aqui que o Dask entra em cena. Imagine dividir seu conjunto de dados em blocos menores e trabalhar com eles como se fosse o Pandas, mas com uma vantagem: o Dask distribui esse trabalho em vários núcleos do seu processador, ou até em diferentes máquinas. Isso significa que você pode processar grandes bases de dados sem se preocupar com a falta de memória.
Exemplo:
No exemplo abaixo, usamos o Dask para carregar e analisar um conjunto de dados de forma eficiente, mostrando como ele calcula estatísticas descritivas rapidamente, mesmo com grandes volumes de informação:
import dask.dataframe as dd
# URL do conjunto de dados
url = "https://raw.githubusercontent.com/ageron/handson-ml/master/datasets/housing/housing.csv"
# Carregando o conjunto de dados usando Dask
dados_casas_dask = dd.read_csv(url)
# Calculando estatísticas descritivas
descricao_dask = dados_casas_dask.describe()
# executa operações de forma eficiente em grandes conjuntos de dados
descricao_dask_computed = descricao_dask.compute()
# Exibindo o resultado das estatísticas descritivas
print(descricao_dask_computed)
longitude latitude housing_median_age total_rooms \
count 20640.000000 20640.000000 20640.000000 20640.000000
mean -119.569704 35.631861 28.639486 2635.763081
std 2.003532 2.135952 12.585558 2181.615252
min -124.350000 32.540000 1.000000 2.000000
25% -121.800000 33.930000 18.000000 1447.750000
50% -118.490000 34.260000 29.000000 2127.000000
75% -118.010000 37.710000 37.000000 3148.000000
max -114.310000 41.950000 52.000000 39320.000000
total_bedrooms population households median_income \
count 20433.000000 20640.000000 20640.000000 20640.000000
mean 537.870553 1425.476744 499.539680 3.870671
std 421.385070 1132.462122 382.329753 1.899822
min 1.000000 3.000000 1.000000 0.499900
25% 296.000000 787.000000 280.000000 2.563400
50% 435.000000 1166.000000 409.000000 3.534800
75% 647.000000 1725.000000 605.000000 4.743250
max 6445.000000 35682.000000 6082.000000 15.000100
median_house_value
count 20640.000000
mean 206855.816909
std 115395.615874
min 14999.000000
25% 119600.000000
50% 179700.000000
75% 264725.000000
max 500001.000000
Utilizando o método compute()em Dask, as operações que foram configuradas de forma paralela são executadas e o resultado é coletado. Isso difere do Pandas, onde todas as operações são realizadas de forma sequencial e em um único núcleo. O Dask, portanto, é ideal para cenários em que o tempo de processamento e a capacidade de memória são críticos, como em grandes bases de dados corporativas.
Benefícios Adicionais:
Dask também é altamente compatível com outras bibliotecas do ecossistema Python, como NumPy e Scikit-learn, facilitando a integração em pipelines de dados já existentes. Além disso, sua capacidade de escalar de um laptop para um cluster distribuído sem alterar o código subjacente o torna uma ferramenta flexível e poderosa para cientistas de dados.
Ao usar o Dask, você aproveita melhor os recursos do seu computador, garantindo que as análises sejam feitas de maneira eficiente, sem comprometer a performance, mesmo com grandes quantidades de dados.
2. XGBoost: Modelos de Gradient Boosting¶
Gradient Boosting é uma técnica que combina o aprendizado sequencial de modelos fracos, geralmente árvores de decisão, para construir um modelo forte. No XGBoost, cada árvore é treinada para corrigir os erros do conjunto anterior, e as previsões são ajustadas iterativamente. A importância dessa abordagem é que ela minimiza o erro ao longo das iterações, resultando em um modelo final que é uma combinação ponderada de todas as árvores. Isso o torna altamente eficaz para tarefas como regressão e classificação, especialmente em conjuntos de dados com ruído e outliers.
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import pandas as pd
# Carregando o conjunto de dados usando pandas
dados_casas = pd.read_csv(url)
# Preparando os dados
X = dados_casas[["total_rooms"]]
y = dados_casas["median_house_value"]
X_treino, X_teste, y_treino, y_teste = train_test_split(X, y, test_size=0.3, random_state=42)
# Treinando um modelo XGBoost
modelo_xgb = xgb.XGBRegressor(objective ='reg:squarederror', n_estimators=100)
modelo_xgb.fit(X_treino, y_treino)
# Faz previsões
y_pred_xgb = modelo_xgb.predict(X_teste)
# Avaliando o modelo
rmse = mean_squared_error(y_teste, y_pred_xgb, squared=False)
print("RMSE do Modelo XGBoost:", rmse)
RMSE do Modelo XGBoost: 113329.45682157896
Gradient Boosting é uma técnica utilizada para melhorar a precisão de modelos preditivos combinando vários modelos simples, como árvores de decisão. No XGBoost, cada árvore é treinada para corrigir os erros das previsões anteriores, resultando em um modelo final que é uma soma ponderada de todas as árvores. Essa metodologia é eficaz para lidar com dados complexos, onde ruídos e outliers podem dificultar a precisão das previsões.
Ao aplicar o XGBoost, é fundamental ajustar os hiperparâmetros, como a profundidade das árvores (max_depth), a taxa de aprendizado (learning_rate), e o número de iterações (n_estimators). Esses ajustes garantem que o modelo não apenas capture as nuances dos dados, mas também evite o overfitting, mantendo a capacidade de generalização para novos dados.
No código apresentado, o modelo inicial alcançou um RMSE de aproximadamente 113329.46, sugerindo uma boa precisão inicial. No entanto, há espaço para otimização, e no próximo passo, utilizaremos o GridSearchCV para refinar esses hiperparâmetros e melhorar ainda mais o desempenho do modelo.
from sklearn.model_selection import GridSearchCV
# Defini os hiperparâmetros que serão otimizados
param_grid = {
'learning_rate': [0.01, 0.1, 0.2],# Taxa de aprendizado, controla o quanto cada nova árvore contribui para corrigir os erros das árvores anteriores
'max_depth': [3, 5, 7], # Profundidade máxima das árvores, controlando a complexidade do modelo
'subsample': [0.6, 0.8, 1.0], # Fração das amostras usadas para treinar cada árvore. Usar menos de 1.0 (100%) ajuda a prevenir overfitting
'n_estimators': [100, 200, 300] # Número de árvores a serem construídas no modelo, controlando o número de iterações
}
# Instancia o modelo XGBoost
modelo_xgb = xgb.XGBRegressor(objective='reg:squarederror', random_state=42)
# Configura o GridSearchCV / validação cruzada com 5 divisões, e critério de avaliação será o erro quadrático médio negativo - scoring
grid_search = GridSearchCV(estimator=modelo_xgb, param_grid=param_grid, cv=5, scoring='neg_mean_squared_error', verbose=1)
# Executa a busca pelos melhores hiperparâmetros
grid_search.fit(X_treino, y_treino)
# Exibi os melhores parâmetros encontrados
print("Melhores Hiperparâmetros:", grid_search.best_params_)
# Treina o modelo com os melhores parâmetros
modelo_otimizado = grid_search.best_estimator_
# Faz previsões e avalia o modelo otimizado
y_pred_otimizado = modelo_otimizado.predict(X_teste)
rmse_otimizado = mean_squared_error(y_teste, y_pred_otimizado, squared=False)
print("RMSE do Modelo Otimizado:", rmse_otimizado)
Fitting 5 folds for each of 81 candidates, totalling 405 fits
Melhores Hiperparâmetros: {'learning_rate': 0.01, 'max_depth': 3, 'n_estimators': 200, 'subsample': 0.6}
RMSE do Modelo Otimizado: 112555.30074019264
Após a execução do GridSearchCV, o modelo XGBoost foi ajustado com os melhores hiperparâmetros encontrados: learning_rate: 0.01, max_depth: 3, n_estimators: 200, subsample: 0.6. Esses ajustes foram fundamentais para melhorar a performance do modelo, resultando em um RMSE de 112555.30. Esse processo de otimização é essencial para garantir previsões mais precisas, refinando o modelo para melhor atender às especificidades do conjunto de dados e das tarefas de previsão.
3. SHAP: Interpretação de Modelos de Machine Learning¶
SHAP (SHapley Additive exPlanations) é uma biblioteca que fornece explicações interpretáveis para os resultados de modelos de machine learning.
import shap
# Criaando um objeto Explainer
explainer = shap.Explainer(modelo_otimizado, X_treino)
shap_values = explainer(X_teste)
# Visualizando os valores SHAP
shap.summary_plot(shap_values, X_teste)
100%|===================| 6184/6192 [00:11<00:00]
SHAP (SHapley Additive exPlanations) é uma poderosa ferramenta que facilita a interpretação de modelos complexos de machine learning. Em nosso exemplo, utilizamos SHAP para
No gráfico de dispersão SHAP, usando o modelo otimisado, cada ponto representa uma previsão individual. A cor dos pontos indica o valor da variável total_rooms, variando de azul (valores baixos) a rosa (valores altos). A posição no eixo x revela o impacto dessa variável nas previsões: pontos à direita (impacto positivo) indicam que valores mais altos de total_rooms tendem a aumentar a previsão do valor da casa, enquanto pontos à esquerda (impacto negativo) sugerem o contrário.
Essa visualização é crucial para entender como o modelo XGBoost está utilizando a variável total_rooms para fazer previsões, além de permitir a identificação de padrões ou possíveis outliers que podem estar influenciando as previsões de maneira inesperada.
4. Plotly: Visualizações Interativas¶
import plotly.express as px
dados_casas = pd.read_csv(url)
# Criando um gráfico de dispersão interativo
fig = px.scatter(dados_casas,
x="total_rooms", # Coluna com o número total de cômodos
y="median_house_value", # Coluna com o valor mediano da casa
title="Número de Cômodos (Agregado) vs. Valor Mediano da Casa",
hover_data={'total_rooms': True, 'median_house_value': ':.1f'})
# Atualizando o layout do gráfico
fig.update_layout(
xaxis_title="Número Total de Cômodos (Agregado por Região)", # Ajuste do rótulo no eixo X
yaxis_title="Valor Mediano da Casa", # Ajuste do rótulo no eixo Y
title_x=0.5 # Centraliza o título
)
# Exibir o gráfico
fig.show()
O gráfico interativo acima mostra a relação entre o número total de cômodos agregados por região (total_rooms) e o valor mediano das casas (median_house_value). Ele revela uma correlação positiva entre o número de cômodos na região e o valor das propriedades, embora fatores como localização e conservação possam influenciar o preço. A interatividade permite explorar detalhes específicos, facilitando a identificação de padrões ocultos nos dados.
5. TensorFlow: Deep Learning¶
import tensorflow as tfqq
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# Carregando o conjunto de dados usando pandas
dados_casas = pd.read_csv(url)
# Preparando os dados
X = dados_casas[["total_rooms"]].values
y = dados_casas["median_house_value"].values
# Definindo a arquitetura do modelo
modelo_tf = Sequential([
Dense(10, activation='relu', input_shape=(X.shape[1],)),
Dense(1)
])
# Compilando o modelo
modelo_tf.compile(optimizer='adam', loss='mse')
# Treinando o modelo
modelo_tf.fit(X, y, epochs=10, batch_size=32)
# Fazendo previsões
y_pred_tf = modelo_tf.predict(X)
d_tf = modelo_tf.predict(X)
Epoch 1/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 5s 1ms/step - loss: 56108036096.0000 Epoch 2/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 931us/step - loss: 54081626112.0000 Epoch 3/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 900us/step - loss: 46221725696.0000 Epoch 4/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 811us/step - loss: 37783916544.0000 Epoch 5/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 780us/step - loss: 31379750912.0000 Epoch 6/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 817us/step - loss: 28132274176.0000 Epoch 7/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 820us/step - loss: 27776878592.0000 Epoch 8/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 898us/step - loss: 27917871104.0000 Epoch 9/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 812us/step - loss: 27391543296.0000 Epoch 10/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 798us/step - loss: 27503605760.0000 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 761us/step 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 768us/step
Neste exemplo, utilizamos tensorflow.keras para construir e treinar uma rede neural simples com uma camada densa (Dense). O modelo foi treinado para prever os preços das casas com base na variável total_rooms, que reflete o número total de cômodos agregados por região. Durante o treinamento, a rede neural ajusta os pesos das conexões para minimizar a função de perda (loss), que, neste caso, foi definida como o erro quadrático médio (mse).
Após o treinamento, usamos o modelo para fazer previsões sobre os dados. No entanto, uma rede neural simples como essa pode ser propensa ao overfitting, especialmente se a arquitetura não for devidamente regularizada ou se o conjunto de dados for limitado.
Após o treinamento, usamos o modelo para fazer previsões sobre os dados. No entanto, uma rede neural simples como essa pode ser propensa ao overfitting, especialmente se a arquitetura não for devidamente regularizada ou se o conjunto de dados for limitado.
A seguir, demonstramos como modificar o modelo original para incluir a camada de Dropout, que ajudará a prevenir o overfitting:
from tensorflow.keras.layers import Dropout
# Modificação da arquitetura do modelo para incluir Dropout
modelo_tf = Sequential([
Dense(10, activation='relu', input_shape=(X.shape[1],)),
Dropout(0.2), # 20% das unidades serão desligadas durante o treinamento
Dense(1)
])
# Compilando o modelo
modelo_tf.compile(optimizer='adam', loss='mse')
# Treinar o modelo com a nova arquitetura
modelo_tf.fit(X, y, epochs=10, batch_size=32)
Epoch 1/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 2s 855us/step - loss: 55228936192.0000 Epoch 2/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 825us/step - loss: 47544848384.0000 Epoch 3/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 934us/step - loss: 34778632192.0000 Epoch 4/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 887us/step - loss: 29066162176.0000 Epoch 5/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 914us/step - loss: 27990056960.0000 Epoch 6/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 893us/step - loss: 28555808768.0000 Epoch 7/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 900us/step - loss: 28106973184.0000 Epoch 8/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 891us/step - loss: 29005492224.0000 Epoch 9/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 928us/step - loss: 29002612736.0000 Epoch 10/10 645/645 ━━━━━━━━━━━━━━━━━━━━ 1s 864us/step - loss: 27780956160.0000
<keras.src.callbacks.history.History at 0x211cfd3db80>
A adição da camada de Dropout no modelo foi essencial para mitigar o risco de overfitting durante o treinamento. Os resultados mostraram uma redução constante na perda ao longo das épocas, indicando que o modelo foi capaz de aprender de maneira controlada. Essa técnica, junto com a otimização dos hiperparâmetros, é crucial para garantir que redes neurais sejam capazes de fazer previsões precisas e confiáveis, mesmo em cenários complexos.