当前位置:   article > 正文

最简数据挖掘|垃圾邮件分类_预测电子邮件的垃圾邮件 文本挖掘

预测电子邮件的垃圾邮件 文本挖掘

目录

一、数据介绍

二、文本预处理

1、预处理

2、划分训练、测试集

三、特征构建

1、tf-词频统计特征

2、tf-idf统计特征

三、模型构建及评估

四、划重点

少走10年弯路


一、数据介绍

        数据源自最简数据挖掘系列,Email英文的邮件内容,其中Label列ham为正常邮件、spam为垃圾邮件。数据获取见文末

图片

        统计邮件是否为垃圾邮件的标签分布如下,可以看到4458样本中有592条垃圾邮件

图片

、文本预处理

1、预处理

        处理简写、小写化、去除停用词、词性还原

  1. from nltk.stem import WordNetLemmatizer
  2. from nltk.corpus import stopwords
  3. from nltk.tokenize import sent_tokenize
  4. import nltk
  5. def replace_abbreviation(text):
  6. rep_list=[
  7. ("it's", "it is"),
  8. ("i'm", "i am"),
  9. ("he's", "he is"),
  10. ("she's", "she is"),
  11. ("we're", "we are"),
  12. ("they're", "they are"),
  13. ("you're", "you are"),
  14. ("that's", "that is"),
  15. ("this's", "this is"),
  16. ("can't", "can not"),
  17. ("don't", "do not"),
  18. ("doesn't", "does not"),
  19. ("we've", "we have"),
  20. ("i've", " i have"),
  21. ("isn't", "is not"),
  22. ("won't", "will not"),
  23. ("hasn't", "has not"),
  24. ("wasn't", "was not"),
  25. ("weren't", "were not"),
  26. ("let's", "let us"),
  27. ("didn't", "did not"),
  28. ("hadn't", "had not"),
  29. ("waht's", "what is"),
  30. ("couldn't", "could not"),
  31. ("you'll", "you will"),
  32. ("i'll", "i will"),
  33. ("you've", "you have")
  34. ]
  35. result = text.lower()
  36. for word_replace in rep_list:
  37. result=result.replace(word_replace[0],word_replace[1])
  38. return result
  39. def drop_char(text):
  40. result=text.lower()
  41. result=re.sub('[^\w\s]',' ',result) # 去掉标点符号、特殊字符
  42. result=re.sub('\s+',' ',result) # 多空格处理为单空格
  43. return result
  44. def stemed_words(text,stop_words,lemma):
  45. word_list = [lemma.lemmatize(word, pos='v') for word in text.split() if word not in stop_words]
  46. result=" ".join(word_list)
  47. return result
  48. def text_preprocess(text):
  49. if pd.isnull(text):
  50. return None
  51. stop_words = stopwords.words("english")
  52. lemma = WordNetLemmatizer()
  53. result=replace_abbreviation(text)
  54. result=drop_char(result)
  55. result=stemed_words(result,stop_words,lemma)
  56. return result

2、划分训练、测试集

  1. test_index=list(df.sample(int(df.shape[0]*0.7)).index)
  2. df['label']=np.where(df.index.isin(test_index),'test','train')
  3. df['label'].value_counts()

三、特征构建

