基于BERT模型进行文本处理(Python)

news2025/1/10 10:48:52

基于BERT模型进行文本处理(Python)

所有程序都由Python使用Spyder运行。
对于BERT,在运行之前,它需要安装一些环境。
首先,打开Spyder。其次,在控制台中单独放置要安装的:

pip install transformers
pip install torch
pip install torch torchvision
conda install pytorch torchvision torchaudio -c pytorch

第三,重新启动内核(这意味着关闭Spyder并重新打开它)。
最后,直接打开python文件(后面有完整代码和运行之后的结果),点击运行,就可以产生结果。
所有数据都存储在名为data的BERT文件夹中。处理时,它将自动加载数据文件夹。然后它将创建traintest.csv和validation_test.csv。之后,它将分析test文件包,以自动生成test.csv和test-analysis.csv

Bert并不是专门用来确定一份文件是由单个作者还是由多个作者撰写的。这是因为,要确定一份文档是单作者还是多作者,需要了解文档的结构和内容,并分析整个文本中使用的写作风格。

检测文本中的变化可以使用BERT(一种预先训练的语言模型)和逻辑回归分类器来实现。这个过程的第一步是使用BERT对两段文本进行编码。BERT将文本编码为一系列向量,其中每个向量表示文本中的不同单词或子单词。然后,可以使用这些编码向量来训练分类器,以预测两段文本是相似还是不同。

为了训练分类器,有必要为其提供一组标记的训练数据。这意味着我们需要有一组文本对,其中每一对都被标记为相似或不同。这些信息可以从JSON文件中获得,但在这种情况下,我们使用前面在数据中提到的CSV文件中第二列的更改。我们使用这些文本对来训练分类器来识别相似文本和不同文本之间的差异。

一旦分类器经过训练,它就可以用来预测新的文本对的相似性。要做到这一点,首先使用BERT对两段文本进行编码,然后将编码后的表示输入到逻辑回归分类器中。然后,分类器将输出一个介于0和1之间的值,该值表示两段文本相似的概率。为了避免输出只有一个类的情况,使用1乘以段落数作为预测结果来处理每个段落样式不同的特殊情况。

检测作者涉及与标记化不同的方法。用于此任务的方法称为BertForSequenceClassification,它将每个段落分解为一系列标记。参数model_name和num_labels在该方法中至关重要。Model_name用于加载适用于特定任务的预训练BERT模型,而num_labels则指定分类任务中的类数。在这个项目中,num_labels等于文档中的段落数。然后,使用BERT模型将标记嵌入到高维空间中,该模型为每个段落创建一个矢量表示,以捕捉其语义。

然后,通过将嵌入向量序列作为输入,使用监督学习算法来预测通信作者。该模型是在标记的数据集上使用损失函数进行训练的,该函数测量预测作者和真实作者之间的差异。训练后,使用单独的数据集对模型进行验证,以评估其准确性,并进行任何必要的调整以提高其性能。

一旦该模型经过训练和验证,就可以用来预测新文本中单个段落的作者身份。但是,段落作者的最大数量应与段落数量相同。根据文献综述,发现多个作者主要在2到5个之间,因此该项目将段落作者的数量限制在段落总数的1到一半之间。

在这里插入图片描述

from sklearn.metrics import f1_score, accuracy_score
from transformers import BertTokenizer, BertForSequenceClassification
import numpy as np
from sklearn.linear_model import LogisticRegression
import transformers
from transformers import BertTokenizer, BertForSequenceClassification
import torch
from collections import defaultdict
#from hmmlearn import hmm
import math
import operator
import numpy as np
import nltk
from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize

import string
import os
import math
from scipy.stats import chi2_contingency
import pandas as pd
import glob

import ast
import json
import csv
import pandas as pd
import re
from sklearn.feature_extraction.text import CountVectorizer
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression


