Python 开发垃圾邮件检测应用 - 图1

垃圾邮件(Spam)与有效邮件(Ham)

创建一个预测文本是否是垃圾邮件的模型是最最常见的应用,尤其是出于教学目的。原始数据集来自于这个——Spam,里面数据包含以后标题行,拥有两列,第一列为 text 表示邮件内容,第二列为 target 值为 spam 或 ham 分别表示垃圾邮件与非垃圾邮件。

  1. import pandas as pd
  2. import numpy as np
  3. from sklearn.metrics import roc_auc_score
  4. from sklearn.feature_extraction.text import TfidfVectorizer
  5. from sklearn.model_selection import train_test_split
  6. from sklearn.linear_model import LogisticRegression
  7. spam_data = pd.read_csv('spam.csv')
  8. spam_data['target'] = np.where(spam_data['target']=='spam',1,0)
  9. spam_data.head(10)

输出结果:
Python 开发垃圾邮件检测应用 - 图2

将数据拆分为训练集和测试集

  1. X_train, X_test, y_train, y_test = train_test_split(spam_data['text'],
  2. spam_data['target'],
  3. random_state=0)

在 N-gram 上构建 tf-idf

使用 sklearn 库中的 TfidfVectorizer 来转换并训练数据 X_train,忽略掉数据字典中出现频次小于 5 的数据,同时让 n-grams 取值从 1 到 3

  1. vect = TfidfVectorizer(min_df=5, ngram_range=(1,3)).fit(X_train) X_train_vectorized = vect.transform(X_train)

添加特殊字符

除了基本字符之外,需要添加诸如:数字美元符号长度等这些除字母、数字及下划线以外字符。下面编写一个函数来实现这个:

  1. def add_feature(X, feature_to_add):
  2. """
  3. Returns sparse feature matrix with added feature.
  4. feature_to_add can also be a list of features.
  5. """
  6. from scipy.sparse import csr_matrix, hstack
  7. return hstack([X, csr_matrix(feature_to_add).T], 'csr')
  8. # 训练数据
  9. add_length=X_train.str.len()
  10. add_digits=X_train.str.count(r'\d')
  11. add_dollars=X_train.str.count(r'\$')
  12. add_characters=X_train.str.count(r'\W')
  13. X_train_transformed = add_feature(X_train_vectorized , [add_length, add_digits, add_dollars, add_characters])
  14. # 测试数据
  15. add_length_t=X_test.str.len()
  16. add_digits_t=X_test.str.count(r'\d')
  17. add_dollars_t=X_test.str.count(r'\$')
  18. add_characters_t=X_test.str.count(r'\W')
  19. X_test_transformed = add_feature(vect.transform(X_test), [add_length_t, add_digits_t, add_dollars_t, add_characters_t])

训练逻辑回归模型

下面将简历逻辑回归模型,并统计测试集的 AUC 得分(译者注:AUC 指的是 ROC 曲线下与坐标轴围成的面积,取值一般在 0.5和 1 之间,越接近 1 表示数据越真实有效)。

  1. clf = LogisticRegression(C=100, solver='lbfgs', max_iter=1000)
  2. clf.fit(X_train_transformed, y_train)
  3. y_predicted = clf.predict(X_test_transformed)
  4. auc = roc_auc_score(y_test, y_predicted)
  5. auc

输出结果:

  1. 0.9674528462047772

取得对结果影响最大的特征词

下面将取得对是否垃圾邮件的预测结果影响排名靠前的 50 个特征词。

  1. feature_names = np.array(vect.get_feature_names() + ['lengthc', 'digit', 'dollars', 'n_char'])
  2. sorted_coef_index = clf.coef_[0].argsort()
  3. smallest = feature_names[sorted_coef_index[:50]]
  4. largest = feature_names[sorted_coef_index[:-51:-1]]

*影响判断为垃圾邮件的特征词排名前 50

  1. largest

输出结果:

  1. array(['text', 'sale', 'free', 'uk', 'content', 'tones', 'sms', 'reply', 'order', 'won', 'ltd', 'girls', 'ringtone', 'to', 'comes', 'darling', 'this message', 'what you', 'new', 'www', 'co uk', 'std', 'co', 'about the', 'strong', 'txt', 'your', 'user', 'all of', 'choose', 'service', 'wap', 'mobile', 'the new', 'with', 'sexy', 'sunshine', 'xxx', 'this', 'hot', 'freemsg', 'ta', 'waiting for your', 'asap', 'stop', 'll have', 'hello', 'http', 'vodafone', 'of the'], dtype='<U31')

影响判断为正常邮件的特征词排名前 50

  1. smallest

输出结果:

  1. array(['ì_ wan', 'for 1st', 'park', '1st', 'ah', 'wan', 'got', 'say', 'tomorrow', 'if', 'my', 'ì_', 'call', 'opinion', 'days', 'gt', 'its', 'lt', 'lovable', 'sorry', 'all', 'when', 'can', 'hope', 'face', 'she', 'pls', 'lt gt', 'hav', 'he', 'smile', 'wife', 'for my', 'trouble', 'me', 'went', 'about me', 'hey', '30', 'sir', 'lovely', 'small', 'sun', 'silent', 'me if', 'happy', 'only', 'them', 'my dad', 'dad'], dtype='<U31')

总结

这里提供了一个使用且可复现的用于预测是否垃圾邮件的算法示例,类似这样的预测算法正式自然语言处理(NLP)领域的主要任务之一。我们上面开发的这个模型 AUC 得分高达 0.97,这已经相当不错了。这套模型还可以继续添加测试用特征词,以便更准确的识别出垃圾邮件中经常特征词,反之亦然。

如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