NLP作业02:课程设计报告

作业头

这个作业属于那个课程自然语言处理
这个作业要求在哪里https://bbs.csdn.net/topics/615901519
我在这个课程的目标是运用自然语言处理的课程知识,完成基于文本内容的垃圾短信识别
这个作业在那个具体方面帮助我实现目标加深中文分词处理的理解,学会中文分词垃圾短信识别的实现
参考文献http://t.csdn.cn/BuUuB

1.设计目的

通过课程设计的练习,加深学生对所学自然语言处理的理论知识与操作技能的理解和掌握,使得学生能综合运用所学理论知识和操作技能进行实际工程项目的设计开发,让学生真正体会到自然语言处理算法在实际工程项目中的具体应用方法,为今后能够独立或协助工程师进行人工智能产品的开发设计工作奠定基础。通过综合应用项目的实施,培养学生团队协作沟通能力,培养学生运用现代工具分析和解决复杂工程问题的能力;引导学生深刻理解并自觉实践职业精神和职业规范;培养学生遵纪守法、爱岗敬业、诚实守信、开拓创新的职业品格和行为习惯。

2.设计要求

2.1 实验仪器及设备

(1)使用64位Windows操作系统的电脑。
(2)使用3.9版本的Python。
(3)使用 Jupyter Notebook (Anaconda3) 编辑器。
(4)使用 pandas,,matplotlib,re,jieba,numpy,PIL,wordcloud,sklearn,prettytable。

2.2 设计要求

课程设计的主要环节包括课程设计作品和课程设计报告的撰写。课程设计作品的完成主要包含方案设计、计算机编程实现、作品测试几个方面。课程设计报告主要是将课程设计的理论设计内容、实现的过程及测试结果进行全面的总结,把实践内容上升到理论高度。

进行代码编写,完成以下任务:
(1)了解垃圾短信识别的背景知识,分析步骤和流程。
(2)掌握 Jieba 分词、去停用词等文本预处理方法与应用。
(3)掌握文本数据的向量表示方法。
(4)在初始代码上创新,自己添加功能或者模型,使得项目实现更多的功能。
(5)提交一份完整的课程设计资料,包括流程图、算法实现代码、调试过程和设计总结等。

3.设计内容

3.1 设计基本原理

基于文本内容的垃圾短信识别是一种利用机器学习和自然语言处理技术,对短信的文本内容进行分析和分类的方法。它通过对短信的文本内容进行特征提取、模型训练和预测,判断一条短信是否是垃圾短信。在这种方法中,通常需要进行文本清洗、分词、去除停用词等预处理步骤,以提高模型的准确性和泛化能力。常用的机器学习算法包括朴素贝叶斯、决策树、支持向量机等。此项目使用了朴素贝叶斯、支持向量机、决策树、神经网络、随机森林和随机梯度下降六种模型来对数据进行训练和测试。

本项目使用的设计原理如下:
(1)数据预处理
导入pandas和matplotlib库,对读取的短信数据文件进行基本处理,包括改变列名、删除重复数据、去除无用字符和停用词、分词等操作。这是机器学习中数据预处理的重要步骤,能够提高模型的性能和准确度。
(2)数据可视化
使用matplotlib库绘制饼图和词云图,饼图用来直观展示垃圾短信和正常短信的数量分布,使用 wordcloud 库生成词云图来展示出垃圾短信和正常短信中出现频率比较高的词语。这是数据分析和理解的重要步骤,有助于对数据集有更深入的了解。
(3)特征提取
使用CountVectorizer和TfidfTransformer对文本进行词频统计和TF-IDF转换,得到训练集和测试集的特征向量。这是机器学习中特征工程的重要步骤,能够将文本数据转换成数值特征,为后续的算法提供输入。
(4)模型训练与评估
建立需要的模型,对训练集进行拟合,并且通过使用confusion_matrix函数和classification_report函数评估模型性能。这是机器学习中建模和评估的重要步骤,能够帮助选择合适的模型和参数,评估模型的性能和准确度。
(5)模型预测
对测试集进行模型预测,使用confusion_matrix和classification_report函数评估模型性能。这是机器学习中模型应用的重要步骤,能够用模型对新数据进行预测和分类,检验模型的泛化能力和准确度。

3.2 设计流程图

Alt 图 1 设计流程图

4.设计过程

4.1 数据抽取

4.1.1读取数据集

  1. 导入pandas库,它提供了高级数据结构和广泛的数据分析工具,以便在后续代码中使用该库完成数据清洗、数据分析和数据可视化等任务。
  2. 导入Matplotlib库中的pyplot模块,并将其命名为plt,后续代码主要使用该模块中的绘图函数进行绘图。
  3. 读取名为message80W1.csv的CSV文件,该文件内存储的是短信文本内容,读取成功后将其存储为一个DataFrame对象,命名为message。其中参数Header = None指示该文件没有列名,参数index_col = 0指示将第一列作为索引列。 数据框列名为’label’和’message’,分别表示每个消息的标签和内容。
  4. 最后输出前10行信息。
