基于Bi-LSTM检测 AI 生成的文本

今天你push了吗 2024-08-03 16:01:01 阅读 55

基于Bi-LSTM检测 AI 生成的文本

1.引言

1.1背景介绍

在当今信息爆炸的时代,机器学习在文本分类中发挥着关键作用,为处理大规模文本数据提供了强大的工具和方法。机器学习通过自动学习模型,能够处理并理解庞大的文本数据,从而提高处理效率和准确性。而文本分类是自然语言处理(NLP)的重要组成部分,其应用涵盖了从情感分析到信息检索等多个领域。例如,在NLP方面,机器学习旨在使计算机能够理解、解释和生成人类语言。文本分类是NLP的核心任务之一;在信息检索方面,机器学习可以实现更准确、高效的信息检索,帮助用户从海量文本中获取所需信息;在情感分析方面,机器学习模型能够分析文本中的情感色彩,从而用于了解用户的情感倾向和反馈。机器学习算法因其具有挖掘文本中模式、关系和趋势的独特优势,可以通过训练模型,从数据中学到规律,提高对文本的理解和推断能力。

同时,随着计算能力的提升和深度学习技术的涌现,人工智能在文本生成领域迎来了繁荣的时期。生成文本的算法和模型的逐步成熟使得其在各种应用中得以广泛应用。例如,AI可以生成自动摘要,从大量文本中提取关键信息,提供快速而准确的概要;智能对话系统利用生成文本模型,使得计算机能够更自然地与用户进行交互,实现更高效的人机对话;AI生成的文本被广泛应用于智能客服系统,提供快速、个性化的服务,提升用户体验;生成文本模型被用于创意写作,辅助作者产生文学作品、广告文案等。但近年来,大型语言模型(LLM)也变得越来越复杂,能够生成难以与人类书面文本区分开来的文本,给社会带来了一些潜在威胁,例如传播虚假信息、滥用文本等

综上所述,机器学习和AI生成文本技术的结合在文本处理和生成领域展现了巨大的潜力,但也需要谨慎应对潜在的挑战和威胁。在此背景下,本研究旨在探索利用简单RNN和LSTM模型进行文本检测的方法,以解决AI生成文本可能带来的问题。

1.2研究目的

在当前技术背景下,区分人工撰写文本和由大型语言模型(LLM)生成的文本面临一系列挑战,这些挑战构成了研究的首要目标。

1.语言差异与写作风格多样性

中小学生的文本通常具有明显的语言水平差异,涵盖了从基础词汇到更高级的表达方式。LLM生成的文本可能在语法和表达上达到了接近自然的水平,使得与中小学生的真实写作之间的区别更加模糊。挑战在于如何有效地捕捉和分析这些微妙的语言差异,从而实现可靠的分类。

2.技术逼真性提高的挑战

随着技术的进步,LLM生成的文本在逼真性上逐渐接近人类写作风格,增加了判别的难度。模型生成的内容可能融入了更多的上下文信息和语法规则,使得传统的规则或特征检测方法难以应对。研究需要解决如何从微妙而复杂的语言特征中提取有效的信号,以准确地鉴别文本的生成来源。

为了解决上述挑战,本研究旨在运用简单的循环神经网络(RNN)、长短时记忆网络(LSTM)和双向长短时记忆网络(Bidirectional LSTM)模型进行文本检测,以实现对人工撰写文本和LLM生成文本的有效区分。

2.文献综述

2.1统计机器学习在文本分类中的先前研究

过去几十年来,统计机器学习在文本分类领域取得了显著的研究成果,涉及多种算法和方法。主要有以下几个方法:

朴素贝叶斯算法

支持向量机(SVM)

决策树和随机森林

原理

基于特征之间的独立性假设,建模文本和类别之间的关系。

找到一个最优的超平面来划分不同类别的文本。

决策树根据特征逐步划分数据来进行分类,随机森林则整合多个决策树的结果。

优势

简单、高效,对于大规模文本分类任务具有较好的性能,计算开销低,具有较好的性能。

在高维空间中表现强大,适用于处理复杂的文本特征

于非线性关系的建模较为灵活,具有较好的泛化性能

局限

对于上下文信息的建模较弱,难以处理长距离依赖性。

计算开销较大,对于非线性关系建模相对困难,不适用于大规模数据集。

在处理高维稀疏数据时可能过拟合,对噪声敏感,需要谨慎调参。

通过回顾这些先前研究,我们可以看到不同方法在文本分类任务中有各自的优势和限制。这为后续的研究提供了借鉴和改进的空间,尤其是在面对越来越复杂的文本数据和不断演进的技术挑战的背景下。在这种背景下,深度学习模型的引入为文本分类任务带来了新的可能性,尤其是对于处理上下文信息和长距离依赖性方面的挑战。

2.2RNN和LSTM在文本生成与检测中的应用

循环神经网络(RNN)是一种递归神经网络,其主要特点是具有循环连接,使得信息能够在网络内部传递。并且RNN由一个神经元单元的序列组成,每个神经元单元接收上一个时间步的输出作为输入,同时考虑当前时间步的输入。

而长短时记忆网络(LSTM)是一种专门设计来解决RNN梯度消失问题的结构,通过引入记忆单元来维护和更新长期信息。LSTM包含输入门、遗忘门、输出门和记忆单元等组件,通过这些组件的协同工作,LSTM能够更好地捕捉长距离依赖关系。RNN被广泛用于生成自然语言文本,如故事、歌词等。通过学习上下文信息,模型能够生成连贯、富有语感的文本,同时它在机器翻译任务中表现出色,能够处理输入和输出之间的复杂语言结构。LSTM因其长期依赖关系,被用于语言建模任务,通过学习文本序列中的长期依赖关系,提高了生成文本的准确性和流畅度,此外,LSTM可以为作者提供灵感和变化,推动文本生成的创造性。

这些成功案例表明RNN和LSTM在文本生成和检测任务中具有广泛的应用前景,尤其是在处理长文本序列和理解上下文关系方面的能力上。在本研究中,我们将借鉴这些成功案例,探索如何运用RNN和LSTM模型来解决文本检测中的挑战,特别是在区分中小学生和LLM生成文本方面。

3 数据集

3.1数据来源

  该研究里的数据集来自Kaggle里一个正在进行的比赛LLM  Detect AI Generated Text的附加数据集。该数据集里面包括44868 行数据,每行数据都是由中小学生根据命题撰写的文本或者LLM根据指令生成的文本。其中使用LLM模型主要包括persuade_corpus、chat_gpt_moth、llama2_chat等。每行数据都包括具体文本,生成标签(0,1),生成指令,源数据集等内容,其中27371是人工撰写的文本,17497是LLM生成的文本。