# create a csv that store the related information from tain or validation(depends on the main part)
def createCsv(rout,csv_name):
    test=[]
    header = ['id', 'multi-author', 'changes','para_author','paragraph']

    rout_txt=glob.glob(rout+'/*.txt')
    
    rout_json=glob.glob(rout+'/*.json')
    
    for n in range(len(rout_txt)):
        for m in range(len(rout_json)):
              if(rout_txt[n].split('.')[0].split('-')[-1]==rout_json[m].split('.')[0].split('-')[-1]):
               
                with open(rout_txt[n],'r', encoding='utf-8') as f1:
                    print(rout_txt[n])
                    paragraph=f1.readlines()
                with open(rout_json[m], 'r', encoding='utf-8') as f2:
                    content = json.load(f2)
                    uniqId=rout_json[m].split('.')[0].split('-')[-1]
                    multiauthor=content['multi-author']
                    changes=content['changes']
                    para_author=content['paragraph-authors']
                    
                csvcontent=(uniqId,multiauthor,changes,para_author,paragraph)
                test.append(csvcontent)
                
    
    with open(csv_name, 'w', encoding='utf-8',newline='') as file_obj1:
            writer = csv.writer(file_obj1)
            writer.writerow(header)
            writer.writerows(test) 





            

def preprocessing(s):
    words = s.translate(str.maketrans('','',string.punctuation))
    #remove the content punctuation
    ps = PorterStemmer()
    word = word_tokenize(ps.stem(words))
    return word
    # stremming all the words


def preanalysis(text):
    # Tokenize text into words
    
    tokens = nltk.word_tokenize(text) 
    stop_words = set(stopwords.words('english'))
    # Remove stop words from tokenized text
    filtered_tokens = [word for word in tokens if word.lower() not in stop_words]
    stemmer = PorterStemmer()
    stemmed_tokens = [stemmer.stem(word) for word in filtered_tokens]
    return stemmed_tokens
    

# using google bert
tokenizerchange = transformers.BertTokenizer.from_pretrained('bert-base-uncased')
modelchange = transformers.BertModel.from_pretrained('bert-base-uncased')


# change the format of changes so that it could matched to train       
def forchanges(changes):
    cleaned_list = [s.strip("[],' ") for s in changes if s not in [",", " "]]
    cleaned_list.pop(0)
    del cleaned_list[-1]
    cleaned_list.insert(0,1)
    return cleaned_list

def forchanges1(changes):
    cleaned_list = [s.strip("[],' ") for s in changes if s not in [",", " "]]
    
    return cleaned_list

# Define a function to predict the author of new paragraphs
def predict_author(texts, tokenizer, model):
    predicted_authors = []
    for text in texts:
        # Tokenize the input text and convert the labels to PyTorch tensors
        tokenized_text = tokenizer(text, padding=True, truncation=True, return_tensors='pt')
        # Forward pass
        outputs = model(**tokenized_text)
        # Get the predicted author
        predicted_author = torch.argmax(outputs.logits).item()
        predicted_authors.append(predicted_author)
    return predicted_authors

def extract_features(paragraphs):
    encoded_inputs = tokenizerchange(paragraphs, padding=True, truncation=True, return_tensors='pt')
    with torch.no_grad():
        outputs = modelchange(**encoded_inputs)
    embeddings = outputs.last_hidden_state.mean(dim=1)
    return embeddings.numpy()


