提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

自然语言处理实现人机自然交互,借助文本自动化处理,大幅提升信息获取与交互效率 ;作为人工智能关键领域,它为高级智能任务筑牢基础,推动行业迈向智能化发展。
今天我将用在网上下载的csldlp数据集来进行模型的训练。


一、PaddleNLP是什么?

PaddleNLP 是基于飞桨的自然语言处理工具包。特点是功能丰富,有多种预训练模型;能支持词法分析、情感分析等多种 NLP 任务,且通过 taskflow 封装成简单 API 调用;开发便捷,支持自定义和微调模型;有完善文档与活跃社区,适用于新闻摘要、智能客服等场景。

二、具体步骤

1.引入库

代码如下(示例):

import json
import pandas as pd
import paddle
import re
from sklearn.model_selection import train_test_split
from paddle.io import Dataset, DataLoader
from paddlenlp.transformers import BertTokenizer, BertForSequenceClassification
from paddle.optimizer import AdamW
from paddle.metric import Accuracy

# 忽略所有警告
import warnings
warnings.filterwarnings('ignore')

2.读入数据

代码如下(示例):

data = []
data_path = ["train_0.json", "train_1.json", "train_2.json", "train_3.json"]  # 修正重复路径
for path in data_path:
    with open(path, 'r', encoding='utf-8') as f:
        for line in f:
            data.append(json.loads(line))

df = pd.DataFrame(data)
labels = df['label'].unique().tolist()
# 生成正确的映射关系:数字ID -> 文本标签
id2label = {int(idx): str(label) for idx, label in enumerate(labels)}  # 强制类型转换
label2id = {str(label): int(idx) for idx, label in enumerate(labels)}  # 键为文本标签
# 将文本标签转换为数字ID(模型需要的格式)
df['label'] = df['label'].map(label2id)  # 此时 df['label'] 存储的是数字

{“content”:
“扫描隧道显微镜(SEM)和原子力显微镜(AFM)具有原子级的极高分辨率,可在纳米尺度上获得实空间的表面微观三维形貌,且可定量表征,因此可用来研究材料断裂与疲劳的微观机理.简要介绍STM和AFM在该领域的应用及所取得的若干进展.”,
“label”: “材料科学与工程”, “id”: 1142} {“content”:
“高质量教师队伍是偏僻地区教育发展的关键因素.日本为满足偏僻地区教育发展的现实需求,制定了偏僻地区教师倾斜待遇政策以吸引并挽留更多优秀教师在偏僻地区任教.该政策主要包括受益对象、经费保障、发放标准、支付方式、环境建设等方面内容.该政策特点表现为:政策法制保障体系完善、落实严格;倾斜待遇额度大、类别清晰、精准投入;政策规定详尽完善、可操作性强.日本在偏僻地区高质量师资队伍建设方面成效显著.”,
“label”: “教育学”, “id”: 732} {“content”:
“以浙江西苕溪流域为研究区,综合考虑地形和土壤类型等信息,采集典型土壤样本,测定土壤颗粒组成,并基于土壤颗粒组成与景观位置和特征之间的关系,利用径向基函数(RBF)神经网络建立了高程、坡度、平面曲率、剖面曲率、径流强度系数和地形湿度指数6个地形因子与土壤颗粒组成之间的非线性映射关系,预测土壤颗粒组成的空间分布.验证结果表明,RBF神经网络方法能够挖掘出地形因子信息与土壤颗粒组成之间的非线性映射关系,其预测精度较高,模型稳定性较好,是一种低成本、高效率的制图方法.”,
“label”: “农业资源利用”, “id”: 2290}

这是数据集中的两条数据,其中包括正文content,标签label,以及ID(在训练过程中并没有用到)。

数据预处理

def clean_text(text):
    text = re.sub(r"\s+", " ", text)  # 将多余的空格去掉
    text = re.sub(r"[^\w\s]", "", text)  # 将标点符号去掉
    return text.strip()

df["content"] = df["content"].apply(clean_text)

划分数据集

不同于照片数据集的训练,文本是由字符或单词组成的序列,其基本单位是离散的符号,不像图像那样具有明显的空间结构。虽然文本也有一定的顺序和语法结构,但这种结构更适合用序列数据的方式来表示,例如将文本转换为单词列表或字符列表,然后通过词嵌入等技术将其映射到向量空间中,而不是用多维数组来表示。
其中的不同就是利用词嵌入技术:词嵌入是一种将文本中的单词或短语转换为低维向量空间表示的技术。在自然语言处理中,计算机难以直接处理文本形式的单词,词嵌入的目的就是将这些离散的单词转化为连续的向量空间中的向量,使得计算机能够对其进行计算和处理,同时尽可能保留单词的语义和句法信息。

class MyDataset(Dataset):
    def __init__(self, df, text_col, label_col, tokenizer, max_len):
        self.df = df
        self.text_col = text_col
        self.label_col = label_col
        self.tokenizer = tokenizer
        self.max_len = max_len
        
        # 验证数据有效性(新增)
        assert not df.empty, "数据集不能为空"
        assert text_col in df.columns, f"{text_col}列不存在"
        assert label_col in df.columns, f"{label_col}列不存在"

    def __getitem__(self, idx):
        # 添加索引范围检查(新增)
        if idx >= len(self.df):
            raise IndexError(f"索引{idx}超出数据集范围(0-{len(self.df)-1})")
            
        text = self.df.loc[idx, self.text_col]
        label = self.df.loc[idx, self.label_col]

        # 添加类型验证(新增)
        if not isinstance(text, str):
            text = str(text)
        if not isinstance(label, int):
            label = int(label)

        encoding = self.tokenizer(
            text,
            max_seq_len=self.max_len,
            pad_to_max_seq_len=True,
            truncation=True,
            return_attention_mask=True
        )

        input_ids = paddle.to_tensor(encoding['input_ids'])
        attention_mask = paddle.to_tensor(encoding['attention_mask'])
        label = paddle.to_tensor(label, dtype=paddle.int64)

        return {
            'input_ids': input_ids,
            'attention_mask': attention_mask,
            'label': label
        }

    def __len__(self):
        return len(self.df)

在模型处理数据集之前,我们需要创建自己的数据集类来读入,将数据集具有可以有被使用的功能,其中类中必须需要重写的函数有__init__(),len()和__geitem__(),这是所有数据集都必须要进行的步骤,具体也可以参考利用PyTorch来训练本地数据的过程。然后利用DataLoader来读入具体的数据。

train_dataset = MyDataset(train_df, 'content', 'label', tokenizer, max_length)
val_dataset = MyDataset(val_df, 'content', 'label', tokenizer, max_length)
test_dataset = MyDataset(test_df, 'content', 'label', tokenizer, max_length)

紧接着就是划分数据集,这就已经对数据进行处理完了。

创建模型

首先我们要自定义训练次数,批量次数和学习率,以及是否需要优化器和正则化,早停策略(按自己的需求来定)。

# 设置GPU
paddle.set_device('gpu')
# 模型初始化
num_classes = len(id2label)  # 直接从映射获取类别数
model = BertForSequenceClassification.from_pretrained(
    'bert-base-chinese',
    num_classes=num_classes,
    id2label=id2label,
    label2id=label2id,
    return_dict=True  # 确保返回字典格式
)

模型测试和结果展示

在这里插入图片描述

总结

此模型在Paddlenlp中基于BERT模型进行改进,对于我这个初学者可以起到边学习边训练的作用,也可以增加对模型训练过程的了解。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