1、tf-词频统计特征

  1. def tf_init_params():
  2. params_count={
  3. 'analyzer': 'word', # 取值'word'-分词结果为词级、'char'-字符级(结果会出现he is,空格在中间的情况)、'char_wb'-字符级(以单词为边界),默认值为'word'
  4. 'binary': False, # boolean类型,设置为True,则所有非零计数都设置为1.(即,tf的值只有0和1,表示出现和不出现)
  5. 'decode_error': 'strict',
  6. 'dtype': np.float64, # 输出矩阵的数值类型
  7. 'encoding': 'utf-8',
  8. 'input': 'content', # 取值filename,文本内容所在的文件名;file,序列项必须有一个'read'方法,被调用来获取内存中的字节;content,直接输入文本字符串
  9. 'lowercase': True, # boolean类型,计算之前是否将所有字符转换为小写。
  10. 'max_df': 1.0, # 词汇表中忽略文档频率高于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
  11. 'min_df': 1, # 词汇表中忽略文档频率低于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
  12. 'max_features': 50, # int或 None(默认值).设置int值时建立一个词汇表,仅用词频排序的前max_features个词创建语料库;如果设置了vocabulary,则忽略此参数。
  13. 'ngram_range': (1, 2), # 要提取的n-grams中n值范围的下限和上限,min_n <= n <= max_n。
  14. 'preprocessor': None, # 覆盖预处理(字符串转换)阶段,同时保留标记化和 n-gram 生成步骤。仅适用于analyzer不可调用的情况。
  15. 'stop_words': 'english', # 仅适用于analyzer='word'。取值english,使用内置的英语停用词表;list,自行设置停停用词列表;默认值None,不会处理停用词
  16. 'strip_accents': None,
  17. 'token_pattern': '(?u)\\b\\w\\w+\\b', # 分词方式、正则表达式,默认筛选长度>=2的字母和数字混合字符(标点符号被当作分隔符)。仅在analyzer='word'时使用。
  18. 'tokenizer': None, # 覆盖字符串标记化步骤,同时保留预处理和 n-gram 生成步骤。仅适用于analyzer='word'
  19. 'vocabulary': None, # 自行设置词汇表(可设置字典),如果没有给出,则从输入文件/文本中确定词汇表
  20. }
  21. return params_count
  22. def CountVectorizer_train(train_data,params):
  23. cv = CountVectorizer(**params)
  24. # 输入训练集矩阵,每行表示一个文本
  25. # 训练,构建词汇表以及词项idf值,并将输入文本列表转成VSM矩阵形式
  26. cv_fit = cv.fit_transform(train_data)
  27. return cv
  28. train_data = ["Chinese Beijing Chinese",
  29. "Chinese Chinese Shanghai",
  30. "Chinese Macao",
  31. "Tokyo Japan Chinese"]
  32. params=tf_init_params()
  33. cv_model=CountVectorizer_train(df[df.label=='train'].clean_text,params)
  34. df_tf=pd.DataFrame(cv_model.transform(df.clean_text).toarray(),columns=cv_model.get_feature_names_out()).add_prefix('tf_')
  35. df_tf

图片

2、tf-idf统计特征

  1. def tfidf_init_params():
  2. params={
  3. 'analyzer': 'word', # 取值'word'-分词结果为词级、'char'-字符级(结果会出现he is,空格在中间的情况)、'char_wb'-字符级(以单词为边界),默认值为'word'
  4. 'binary': False, # boolean类型,设置为True,则所有非零计数都设置为1.(即,tf的值只有0和1,表示出现和不出现)
  5. 'decode_error': 'strict',
  6. 'dtype': np.float64, # 输出矩阵的数值类型
  7. 'encoding': 'utf-8',
  8. 'input': 'content', # 取值filename,文本内容所在的文件名;file,序列项必须有一个'read'方法,被调用来获取内存中的字节;content,直接输入文本字符串
  9. 'lowercase': True, # boolean类型,计算之前是否将所有字符转换为小写。
  10. 'max_df': 1.0, # 词汇表中忽略文档频率高于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
  11. 'min_df': 1, # 词汇表中忽略文档频率低于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
  12. 'max_features': 50, # int或 None(默认值).设置int值时建立一个词汇表,仅用词频排序的前max_features个词创建语料库;如果设置了vocabulary,则忽略此参数。
  13. 'ngram_range': (1, 1), # 要提取的n-grams中n值范围的下限和上限,min_n <= n <= max_n。
  14. 'norm': None, # 输出结果是否标准化/归一化。l2:向量元素的平方和为1,当应用l2范数时,两个向量之间的余弦相似度是它们的点积;l1:向量元素的绝对值之和为1
  15. 'preprocessor': None, # 覆盖预处理(字符串转换)阶段,同时保留标记化和 n-gram 生成步骤。仅适用于analyzer不可调用的情况。
  16. 'smooth_idf': True, # 在文档频率上加1来平滑 idf ,避免分母为0
  17. 'stop_words': 'english', # 仅适用于analyzer='word'。取值english,使用内置的英语停用词表;list,自行设置停停用词列表;默认值None,不会处理停用词
  18. 'strip_accents': None,
  19. 'sublinear_tf': False, # 应用次线性 tf 缩放,即将 tf 替换为 1 + log(tf)
  20. 'token_pattern': '(?u)\\b\\w\\w+\\b', # 分词方式、正则表达式,默认筛选长度>=2的字母和数字混合字符(标点符号被当作分隔符)。仅在analyzer='word'时使用。
  21. 'tokenizer': None, # 覆盖字符串标记化步骤,同时保留预处理和 n-gram 生成步骤。仅适用于analyzer='word'
  22. 'use_idf': True, # 是否计算idf,布尔值,False时idf=1。
  23. 'vocabulary': None, # 自行设置词汇表(可设置字典),如果没有给出,则从输入文件/文本中确定词汇表
  24. }
  25. return params
  26. def TfidfVectorizer_train(train_data,params):
  27. tv = TfidfVectorizer(**params)
  28. # 输入训练集矩阵,每行表示一个文本
  29. # 训练,构建词汇表以及词项idf值,并将输入文本列表转成VSM矩阵形式
  30. tv_fit = tv.fit_transform(train_data)
  31. return tv
  32. tfidf_model=TfidfVectorizer_train(df[df.label=='train'].clean_text,tfidf_init_params())
  33. df_tfidf=pd.DataFrame(tfidf_model.transform(df.clean_text).toarray(),columns=tfidf_model.get_feature_names_out()).add_prefix('tfidf_')
  34. df_tfidf