if __name__ == "__main__":
    rout1 = "data/train"
    csv_name1 = "train_test.csv"
    createCsv(rout1, csv_name1)
    counter=0
    vectorizer1 = CountVectorizer()
    #create a new csv file to store real results and predicted results
    with open('test.csv', mode='w', newline='') as result:
        writer = csv.writer(result)
        #create a new csv file to store all f1 and accuracy
        with open('test_analysis.csv', mode='w', newline='') as result1:
            f1_writer = csv.writer(result1)
            writer.writerow(['id', 'real-multiauthor','pre-multiauthor','real-changes','pre-changes','real-para_author'])
            f1_writer.writerow(['id', 'multi-accuracy','changes-f1score','changes-accuracy','para-f1score','para-accuracy'])
            with open ('validation_test.csv',"r", encoding='utf-8')as csvFile:
                rows=csv.reader(csvFile)    
                for row in rows:       
                        if(counter>0):
                            sentsplit=row[-1].split('\\n')
                            if len(sentsplit) <= 10:
                                sentsplit1= sentsplit
                            else:
                                sentsplit1 = sentsplit.pop()
                                
                            # load the content inside csv
                            authors = row[3]
                            changes = row[2]
                            authors1 = ast.literal_eval(authors)
                            multiple = row[1]
                            filename = row[0]
                           
                            if int(filename) not in [71,301,340,642,700,1752, 1823, 2019, 2021, 2022, 2096] and int(filename) <= 1000:
                            
                                #print("filename")
                                #print(filename)
                                print("filename")
                                print(filename)
                                features = extract_features(sentsplit1)
                                cleaned_list = forchanges(changes)
                                    
                                #print("correct changes")
                                #print((cleaned_list))
                                
                                # Train a logistic regression model to predict the author of a document based on its BERT embeddings
                                
                                try:
                                    clf1 = LogisticRegression()
                                    clf1.fit(features, cleaned_list)
                                    test_embedding1 = extract_features(sentsplit1)
                                    predicted_changes1 = clf1.predict(test_embedding1)
                                    sumchange= sum(int(x) for x in predicted_changes1)
                                    #criteria = predicted_changes1.count('1')
                                    print('Number of segments with style changes:', sumchange)
                                    
                                    if sumchange == 1:
                                        multiauthor = 0
                                    else:
                                        multiauthor = 1
                                    
                                    
                                    #print("predict multiauthor")
                                    #print(multiauthor)
                                    #print("authors")
                                    #print(multiple)
                                    if int(multiauthor) == int(multiple):
                                        multiauthorf1 = 1
                                        print(f"F1 score of multiauthor: {multiauthorf1:.2f}")
                                    else:
                                        multiauthorf1 = 0
                                        print(f"F1 score of multiauthor: {multiauthorf1:.2f}")
                                    
                                    
                                    changesf1 = f1_score(cleaned_list, predicted_changes1,pos_label='1')
                                    changesac = accuracy_score(cleaned_list, predicted_changes1)
                                    #print(f"F1 score of change: {changesf1:.2f}")
                                except Exception as e:
                                    print(f"Error occurred: {e}")
                                   
                                    #changesf1 = (1/len(sentsplit1))
                                    #print(f"F1 score of change: {changesf1:.2f}")
                                    multiauthor = 1
                                    #print("multiauthor")
                                    #print(multiauthor)
                                    #print("authors")
                                    #print(multiple)
                                    if int(multiauthor) == int(multiple):
                                        multiauthorf1 = 1
                                        print(f"F1 score of multiauthor: {multiauthorf1:.2f}")
                                    else:
                                        multiauthorf1 = 0
                                        print(f"F1 score of multiauthor: {multiauthorf1:.2f}")
                                    changesf1 = 0
                                    changesac = (1/len(sentsplit1))

                                num_authors = (len(sentsplit1))
                                # load pre-trained BERT model and tokenizer
                                model_name = 'bert-base-uncased'
                                tokenizer = BertTokenizer.from_pretrained(model_name)
                                model = BertForSequenceClassification.from_pretrained(model_name, num_labels=num_authors)
                                
            
                                # map paragraph indices to author indices
                                author_mapping = authors1
                                if len(author_mapping) < len(sentsplit1):
                                    author_mapping += [author_mapping[-1]] * (len(sentsplit1) - len(author_mapping))  
                                new_paragraphs = sentsplit1
                                    
                                # tokenize input paragraphs
                                input_paragraphs = []
                                for paragraph in new_paragraphs:
                                    inputs = tokenizer.encode_plus(paragraph, add_special_tokens=True, return_tensors='pt')
                                    input_paragraphs.append(inputs)
                                    
                                # predict authors of new paragraphs
                                predicted_authors = []
                                for i in range(1, len(input_paragraphs)):
                                    # concatenate previous paragraph with current paragraph
                                    inputs = input_paragraphs[i].copy()
                                    inputs['input_ids'] = torch.cat([inputs['input_ids'], input_paragraphs[i]['input_ids']], dim=1)
                                    inputs['token_type_ids'] = torch.cat([inputs['token_type_ids'], input_paragraphs[i]['token_type_ids']], dim=1)
                                    inputs['attention_mask'] = torch.cat([inputs['attention_mask'], input_paragraphs[i]['attention_mask']], dim=1)
                                        
                                    # predict author using BERT
                                    outputs = model(**inputs)
                                    probabilities = torch.softmax(outputs.logits, dim=1)[0].tolist()
                                        
                                    # choose author based on maximum probability
                                    predicted_author = author_mapping[i]  # default to known author
                                    max_prob = probabilities[author_mapping[i]-1]  # probability of known author
                                    for j in range(1,int((len(authors1))/2)):
                                        if j != author_mapping[i] and probabilities[j] > max_prob:
                                            predicted_author = j+1
                                            max_prob = probabilities[j]
                                    predicted_authors.append(predicted_author)
                                    
                                    # add first author to predicted author list
                                predicted_authors.insert(0, 1)
                                    
                                print("Predicted authors:", predicted_authors)
                   
                                print(authors1)
                                f1 = f1_score(authors1, predicted_authors, average='weighted')
                                print(f"F1 score: {f1:.2f}")
                                accuracy = accuracy_score(authors1, predicted_authors)
                                writer.writerow([filename,multiple,multiauthor,cleaned_list,predicted_changes1,authors1,predicted_authors ])
                                f1_writer.writerow([filename,multiauthorf1,changesf1,changesac,f1,accuracy ])
                        counter+=1
                  
            
    

   
            