3.2数据处理与划分

原始数据集中包含五列,具体信息如下表:

Text

Label

Prompt_name

Source

RDizzl3_seven

essay text

1 for AI generated, 0 for human

original persuade promp

source dataset

True or Flase

在实际的研究中,我们只需要保留Text和Label列,故我们将这两列提取出来,形成一个新数据集。为保证数据真实性与准确性,我们处理了数据的缺失数据和重复行。同时,由于我们的的问题是一个二分类问题,我们采取了平衡抽样,使得Label不同的数据量相同,都为17497行。最后,我们对文本内容进行了处理,包括去除文本中的换行符和制表符、处理带有重音符号、将文本分词、转换为小写、去除标点符号、去除停用词、去除长度小于等于2的单词和去除非字母字符和对文本进行词形还原等操作。

最后,我们用Tokenizer 将文本数据转换为序列(整数序列),Tokenizer 会基于训练集文本构建一个词汇表,并将每个单词映射到一个唯一的整数。在神经网络中,嵌入层(Embedding Layer)通常用于将整数序列映射为密集的词嵌入表示。Tokenizer的输出(整数序列)可以直接作为嵌入层的输入。

4. 研究方法

4.1RNN模型

RNN(循环神经网络)是一种能够处理序列数据的神经网络结构。它是一类具有内部环的神经网络。其基本结构包括输入层、隐藏层和输出层。

输入层接收文本数据的输入,通常以词向量的形式表示。每个词向量作为一个时间步的输入;在每个时间步都包含一个隐藏层,其神经元单元会接收来自上一个时间步隐藏层的输出作为输入。这种循环连接允许网络记忆过去的信息,捕捉文本中的序列信息;输出层产生网络的最终输出,通常是一个概率分布,表示文本属于不同类别的概率,如果要输出具体分类的信息,例如二分类问题可以采用astype(int)函数转为具体的分类。RNN这样的结构允许网络在处理文本时考虑上下文信息,更好地理解文本的语境和顺序。

在超参数选择方面,可以选择合适的学习率和通过交叉验证等方法选择合适的迭代次数。在初始化时,可以使用较小的随机值初始化权重,以避免落入梯度消失或梯度爆炸的问题。常见的初始化方法包括零均值高斯分布和Xavier/Glorot初始化,它们能够有效地平衡权重的初始值,有助于更快地收敛。在文本分类问题中,RNN常用的损失函数包括交叉熵损失。其能够衡量模型输出的概率分布与真实标签的差异,是分类问题的常用指标。但是在处理长序列文本中,容易遇到梯度消失的问题,导致模型难以学习长距离依赖性。这个就可以考虑使用别的变体,例如LSTM、双向RNN和GRU等结构,这些结构能够更好地处理长期依赖关系,在下面我们就会介绍一些适用于处理长序列的RNN的变体

​​​​​​​4.2LSTM模型

SimpleRNN虽然理论上能记住许多时间步之前见过的信息,但实际上它是不能学到这种长期依赖的(由于梯度消失问题)。所以在它的基础上,又产生了一个新的模型:LSTM模型。它增加了一种携带跨越多个时间步的方法。假设有一条传送带,其运行方向平行于你所处理的序列。序列中的信息可以在任意位置跳上传送带,然后被送到更晚的时间步,并在需要时原封不动地跳回来,这实际上就是LSTM的原理。

LSTM由以下几个部分组成:输入门(Input Gate):决定哪些信息将被存储到细胞状态中。通过Sigmoid激活函数来决定哪些信息需要更新;遗忘门(Forget Gate):决定要从细胞状态中删除哪些信息。同样通过Sigmoid激活函数来决定删除的程度;细胞状态(Cell State):负责存储短期和长期信息。通过输入门和遗忘门的控制来更新和维护;输出门(Output Gate):基于更新后的细胞状态,决定最终的LSTM输出。

这种结构使得LSTM相对于简单RNN在处理长序列上更为优越。LSTM能够有效地捕捉长期依赖关系,避免了简单RNN中的梯度消失问题。

在超参数选择上,LSTM与简单RNN相似,需要选择学习率、迭代次数等超参数。但LSTM还有自己独有的参数,包括细胞状态维度和门控单元数量等。这些参数需要根据任务进行调整。LSTM通过引入遗忘门和输入门,有选择性地更新和保留信息,有效地缓解了梯度消失问题,主要是遗忘门的存在允许模型在长序列中保持长期的记忆。

​​​​​​​4.3Bidirectional LSTM模型

双向循环神经网络由两个方向的循环神经网络组成,分别处理输入序列的正向和反向信息。这允许模型在处理序列时更好地捕获上下文信息。而双向Bi-LSTM 将双向RNN 和 LSTM 结合起来,通过双向RNN捕获上下文信息,而LSTM则负责更好地处理序列中的长距离依赖关系。这种组合有助于提高模型的性能,特别是在文本分类和生成任务中。

其中双向循环神经网络(BiRNN)是由两个循环神经网络组成,分别处理输入序列的正向和逆向信息。正向网络按顺序处理输入,而逆向网络按相反的顺序处理,然后将两者的输出进行合并。这使得模型能够在每个时刻都考虑到序列中前后的信息,更好地捕捉上下文。

在超参数选择时,BiLSTM 不仅需要选择与传统 RNN 相似的超参数,如学习率、迭代次数等,同时还需要调整 BiRNN 和 LSTM 的BiRNN 的隐藏层大小、LSTM 的细胞状态维度等独有参数。

5. 研究设计与具体操作

5.1研究目标

评估模型性能:确保模型在检测中小学生和LLM生成文本方面具有有效性。对比模型性能:比较简单RNN、LSTM、BiRNN-LSTM的性能差异,特别关注它们在中小学生文本和LLM生成文本的检测上的表现。

5.2具体操作

5.2.1数据加载与处理

这一部分主要是数据的加载与基本的处理,首先从CSV文件中加载训练数据,包括文本内容和生成标签,查看数据中是否有重复值或确实值,并进行处理

​​​​​​​5.2.1.1文本处理函数

在这个部分定义了四个文本处理函数,用于处理训练前的文本,具体包括:

1.去除空白字符函数(remove_blank):用于去除文本中的换行符和制表符。

2.处理重音符号(handle_accented):使用Unidecode库处理文本中的重音符号。

3.文本清洗(clean_text):进行分词、转小写、去停用词等预处理步骤。