图片

三、模型构建及评估

        分别使用tf特征、tfidf特征、tf+tfidf特征构建二分类模型,对比评估模型效果如下

图片

  1. def init_params():
  2. params_lgb={
  3. 'boosting_type': 'gbdt',
  4. 'objective': 'binary',
  5. 'metric':'auc',
  6. 'n_jobs': 8,
  7. 'n_estimators':300,
  8. 'learning_rate': 0.01,
  9. 'max_depth':3,
  10. 'num_leaves': 8,
  11. 'max_bin':255,
  12. 'subsample_for_bin':100000,
  13. 'min_split_gain':0,
  14. 'min_child_samples':1,
  15. 'colsample_bytree': 0.8,
  16. 'subsample': 0.8,
  17. 'subsample_freq': 1,
  18. 'feature_fraction_seed':2,
  19. 'bagging_seed': 1,
  20. 'reg_alpha':1,
  21. 'reg_lambda':1,
  22. 'scale_pos_weight':1,
  23. 'silent':True,
  24. 'random_state':1,
  25. 'verbose':-1, # 控制模型训练过程的输出信息,-1为不输出信息
  26. }
  27. return params_lgb
  28. def ks_auc_value(y_true,df,model):
  29. y_pred=model.predict_proba(df)[:,1]
  30. fpr,tpr,thresholds= roc_curve(list(y_true),list(y_pred))
  31. ks=max(tpr-fpr)
  32. auc= roc_auc_score(list(y_true),list(y_pred))
  33. return ks,auc
  34. def model_train_sklearn(train,y_name,fea_list):
  35. params=init_params()
  36. x_train,x_test =df[df.label=='train'][fea_list],df[df.label=='test'][fea_list]
  37. y_train,y_test =df[df.label=='train'][y_name],df[df.label=='test'][y_name]
  38. model=lgb.LGBMClassifier(**params)
  39. model.fit(x_train,y_train,eval_set=[(x_train, y_train),(x_test, y_test)])
  40. train_ks,train_auc=ks_auc_value(y_train,x_train,model)
  41. test_ks,test_auc=ks_auc_value(y_test,x_test,model)
  42. dic={
  43. 'train_good':(y_train.count()-y_train.sum()),
  44. 'train_bad':y_train.sum(),
  45. 'test_good':(y_test.count()-y_test.sum()),
  46. 'test_bad':y_test.sum(),
  47. 'train_ks':train_ks,
  48. 'train_auc':train_auc,
  49. 'test_ks':test_ks,
  50. 'test_auc':test_auc,
  51. }
  52. return dic,model

四、划重点

少走10年弯路

        关注威信公众号 Python风控模型与数据分析,回复 垃圾邮件分类 获取本篇数据及代码

        还有更多理论、代码分享等你来拿

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/725449
推荐阅读
相关标签
  

闽ICP备14008679号