Detecção de Fraudes — Como foi feito (explicado fácil)
Pensa numa cidade com 1,3 milhão de moradores. Cerca de 7 mil deles são bandidos. Tem polícia em toda esquina? Não — precisa saber em quais bairros a coisa pega mais. Aqui fiz isso com transações de cartão: onde a fraude se concentra?
O que é isso, em uma frase?
É uma análise sobre 1,3 milhão de transações de cartão (dataset do Kaggle) que responde: quais categorias de comércio têm maior taxa de fraude?. Não é um modelo — é o trabalho antes do modelo, que diz onde a fraude vive.
O problema central é desbalanceio: só ~0,5% das transações são fraude. Um modelo que chuta "tudo normal" acerta 99,5% e parece um gênio — mas é inútil. Por isso a primeira coisa é entender onde e como a fraude se distribui.
Por que importa? Banco/cartão não tem cérebro infinito. Saber que "compras online de eletrônicos" têm 3× a taxa global muda a regra de monitoramento — pode pedir 2FA só nessas, e deixar transações no posto de gasolina passar mais leves.
Achando os "bairros perigosos"
1 · Carregar com dtypes compactos. 1,3 milhão de linhas em Python explode RAM se a gente não cuidar. Uso category pra texto repetido e int8/float32 pra números — reduz uso de memória em 5-10×.
df = pd.read_csv(
"fraudTrain.csv",
usecols=["category", "amt", "is_fraud"],
dtype={"category": "category", "amt": "float32", "is_fraud": "int8"},
)
print(f"{len(df):,} linhas, RAM: {df.memory_usage(deep=True).sum()/1e6:.1f} MB")
2 · Calcular a taxa global. Antes de comparar, preciso saber qual é a média. is_fraud é 0 ou 1 — então a média é a proporção de 1s, ou seja, a taxa de fraude.
taxa_global = df["is_fraud"].mean() * 100
print(f"Taxa global de fraude: {taxa_global:.3f}%") # ~0,52%
3 · Quebrar por categoria. Aqui o groupby é o herói. Para cada categoria de comércio, calculo a média de is_fraud — que é a taxa daquela categoria — e ordeno.
g = (
df.groupby("category", observed=True)["is_fraud"]
.agg(["mean", "count"])
)
g["taxa_pct"] = g["mean"] * 100
g = g.sort_values("taxa_pct", ascending=False).head(10)
| categoria (top 3) | taxa de fraude |
|---|---|
| shopping_net | ~1,8% (3,4× a média) |
| misc_net | ~1,3% |
| grocery_pos | ~1,1% |
4 · Comparar valores entre classes. O valor médio da transação fraudulenta é diferente do normal? Pode ser maior (saquear de uma vez), pode ser pequeno (testar o cartão sem alertar). Dá pra ver com 1 linha.
por_classe = df.groupby("is_fraud")["amt"].agg(["count", "mean", "median"])
print(por_classe.round(2))
# is_fraud count mean median
# 0 ~1.290.000 67.23 47.50
# 1 ~7.500 530.66 396.50 <-- valor MUITO maior na fraude
5 · Honestidade nas conclusões. Reportei tudo: a taxa global, as top categorias, a diferença de valor médio. Não inventei "modelo com 99,8% de acurácia" — porque qualquer modelo bobo bate isso. O insight real é descritivo: onde monitorar com mais força.
As categorias mais arriscadas
Em uma linha: o que esse projeto ensina
Que antes de modelar, é preciso conhecer o problema. Em classes desbalanceadas, análise descritiva inteligente vale mais que classifier mediano. Esse trabalho é o que separa o ML que funciona do ML que parece funcionar.
Coisas técnicas que apareceram aqui: Pandas com dtypes compactos (memory optimization), groupby + agg de múltiplas funções, análise de classes desbalanceadas, leitura honesta de métricas (taxa global como baseline).