4.词形还原(lemmatization):使用WordNetLemmatizer进行词形还原。

​​​​​​​5.2.1.2平衡抽样与数据集划分

在文本分类问题中,数据集中各个类别的样本数量不平衡可能会对模型的性能产生影响。原始数据集两个类别的数据比例差别较大,在这里我们使用平衡抽样,使得正负样本的数量相近,确保模型在学习时不会过于偏向样本数较多的类别,从而提高模型对所有类别的学习效果。最后,我们将平衡抽样后的数据集划分为训练集和测试集,比例为7:3。

​​​​​​​​​​​​​​​​​​​​​5.2.1.3文本向量化

使用Tokenizer对文本进行向量化的目的是将文本数据转换为计算机能够理解的数字形式,便于神经网络的训练。Tokenizer会为文本中的每个单词分配一个唯一的整数编号,形成一个词汇表。在这里面我们使用Tokenizer将文本转换为数值序列,设定词汇表大小为5000,防止过于庞大的词汇表导致计算资源的过度消耗

为了输入神经网络的文本数据具有相同的长度,还需要对文本序列进行处理。我们查看了文本长度的分布,发现最大长度为878,最小长度为1,长度主要分布在200左右,设截断或填充长度为700能覆盖绝大多数的文本。故我们将文本序列进行填充或截断,使其长度固定为700。

在这里,将文本序列进行填充或截断,使其长度固定为700。这一步的目的是确保输入到模型中的文本数据具有相同的维度,以便于神经网络的训练。

​​​​​​​​​​​​​​5.2.2模型构建

简单RNN网络中嵌入层为5001个输入词,每个词映射为500维向量;SimpleRNN层有100个神经元,返回最终输出序列;两个全连接层分别包含100个神经元,激活函数为ReLU;设置Dropout层防止过拟合,最后输出层使用Sigmoid激活函数,输出二分类结果。

LSTM网络的嵌入层、两个全连接层、Dropout层、输出层与模型1相同,只是将SimpleRNN层换成了LSTM层,并设置有100个神经元,激活函数为ReLU。

双向RNN-LSTM网络嵌入层、两个全连接层、Dropout层、输出层与模型1相同,将SimpleRNN层换成了双向LSTM层,并设置有64个神经元,激活函数为ReLU。

​​​​​​​​​​​​​​​​​​​​​​​​​​​​5.2.3模型构建模型训练与评估

三个模型都使用Adam优化器和二元交叉熵损失函数编译,在训练时,设定epochs为5,batch_size为64来训练模型,输出在训练集和测试集上的准确率和损失值,最后使用折线图进行可视化。

6. 研究结果与讨论

6.1模型性能比较

模型的性能比较我们主要从四个指标来评估:

准确度 (Accuracy) : 

  ,表示模型在所有样本中正确分类的比例,但是会受类别不平衡的影响。精确度 (Precision) : ​​​​​​​

 ,指在模型预测为正例的情况下,实际为正例的比例。在AI检测中,精确度衡量了模型对于正例(LLM生成文本)的预测准确性。高精确度表示模型对于正例的判别能力较强。召回率 (Recall) : ​​​​​​​

 ,指实际为正例的样本中,模型成功预测为正例的比例。在AI生成文本检测中,召回率衡量了模型对正例的覆盖能力。高召回率表示模型能够较好地捕获正例,避免漏判。F1分数:

,F1 分数是精确度和召回率的调和平均,它综合考虑了模型的准确性和覆盖能力。在中小学生文本和LLM生成文本检测中,F1 分数可用于综合评估模型在正例和负例上的性能,尤其在类别不平衡的情况下更具意义。

(这里 TP 表示真正例,TN 表示真负例,FP 表示假正例,FN 表示假负例)

​​​​​​​6.2.1SimpleRNN

在简单RNN中,模型的准确率并不高,五次训练的平均准确率为50.41%,损失下降很低,仅从0.698下降到0.691,表明模型在任务上的整体性能较差。此外,RNN模型的精确度为0.546,说明在模型判别为LLM生成文本的情况下,有54.6%是真正的LLM生成文本。相对较低的精确度可能表示模型存在一定的误判,将一些中小学生文本错误地分类为LLM生成文本;召回率为0.348,表示模型成功捕获的真正LLM生成文本仅占实际LLM生成文本的34.8%。低召回率表明模型在检测LLM生成文本方面存在一定的遗漏,未能充分捕捉真正的LLM生成文本;F1分数为0.425,在平衡精确度和召回率时,模型的整体性能相对较差。

综上,SimpleRNN模型的准确率表现较差,说明模型未能有效地区分中小学生文本和LLM生成文本;精确度和召回率都相对较低,说明模型在两个类别上的表现都存在一定问题;F1 分数作为综合评价指标也相对较低,提示模型在平衡精确度和召回率时存在挑战。

​​​​​​​​​​​​​​​​​​​​​6.2.2 LSTM

在LSTM中,模型的五次训练的准确率为50.19%,损失下降很低,仅从0.694下降到0.693。此外,精确度、召回率和F1分数分别为0.49、1.00、0.658。其中值得关注的是召回率为1,表示模型成功捕获的真正LLM生成文本占实际LLM生成文本的100%。高召回率表明模型在检测LLM生成文本方面非常成功,几乎没有遗漏。

综上,LSTM模型的准确率相对较低,但召回率非常高,说明模型在LLM生成文本的识别上表现良好,几乎没有遗漏;精确度较低可能表示模型在中小学生文本和LLM生成文本的区分上存在问题,有一定的误判;F1 分数相对较高,显示了在精确度和召回率之间取得了一定的平衡。

​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​6.2.3Bi-LSTM

Bi-LSTM在五次训练中的准确率较高,为98.57%,损失下降较多。精确度、召回率和FI分数分别为0.991、0.979、0.985。可以看出Bi-LSTM 模型在中小学生文本和LLM生成文本的检测任务上表现非常出色,准确率高、精确度高、召回率高,F1 分数也很高。模型的高精确度表明它在区分中小学生文本和LLM生成文本方面非常可靠,几乎没有误判。虽然召回率略低于精确度,但在实际任务中,相对较高的召回率仍然是非常可接受的。

​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​6.2.4三个模型对比

SimpleRNN 相对较差,表现欠佳,可能无法很好地捕捉到序列中的复杂关系,梯度消失问题可能影响了性能。LSTM 在召回率上表现很好,但精确度较低,可能过于保守。对于正类别的识别较好,但有一定的误判。Bi-LSTM 表现最为优越,准确率极高,且在精确度、召回率和 F1 分数上都取得了很好的平衡。双向循环和长短时记忆的结合使其能够更全面地捕获序列信息。

