Este é realmente um problema muito profundo no qual muitas pessoas e empresas trabalharam. Aqui estão alguns princípios básicos:
Primeiro, precisamos representar bem os dados. Isso envolve, de alguma forma, representar cada documento como um vetor no espaço dimensional. Idealmente, nesse espaço, queremos que amostras com o mesmo rótulo estejam próximas à distância euclidiana e amostras com rótulos diferentes que estejam distantes na distância euclidiana. Essa etapa pode ser realmente difícil, mas uma representação testada e verdadeira é chamada de Frequência de termo inversa a frequência de documento (tf-idf). Aqui, cada dimensão no espaço representa uma palavra específica e o valor nessa dimensão para uma amostra específica representa basicamente o número normalizado de vezes que a palavra ocorre no documento. Você pode ler mais sobre isso aqui . Existe uma implementação muito boa de scikit-learn dessa representação, se você quiser experimentá-la.d
Agora, os dados estão em um espaço útil, mas em um espaço realmente de alta dimensão. Eu recomendaria reduzir essa dimensionalidade de alguma forma, mas esse é um assunto completo para outro tópico.
Finalmente, você pode treinar algum algoritmo para classificar as amostras (que é o que as outras respostas tratam). Existem muitas ótimas opções - redes neurais, adaboost, SVMs, Naive Bayes e modelos gráficos de classificação fornecerão bons resultados. Muitos deles também têm implementações no scikit-learn.
Mas os melhores algoritmos aproveitam o fato de que esse problema é realmente um aprendizado de transferência. Ou seja, as distribuições das quais os dados de treinamento e teste provêm podem não ser exatamente as mesmas - porque os tipos de coisas que uma pessoa considera spam podem ser diferentes dos tipos de coisas que outra pessoa considera spam.