-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspam.py
151 lines (121 loc) · 5.49 KB
/
spam.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 18 20:37:08 2011
@authors: Claudio, Debora, Gerson, Diego
"""
"""
PI Lista 2:
5. O arquivo spam.xls contém dados relativos a emails recebidos por um pesquisador,
classificados como spam (1) ou não spam (0). Para cada um dos emails foi tabulada a
ocorrência ou não das palavras mais comuns. Para este exercício, 10% das
mensagens de cada tipo foram extraídas, para formar um conjunto de teste, enquanto
as demais 90% permaneceram no conjunto de treinamento. Utilizando o método
“Naive Bayes”, classifique os emails do conjunto de teste em spam ou não. Tabule os
resultados, indicando o percentual de mensagens classificadas corretamente e
incorretamente em cada grupo. Envie um pequeno relatório para pcezar@,
com os seus resultados e descrevendo como implementou o classificador.
"""
import csv
from numpy import loadtxt
class Relatorio:
ACERTOS_EM_SPAM = 0
ACERTOS_EM_NAO_SPAM = 0
def __init__(self, total_de_mensagens, numero_de_spams):
self.total_de_mensagens = total_de_mensagens
self.numero_de_spams = numero_de_spams
self.numero_de_nao_spams = total_de_mensagens - numero_de_spams
acertou = "ACERTOU!"
errou = "errou..."
def __call__(self, Spam, r):
msg = ""
if Spam:
if r >= 1.0:
msg = self.acertou
self.ACERTOS_EM_SPAM += 1
else:
msg = self.errou
if not Spam:
if r < 1.0:
msg = self.acertou
self.ACERTOS_EM_NAO_SPAM += 1
else:
msg = self.errou
return "%s %s %s" % (msg, Spam, r)
def __str__(self):
msg = "\n"
msg += "em um total de %s mensagens:\n" % self.total_de_mensagens
msg += "%s acertos e %s erros em %s spams (%.2f%% correto)\n" % (
self.ACERTOS_EM_SPAM,
self.numero_de_spams-self.ACERTOS_EM_SPAM,
self.numero_de_spams,
(1.0*self.ACERTOS_EM_SPAM / self.numero_de_spams) * 100)
msg += "%s acertos e %s erros em %s NAO spams (%.2f%% correto)\n" % (
self.ACERTOS_EM_NAO_SPAM,
self.numero_de_nao_spams-self.ACERTOS_EM_NAO_SPAM,
self.numero_de_nao_spams,
(1.0*self.ACERTOS_EM_NAO_SPAM / self.numero_de_nao_spams) * 100)
return msg
class Palavra:
def __init__(self, palavra, coluna):
self.palavra = palavra.strip('\'"')
self.coluna = coluna
self.em_spam = 0
self.em_nao_spam = 0
@property
def P_em_spam(self):
return (1.0 * self.em_spam / espaco_amostral) / P_de_ser_spam
@property
def P_em_nao_spam(self):
return (1.0 * self.em_nao_spam / espaco_amostral) / P_de_nao_ser_spam
# arquivos csv para treinamento e teste:
arq_teste = 'teste.csv'
arq_treinamento = 'treinamento.csv'
# obtendo do cabecalho as palavras:
with open(arq_treinamento, 'rb') as arq:
palavras = [Palavra(palavra, n) for n, palavra in enumerate(csv.reader(arq, delimiter=';').next())]
# coluna onde as msgs estao classificadas como spam ou nao:
SPAM = 0
# obtendo os dados para treinamento como um ndarray:
treinamento = loadtxt(arq_treinamento, skiprows=1, delimiter=';')
# tamanho do espaco amostral e quantidade de spams:
espaco_amostral = len(treinamento)
numero_de_spams = list(treinamento[:,SPAM]).count(1.0)
# probabilidades de ser e nao ser spam:
P_de_ser_spam = 1.0*numero_de_spams / espaco_amostral
P_de_nao_ser_spam = 1.0 - P_de_ser_spam
# contando as palavras:
for linha in range(espaco_amostral):
for palavra in palavras:
# se a palavra esta presente...
if treinamento[linha,palavra.coluna]:
# em um spam...
if treinamento[linha,SPAM]:
palavra.em_spam += 1
# ou nao spam:
else:
palavra.em_nao_spam += 1
# obtendo dados para classificar:
teste = loadtxt(arq_teste, skiprows=1, delimiter=';')
total_de_mensagens_no_teste = len(teste)
numero_de_spams_no_teste = list(teste[:,SPAM]).count(1.0)
acertou = Relatorio(total_de_mensagens_no_teste, numero_de_spams_no_teste)
# para cada mensagem,
for linha in range(total_de_mensagens_no_teste):
Produtorio_spam = 1.0
Produtorio_nao_spam = 1.0
# para cada palavra...
for palavra in palavras[1:]:
# ...presente na mensagem...
if teste[linha,palavra.coluna]:
# ...multiplica suas probabilidades para spam e nao spam:
Produtorio_spam *= palavra.P_em_spam
Produtorio_nao_spam *= palavra.P_em_nao_spam
# em cada linha/mensagem, levando em conta as palavras...
P_spam_dado_palavras = Produtorio_spam * P_de_ser_spam
P_nao_spam_dado_palavras = Produtorio_nao_spam * P_de_nao_ser_spam
# ...calcula razao entre ser ou nao ser spam:
r = P_spam_dado_palavras / P_nao_spam_dado_palavras
# acertou?
print linha, acertou(teste[linha,SPAM], r)
# relatorio final:
print acertou