总之,Bi-LSTM 模型在中小学生文本和LLM生成文本的检测任务上展现了卓越的性能,是一个强大的模型。相比之下,SimpleRNN 和 LSTM 在这个任务上的表现相对较差,可能受制于梯度消失等问题。上面有说过LSTM跟RNN相比有长期依赖性,但是在遇到过长的序列时,RNN和LSTM性能没有太大差别。

6.2 错误分析

SimpleRNN 的误判

我们先从一个SimpleRNN误判的例子来分析原因:

SimpleRNN案例:

True Label: 1, Predicted Label: 0

Text: imagination powerful tool ability shape life countless way knowledge important not always enough lead innovation creative thinking fact imagination often important knowledge come thing one obvious example importance imagination field invention many successful invention history result someone using imagination envision better way something example  brother invention airplane made possible ability imagine would like fly without imagination would still stuck ground another way imagination important world movie entertainment  use imagination create new exciting story  audience without imagination movie would nothing series  image screen instead able transport different world let experience thing may never opportunity see real life addition example imagination also used bring joy life whether  vacation  new hobby imagination help find happiness fulfillment also source comfort difficult time feeling use imagination escape happier place even little course imagination not always easy come take practice effort develop  imagination reward well worth using imagination come new innovative idea create exciting work art find joy even  aspect life conclusion imagination powerful tool important knowledge many way ability lead innovation creative thinking bring joy life knowledge important not enough must use imagination truly unlock full potential live best life

分析:

内容特点:文本强调想象力的重要性,与知识一同推动创新和创造性思维。

模型可能误判原因: SimpleRNN 对于强调抽象概念和创造性思维的文本可能不具备足够理解能力。

总体来说,SimpleRNN 在处理包含较长、语义结构较复杂的文本时表现较差,出现了误判。其主要误判原因可能包括:

难以捕捉长期依赖关系: SimpleRNN 在处理长序列时可能遇到梯度消失或梯度爆炸的问题,导致难以捕捉文本中的长期依赖关系。这使得模型在理解包含多个句子、复杂逻辑结构的文本时性能下降。

处理复杂语义结构的挑战: SimpleRNN 对于复杂的语义结构、抽象概念的理解能力相对有限。在处理需要深层次理解和推理的文本时,模型可能无法准确地捕捉关键信息。

对抽象概念的理解有限: SimpleRNN 在处理强调抽象概念、创造性思维的文本时可能表现不佳。这使得模型在区分包含抽象思维和创意元素的文本时容易出现误差。

综上,SimpleRNN 在处理一些复杂、抽象的语境和语义结构时存在局限性,对于更长、更具挑战性的文本任务可能需要更复杂的循环神经网络结构来提高性能。​​​​​​​

2.LSTM 的误判

我们先从一个LSTM误判的例子来分析原因:

LSTM案例:

True Label: 1, Predicted Label: 0

Text: le car usage answer yes could stop alot pollution going atmosphere could help green house gas going ozone layer harming earth one reason cut back car use green house gas going air europe passenger car green house gas  even responsible   area cut back would good thing cut back pollution bet use bike instead car would cut back green house gas example take look  program helped mobile world think another reason lot people really like fact not car great factor earth take look germany town vauban resident town went  driving soccer mom people feel ease  willingly gave car lot people not like family vauban not car sold car move mean  gave automobile stay town cut back lot pollution europe passage woman say car always tense much happier way conclusion belive giving car cut back pollution like europe great idea quite  think would whole better situation would mean lot green house gas ozone would not get added onto bike perfect way even walking good  explained everything

分析:

内容特点:文本谈到了无人驾驶汽车对减少污染的好处。

模型可能误判原因模型未能准确理解文本中提到的一些建议和担忧,如对无人驾驶汽车技术的信任问题和责任归属问题。

综合而言,LSTM 模型在处理复杂文本时可能面临对上下文理解的挑战,以及在处理多样性观点和主题转换时的困难。改进的方向包括增加多样性数据、调整模型参数、平衡数据集等,以提高模型对复杂文本的泛化能力。

​​​​​​​3.Bi-LSTM 的误判

从上述BI-LSTM误判的例子中,我们可发现Bi-LSTM对生动的描述性语言、多样的主题和较长的文本的判断准确度较低。主要是因为这些文本具有更高的语义复杂性、上下文理解更加困难、主观性和情感分析困难和主题多样化。

​​​​​​​4.讨论

SimpleRNN和LSTM的问题: SimpleRNN和LSTM在处理长序列文本时可能遇到梯度消失的问题,导致模型难以学习长距离依赖性。这可能是它们在任务上表现较差的原因之一。

Bi-LSTM的优势是它的双向循环结构,在捕捉序列信息方面表现优越。这种结构允许模型在每个时刻都考虑到序列中前后的信息,更全面地捕获上下文。

在实际应用中,选择合适的模型并进行超参数的调优是关键步骤。Bi-LSTM在本任务上表现良好,但在其他任务中可能需要进一步验证和调整。此外,我们还需要评估模型在新数据上的泛化能力,以确保模型在不同数据集上的性能稳定。

7.总结

通过本次研究,我们对中小学生文本和LLM生成文本进行了检测,并在实验中采用了RNN、LSTM和Bi-LSTM等模型。以下是本研究的主要总结:

我们从Kaggle比赛中获取了一个附加数据集,其中包含中小学生文本和LLM生成文本。通过数据的处理和划分,我们构建了一个平衡抽样的数据集,确保了两个类别的样本数量相近。

在模型上,选择了RNN、LSTM和Bi-LSTM这三种模型进行实验。RNN是一种能够处理序列数据的神经网络结构,但容易面临梯度消失等问题。为了克服这些问题,我们引入了LSTM和Bi-LSTM,它们通过引入门控结构有效地处理了长期依赖关系。

通过最后的实验,我们对比了SimpleRNN、LSTM和Bi-LSTM模型的性能。SimpleRNN表现较差,LSTM在召回率上表现良好但精确度较低,而Bi-LSTM在所有指标上都表现卓越,尤其在中小学生文本和LLM生成文本的检测任务上表现出色。

综合而言,本研究通过对比不同模型的性能,突显了Bi-LSTM在中小学生文本和LLM生成文本检测任务上的卓越表现。我们强调了模型选择和超参数调整的重要性,并提出了对未来研究的建议,包括进一步验证模型的泛化能力和深入研究其他影响模型性能的因素。