使用BERT和文本文件夹中的输入txt文件的结果存储在test.csv和test_analysis.csv中。文件test.csv由与三个任务相关的真实结果和预测结果组成。每个列的名称都提供了其内容的清晰指示,每个属性的内容可以在下面看到:

在这里插入图片描述

在这里插入图片描述
基于之前的分析,逻辑回归在三项任务中表现良好,执行时间最低。然而,仍然存在一些提高准确性的促销活动。当有四个以上的作者时,检测所有作者是很困难的,当只有一个段落是由另一个作者写的时,识别格式也是很有挑战性的。
解决这些问题的一种可能方法是探索更先进的特征提取技术,例如深度学习模型。此外,结合其他语言特征或元数据(如写作风格或文档结构)以提高检测的准确性可能是有益的。
此外,研究组合多个模型的输出以提高整体性能的集成方法可能是有用的。最后,结合用户反馈或手动验证可以帮助进一步细化检测结果并提高准确性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1068216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三维模型3DTile格式轻量化的纹理压缩和质量关系分析

三维模型3DTile格式轻量化的纹理压缩和质量关系分析 在三维模型的3DTile格式轻量化处理中&#xff0c;纹理压缩是一个重要环节。但是&#xff0c;纹理压缩和模型质量之间存在明显的关系需要权衡。以下是纹理压缩和模型质量关系的详细分析&#xff1a; 1、压缩率与纹理质量&…

Sklearn入门

Scikit learn 也简称 sklearn, 是机器学习领域当中最知名的 python 模块之一. Sklearn 包含了很多种机器学习的方式: Classification 分类Regression 回归Clustering 非监督分类Dimensionality reduction 数据降维Model Selection 模型选择Preprocessing 数据预处理 我们总能…

Java-包装类

这里写目录标题 包装类&#xff08;Wrapper&#xff09;包装类和基本数据的转换 String VS StringBuffer VS StringBuilderStringStringBufferStringBuilder 包装类&#xff08;Wrapper&#xff09; 针对八种基本数据类型相应的引用类型 基本数据类型包装类booleanBooleancha…

C++设计模式(1)-- 单例模式

基本概念 在一个项目中&#xff0c;全局范围内&#xff0c;某个类的实例有且仅有一个&#xff0c;通过这个唯一实例向其他模块提供数据的全局访问&#xff0c;这种模式就叫单例模式&#xff0c;单例模式的典型应用就是任务队列 涉及一个类多对象操作的函数有以下几个&#xff…

嵌入式基础知识-IP地址与子网划分

本篇介绍IP地址与子网划分的一些基础知识&#xff0c;在嵌入式开发&#xff0c;使用网络功能时&#xff0c;需要了解网络的一些基础知识。 1 IP地址 1.1 IPv4与IPv6 对比信息IPv4IPv6长度32位128位地址表示形式点分十进制冒分十六进制表示示例192.168.5.1002002:0000:0000:0…

this关键字在不同上下文中的值是如何确定的?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

最全解决docker配置kibana报错 Kibana server is not ready yet

问题复现&#xff1a; 在浏览器输入http://192.168.101.65:5601/ 访问kibana报错 Kibana server is not ready yet 问题报错&#xff1a; 首先查看kibana的日志 docker logs kibana 看到报错如下&#xff1a; {"type":"log","timestamp":&q…

【小笔记】复杂模型小数据可能会造成过拟合还是欠拟合?

【学而不思则罔&#xff0c;思而不学则殆】 10.8 问题 针对这个问题&#xff0c;我先问了一下文心一言 它回答了为什么会过拟合和欠拟合&#xff0c;但并没有回答我给的场景。 简单分析 分析模型 复杂模型就表示模型的拟合能力很强&#xff0c;对于数据中特征&#xff08…

