zoukankan      html  css  js  c++  java
  • 13-垃圾邮件分类2

    文本特征提取:

    把文本数据转化成特征向量的过程,比较常用的文本特征表示法为词袋法
    词集:0、1

    词袋模型:

    不考虑词语出现的顺序怕,每个出现过的词汇单独作为一列特征,这些不重复的特征词汇集合为词表[room desk]10000
    每一个文本都可以在很长的词表上统计出一个很多列的特征向量[2, 0, 0, 0, 0, 0, 0, 0]10000
    如果每个文本都出现的词汇,一般被标记为停用词不计入特征向量

    TF-IDF 概念

    1. 是一种统计方法,用以评估一个词对于一个语料库中一份文件的重要程度。
    2. 词的重要性随着在文件中出现的次数正比增加,同时随着它在语料库其他文件中出现的频率反比下降。就是说一个词在某一个文档中出现次数比较多,其他文档没有出现,说明该词对该份文档分类很重要。然而如果其他文档也出现比较多,说明该词区分性不大,就用IDF来降低该词的权重。

    TF-IDF “词频-逆文本频率指数”

    TF-IDF(Term Frequency - Inverse Document Frequency)

    词频:TF = 词在文档中出现的次数 / 文档中总词数

    逆文档频率:IDF = log[ (语料库中的文档总数 / (包含词条w的文档数 + 1) ],分母加1,是为了避免分母为0

    TF-IDF = TF(词频) * IDF(逆文档频率)

    TF:词频,文本中各个词的出现频率统计,并作为文本特征,这个很好理解。big:tf = 30 / 240

    IDF:逆文本频率,其他文本里面都没有出现big,idf = log(101 / 2)。->∞

    其他99篇文本里都出现big,log(100 / 101)。->0

    概括来讲,IDF反应了一个词在所有文本中出现的频率,如果一个词在很多的文本中出现,那么它的IDF值应该低。而反过来如果一个词在比较少的文本中出现,那么它的IDF值应该高,比如一些专业的名词如”Machine Learning“,这样的词IDF值应该高。一个极端的情况,如果一个词在所有的文本中都出现,那么它的IDF值应该为0。


    1.读取

    2.数据预处理

    3.数据划分—训练集和测试集数据划分

    from sklearn.model_selection import train_test_split

    x_train,x_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=0, stratify=target)

    4.文本特征提取

    sklearn.feature_extraction.text.CountVectorizer

    https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html?highlight=sklearn%20feature_extraction%20text%20tfidfvectorizer

    sklearn.feature_extraction.text.TfidfVectorizer

    https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html?highlight=sklearn%20feature_extraction%20text%20tfidfvectorizer#sklearn.feature_extraction.text.TfidfVectorizer

    from sklearn.feature_extraction.text import TfidfVectorizer

    tfidf2 = TfidfVectorizer()

    观察邮件与向量的关系

    向量还原为邮件

    4.模型选择

    from sklearn.naive_bayes import GaussianNB

    from sklearn.naive_bayes import MultinomialNB

    说明为什么选择这个模型?

       模型需要根据数据集中特征的特点来进行选取,垃圾邮件分类重点在于文档中单词出现的频率以及文档的重要性,数据并不符合正态分布的特征,并且垃圾邮件判定过程是一个随机事件,单词在邮件中出现的次数并不是固定的,因此不能选择高斯型分布模型,此处选择多项式分布模型。比如鸢尾花数据,其中判定是否是鸢尾花需要通过4种特征判断,并且这4种特征大小分布范围呈正态分布形状,因此鸢尾花的判断可以采用高斯型分布较为合适。

    5.模型评价:混淆矩阵,分类报告

    from sklearn.metrics import confusion_matrix

    confusion_matrix = confusion_matrix(y_test, y_predict)

    说明混淆矩阵的含义

    from sklearn.metrics import classification_report

    说明准确率、精确率、召回率、F值分别代表的意义 。

    混淆矩阵(confusion-matrix)

    TP(True Positive):真实为0,预测也为0

    FN(False Negative):真实为0,预测为1

    FP(False Positive):真实为1,预测为0

    TN(True Negative):真实为1,预测也为1

    TP FN
    FP TN

    准确率:代表分类器对整个样本判断正确的比重。

     精确率:指被分类器判断正例中的正样本的比重。

     

     召回率:指被预测为正例的占总的正例的比重。

     

    F1-score:是分类问题的一个衡量指标。一些多分类问题的机器学习竞赛,常常将F1-score作为最终测评的方法。它是精确率和召回率的调和平均数,最大为1,最小为0。

    6.比较与总结

    如果用CountVectorizer进行文本特征生成,与TfidfVectorizer相比,效果如何?

    CountVectorizer

    • 只考虑词汇在文本中出现的频率

    TfidfVectorizer:

    • 除了考量某词汇在本文本中出现的频率,还关注包含这个词的其他文本的数量
    • 能够削减高频没有意义的词汇出现带来的影响,挖掘更有意义的特征

     代码实现:

      1 from nltk.corpus import stopwords
      2 from nltk.stem import WordNetLemmatizer
      3 from sklearn.model_selection import train_test_split
      4 from sklearn.feature_extraction.text import TfidfVectorizer
      5 from sklearn.naive_bayes import MultinomialNB
      6 from sklearn.metrics import confusion_matrix, classification_report
      7 import nltk
      8 import csv
      9 import numpy as np
     10 
     11 
     12 def get_wordnet_pos(treebank_tag):  # 根据词性,生成还原参数pos
     13     """
     14     根据词性,生成还原参数 pos
     15     """
     16     if treebank_tag.startswith('J'):  # 形容词
     17         return nltk.corpus.wordnet.ADJ
     18     elif treebank_tag.startswith('V'):  # 动词
     19         return nltk.corpus.wordnet.VERB
     20     elif treebank_tag.startswith('N'):  # 名词
     21         return nltk.corpus.wordnet.NOUN
     22     elif treebank_tag.startswith('R'):  # 副词
     23         return nltk.corpus.wordnet.ADV
     24     else:
     25         return nltk.corpus.wordnet.NOUN
     26 
     27 
     28 def preprocessing(text):
     29     """
     30     预处理
     31     """
     32     # text = text.decode("utf-8")
     33     tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]  # 分词
     34     stops = stopwords.words('english')  # 使用英文的停用词表
     35     tokens = [token for token in tokens if token not in stops]  # 去除停用词
     36 
     37     tokens = [token.lower() for token in tokens if len(token) >= 3]  # 大小写,短词
     38     lmtzr = WordNetLemmatizer()
     39     tag = nltk.pos_tag(tokens)  # 词性
     40     tokens = [lmtzr.lemmatize(token, pos=get_wordnet_pos(tag[i][1])) for i, token in enumerate(tokens)]  # 词性还原
     41     preprocessed_text = ' '.join(tokens)
     42     return preprocessed_text
     43 
     44 
     45 def create_dataset():
     46     """
     47     导入数据
     48     """
     49     file_path = r'D://PycharmProjects//naive_bayes//data//SMSSpamCollection'
     50     sms = open(file_path, encoding='utf-8')
     51     sms_data = []
     52     sms_label = []
     53     csv_reader = csv.reader(sms, delimiter='	')
     54     for line in csv_reader:
     55         sms_label.append(line[0])  # 提取出标签
     56         sms_data.append(preprocessing(line[1]))  # 提取出特征
     57     sms.close()
     58     # print("数据集标签:
    ", sms_label)
     59     # print("数据集特征:
    ", sms_data)
     60     return sms_data, sms_label
     61 
     62 
     63 def revert_mail(x_train, X_train, model):
     64     """
     65     向量还原成邮件
     66     """
     67     s = X_train.toarray()[0]
     68     print("=====================================================")
     69     print("第一封邮件向量表示为:", s)
     70     # 该函数输入一个矩阵,返回扁平化后矩阵中非零元素的位置(index)
     71     a = np.flatnonzero(X_train.toarray()[0])  # 非零元素的位置(index)
     72     print("向量的非零元素的值:", s[a])
     73     b = model.vocabulary_  # 词汇表
     74     key_list = []
     75     for key, value in b.items():
     76         if value in a:
     77             key_list.append(key)  # key非0元素对应的单词
     78     print("向量非零元素对应的单词:", key_list)
     79     print("向量化之前的邮件:", x_train[0])
     80 
     81 
     82 def split_dataset(data, label):
     83     """
     84     划分数据集
     85     """
     86     x_train, x_test, y_train, y_test = train_test_split(data, label, test_size=0.2, random_state=0, stratify=label)
     87     tfidf2 = TfidfVectorizer()
     88     X_train = tfidf2.fit_transform(x_train)  # X_train用fit_transform生成词汇表
     89     X_test = tfidf2.transform(x_test)  # X_test要与X_train词汇表相同,因此在X_train进行fit_transform基础上进行transform操作
     90     revert_mail(x_train, X_train, tfidf2)
     91 
     92     return X_train, X_test, y_train, y_test
     93 
     94 
     95 def mnb_model(x_train, x_test, y_train):
     96     """
     97     模型构建(根据数据特点选择多项式分布)
     98     """
     99     mnb = MultinomialNB()
    100     mnb.fit(x_train, y_train)
    101     y_mnb = mnb.predict(x_test)
    102     return y_mnb
    103 
    104 
    105 def class_report(y_mnb, y_test):
    106     """
    107     模型评价:混淆矩阵
    108     """
    109     conf_matrix = confusion_matrix(y_test, y_mnb)
    110     print("=====================================================")
    111     print("混淆矩阵:
    ", conf_matrix)
    112     cr = classification_report(y_test, y_mnb)
    113     print("=====================================================")
    114     print("分类报告:
    ", cr)
    115     print("模型准确率:", (conf_matrix[0][0] + conf_matrix[1][1]) / np.sum(conf_matrix))
    116 
    117 
    118 if __name__ == '__main__':
    119     sms_data, sms_label = create_dataset()
    120     X_train, X_test, y_train, y_test = split_dataset(sms_data, sms_label)
    121     y_mnb = mnb_model(X_train, X_test, y_train)
    122     class_report(y_mnb, y_test)

    运行结果:

  • 相关阅读:
    Leetcode 50.Pow(x,n) By Python
    Leetcode 347.前K个高频元素 By Python
    Leetcode 414.Fizz Buzz By Python
    Leetcode 237.删除链表中的节点 By Python
    Leetcode 20.有效的括号 By Python
    Leetcode 70.爬楼梯 By Python
    Leetcode 190.颠倒二进制位 By Python
    团体程序设计天梯赛 L1-034. 点赞
    Wannafly挑战赛9 C-列一列
    TZOJ Start
  • 原文地址:https://www.cnblogs.com/xiaolan-Lin/p/12930597.html
Copyright © 2011-2022 走看看