<code>#!/usr/bin/env python

# coding: utf-8

# In[1]:

# Import Libraries

import matplotlib.pyplot as plt

import numpy as np

import pandas as pd

import re

import seaborn as sns

from nltk.tokenize import word_tokenize

from nltk.stem import WordNetLemmatizer

from unidecode import unidecode

from string import punctuation

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

from sklearn.model_selection import train_test_split

from wordcloud import WordCloud

from tqdm import tqdm

tqdm.pandas()

import warnings

warnings.filterwarnings("ignore")

# In[2]:

import tensorflow as tf

from tensorflow import keras

from keras.models import Sequential

from keras.layers import Dense, Input, SimpleRNN, LSTM , Bidirectional, Embedding

from keras.layers import Dropout

from tensorflow.keras.preprocessing.text import Tokenizer

from tensorflow.keras.preprocessing.sequence import pad_sequences

from keras.utils import to_categorical

# In[3]:

import os

train_gpu = [0,]

os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(str(x) for x in train_gpu)

ngpus_per_node = len(train_gpu)

gpus = tf.config.experimental.list_physical_devices(device_type='GPU')code>

for gpu in gpus:

tf.config.experimental.set_memory_growth(gpu, True)

if ngpus_per_node > 1:

strategy = tf.distribute.MirroredStrategy()

else:

strategy = None

print('Number of devices: {}'.format(ngpus_per_node))

# In[4]:

#载入数据

train_essays = pd.read_csv('C:\\Users\\huaix\\PycharmProjects\\pythonProject4\\kaggle\\input\\ai\\train_v2_drcat_02.csv')

train_essays = train_essays.rename(columns={'label': 'generated', 'prompt_name': 'prompt_id'}, errors='ignore')code>

# In[5]:

train_essays

# In[6]:

#定义新数据集

df1 = train_essays[['text','generated']]

df1.generated.value_counts()

# In[7]:

#文本处理函数

def remove_blank(data):

formated_text = data.replace("\\n"," ").replace("\t"," ")

return formated_text

def handle_accented(data):

fixed_text = unidecode(data)

return fixed_text

def clean_text(data):

tokens = word_tokenize(data)

text=[i.lower() for i in tokens if (i.lower() not in punctuation) and (i.lower() not in stopwords_list) and (len(i)>2) and (i.isalpha())]

return text

def lemmatization(data):

lemma = WordNetLemmatizer()

final_text = []

for i in data:

lemma_word = lemma.lemmatize(i)

final_text.append(lemma_word)

return " ".join(final_text)

stopwords_text = """"i me my myself we our ours ourselves you you're you've you'll you'd your yours yourself yourselves he him his himself she she's her hers herself it it's its itself they them their theirs themselves what which who whom this that that'll these those am is are was were be been being have has had having do does did doing a an the and but if or because as until while of at by for with about against between into through during before after above below to from up down in out on off over under again further then once here there when where why how all any both each few more most other some such only own same so than too very s t can will just don don't should should've now d ll m o re ve y ain aren aren't couldn couldn't didn didn't doesn doesn't hadn hadn't hasn hasn't haven haven't isn isn't ma mightn mightn't mustn mustn't needn needn't shan shan't shouldn shouldn't wasn wasn't weren weren't won won't wouldn wouldn't"

"""

stopwords_list = stopwords_text.split()

# In[8]:

# 处理缺失数据——无缺失数据

num_missing = df1.isna().sum()

num_missing

# In[9]:

# 处理重复数据——无重复行

duplicates = df1.duplicated(subset=['text']).sum()

df1 = df1.drop_duplicates()

print("重复行的数量:", duplicates)

# In[10]:

#平衡抽样

sampled_data1 = df1[df1['generated'] == 1]

sampled_data0 = df1[df1['generated'] == 0].sample(len(sampled_data1)) # samples a number of rows equal to the length of df_neg

sampled_data0.generated.value_counts()

# In[11]:

sampled_data1.generated.value_counts()

# In[12]:

#新建数据集

df2 = pd.concat([sampled_data1, sampled_data0], axis = 0)

# In[13]:

df2

# In[14]:

x_train,x_test,y_train,y_test=train_test_split(df2.text, df2.generated,test_size=0.3,shuffle=True)

clean_train = x_train.apply(remove_blank)

clean_test = x_test.apply(remove_blank)

clean_train = clean_train.apply(handle_accented)

clean_test = clean_test.apply(handle_accented)

clean_train = clean_train.apply(clean_text)

clean_test = clean_test.apply(clean_text)

clean_train = clean_train.apply(lemmatization)

clean_test = clean_test.apply(lemmatization)

# In[16]:

# 训练集词云图

str_text=clean_train.str.cat(sep=" ") # we have to convert all review into single stringcode>

wordcloud=WordCloud(width=500,height=300).generate(str_text)

plt.figure(figsize=(10,6))

plt.imshow(wordcloud)

plt.axis("off")

plt.show()

# In[15]:

#测试集词云图

str_text=clean_test.str.cat(sep=" ") # we have to convert all review into single stringcode>

wordcloud=WordCloud(width=500,height=300).generate(str_text)

plt.figure(figsize=(10,6))

plt.imshow(wordcloud)

plt.axis("off")

plt.show()

# In[39]:

#单词嵌入

x_train_list = clean_train.to_list()

x_test_list = clean_test.to_list()

max_words = 5000

tk = Tokenizer(num_words=max_words, oov_token="##oov##")code>

tk.fit_on_texts(x_train_list)

x_train_seq = tk.texts_to_sequences(x_train_list)

x_test_seq = tk.texts_to_sequences(x_test_list)

# In[40]:

lst = []

for i in range(0, len(x_train_seq)):

a = len(x_train_seq[i])

lst.append(a)

print("Max len of sent:",max(lst))

print("Min len of sent:",min(lst))

# In[41]:

sns.histplot(lst, color="red", label='All Essays', kde=True)code>

plt.title('Distribution of Essay Lengths')

plt.xlabel('Essay Length (Number of Characters)')

plt.ylabel('Frequency')

plt.legend()

plt.show()

# In[42]:

#文本序列填充或截断到指定的最大长度

max_len_per_sent = 700

x_train_seq1 = pad_sequences(x_train_seq, maxlen=max_len_per_sent, padding="post", truncating="post")code>

x_test_seq1 = pad_sequences(x_test_seq, maxlen=max_len_per_sent, padding="post", truncating="post")code>

# In[43]:

#简单RNN网络

max_len_per_sent = 700

vocab_size = 137759

model1 = Sequential()