import pandas as pd
import matplotlib.pyplot as plt
message = pd.read_csv('message80W1.csv', header = None, index_col = 0)                                                                     
message.columns = ['label', 'message']                     
message.head(10

通过以上步骤,对数据集的内容有一个初步的了解,为后续的数据分析和可视化做好准备。

4.1.2查看数据的分布情况,用饼图展示

  1. 该部分统计短信数据集中正常短信和垃圾短信的数量,并绘制饼图展示它们的分布情况。
  2. 统计正负样本数量。对短信数据集中的标签列进行频次统计,计算message数据集中标签列(即短信的分类信息:正常短信0,垃圾短信1)的值的频次,返回一个Pandas Series对象。取Series对象中的第一个元素,即正常短信的数量。取Series对象中的第二个元素,即垃圾短信的数量。输出正常短信和垃圾短信的数量。
  3. 设置matplotlib的字体和坐标轴。设置图表中的中文字符集为SimHei,同时解决负号显示为方块的问题。
  4. 创建一个元组,其中包含两个字符串,分别表示正常短信和垃圾短信。
  5. 使用Matplotlib.pyplot模块中的axes()函数,参数aspect = 1表示纵横比为1,即绘制的图形是一个正圆。
  6. 设定每个扇形的偏移量,第二个值0.20表示将垃圾短信的扇形向外偏移0.2个半径的长度
  7. 使用Matplotlib.pyplot模块中的title()函数设置图表标题为“垃圾短信与正常短信数量分布情况”。
  8. 使用Matplotlib.pyplot模块中的pie()函数来绘制饼图的内容。参数X表示数组,指定数据分别为正常短信数量和垃圾短信数量。参数labels为数据标签。参数explode为扇形的偏移量。参数autopct代表数值的显示格式,'%1.1f%%'表示百分比的显示格式。参数shadow代表是否显示阴影。参数labeldistance为标签与扇形的距离。参数startangle表示起始角度。参数pctdistance表示百分比的位置,即与圆心的距离。参数radius为饼图半径。参数colors表示扇形的颜色。
  9. 最后用plt.show()和plt.close()来显示图表并关闭绘图窗口。
a = message['label'].value_counts()[0] 
b = message['label'].value_counts()[1]  
print('正常短信:', a )
print('垃圾短信:', b )

plt.rcParams['font.sans-serif'] = ['SimHei']  
plt.rcParams['axes.unicode_minus'] = False   
labels = ' 正常短信', ' 垃圾短信'
plt.axes(aspect = 1)                         
explode = [0, 0.20]                         
plt.title(' 垃圾短信与正常短信数量分布情况') 

plt.pie(
    x = [a,b],            
    labels = labels,     
    explode = explode,    
    autopct = '%1.1f %%',  
    shadow = True,       
    labeldistance = 1.2,  
    startangle = 170,    
    pctdistance = 0.7,    
    radius = 1.2,        
    colors = ['CadetBlue','MediumTurquoise']   
    ) 

plt.show()
plt.close()            

4.2 数据预处理

4.2.1 数据清洗——去除重复文本

  1. 定义一个变量n,表示每类短信需采样的数量。
  2. 从样本集message中抽取出所有正常短信(标签为0),使用sample()函数随机抽取n个样本,并将结果赋值给pos变量。其中设置随机种子random_state = 123,保证每次运行程序时抽样结果相同。
  3. 从样本集message中抽取出所有垃圾短信(标签为1),使用sample()函数随机抽取n个样本,并将结果赋值给neg变量。其中设置随机种子random_state = 123。
  4. 使用concat()函数将pos和neg两个数据框以行的方向拼接在一起,形成一个新的数据框new_data,其中正常短信和垃圾短信各有n条。
  5. 输出new_data数据框的行列数,即未删除重复数据的样本量。
  6. drop_duplicates() 是 pandas库中的一个函数,用于去重操作,即删除 DataFrame 或 Series中重复的行或列。使用drop_duplicates()函数删除new_data数据框中的重复行,并将结果赋值给data_drop变量。
  7. 输出data_drop数据框的行列数,即删除重复数据后的样本量。
n = 3000
pos = message[message['label'] == 0].sample(n,random_state = 123)  
neg = message[message['label'] == 1].sample(n,random_state = 123)  
new_data = pd.concat([pos, neg], axis = 0)  
print('未删除重复数据的样本量:',new_data.shape)    

data_drop = new_data.drop_duplicates()
print('删除重复数据后的样本量:',data_drop.shape)  

4.2.2 数据清洗——去除特殊字符

  1. 导入re库,re 库是 Python的标准库之一,提供了正则表达式相关的功能。正则表达式是一种用来匹配、查找、替换文本的字符串模式,可以用来处理各种文本数据。re库提供了多种函数和方法,可以在字符串中使用正则表达式进行查找、替换和分割等操作。
  2. 然后进行删除特殊字符, x、不常见中文以及空格等的操作。首先将data_drop 中的一个名为 message的列全部转换为字符串类型(astype(‘str’))。接着,应用 lambda 函数,使用正则表达式 re.sub()将该列的每行文本中的 ‘x’、非中文字符([^\u4E00-\u9FD5])、数字([0-9])、空格(\s)和制表符(\t)全部替换为空字符串(即删除),得到一个新的字符串。最后用apply()方法将该 lambda 函数应用于该列的每一行,返回一个新的 Series 对象。
  3. 最后输出前10行结果。
import re
data_clean = data_drop['message'].astype('str').apply(lambda x: re.sub('x|[^\u4E00-\u9FD5]|[0-9]|\\s|\\t', '', x))
data_clean.head(10)  

4.2.3 Jieba中文分词

  1. 导入jieba库,jieba是一个流行的中文分词库,它可以帮助将一段中文文本切分成一个个有意义的词语或词组。
  2. 设置jieba分词的日志级别为INFO,即只输出重要信息。
  3. 使用load_userdict()函数,加载自定义词典’newdic1.txt’,将用户定义的自定义词典加载到jieba分词器中。
  4. 接着对data_clean中每个元素(单元格)进行中文分词,并将分词结果转换为一个列表。使用astype()函数将data_clean中的所有元素转换为字符串类型。用jieba.cut()函数进行中文分词,并将分词结果转换为一个列表。再使用apply()方法将这个操作应用到每个元素。
  5. 最后输出前10行结果。
import jieba
jieba.setLogLevel(jieba.logging.INFO)  
jieba.load_userdict('newdic1.txt')    
data_cut = data_clean.astype('str').apply(lambda x : list(jieba.cut(x)))
data_cut.head(10)  

4.2.4 去除评论中的停用词

  1. 停用词是指在文本分析中没有实际意义,只是用来连接或填充句子的一些常用词语,例如“的”、“是”、“一”等,去除这些词语可以减少噪音和提高文本分析的效果。
  2. 将停用词表的路径赋值给变量stopword_file。
  3. 使用 pandas 库中的 read_csv 函数读取stopword_file 文件并赋值给变量 stopword,其中参数 sep 表示分隔符为 ‘buchunzai’,encoding表示文件编码为 gbk,header = None 表示文件中没有列名,engine = ‘python’ 表示使用 python引擎读取文件。
  4. 将列表 [’ ‘,’,', ‘会’, ‘的’, ‘】’, ‘【’, ‘月’, ‘日’] 与 stopword中的第一列合并,并将结果赋值给变量 stopword。 变量 data_cut 应用一个 lambda 函数,该函数将 x中的元素逐个判断是否在stopword 列表中,如果不在则保留,否则删除。最终将处理后的结果赋值给变量data_delstop。
  5. 最后输出前10行结果。
stopword_file = 'stopword.txt' 
stopword = pd.read_csv(stopword_file, sep = 'buchunzai', encoding = 'gbk', header = None,engine = 'python') 
stopword = [' ',',', '会', '的', '】', '【', '月', '日'] + list(stopword[0]) 
data_delstop = data_cut.apply(lambda x: [i for i in x if i not in stopword]) 
data_delstop.head(10)

4.3 词云图展示

4.3.1 文本数据的词统计

  1. 定义一个名为 data_process 的函数,该函数接受一个参数file,用于读取指定文件,并进行数据处理,函数的输出可以作为后续文本分类和分析的输入。首先使用 pandas 库中的read_csv 函数读取指定文件并将结果赋值给变量 message,其中参数 header = None表示文件中没有列名,index_col = 0 表示将数据的第一列作为索引。然后将 message DataFrame中的列名分别设置为 ‘label’ 和 ‘message’,并将结果赋值给变量 message。接着使用之前处理好的data_delstop 的索引获取 labels。然后对 data_delstop 应用一个 lambda函数,将每个元素中的词汇用空格连接起来,并将结果赋值给变量 adata。最后返回 adata、data_delstop 和labels 三个变量。
  2. 调用 data_process 函数并将返回的结果分别赋值给变量 adata、data_after_stop和 labels。
  3. 定义一个名为 words_count 的函数,该函数接受一个参数label,用于统计指定标签下所有文本中每个词汇出现的次数。首先创建一个空的字典变量 word_fre,然后遍历data_after_stop[labels == label] 中的每个元素 i,再遍历该元素中的每个词汇 j,如果 j 不在word_fre 的键中,则将 j 添加到字典中并将其出现次数设置为 1;否则将 j 对应的值加 1。最后返回统计结果word_fre。
  4. 调用 words_count 函数,不指定参数,统计文本中每个词汇出现的次数。
import pandas as pd
import re
import jieba
def data_process(file):
    message = pd.read_csv(file, header = None, index_col = 0)
    message.columns = ['label', 'message']
    labels = new_data.loc[data_delstop.index, 'label']  
    adata = data_delstop.apply(lambda x: ' '.join(x))  
    return adata, data_delstop, labels

adata, data_after_stop, labels = data_process('message80W1.csv')

def words_count(label = 0):
    word_fre = {}
    for i in data_after_stop[labels == label]:
        for j in i:
            if j not in word_fre.keys():
                word_fre[j] = 1
            else:
                word_fre[j] += 1
    return word_fre

words_count()

4.3.2 绘制词云图

  1. 导入numpy库,用来将图像文件转换为numpy数组,然后传递给WordCloud对象的mask参数。 导入Image类,PIL库提供了Image类,用于打开、加载和保存图像文件。导入WordCloud、STOPWORDS类,WordCloud库提供了WordCloud类,用于生成词云图。
  2. 定义一个名为 WordCloud_plot的函数,该函数用于生成词云图。首先定义变量 te 作为列表,其中包含两张图片的文件名。然后通过 for 循环遍历 te列表中的每个文件名,将其赋值给变量 mask_picture。接着创建一个名为 p1 的 Figure 对象,设置大小为(16,10),dpi 为 80。使用 Image.open 函数打开变量 mask_picture 对应的图片文件,并将其转换为numpy 数组格式,将结果赋值给变量 graph。
  3. 然后创建一个 WordCloud 对象 wc,其中设置背景颜色为白色,使用变量graph 作为词云图的形状,max_words表示最大显示的字数,使用 STOPWORDS 类来过滤停用词,使用字体文件FZSJ-BANRXS.ttf,参数max_font_size设置最大字号为 100,随机数种子为 30。接着使用wc.generate_from_frequencies 函数,传入 words_count(i) 的结果来生成词云图。最后通过plt.imshow 函数将生成的词云图显示出来,并使用 plt.axis(“off”) 函数去除坐标轴。然后调用 plt.show()函数显示所有生成的词云图。
  4. 调用 WordCloud_plot 函数生成词云图。
import numpy as np
from PIL import Image
from wordcloud import WordCloud,STOPWORDS

def WordCloud_plot():
    te = ['xing.jpg','xiong.jpg']       #轮廓图可随意替换为自己想要的图案
    for i in [0,1]:
        mask_picture = te[i]
        p1 = plt.figure(figsize = (16,10),dpi = 80) 
        image = Image.open(mask_picture)            
        graph = np.array(image)                   
        wc = WordCloud(background_color = 'White', 
                        mask = graph,            
                        max_words = 500,            
                        stopwords = STOPWORDS,     
                        font_path = 'FZSJ-BANRXS.ttf',   
                        max_font_size = 100,      
                        random_state = 30
                      )        
        wc.generate_from_frequencies(words_count(i)) 
        plt.imshow(wc)                               
        plt.axis("off")                                                               
    plt.show()
WordCloud_plot()

得到的词云图:
词云图
图2 词云图展示

4.4 模型构建、训练、验证与评估

4.4.1 构建词条文档矩阵

  1. 从sklearn库中导入CountVectorizer和TfidfTransformer类,用于将文本转换成数字向量表示以及计算TF-IDF权重。
  2. 从sklearn库中导入confusion_matrix和classification_report函数,用于评估模型的性能。
  3. 从sklearn库中导入train_test_split函数,用于将数据集划分为训练集和测试集。
  4. 调用名为 data_process的函数,将 ‘message80W1.csv’ 文件作为参数传入,将其返回值分别赋值给 dataAlready 和 labels变量。其中第二个返回值没有使用,使用 _ 变量代替。
  5. 使用 train_test_split函数将dataAlready和labels按照8:2的比例划分为训练集和测试集,并将划分后的数据分别赋值给train_data、test_data、train_y和test_y变量。
  6. 创建一个CountVectorizer对象,并赋值给变量vectorizer,用于将文本转换为数字向量表示。
  7. 创建一个TfidfTransformer对象,并赋值给变量transformer,用于计算TF-IDF权重。
  8. 使用vectorizer.fit_transform 函数将训练集数据 train_data 转换为词频矩阵,将结果赋值给 train_cv变量。
  9. 使用 transformer.fit_transform 函数将 train_cv 转换为 TF-IDF 特征矩阵,将结果赋值给tfidf_train 变量。
  10. 打印训练集词频矩阵 train_cv 和 TF-IDF 特征矩阵 tfidf_train。
  11. 创建一个CountVectorizer对象,并设置其vocabulary参数为训练集中出现的词汇表,将其赋值给变量vectorizer1,其中vocabulary 参数等于 vectorizer.vocabulary_,即使用训练集的词向量作为测试集的词向量。
  12. 使用vectorizer1.fit_transform 函数将测试集数据 test_data 转换为词频矩阵,将结果保存到 test_cv变量中。
  13. 使用 transformer.fit_transform 函数将 test_cv 转换为 TF-IDF 特征矩阵,将结果保存到tfidf_test 变量中。
  14. 打印测试集词频矩阵 test_cv 和 TF-IDF 特征矩阵 tfidf_test。
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.model_selection import train_test_split

dataAlready,  _ ,labels = data_process('message80W1.csv') 
train_data, test_data, train_y, test_y = train_test_split(dataAlready, labels, test_size = 0.2)
 
vectorizer = CountVectorizer()
transformer = TfidfTransformer()
train_cv = vectorizer.fit_transform(train_data)     
tfidf_train = transformer.fit_transform(train_cv.toarray())  
print(' 训练集 词频结果:\n',train_cv)
print('训练集 TF-IDF 结果:\n',tfidf_train) 

vectorizer1 = CountVectorizer(vocabulary = vectorizer.vocabulary_)  
test_cv = vectorizer1.fit_transform(test_data)                      
tfidf_test = transformer.fit_transform(test_cv.toarray())           
print(' 测试集 词频结果:\n',test_cv)
print('测试集 TF-IDF 结果:\n',tfidf_test) 

4.4.2 多项式贝叶斯模型

MultinomialNB是一种朴素贝叶斯分类器,适用于文本分类等离散特征的分类问题。在这个分类器中,每个特征的取值都是离散的,而且可以是多项式分布,例如文本分类中的词频。朴素贝叶斯分类器基于贝叶斯定理,通过计算后验概率来进行分类。在MultinomialNB中,每个特征的取值都是离散的,所以可以使用多项式分布来建立特征的概率模型。具体来说,对于每个特征,根据训练数据计算其在每个类别中出现的概率,然后根据贝叶斯定理计算后验概率,最终选择概率最大的类别作为预测结果。以下是代码实现:

  1. 导入 MultinomialNB 类。
  2. 创建 MultinomialNB 对象 model_nb。
  3. 使用 model_nb.fit函数在训练集上训练模型,其中 tfidf_train 是特征矩阵,train_y 是训练集标签。
  4. 使用 model_nb.predict函数在训练集上进行预测,将结果保存在 res 变量中。
  5. 使用 model_nb.score 函数计算模型在训练集上的准确率,将结果保存在bys_tr 变量中。
  6. 打印混淆矩阵,使用 confusion_matrix 函数,其中第一个参数是真实标签,第二个参数是预测标签。
  7. 打印模型在训练集上的准确率 bys_tr。
  8. 打印模型在训练集上的性能报告,使用 classification_report函数,其中第一个参数是真实标签,第二个参数是预测标签。
from sklearn.naive_bayes import MultinomialNB
model_nb = MultinomialNB()
model_nb.fit(tfidf_train,train_y) 

res = model_nb.predict(tfidf_train) 
bys_tr = model_nb.score(tfidf_train,train_y)
print(' 混淆矩阵如下:\n',confusion_matrix(train_y, res)) 
print(' 模型训练正确率:',bys_tr) 
print(' 多项式贝叶斯模型的性能报告: \n',classification_report(train_y, res))
  1. 使用 model_nb.predict 函数在测试集上进行预测,将结果保存在 res_nb 变量中。
  2. 使用 model_nb.score函数计算模型在测试集上的准确率,将结果保存在 bys 变量中。
  3. 打印混淆矩阵,使用 confusion_matrix函数,其中第一个参数是真实标签,第二个参数是预测标签。打印模型在测试集上的准确率 bys。
res_nb = model_nb.predict(tfidf_test) 
bys = model_nb.score(tfidf_test,test_y)
print(' 混淆矩阵如下:\n',confusion_matrix(test_y, res_nb) ) 
print(' 模型验证正确率:',bys) 
print(' 多项式贝叶斯模型的性能报告: \n',classification_report(test_y, res_nb))

4.4.3 支持向量机模型

  1. 支持向量机(SVM)是一种在统计学习中广泛使用的监督式学习算法,主要用于分类和回归问题。SVM的核心思想是将数据从原始空间转换到高维空间中,然后在高维空间中寻找最优的超平面或者回归曲线,以实现分类或回归分析。
  2. SVM的工作原理可以简单概括为以下几个步骤:将每个样本表示为一个向量,并找到一个合适的特征空间来描述这些向量。在特征空间中寻找一个最优的超平面,以最大化不同类别之间的间隔(称为“间隔最大化”)。通过使用核函数将数据集映射到高维空间来找到非线性超平面。使用训练数据集来训练分类器,然后使用测试数据集来测试模型的性能。
  3. 调用SVM模型,其中训练,测试,计算以及模型评价的原理,与第一个模型多项式贝叶斯模型的使用步骤一样。
  4. 过程中使用model_SVM.score 函数分别计算模型在训练集上和在测试集上的准确率,并将结果保存在 svm_tr 、svm 变量中。

代码实现:

from sklearn import svm
model_SVM = svm.SVC()
model_SVM.fit(tfidf_train,train_y)

res = model_SVM.predict(tfidf_train) 
svm_tr = model_SVM.score(tfidf_train,train_y)
print(' 混淆矩阵如下:\n',confusion_matrix(train_y, res)) 
print(' 模型训练正确率:',svm_tr) 
print(' 支持向量机模型的性能报告: \n',classification_report(train_y, res))

res_nb = model_SVM.predict(tfidf_test) 
svm = model_SVM.score(tfidf_test,test_y)
print(' 混淆矩阵如下:\n',confusion_matrix(test_y, res_nb) ) 
print(' 模型验证正确率:',svm) 
print(' 支持向量机模型的性能报告: \n',classification_report(test_y, res_nb))

4.4.4 决策树模型

  1. 决策树是一种常用的分类和回归算法。它可以用树形结构来表示一个决策过程,每个内部节点表示一个属性或特征,每个叶节点表示一个分类或回归结果。决策树算法的目标是通过不断地选择最优的属性,将输入样本划分为不同的类别或产生连续的输出。
  2. 在sklearn库中,tree模块提供了决策树学习的工具。其中DecisionTreeClassifier和DecisionTreeRegressor类是最常用的。前者用于解决分类问题,后者用于解决回归问题。这些类都提供了fit()方法来训练模型,predict()方法来预测新数据的类别或输出,score()方法来评估模型的准确性。
  3. 总的来说,tree模块为我们提供了方便快捷的决策树算法实现,可以用于分类和回归问题。在使用时需要注意特征选择、剪枝和处理缺失值等问题。
  4. 调用tree模型,其中训练,测试,计算以及模型评价的原理,与第一个模型多项式贝叶斯模型的使用步骤一样。
  5. 过程中使用model_tDC.score 函数分别计算模型在训练集上和在测试集上的准确率,并将结果保存在 tree_tr 、tree变量中。

代码实现如下:

from sklearn import tree
model_tDC = tree.DecisionTreeClassifier()
model_tDC.fit(tfidf_train,train_y)

res = model_tDC.predict(tfidf_train) 
tree_tr = model_tDC.score(tfidf_train,train_y)
print(' 混淆矩阵如下:\n',confusion_matrix(train_y, res)) 
print(' 模型训练正确率:',tree_tr ) 
print(' 决策树模型的性能报告: \n',classification_report(train_y, res))

res_nb = model_tDC.predict(tfidf_test) 
tree = model_tDC.score(tfidf_test,test_y)
print(' 混淆矩阵如下:\n',confusion_matrix(test_y, res_nb) ) 
print(' 模型验证正确率:',tree) 
print(' 决策树模型的性能报告: \n',classification_report(test_y, res_nb))

4.4.5 神经网络模型

  1. 构建神经网络模型,这里用到的方法是多层感知机。多层感知机(Multilayer Perceptron,简称MLP)是一种神经网络模型。它是一种前馈神经网络,由多个神经元层组成,每层之间都是全连接的。MLP是一种通用的非线性函数逼近器,可以用于分类、回归和其他任务。
  2. 在MLP中,每个神经元都与前一层的每个神经元相连,使用权重进行连接。每个神经元接收前一层神经元的输出,并将其加权求和,再通过激活函数进行非线性变换,最后输出到下一层的神经元。MLP的训练过程通常使用反向传播算法。该算法通过计算输出与目标值之间的误差来更新各层之间的权重,从而逐步优化模型的性能。
  3. 导入多层感知机模块MLPClassifier,使用scikit-learn库中的MLPClassifier类,创建一个多层感知机模型,具体参数如下:solver指定优化算法。alpha:L2正则化参数。hidden_layer_sizes:指定隐藏层的神经元数量,这里有2个隐藏层,分别有5个神经元和2个神经元。shuffle:指定是否在每次迭代时随机打乱样本顺序。
  4. 后续训练,测试,计算以及模型评价的原理,与第一个模型多项式贝叶斯模型的使用步骤一样。过程中使用 model_MLP.score函数分别计算模型在训练集上和在测试集上的准确率,并将结果保存在 mlp_tr 、mlp变量中。

代码实现如下:

from sklearn.neural_network import MLPClassifier 
model_MLP = MLPClassifier(solver = 'lbfgs', alpha = 1e-5,hidden_layer_sizes = (5, 2), shuffle=False)
model_MLP.fit(tfidf_train,train_y)

res = model_MLP.predict(tfidf_train) 
mlp_tr = model_MLP.score(tfidf_train,train_y)
print(' 混淆矩阵如下:\n',confusion_matrix(train_y, res)) 
print(' 模型训练正确率:',mlp_tr) 
print(' 神经网络模型的性能报告: \n',classification_report(train_y, res))

res_nb = model_MLP.predict(tfidf_test) 
mlp = model_MLP.score(tfidf_test,test_y)
print(' 混淆矩阵如下:\n',confusion_matrix(test_y, res_nb) ) 
print(' 模型验证正确率:',mlp) 
print(' 神经网络模型的性能报告: \n',classification_report(test_y, res_nb))

4.4.6 随机森林模型

  1. 随机森林模型的基本思想是建立多棵决策树,每棵树都是在随机子集上构建的。对于每个节点,模型会随机选择一些特征来进行划分,以减少模型的方差,并防止过拟合。由于这种随机选择特征的方式,随机森林通常比单个决策树更准确,并且泛化能力更好,因为它们可以抵消单棵决策树的错误。
  2. RandomForestClassifier类有许多可调参数,包括森林中树的数量,每个树的最大深度,要考虑的特征数量等等。这些参数可以根据数据集和特定问题进行调整以达到最佳性能。在使用随机森林模型时,可以使用fit方法拟合数据,并使用predict方法进行预测。与许多其他分类器类似,RandomForestClassifier还提供了许多其他方法来评估模型性能,如score和predict_proba。
  3. 导入scikit-learn库中的RandomForestClassifier类,用于创建一个随机森林分类器模型。创建一个名为model_RFC的随机森林分类器对象,并给定n_estimators参数值为10,即设置了森林中决策树的数量为10。
  4. 后续训练,测试,计算以及模型评价的原理,与第一个模型多项式贝叶斯模型的使用步骤一样。过程中使用 model_RFC.score函数分别计算模型在训练集上和在测试集上的准确率,并将结果保存在 rfc_tr 、rfc变量中。

代码实现如下:

from sklearn.ensemble import RandomForestClassifier
model_RFC = RandomForestClassifier(n_estimators = 10)
model_RFC.fit(tfidf_train,train_y)

res = model_RFC.predict(tfidf_train) 
rfc_tr = model_RFC.score(tfidf_train,train_y)
print(' 混淆矩阵如下:\n',confusion_matrix(train_y, res)) 
print(' 模型训练正确率:',rfc_tr) 
print(' 随机森林模型的性能报告: \n',classification_report(train_y, res))

res_nb = model_RFC.predict(tfidf_test) 
rfc = model_RFC.score(tfidf_test,test_y)
print(' 混淆矩阵如下:\n',confusion_matrix(test_y, res_nb) ) 
print(' 模型验证正确率:',rfc) 
print(' 随机森林模型的性能报告: \n',classification_report(test_y, res_nb))

4.4.7 随机梯度下降模型

  1. SGDClassifier是一种基于随机梯度下降(SGD)算法的线性分类器,它是一种高效的算法,尤其适用于大规模数据集和高维数据。在机器学习中,分类是一种重要的任务,SGDClassifier可以用于二元分类和多类分类问题。它采用的是随机梯度下降法(SGD),这是一种优化算法,它通过迭代来最小化损失函数。在SGDClassifier中,每次迭代选择一个样本进行计算,然后根据该样本的误差梯度更新模型参数。由于每次迭代仅使用一个样本,因此SGDClassifier具有高效的特点。使用fit方法拟合数据,并使用predict方法进行预测。在拟合数据时,可以通过设置参数来调整模型的性能,如惩罚项、学习率、收敛条件等。此外,SGDClassifier还支持各种损失函数,如对数损失、平方损失等。
  2. 从sklearn.linear_model引入SGDClassifier类。创建一个SGDClassifier对象,具体参数如下:loss指定损失函数。enalty指定正则化项。max_iter指定模型的最大迭代次数。
  3. 后续训练,测试,计算以及模型评价的原理,与第一个模型多项式贝叶斯模型的使用步骤一样。过程中使用 model_SGD.score函数分别计算模型在训练集上和在测试集上的准确率,并将结果保存在 sgd_tr 、sgd变量中。

代码实现如下:

from sklearn.linear_model import SGDClassifier
model_SGD = SGDClassifier(loss = "hinge", penalty = "l2", max_iter = 5)
model_SGD.fit(tfidf_train,train_y)

res = model_SGD.predict(tfidf_train) 
sgd_tr = model_SGD.score(tfidf_train,train_y)
print(' 混淆矩阵如下:\n',confusion_matrix(train_y, res)) 
print(' 模型训练正确率:',sgd_tr) 
print(' 随机梯度模型的性能报告: \n',classification_report(train_y, res))

res_nb = model_SGD.predict(tfidf_test) 
sgd = model_SGD.score(tfidf_test,test_y)
print(' 混淆矩阵如下:\n',confusion_matrix(test_y, res_nb) ) 
print(' 模型验证正确率:',sgd) 
print(' 随机梯度模型的性能报告: \n',classification_report(test_y, res_nb))

4.5 模型比较

4.5.1 直方图可视化展示

  1. 使用pyplot模块中的rcParams属性,设置字体为中文SimHei,以便图表中可以显示中文字符。
  2. 使用pyplot模块中的figure属性,创建一个名为fig的图形对象,设置图形大小为5*4,像素密度为100dpi。
  3. 定义一个列表models,包含6个字符串元素,分别表示以上使用的6种分类模型。
  4. 创建一个包含6个浮点数元素的列表,用于表示6种机器学习模型在训练集上的正确率,赋值给accuracies_tr。
  5. 创建一个包含6个浮点数元素的列表,用于表示6种机器学习模型在测试集上的正确率,赋值给accuracies。
  6. 使用np.arange()函数生成一个长度为6的等差数列,并将其赋值给变量x,用于表示6种机器学习模型的索引。
  7. 定义一个变量width,表示每个柱形图的宽度。 使用subplots()创建一个画布和一个坐标系,并将其分别赋值给变量fig和ax。
  8. 在坐标系上绘制一个条形图,其中x - width/2表示条形图的横坐标,accuracies_tr表示条形图的纵坐标,width表示条形图的宽度,label表示条形图的标签,color表示条形图的颜色,将其赋值给变量rects1。代表模型在训练集上的正确率显示。
  9. 同理,将accuracies_tr改为accuracies,将其赋值给变量rects2。代表模型在测试集上的正确率显示。
  10. 接着使用了Matplotlib中的Axes.bar_label()函数,向柱状图添加标签,并设置标签与柱状图之间的间距为3。
  11. 使用ax.set_ylabel()设置Y标签,ax.set_title()设置标题,ax.set_xticks(x)设置x轴上的刻度位置为x,ax.set_xticklabels(models)设置x轴上的刻度标签为models,ax.legend(loc=‘upper right’)添加图例。
  12. 最后用plt.show()显示直方图。
import matplotlib
import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.sans-serif'] = ['SimHei']    
fig = plt.figure(figsize = (5,4),dpi = 100)   

models = ['多项式贝叶斯','支持向量机','决策树','神经网络','随机森林','随机梯度下降']
accuracies_tr = [bys_tr,svm_tr,tree_tr,mlp_tr,rfc_tr,sgd_tr]
accuracies = [bys,svm,tree,mlp,rfc,sgd]

x = np.arange(len(models))  
width = 0.25   
fig, ax = plt.subplots()
rects1 = ax.bar(x - width/2, accuracies_tr, width, label = '训练正确率', color = 'AntiqueWhite')
rects2 = ax.bar(x + width/2, accuracies, width, label = '验证正确率', color = 'Grey')

ax.bar_label(rects1, padding = 3)
ax.bar_label(rects2, padding = 3)

ax.set_ylabel('正确率')
ax.set_title('模型训练正确率and模型验证正确率')
ax.set_xticks(x)
ax.set_xticklabels(models)
ax.legend(loc='upper right')
plt.show()

Alt
图3 模型准确率直方图

4.5.2 模型准确率排序

  1. 从prettytable库中导入PrettyTable类,以便后续可以使用该类来创建漂亮的表格。
  2. 创建一个Pandas DataFrame对象model_df,其中包含两列数据:模型和准确率。models代表不同的机器学习模型列表,accuracies代表不同的机器学习模型和它们对应的测试准确率。
  3. 使用sort_values()函数对准确率进行排序,参数ascending = False表示降序排列,使得准确率最高的模型排在最前面。
  4. 重置数据框的索引,使其按顺序排列。创建PrettyTable对象。设置表格的列名为“模型”和“准确率”。
  5. 定义table.field_names,用来放置表格的列名。使用一个for循环,遍历每一行,取出模型名称和准确率,然后将它们添加到PrettyTable对象中。add_row()是PrettyTable对象的方法,用于向表格中添加行数据。打印整个表格。
  6. 再使用一个for 循环,遍历每一行,取出模型名称和准确率,然后格式化输出。每一行的格式为“模型名称: 准确率”,索引从1开始。
import pandas as pd
from prettytable import PrettyTable

model_df = pd.DataFrame({'模型': models, '准确率': accuracies})
model_df = model_df.sort_values('准确率', ascending = False)
model_df.reset_index(drop = True, inplace = True)

table = PrettyTable()
table.field_names = ["模型", "准确率"]

for i in range(len(model_df)):
    model_name = model_df.iloc[i, 0]
    accuracy = model_df.iloc[i, 1]
    table.add_row([model_name, accuracy])
print(table)

for i in range(len(model_df)):
    print(f'{i+1}. {model_df.iloc[i, 0]}: {model_df.iloc[i, 1]}')

模型准确率
图4 模型准确率排序

5.设计总结与体会

  1. 数据抽取部分,得到了一个正常短信和垃圾短信的饼状图,可以看见数据集里面,正常短信有720000条,垃圾短信有80000条。正常短信占90%,垃圾短信占10%。
  2. 数据预处理部分,选取部分样本,进行了去除重复数据,分词,去除停用词等操作。得到了想要的数据结果,为后续的工作做了准备。
  3. 词云图展示部分,首先对处理好的数据进行统计,得到了每个词出现的次数。接着用WordCloud绘图,进行词云图展示,分别得到了正常短信词云图和垃圾短信词云图。
  4. 模型部分,通过调用多项式贝叶斯、支持向量机、决策树、神经网络、随机森林、随机梯度下降六个模型,来进行数据训练与验证,通过模型准确率可以看出其中最好的为随机梯度下降模型。

在本次的课程设计中,我选择的题目是基于文本内容的垃圾短信识别。项目要求在老师所给的基础代码上添加自己的功能,使程序实现不一样的功能展现。在实训的这几天,我不断的尝试,不断的失败,又不断的查找资料,解决问题,最后自主的完成一个项目,是一个全新的挑战。对于我来说这一次实训给我带来了许多收获,以下是此次我的实验收获,以及项目完成过程中得到的一些理解。在开始实验之前我查找了相关的资料。知道了在进行垃圾短信文本分类时,首先需要对原始数据进行清洗和预处理,去除无用的特殊字符和停用词,从而提取出短信文本的关键信息。然后选取合适的算法和模型进行分类,例如朴素贝叶斯、支持向量机等。在模型训练过程中,需要充分考虑特征选择和优化模型参数等问题,以提高分类的准确率和效率。项目实现中,我首先先进行数据抽取,得到了正常短信和垃圾短信的一个分布状况,再将数据进行预处理,选取部分的样本进行去除重复数据,进行中文分词,去除停用词等操作后再进行词云图展示。到这一步,数据预处理过程就已经完成了,接下来是选用模型对数据进行训练和测试评价。构建一个词条文档矩阵,再调用多项式贝叶斯、支持向量机、决策树、神经网络、随机森林、随机梯度下降六个模型对数据进行测试评价,得出了他们的准确率排名。通过模型准确率可以看出其中最好的为随机梯度下降模型。通过此次实训,我学会了许多的知识,收获很大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值