如何保证 RabbitMQ 的消息可靠性?

项目开发中经常会使用消息队列来完成异步处理、应用解耦、流量控制等功能。虽然消息队列的出现解决了一些场景下的问题&#xff0c;但是同时也引出了一些问题&#xff0c;其中使用消息队列时如何保证消息的可靠性就是一个常见的问题。如果在项目中遇到需要保证消息一定被消费的…

Mybatis 拦截器(Mybatis插件原理)

Mybatis为我们提供了拦截器机制用于插件的开发&#xff0c;使用拦截器可以无侵入的开发Mybatis插件&#xff0c;Mybatis允许我们在SQL执行的过程中进行拦截&#xff0c;提供了以下可供拦截的接口&#xff1a; Executor&#xff1a;执行器ParameterHandler&#xff1a;参数处理…

深入解析PostgreSQL:命令和语法详解及使用指南

文章目录 摘要引言基本操作安装与配置连接和退出 数据库操作创建数据库删除数据库切换数据库 表操作创建表删除表插入数据查询数据更新数据删除数据 索引和约束创建索引创建约束 用户管理创建用户授权用户修改用户密码 备份和恢复备份数据库恢复数据库 高级特性结语参考文献 摘…

在win10里顺利安装了apache2.4.41和php7.4.29以及mysql8.0.33

一、安装apache和php 最近在学习网站搭建。其中有一项内容是在windows操作系统里搭建apachephp环境。几天前根据一本书的上的说明尝试了一下&#xff0c;在win10操作系统里安装这两个软件&#xff1a;apache2.4.41和php7.4.29&#xff0c;安装以后apche能正常启动&#xff0c;…

【转载】LLM-Native 产品的变与不变

1. LLM-Native&#xff1a;AGI 的另一种路径 《银河系漫游指南》的作者——道格拉斯亚当斯曾经对「技术」一词做出这样一种解释&#xff1a; 「技术」是描述某种尚未发挥作用的东西的词汇。 这是一个充满实用主义的定义&#xff0c;这句话可以被更直观地表述为&#xff1a;当…

机器学习7:pytorch的逻辑回归

一、说明 逻辑回归模型是处理分类问题的最常见机器学习模型之一。二项式逻辑回归只是逻辑回归模型的一种类型。它指的是两个变量的分类&#xff0c;其中概率用于确定二元结果&#xff0c;因此“二项式”中的“bi”。结果为真或假 — 0 或 1。 二项式逻辑回归的一个例子是预测人…

安卓玩机----解锁system分区 可读写系统分区 magisk面具模块

玩机教程----安卓机型解锁system分区 任意修改删除系统文件 system分区可读写 参考上个博文可以了解到解锁system分区的有关常识。但目前很多机型都在安卓12 13 基础上。其实最简单的方法就在于刷写一个解锁system分区的第三方补丁包。在面具更新不能解锁系统分区的前提下。…

8.2 JUC - 5.CountdownLatch

目录 一、是什么&#xff1f;二、demo演示三、应用之同步等待多线程准备完毕四、 应用之同步等待多个远程调用结束五、CountDownLatch 原理 一、是什么&#xff1f; CountdownLatch 用来进行线程同步协作&#xff0c;等待所有线程完成倒计时。 其中构造参数用来初始化等待计数…

C#,数值计算——数据建模Fitab的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Fitting Data to a Straight Line /// </summary> public class Fitab { private int ndata { get; set; } private double a { get; set; } …

RabbitMQ之Fanout(扇形) Exchange解读

目录 基本介绍 适用场景 springboot代码演示 演示架构 工程概述 RabbitConfig配置类&#xff1a;创建队列及交换机并进行绑定 MessageService业务类&#xff1a;发送消息及接收消息 主启动类RabbitMq01Application&#xff1a;实现ApplicationRunner接口 基本介绍 Fa…

跨域请求方案整理实践

项目场景&#xff1a; 调用接口进行手机验证提示,项目需要调用其它域名的接口,导致前端提示跨域问题 问题描述 前端调用其他域名接口时报错提示: index.html#/StatisticalAnalysisOfVacancy:1 Access to XMLHttpRequest at http://xxxxx/CustomerService/template/examineMes…