model1.add(Embedding(input_dim = 5001 , output_dim = 500 , input_length = max_len_per_sent))

model1.add(SimpleRNN(units=100 , return_sequences=False))

model1.add(Dense(units=100 , activation='relu'))code>

model1.add(Dropout(0.2))

model1.add(Dense(units=1, activation='sigmoid'))code>

model1.compile(optimizer="adam",code>

loss="binary_crossentropy",code>

metrics=["accuracy"])

model1.summary()

# In[44]:

history = model1.fit(x_train_seq1 , y_train , epochs=5 ,

batch_size=64, validation_data=(x_test_seq1 , y_test))

# In[45]:

acc=history.history['accuracy']

val_acc=history.history['val_accuracy']

loss=history.history['loss']

val_loss=history.history['val_loss']

epochs=range(1,len(acc)+1)

# In[46]:

plt.plot(epochs,acc,'bo',label='Training acc',color='red')code>

plt.plot(epochs,val_acc,'b',label='validation acc',color='red')code>

plt.title('Training and validation accracy in SimpleRNN')

plt.legend()

plt.figure()

plt.plot(epochs,loss,'bo',label='Training loss',color='red')code>

plt.plot(epochs,val_loss,'b',label='validation loss',color='red')code>

plt.title('Training and validation loss in SimpleRNN')

plt.legend()

plt.show()

# In[99]:

# 创建一个包含两个子图的大图形,每个子图一行两列

plt.figure(figsize=(14, 6))

# 在第一个子图中绘制训练准确度和验证准确度

plt.subplot(1, 2, 1)

plt.plot(epochs, acc, 'b-', label='Training acc', color='red')code>

plt.plot(epochs, val_acc, 'b--', label='Validation acc', color='blue')code>

plt.title('Training and Validation Accuracy in SimpleRNN')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_acc):

plt.annotate(f'{txt:.2f}', (epochs[i], val_acc[i]), textcoords="offset points", xytext=(0,5), ha='center')code>

# 在第二个子图中绘制训练损失和验证损失

plt.subplot(1, 2, 2)

plt.plot(epochs, loss, 'b-', label='Training loss', color='red')code>

plt.plot(epochs, val_loss, 'b--', label='Validation loss', color='blue')code>

plt.title('Training and Validation Loss in SimpleRNN')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_loss):

plt.annotate(f'{txt:.3f}', (epochs[i], val_loss[i]), textcoords="offset points", xytext=(0,5), ha='center')code>

# 调整子图之间的水平间距

plt.subplots_adjust(wspace=0.3)

# 展示图形

plt.show()

# In[47]:

# vocab_size = len(tk.word_index) + 1 # 17231

#双向RNN-LSTM模型

model2 = Sequential()

model2.add(Embedding(input_dim = 5001 , output_dim = 500 , input_length = max_len_per_sent))

model2.add(Bidirectional(LSTM(units=64 , return_sequences=False)))

model2.add(Dense(units=100 , activation='relu'))code>

model2.add(Dropout(0.2))

model2.add(Dense(units=100 , activation='relu'))code>

model2.add(Dropout(0.2))

model2.add(Dense(units=1, activation='sigmoid'))code>

model2.compile(optimizer="adam",code>

loss="binary_crossentropy",code>

metrics=["accuracy"])

model2.summary()

# In[48]:

history2 = model2.fit(x_train_seq1 , y_train , epochs=5 ,

batch_size=64, validation_data=(x_test_seq1 , y_test))

# In[49]:

acc2=history2.history['accuracy']

val_acc2=history2.history['val_accuracy']

loss2=history2.history['loss']

val_loss2=history2.history['val_loss']

epochs=range(1,len(acc)+1)

# In[50]:

plt.plot(epochs,acc2,'bo',label='Training acc',color="green")code>

plt.plot(epochs,val_acc2,'b',label='validation acc',color="green")code>

plt.title('Training and validation accracy in BiRNN-LSTM')

plt.legend()

plt.figure()

plt.plot(epochs,loss2,'bo',label='Training loss',color="green")code>

plt.plot(epochs,val_loss2,'b',label='validation loss',color="green")code>

plt.title('Training and validation loss in BiRNN-LSTM')

plt.legend()

plt.show()

# In[105]:

# 创建一个包含两个子图的大图形,每个子图一行两列

plt.figure(figsize=(14, 6))

# 在第一个子图中绘制训练准确度和验证准确度

plt.subplot(1, 2, 1)

plt.plot(epochs, acc2, 'b-', label='Training acc', color='green')code>

plt.plot(epochs, val_acc2, 'b--', label='Validation acc', color='blue')code>

plt.title('Training and Validation Accuracy in BiRNN-LSTM')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_acc2):

plt.annotate(f'{txt:.2f}', (epochs[i], val_acc2[i]), textcoords="offset points", xytext=(0,5), ha='center')code>

# 在第二个子图中绘制训练损失和验证损失

plt.subplot(1, 2, 2)

plt.plot(epochs, loss2, 'b-', label='Training loss', color='green')code>

plt.plot(epochs, val_loss2, 'b--', label='Validation loss', color='blue')code>

plt.title('Training and Validation Loss in BiRNN-LSTM')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_loss2):

plt.annotate(f'{txt:.3f}', (epochs[i], val_loss2[i]), textcoords="offset points", xytext=(0,5), ha='center')code>

# 调整子图之间的水平间距

plt.subplots_adjust(wspace=0.3)

# 展示图形

plt.show()

# In[51]:

#LSTM模型

model3 = Sequential()

model3.add(Embedding(input_dim = 5001 , output_dim = 500 , input_length = max_len_per_sent))

model3.add(LSTM(units=64 , return_sequences=False))

model3.add(Dense(units=100 , activation='relu'))code>

model3.add(Dropout(0.2))

model3.add(Dense(units=100 , activation='relu'))code>

model3.add(Dropout(0.2))

model3.add(Dense(units=1, activation='sigmoid'))code>

model3.compile(optimizer="adam",code>

loss="binary_crossentropy",code>

metrics=["accuracy"])

model3.summary()

# In[52]:

history3 = model3.fit(x_train_seq1 , y_train , epochs=5 ,

batch_size=64, validation_data=(x_test_seq1 , y_test))

# In[53]:

acc3=history3.history['accuracy']

val_acc3=history3.history['val_accuracy']

loss3=history3.history['loss']

val_loss3=history3.history['val_loss']

epochs=range(1,len(acc)+1)

# In[54]:

plt.plot(epochs,acc3,'bo',label='Training acc',color="skyblue")code>

