Projetos
Pandas · Fraude · Desenvolvimento

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?

Nível Intermediário Stack Python · Pandas Tipo Projeto analítico
Visão geral

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.

Passo a passo

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.

Resultado

As categorias mais arriscadas

O que dá pra levar daqui

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).