Karla Rosario
Karla Rosario08/03/2026 15:07
Compartilhe

Previsão de Adoção de Pets com Machine Learning: O que os Dados (Não) Revelam 🐾

    Ao iniciarmos um projeto de Ciência de Dados, é comum focarmos todas as nossas energias na busca pela maior métrica de acerto. No entanto, a verdadeira maturidade analítica surge quando percebemos que um modelo também serve para nos dizer o que não funciona.

    Neste artigo, compartilho a jornada de construção de um pipeline robusto de Machine Learning que desenvolvi com a equipe DataMind (composta por mim, Bruno Said e Waleska) para o projeto final do Bootcamp em Ciência de Dados da Avanti.ia.

    📌 O Desafio de Negócio

    Toda a nossa análise foi guiada por uma "Pergunta de Ouro":

    "Quando um animal entra pela porta do abrigo, quanto tempo estimamos que ele vai ocupar uma vaga e gerar custos?" O nosso objetivo inicial era permitir que a gestão de um abrigo de animais pudesse prever os dias de permanência (TimeInShelterDays). Isso permitiria estimar custos operacionais diários, gerenciar as baias de forma inteligente e planejar campanhas proativas. Optamos, portanto, por uma abordagem de Regressão.

    🛠️ Engenharia de Dados e Pré-processamento

    Para garantir que a base de dados estava pronta para a modelagem, criamos um Pipeline de pré-processamento avançado utilizando a biblioteca Scikit-Learn.

    1. Engenharia de Features Começamos expandindo as nossas variáveis de 10 para 14, criando features lógicas como WeightAgeRatio (Relação Peso/Idade), IsYoung (É jovem), IsSenior (É idoso) e HealthScore (Pontuação de Saúde).

    2. Tratamento de Outliers com POO Em vez de simplesmente apagar linhas de forma manual, desenvolvemos uma classe customizada utilizando o método IQR para fazer o clipping dinâmico de outliers. Um excelente exemplo da fusão entre Ciência de Dados e a Programação Orientada a Objetos no Python:

    Python

    # Classe para tratamento de outliers usando método IQR
    class OutlierClipper(BaseEstimator, TransformerMixin):
      def __init__(self, factor=1.5):
          self.factor = factor
          self.lower_bounds = {}
          self.upper_bounds = {}
    
      def fit(self, X, y=None):
          for col in range(X.shape[1]):
              Q1 = np.percentile(X[:, col], 25)
              Q3 = np.percentile(X[:, col], 75)
              IQR = Q3 - Q1
              self.lower_bounds[col] = Q1 - self.factor * IQR
              self.upper_bounds[col] = Q3 + self.factor * IQR
          return self
    

    3. O Pipeline Orquestramos tudo em um ColumnTransformer, integrando SimpleImputer para dados faltantes, RobustScaler para variáveis contínuas, e OneHotEncoder e OrdinalEncoder para dados categóricos.

    ⚔️ A Batalha dos 7 Modelos

    Com os dados limpos, iniciamos os testes de algoritmos. Avaliamos sete modelos: Regressão Linear, Ridge, K-Nearest Neighbors (KNN), Decision Tree, Random Forest, Gradient Boosting (GBR) e Support Vector Regressor (SVR).

    Para garantir a robustez e evitar que o nosso modelo ficasse dependente de uma única divisão de dados de treino e teste, aplicamos uma validação cruzada do tipo ShuffleSplit com 30 iterações. Paralelamente, utilizamos o RandomizedSearchCV para realizar o tuning automatizado dos hiperparâmetros.

    Avaliamos as métricas de Erro Médio Absoluto (MAE), Erro Médio Quadrático (MSE), Coeficiente de Determinação (R²) e o Erro Percentual Médio Absoluto (MAPE).

    Os resultados em termos de Erro Absoluto Médio (MAE) situaram-se na casa dos 22 dias para todos os algoritmos. O SVR apresentou o erro mais baixo (22,18 dias) e o Random Forest o mais alto (22,66 dias). O MSE girou em torno de 660.

    E é aqui que a magia (ou a realidade) dos dados acontece.

    🚀 O Grande Achado (O Plot Twist Analítico)

    Mesmo com um pré-processamento rigoroso e com o ajuste de parâmetros refinado, reparamos que a métrica em todos os modelos estacionou em valores levemente negativos (entre -0,003 e -0,05).

    O que um R² negativo nos diz na prática? Ele indica que as variáveis disponíveis não foram suficientes para explicar adequadamente a variabilidade da nossa variável alvo. Basicamente, os nossos modelos ultracomplexos tiveram um desempenho equivalente ao de tentar prever o tempo de adoção apostando simplesmente na média histórica.

    E ao contrário do que se possa pensar, esta é uma conclusão estatística de extremo valor.

    Nós provamos, de forma rigorosa, que a biologia e os dados cadastrais do pet (idade, peso, cor ou raça) não ditam o seu tempo de espera para a adoção. Um modelo de Machine Learning não pode aprender um padrão que simplesmente não existe nos dados fornecidos.

    Um bom cientista de dados não força métricas para agradar o negócio, mas sim traduz a realidade dos dados: no mundo real, a adoção depende de variáveis externas que não constam neste dataset, como as condições econômicas do bairro, a qualidade das fotos nas campanhas de adoção, ou até a lotação momentânea do próprio abrigo.

    🔭 Próximos Passos na Jornada

    O projeto não termina aqui. Como trabalhos futuros, planejamos:

    1. Realizar ajustes de hiperparâmetros ainda mais aprofundados com técnicas como o GridSearchCV.
    2. Explorar ainda mais técnicas de engenharia de atributos para extrair mais valor do dataset.
    3. Avaliar métodos ensemble mais robustos na busca por eventuais ganhos de performance.

    Espero que este compartilhamento seja útil para quem está estudando modelos preditivos. Nem sempre o R² vai ser de 0.90, mas os insights de negócio valem seu peso em ouro.

    🔗 Repositório do projeto com todo o código fonte: karlarenatadev/projeto-final-bootcamp-avantiia-ciencia-de-dados

    E vocês? Já enfrentaram projetos onde os dados mostraram que o comportamento não correspondia à expectativa inicial? Compartilhem suas experiências nos comentários!

    Compartilhe
    Comentários (0)