plt.plot(epochs,val_acc3,'b',label='validation acc',color="skyblue")code>

plt.title('Training and validation accracy in LSTM')

plt.legend()

plt.figure()

plt.plot(epochs,loss3,'bo',label='Training loss',color="skyblue")code>

plt.plot(epochs,val_loss3,'b',label='validation loss',color="skyblue")code>

plt.title('Training and validation loss in LSTM')

plt.legend()

plt.show()

# In[111]:

# 创建一个包含两个子图的大图形,每个子图一行两列

plt.figure(figsize=(14, 6))

# 在第一个子图中绘制训练准确度和验证准确度

plt.subplot(1, 2, 1)

plt.plot(epochs, acc3, 'b-', label='Training acc', color='skyblue')code>

plt.plot(epochs, val_acc3, 'b--', label='Validation acc', color='blue')code>

plt.title('Training and Validation Accuracy in LSTM')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_acc3):

plt.annotate(f'{txt:.2f}', (epochs[i], val_acc3[i]), textcoords="offset points", xytext=(0,5), ha='center')code>

# 在第二个子图中绘制训练损失和验证损失

plt.subplot(1, 2, 2)

plt.plot(epochs, loss3, 'b-', label='Training loss', color='skyblue')code>

plt.plot(epochs, val_loss3, 'b--', label='Validation loss', color='blue')code>

plt.title('Training and Validation Loss in LSTM')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_loss3):

plt.annotate(f'{txt:.3f}', (epochs[i], val_loss3[i]), textcoords="offset points", xytext=(0,5), ha='center')code>

# 调整子图之间的水平间距

plt.subplots_adjust(wspace=0.3)

# 展示图形

plt.show()

# In[55]:

plt.plot(epochs,val_acc,'b',label='RNN',color="red")code>

plt.plot(epochs,val_acc3,'b',label='LSTM',color="skyblue")code>

plt.plot(epochs,val_acc2,'b',label='biRNN-LSTM',color="green")code>

plt.title('validation accracy')

plt.legend()

plt.figure()

plt.plot(epochs,val_loss,'b',label='RNN',color="red")code>

plt.plot(epochs,val_loss3,'b',label='LSTM',color="skyblue")code>

plt.plot(epochs,val_loss2,'b',label='biRNN-LSTM',color="green")code>

plt.title('validation loss')

plt.legend()

plt.show()

# In[110]:

# 创建一个包含两个子图的大图形,每个子图一行两列

plt.figure(figsize=(14, 6))

# 在第一个子图中绘制验证准确度

plt.subplot(1, 2, 1)

plt.plot(epochs, val_acc, 'b-', label='RNN', color='red')code>

plt.plot(epochs, val_acc3, 'b--', label='LSTM', color='skyblue')code>

plt.plot(epochs, val_acc2, 'b-.', label='biRNN-LSTM', color='green')code>

plt.title('Validation Accuracy')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_acc):

plt.annotate(f'{txt:.2f}', (epochs[i], val_acc[i]), textcoords="offset points", xytext=(0,10), ha='center')code>

for i, txt in enumerate(val_acc3):

plt.annotate(f'{txt:.2f}', (epochs[i], val_acc3[i]), textcoords="offset points", xytext=(0,10), ha='center')code>

for i, txt in enumerate(val_acc2):

plt.annotate(f'{txt:.2f}', (epochs[i], val_acc2[i]), textcoords="offset points", xytext=(0,10), ha='center')code>

# 在第二个子图中绘制验证损失

plt.subplot(1, 2, 2)

plt.plot(epochs, val_loss, 'b-', label='RNN', color='red')code>

plt.plot(epochs, val_loss3, 'b--', label='LSTM', color='skyblue')code>

plt.plot(epochs, val_loss2, 'b-.', label='biRNN-LSTM', color='green')code>

plt.title('Validation Loss')

plt.legend()

# 在每个点上展示具体数字

for i, txt in enumerate(val_loss):

plt.annotate(f'{txt:.3f}', (epochs[i], val_loss[i]), textcoords="offset points", xytext=(0,-10), ha='center')code>

for i, txt in enumerate(val_loss3):

plt.annotate(f'{txt:.3f}', (epochs[i], val_loss3[i]), textcoords="offset points", xytext=(0,10), ha='center')code>

for i, txt in enumerate(val_loss2):

plt.annotate(f'{txt:.3f}', (epochs[i], val_loss2[i]), textcoords="offset points", xytext=(0,10), ha='center')code>

# 调整子图之间的水平间距

plt.subplots_adjust(wspace=0.3)

# 展示图形

plt.show()

# In[56]:

sns.histplot(lst, color="red", label='All Essays', kde=True)code>

plt.title('Distribution of Essay Lengths')

plt.xlabel('Essay Length (Number of Characters)')

plt.ylabel('Frequency')

plt.legend()

plt.show()

# In[57]:

# 使用模型进行预测

y_pred_proba1 = model1.predict(x_test_seq1)

y_pred_proba2 = model2.predict(x_test_seq1)

y_pred_proba3 = model3.predict(x_test_seq1)

# 将概率转换为二进制标签

y_pred1 = (y_pred_proba1 > 0.5).astype(int)

y_pred2 = (y_pred_proba2 > 0.5).astype(int)

y_pred3 = (y_pred_proba3 > 0.5).astype(int)

# In[58]:

#计算准确率额

from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score

precision_simple_rnn = precision_score(y_test, y_pred1)

precision_lstm = precision_score(y_test, y_pred3)

precision_birnn_lstm = precision_score(y_test, y_pred2)

precision_simple_rnn

# In[81]:

#LSTM模型

model3 = Sequential()

model3.add(Embedding(input_dim = 5000 , output_dim = 500 , input_length = max_len_per_sent))

model3.add(LSTM(units=32 , return_sequences=False))

model3.add(Dense(units=100 , activation='relu'))code>

model3.add(Dropout(0.2))

model3.add(Dense(units=1, activation='sigmoid'))code>

model3.compile(optimizer="rmsprop",code>

loss="binary_crossentropy",code>

metrics=["accuracy"])

model3.summary()

# In[82]:

history3 = model3.fit(x_train_seq1 , y_train , epochs=2 ,

batch_size=64, validation_data=(x_test_seq1 , y_test))

# In[83]:

y_pred_proba3 = model3.predict(x_test_seq1)

y_pred3 = (y_pred_proba3 > 0.5).astype(int)

precision_lstm = precision_score(y_test, y_pred3)

precision_lstm

# In[84]:

precision_birnn_lstm

# In[85]:

#计算召回旅率

