机器学习——13-垃圾邮件分类2

1.读取

file_path=r'C:\Users\AAAA\PycharmProjects\untitled\data\SMSSpamCollection' #读取文件
sms=open(file_path,'r',encoding='utf-8')   #打开文件
sms_data=[]
sms_label=[]
csv_reader=csv.reader(sms,delimiter='\t')  #读取文件
for line in csv_reader:     #对每封邮件做预处理
    sms_label.append(line[0])      #第一个字段存为一个类别,标签
    sms_data.append(preprocessing(line[1])) #第二个字段存为一个类别,邮件内容
sms.close()
print("邮件类别:",sms_label)
print("处理后的邮件内容:",sms_data)

 

2.数据预处理  

注意:preprocessed_text = '  '.join(tokens) 引号里面要加空格

import csv
import nltk
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer

def get_wordnet_pos(treebank_tag):#根据词性,生成还原参数pos
    if treebank_tag.startswith('J'):
        return nltk.corpus.wordnet.ADJ
    elif treebank_tag.startswith('V'):
        return nltk.corpus.wordnet.VERB
    elif treebank_tag.startswith('N'):
        return nltk.corpus.wordnet.NOUN
    elif treebank_tag.startswith('R'):
        return nltk.corpus.wordnet.ADV
    else:
        return nltk.corpus.wordnet.NOUN
def preprocessing(text): #预处理
tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]#分词
print("去掉停用词前数据长度:", len(tokens))
stops = stopwords.words("english")#停用词
tokens = [token for token in tokens if token not in stops]#
print("去掉停用词后数据长度:",len(tokens))
tokens = [token.lower() for token in tokens if len(token) >= 3]#将大写字母变为小写

lemmatizer = WordNetLemmatizer() #构建词性转换器
tag = nltk.pos_tag(tokens) #
词性标注

tokens = [lemmatizer.lemmatize(token, pos=get_wordnet_pos(tag[i][1])) for i, token in enumerate(tokens)]
preprocessed_text = ' '.join(tokens)
return preprocessed_text #返回处理结果

  

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=y_train)

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(sms_data, sms_label, test_size=0.2,
                                                    random_state=0,stratify=sms_label)
print('原数据长度:', len(sms_data),
      '\n训练数据长度:', len(x_train),
      '\n测试数据长度:', len(x_test))

  

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()

#向量化
from sklearn.feature_extraction.text import TfidfVectorizer

tfidf2 = TfidfVectorizer()
X_train = tfidf2.fit_transform(x_train)
X_test = tfidf2.transform(x_test)
print('邮件以及向量关系数组:\n', X_train.toarray())
print('X_train矩阵:', X_train.toarray().shape, '\nX_test矩阵:', X_test.toarray().shape)   #第一个数为邮件数,第二个数为单词数
print('词汇表:\n', tfidf2.vocabulary_)  #第一个为单词,第二个为该单词下标

观察邮件与向量的关系

 

向量还原为邮件

import numpy as np
s = X_train.toarray()[0]    # 邮件0的向量
a = np.flatnonzero(s)       # 非零元素的位置(index)
s[a]                        # 向量的非0元素
b = tfidf2.vocabulary_      # 词汇表
key_list = []
for key,value in b.items():
    if value in a:
        key_list.append(key)    # key非0元素对应的单词
print('向量非零元素对应的单词:',key_list)
print('向量化之前的邮件',x_train[0])

  

4.模型选择

from sklearn.naive_bayes import GaussianNB

from sklearn.naive_bayes import MultinomialNB

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

GaussianNB:高斯分布模型先验概率为正态分布,可将连续型变量转换成离散型的值。

MultinomialNB:多项式分布模型先验概率为多项式分布,该模型常用于文本分类,特征是单词,值是单词的出现次数。

所以选择多项式分布模型

from sklearn.naive_bayes import MultinomialNB

mnb = MultinomialNB()
mnb.fit(X_train, y_train)      # 训练
y_mnb = mnb.predict(X_test)   # 预测结果
print('预测结果',y_mnb)
print('实际结果',y_test)

 

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

from sklearn.metrics import confusion_matrix

confusion_matrix = confusion_matrix(y_test, y_predict)

说明混淆矩阵的含义

混淆矩阵也称误差矩阵,是表示精度评价的一种标准格式,用n行n列的矩阵形式来表示。

在人工智能中,混淆矩阵是可视化工具,特别用于监督学习,在无监督学习一般叫做匹配矩阵。

混淆矩阵是数据科学、数据分析和机器学习中总结分类模型预测结果的情形分析表,以矩阵形式将数据集中的记录按照真实的类别与分类模型作出的分类判断两个标准进行汇总。

 混淆矩阵的每一列代表了预测类别 ,每一列的总数表示预测为该类别的数据的数目;每一行代表了数据的真实归属类别 ,每一行的数据总数表示该类别的数据实例的数目。

混淆矩阵:【TP FN】

      【FP TN】

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

FN:(False Positive):真实为0,测试也为1

FP:(False Negative):真实为1,测试为0

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

 

from sklearn.metrics import classification_report

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

准确率(正确率)=所有预测正确的样本/总的样本  (TP+TN)/总   即所有预测都正确的比率

 精确率=  将正类预测为正类 / 所有预测为正类 TP/(TP+FP)  即查准率,全部预测为1中实际标签为1的比率

 召回率 = 将正类预测为正类 / 所有正真的正类 TP/(TP+FN) 即查全率,实际标签为1中正确预测为1的比率

 F值 = 精确率 * 召回率 * 2 / ( 精确率 + 召回率) (F 值即为精确率和召回率的调和平均值) 

 

from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report

cm = confusion_matrix(y_test, y_mnb)
print('混淆矩阵',cm)
cr = classification_report(y_test, y_mnb)
print('分类报告',cr)
print('准确度:', (cm[0][0]+cm[1][1])/np.sum(cm))

  

6.比较与总结

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

CountVectorizer是属于常见的特征数值计算类,是一个文本特征提取方法。对于每一个训练文本,它只考虑每种词汇在该训练文本中出现的频率(词频)。CountVectorizer会将文本中的词语转换为词频矩阵,它通过fit_transform函数计算各个词语出现的次数。

TfidfVectorizer,每个文本的各维度值是特征词的Tfidf值,除了考虑特征词在文本中的出现次数外,还考虑了词语在文档集中的分布情况(也就是idf值),所以虽然CountVectorizer准确率高但是TfidfVectorizer的模型更加可靠。

猜你喜欢

转载自www.cnblogs.com/lcj170/p/12943085.html