O código que o assistente não escreveu
Peça a um assistente de IA um random forest e olhe as quatro linhas que ele devolve: os imports estão corretos, o estimador treina e as previsões voltam no formato esperado. Agora repare nos argumentos que ninguém especificou — porque essas quatro linhas já decidiram muito mais coisas do que o seu prompt pediu.
Quantas features cada árvore deve considerar? Quanto de regularização o modelo deve aplicar? Como as dobras de validação devem refletir a estrutura dos seus dados? É isso que os padrões (defaults) fazem: transformam um pedido subespecificado em um programa executável. Modelos de linguagem aprendem padrões de código por predição do próximo token, então implementações familiares viram o ponto de partida natural da geração — e, quando um argumento fica de fora, a biblioteca fornece o valor, deixando uma escolha estatística migrar da convenção para o seu pipeline sem nunca entrar na conversa.
O perigo é sutil: receber código que funciona não é evidência de que essas escolhas foram examinadas. A omissão passa despercebida justamente porque nada quebra. Abaixo, cinco padrões do scikit-learn que aparecem com frequência em produção e já causaram dores de cabeça reais.
1. RandomForestRegressor(max_features=1.0)
Se você aprendeu random forest como “faça bootstrap das linhas, subamostre as features e tire a média das árvores”, o regressor padrão guarda uma surpresa: o RandomForestClassifier usa max_features="sqrt", mas o RandomForestRegressor usa max_features=1.0 — ou seja, todas as features disponíveis em cada divisão.
Isso desliga a subamostragem de features que distingue a receita clássica de random forest do simples bagging. O bootstrap continua lá, então as árvores seguem aleatórias pelas linhas que recebem — mas a segunda camada de aleatoriedade (restringir deliberadamente quais features cada split pode considerar) desaparece.
Por que isso importa? Imagine um dataset com um preditor muito forte, como preço ou desconto em um modelo de vendas. Mesmo com amostras de bootstrap diferentes, o preço pode continuar vencendo as divisões iniciais, porque o sinal sobrevive às variações nas linhas de treino. As árvores acabam desenvolvendo estruturas parecidas e a média reduz menos a variabilidade compartilhada. A subamostragem interrompe essa repetição ao ocasionalmente excluir o preditor dominante da consideração. Definir max_features=0.33, por exemplo, disponibiliza cerca de um terço das features em cada split e restaura essa parte da receita.
2. LogisticRegression(C=1.0)
Ao pedir uma regressão logística, você talvez espere um modelo que encontre os coeficientes que melhor explicam os resultados observados. O que LogisticRegression() realmente ajusta é uma versão regularizada, com penalidade L2 e um C=1.0 que determina o quanto essa penalidade compete com o ajuste aos dados.
O problema é que o número 1.0 não sabe nada sobre o seu problema — e, pior, “coeficiente grande” depende de como você mediu a feature. Suponha que a renda seja registrada em reais e o coeficiente seja 0,0001. Expresse a mesma renda em milhares de reais e o coeficiente vira 0,1, mantendo a mesma contribuição à predição. A informação não mudou, mas a contribuição à penalidade L2 (que eleva os coeficientes ao quadrado) fica um milhão de vezes maior. Um ponto de partida prático é padronizar as features contínuas dentro de um Pipeline e depois ajustar C com validação adequada.
3. cross_val_score(model, X, y, cv=5)
Validação cruzada de cinco dobras soa como uma checagem tranquilizadora — mas cv=5 especifica o número de dobras enquanto deixa outra decisão para o scikit-learn: como essas dobras são construídas. Para regressão, o padrão é KFold com shuffle=False, ou seja, as dobras de validação são blocos consecutivos na ordem em que as linhas estão.
Se o seu dataframe está ordenado por data, cliente ou região, essa ordem vira parte do desenho da avaliação, queira você ou não. Em 100 semanas de vendas organizadas cronologicamente, a primeira dobra avalia as semanas 1–20 depois de treinar nas semanas 21–100 — o modelo usa o futuro para prever o passado. O código roda perfeitamente, mas o experimento não representa previsão. Para previsão temporal, use um esquema baseado em tempo; para previsões sobre novos clientes, um splitter agrupado que mantenha cada cliente inteiro em um lado só da fronteira treino-validação.
4. KMeans(n_init=”auto”)
“Auto” soa reconfortante — mas, com a inicialização padrão init="k-means++", n_init="auto" significa exatamente uma execução completa. O KMeans parte de um conjunto inicial de centros e converge para um mínimo local que iterações posteriores não escapam. Múltiplas inicializações repetem o procedimento inteiro de pontos de partida diferentes e ficam com a de menor inércia.
O k-means++ escolhe centros iniciais com mais cuidado, tornando uma única execução um atalho computacional razoável — mas não garante que outra inicialização não produziria solução melhor. Aumentar max_iter não restaura as reinicializações ausentes: apenas permite mais atualizações dentro de cada execução. Se você quer múltiplas tentativas, peça explicitamente (por exemplo, n_init=10) e aceite o custo extra.
5. SimpleImputer(keep_empty_features=False)
Você adiciona SimpleImputer() ao pipeline esperando preencher valores ausentes, mas os padrões também permitem que ele remova colunas inteiras. Com a estratégia de média padrão, qualquer feature que contenha apenas valores ausentes no treino não tem média para calcular — então o imputer a descarta da saída transformada. Um modelo que você ainda pensa como “20 features” pode, na prática, treinar com 19.
Quando dados novos chegam com valores reais naquela coluna antes vazia, o imputer ajustado continua removendo-a, porque a decisão foi tomada no treino. E, pior: nenhum erro é lançado. O modelo recebeu 19 features no treino e recebe as mesmas 19 na predição — tudo roda normalmente, o que torna a mudança fácil de não notar. Definir keep_empty_features=True preserva as colunas, mas a lição central é outra: inspecione o que o pré-processamento realmente passa adiante, incluindo nomes e formato das features de saída.
O ponto
Nenhum desses casos é um bug — existem boas razões para os padrões, de eficiência computacional a facilitar fluxos comuns. O problema começa quando os aceitamos sem notar as escolhas que fazem, sobretudo quando o código executa limpo e o resultado parece plausível. Assistentes de codificação facilitam carregar essas omissões adiante, porque uma implementação familiar chega pronta antes de discutirmos as premissas por trás dela.
É aí que a experiência ainda importa: reconhecer quais escolhas aparentemente rotineiras merecem uma segunda olhada e pedir a explicação dos padrões junto com a implementação. Às vezes o desfecho certo é manter o padrão — mas com clareza do porquê. O trabalho nunca foi só digitar as quatro linhas; era saber quais perguntas elas deixaram sem resposta.
Descubra mais sobre noticiAI
Assine para receber nossas notícias mais recentes por e-mail.