from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score

recall_simple_rnn = recall_score(y_test, y_pred1)

recall_lstm = recall_score(y_test, y_pred3)

recall_birnn_lstm = recall_score(y_test, y_pred2)

recall_simple_rnn

# In[87]:

recall_lstm

# In[88]:

recall_birnn_lstm

# In[89]:

#计算F1

from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score

f1_simple_rnn = f1_score(y_test, y_pred1)

f1_lstm = f1_score(y_test, y_pred3)

f1_birnn_lstm = f1_score(y_test, y_pred2)

f1_simple_rnn

# In[90]:

f1_lstm

# In[91]:

f1_birnn_lstm

# In[92]:

import matplotlib.pyplot as plt

import numpy as np

# 假设你已经得到了三个模型的性能指标

models = ['Simple RNN', 'LSTM', 'BiRNN-LSTM']

precision_scores = [precision_simple_rnn, precision_lstm, precision_birnn_lstm]

recall_scores = [recall_simple_rnn, recall_lstm, recall_birnn_lstm]

f1_scores = [f1_simple_rnn, f1_lstm, f1_birnn_lstm]

# 设置图表布局

fig, axs = plt.subplots(3, 1, figsize=(10, 12))

# 绘制精确度

axs[0].bar(models, precision_scores, color='blue', alpha=0.7)code>

axs[0].set_ylabel('Precision')

axs[0].set_title('Model Precision Comparison')

# 绘制召回率

axs[1].bar(models, recall_scores, color='green', alpha=0.7)code>

axs[1].set_ylabel('Recall')

axs[1].set_title('Model Recall Comparison')

# 绘制F1分数

axs[2].bar(models, f1_scores, color='orange', alpha=0.7)code>

axs[2].set_ylabel('F1 Score')

axs[2].set_title('Model F1 Score Comparison')

# 显示图表

plt.tight_layout()

plt.show()

# In[112]:

import matplotlib.pyplot as plt

import numpy as np

# 假设你已经得到了三个模型的性能指标

models = ['Simple RNN', 'LSTM', 'BiRNN-LSTM']

precision_scores = [precision_simple_rnn, precision_lstm, precision_birnn_lstm]

recall_scores = [recall_simple_rnn, recall_lstm, recall_birnn_lstm]

f1_scores = [f1_simple_rnn, f1_lstm, f1_birnn_lstm]

# 设置图表布局

fig, axs = plt.subplots(3, 1, figsize=(10, 12))

# 绘制精确度

bars = axs[0].bar(models, precision_scores, color='blue', alpha=0.7)code>

axs[0].set_ylabel('Precision')

axs[0].set_title('Model Precision Comparison')

# 在每个柱状图上方添加具体数值标签

for bar, value in zip(bars, precision_scores):

axs[0].text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.01, f'{value:.3f}', ha='center', va='bottom')code>

# 绘制召回率

bars = axs[1].bar(models, recall_scores, color='green', alpha=0.7)code>

axs[1].set_ylabel('Recall')

axs[1].set_title('Model Recall Comparison')

# 在每个柱状图上方添加具体数值标签

for bar, value in zip(bars, recall_scores):

axs[1].text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.01, f'{value:.3f}', ha='center', va='bottom')code>

# 绘制F1分数

bars = axs[2].bar(models, f1_scores, color='orange', alpha=0.7)code>

axs[2].set_ylabel('F1 Score')

axs[2].set_title('Model F1 Score Comparison')

# 在每个柱状图上方添加具体数值标签

for bar, value in zip(bars, f1_scores):

axs[2].text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.01, f'{value:.3f}', ha='center', va='bottom')code>

# 显示图表

plt.tight_layout()

plt.show()

# In[113]:

#计算平均验证集准确率

average_val_accuracy1 = sum(val_acc) / len(val_acc)

average_val_accuracy3 = sum(val_acc3) / len(val_acc3)

average_val_accuracy2 = sum(val_acc2) / len(val_acc2)

print(f'Average Validation Accuracy in RNN: {average_val_accuracy1}')

print(f'Average Validation Accuracy in LSTM: {average_val_accuracy3}')

print(f'Average Validation Accuracy in BiLSTM: {average_val_accuracy2}')

# In[121]:

#错误分析

#RNN

# 检查维度

print(y_pred1.shape)

print(y_test.shape)

# 将多维数组转换为一维数组

y_pred1 = y_pred1.ravel()

y_test = y_test.ravel()

# 确认转换后的维度

print(y_pred1.shape)

print(y_test.shape)

# In[123]:

# 执行误判样本的查找

misclassified_samples = np.where(y_pred1 != y_test)[0]

# 取前十个误判案例

for sample_index in misclassified_samples[:10]:

print(f"Index: {sample_index}")

print(f"True Label: {y_test[sample_index]}, Predicted Label: {y_pred1[sample_index]}")

print(f"Text: {tk.sequences_to_texts(x_test_seq)[sample_index]}")

print("\n")

# In[124]:

#lstm

# 检查维度

print(y_pred3.shape)

print(y_test.shape)

# 将多维数组转换为一维数组

y_pred3= y_pred3.ravel()

y_test = y_test.ravel()

# 确认转换后的维度

print(y_pred3.shape)

print(y_test.shape)

# In[127]:

# 执行误判样本的查找

misclassified_samples3 = np.where(y_pred3 != y_test)[0]

# 取前十个误判案例

for sample_index in misclassified_samples3[:10]:

print(f"Index: {sample_index}")

print(f"True Label: {y_test[sample_index]}, Predicted Label: {y_pred3[sample_index]}")

print(f"Text: {tk.sequences_to_texts(x_test_seq)[sample_index]}")

print("\n")

# In[128]:

#BIlstm

# 检查维度

print(y_pred2.shape)

print(y_test.shape)

# 将多维数组转换为一维数组

y_pred2= y_pred2.ravel()

y_test = y_test.ravel()

# 确认转换后的维度

print(y_pred2.shape)

print(y_test.shape)

# In[130]:

# 执行误判样本的查找

misclassified_samples2 = np.where(y_pred2 != y_test)[0]

# 取前十个误判案例

for sample_index in misclassified_samples3[100:110]:

print(f"Index: {sample_index}")

print(f"True Label: {y_test[sample_index]}, Predicted Label: {y_pred2[sample_index]}")

print(f"Text: {tk.sequences_to_texts(x_test_seq)[sample_index]}")

print("\n")

# In[ ]:

data 来自:https://www.kaggle.com/code/harshithvarma007/llm-text-detection-99-47-accuracy/input



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。