昇思MindSpore学习总结十七 —— 基于MindSpore通过GPT实现情感分类

 1、要求

2、导入了一些必要的库和模块

        以便在使用MindSpore和MindNLP进行深度学习任务时能使用各种功能,比如数据集处理、模型训练、评估和回调功能。

import os  # 导入操作系统相关功能的模块,如文件和目录操作

import mindspore  # 导入MindSpore库,这是一个深度学习框架
from mindspore.dataset import text, GeneratorDataset, transforms  # 从MindSpore的数据集模块导入处理文本、生成数据集和变换功能
from mindspore import nn  # 从MindSpore库导入神经网络模块

from mindnlp.dataset import load_dataset  # 从MindNLP库导入加载数据集的功能

from mindnlp._legacy.engine import Trainer, Evaluator  # 从MindNLP库的旧版本引擎模块导入训练器和评估器
from mindnlp._legacy.engine.callbacks import CheckpointCallback, BestModelCallback  # 导入旧版本引擎模块的回调功能,用于检查点保存和最佳模型保存
from mindnlp._legacy.metrics import Accuracy  # 从MindNLP库的旧版本指标模块导入准确率指标

 3、加载IMDB数据集

        并将其分为训练集和测试集。load_dataset函数会返回一个包含数据集各个部分的字典,然后你可以通过键 'train''test' 来访问相应的数据。

imdb_ds = load_dataset('imdb', split=['train', 'test'])  # 加载IMDB数据集,并将数据集分为训练集和测试集,返回一个包含两个部分的字典

imdb_train = imdb_ds['train']  # 从字典中提取训练集数据
imdb_test = imdb_ds['test']  # 从字典中提取测试集数据

4、获取训练集数据集大小

get_dataset_size() 用于返回数据集中包含的样本数量。这个方法的返回值通常是一个整数,表示训练集中有多少个样本。 

imdb_train.get_dataset_size()  # 获取训练集数据集中样本的数量

 5、定义一个用于处理数据集的函数 process_dataset

        将输入文本数据进行tokenization,并根据设备类型选择不同的批处理方式。如果需要,还可以对数据集进行打乱和批处理。

import numpy as np  # 导入NumPy库,用于数值计算和数组操作

def process_dataset(dataset, tokenizer, max_seq_len=512, batch_size=4, shuffle=False):
    # 定义处理数据集的函数,接受数据集、tokenizer、最大序列长度、批量大小和是否打乱数据集作为参数

    is_ascend = mindspore.get_context('device_target') == 'Ascend'
    # 检查当前设备是否为Ascend(华为的深度学习处理器),根据设备类型选择不同的tokenizer处理方式

    def tokenize(text):
        # 定义tokenize函数,用于对文本进行tokenization
        if is_ascend:
            # 如果在Ascend设备上,使用'padding'和'truncation'进行tokenization
            tokenized = tokenizer(text, padding='max_length', truncation=True, max_length=max_seq_len)
        else:
            # 否则只进行'truncation'和设置最大长度
            tokenized = tokenizer(text, truncation=True, max_length=max_seq_len)
        return tokenized['input_ids'], tokenized['attention_mask']
        # 返回tokenized的'input_ids'和'attention_mask'字段

    if shuffle:
        dataset = dataset.shuffle(batch_size)
        # 如果设置了shuffle参数为True,则对数据集进行打乱

    # 对数据集应用map操作
    dataset = dataset.map(operations=[tokenize], input_columns="text", output_columns=['input_ids', 'attention_mask'])
    # 使用tokenize函数处理数据集中的"text"列,并生成新的列'input_ids'和'attention_mask'

    dataset = dataset.map(operations=transforms.TypeCast(mindspore.int32), input_columns="label", output_columns="labels")
    # 将数据集中的"label"列转换为mindspore.int32类型,并生成新的列"labels"

    # 根据设备类型选择批处理方式
    if is_ascend:
        dataset = dataset.batch(batch_size)
        # 如果在Ascend设备上,直接进行批处理
    else:
        dataset = dataset.padded_batch(batch_size, pad_info={'input_ids': (None, tokenizer.pad_token_id),
                                                             'attention_mask': (None, 0)})
        # 否则使用padded_batch进行批处理,设置填充信息(input_ids和attention_mask的填充值)

    return dataset  # 返回处理后的数据集

6、初始化一个GPT模型的tokenizer

加载预训练的GPT模型,然后添加了一些特殊标记,如句子开始标记、句子结束标记和填充标记。

from mindnlp.transformers import GPTTokenizer
# 从MindNLP库中导入GPTTokenizer,用于加载和处理GPT模型的tokenizer

gpt_tokenizer = GPTTokenizer.from_pretrained('openai-gpt')
# 使用预训练的GPT tokenizer进行初始化,指定预训练模型名称为'openai-gpt'

# add special token: <PAD>
special_tokens_dict = {
    "bos_token": "<bos>",  # 句子开始标记
    "eos_token": "<eos>",  # 句子结束标记
    "pad_token": "<pad>",  # 填充标记
}
# 定义一个字典,用于添加特定的特殊标记到tokenizer中

num_added_toks = gpt_tokenizer.add_special_tokens(special_tokens_dict)
# 将定义的特殊标记添加到tokenizer中,并返回添加的标记数量

 7、划分训练集、验证集

将一个训练数据集 imdb_train 按照 70% 和 30% 的比例分割成两个数据集:一个用于训练 (imdb_train),另一个用于验证 (imdb_val)。

# split train dataset into train and valid datasets
# 将训练数据集拆分成训练集和验证集

imdb_train, imdb_val = imdb_train.split([0.7, 0.3])
# 将 imdb_train 数据集按 70% 和 30% 的比例分割成两个数据集
# imdb_train 包含 70% 的数据,用于继续训练
# imdb_val 包含 30% 的数据,用于验证模型

8、处理三个数据集:训练集、验证集和测试集。

process_dataset 函数的作用是对数据集进行预处理,包括标记化、清洗或其他转换操作。gpt_tokenizer 是用于将文本数据转换为模型可以理解的格式的标记化工具。数据集的打乱(shuffle=True)有助于防止模型训练中的过拟合和提升泛化能力。

dataset_train = process_dataset(imdb_train, gpt_tokenizer, shuffle=True)
# 使用 process_dataset 函数处理 imdb_train 数据集
# gpt_tokenizer 用于对数据进行标记化处理
# shuffle=True 表示对数据进行随机打乱,以提高训练效果
# 处理后的数据集存储在 dataset_train 中

dataset_val = process_dataset(imdb_val, gpt_tokenizer)
# 使用 process_dataset 函数处理 imdb_val 数据集
# gpt_tokenizer 用于对数据进行标记化处理
# 处理后的数据集存储在 dataset_val 中
# 这里没有指定 shuffle 参数,默认情况下数据不会被打乱

dataset_test = process_dataset(imdb_test, gpt_tokenizer)
# 使用 process_dataset 函数处理 imdb_test 数据集
# gpt_tokenizer 用于对数据进行标记化处理
# 处理后的数据集存储在 dataset_test 中
# 这里也没有指定 shuffle 参数,默认情况下数据不会被打乱

9、从 dataset_train 中获取下一个数据样本

  • dataset_train.create_tuple_iterator():将 dataset_train 数据集转换为一个迭代器,这个迭代器返回的每一项都是一个元组(通常包含输入数据和对应的标签)。
  • next():从迭代器中获取下一个数据项。如果迭代器中没有更多的数据项,它将引发 StopIteration 异常。
next(dataset_train.create_tuple_iterator())
# 创建一个迭代器,用于遍历 dataset_train 数据集中的数据
# 使用 create_tuple_iterator() 方法将 dataset_train 转换为一个元组迭代器
# 然后调用 next() 函数从迭代器中获取下一个数据样本
# 这将返回数据集中的第一个数据项(通常是一个包含特征和标签的元组)

10、配置模型

配置一个 GPT 模型进行序列分类任务,并设置了训练过程中的优化器、评估指标、回调函数等。

  1. 模型定义和配置

    • GPTForSequenceClassification.from_pretrained('openai-gpt', num_labels=2):从预训练的 GPT 模型加载,并配置为二分类任务。
    • model.config.pad_token_id = gpt_tokenizer.pad_token_id:设置模型的填充标记 ID。
    • model.resize_token_embeddings(model.config.vocab_size + 3):扩展模型的词汇表以适应新增的词汇。
  2. 优化器和学习率

    • optimizer = nn.Adam(model.trainable_params(), learning_rate=2e-5):使用 Adam 优化器,学习率设置为 0.00002。
  3. 评估指标

    • metric = Accuracy():使用准确率作为模型性能评估指标。
  4. 回调函数

    • CheckpointCallback:用于保存训练过程中的模型检查点。
    • BestModelCallback:用于保存和自动加载最佳模型检查点。
  5. 训练配置

    • Trainer:用于模型的训练,指定了模型、数据集、优化器、回调函数等参数。
from mindnlp.transformers import GPTForSequenceClassification
from mindspore.experimental.optim import Adam

# set bert config and define parameters for training
# 设置模型配置和训练参数

# 创建一个 GPT 模型用于序列分类任务,num_labels=2 表示有两个分类标签
model = GPTForSequenceClassification.from_pretrained('openai-gpt', num_labels=2)

# 配置模型的填充标记 ID 为 tokenzier 中的 pad_token_id
model.config.pad_token_id = gpt_tokenizer.pad_token_id

# 调整模型的词汇表大小,为模型词汇表增加 3 个新的词汇
model.resize_token_embeddings(model.config.vocab_size + 3)

# 使用 Adam 优化器,并设置学习率为 2e-5
optimizer = nn.Adam(model.trainable_params(), learning_rate=2e-5)

# 定义准确率作为评估指标
metric = Accuracy()

# 定义回调函数以保存检查点
# ckpoint_cb 用于保存模型检查点
ckpoint_cb = CheckpointCallback(save_path='checkpoint', ckpt_name='gpt_imdb_finetune', epochs=1, keep_checkpoint_max=2)

# best_model_cb 用于保存最佳模型检查点,并自动加载最佳模型
best_model_cb = BestModelCallback(save_path='checkpoint', ckpt_name='gpt_imdb_finetune_best', auto_load=True)

# 创建一个 Trainer 对象用于训练模型
trainer = Trainer(
    network=model,                       # 训练的模型
    train_dataset=dataset_train,         # 训练数据集
    eval_dataset=dataset_train,          # 验证数据集(这里使用了训练集进行验证)
    metrics=metric,                      # 评估指标
    epochs=1,                            # 训练轮次
    optimizer=optimizer,                 # 优化器
    callbacks=[ckpoint_cb, best_model_cb], # 回调函数
    jit=False                            # 是否使用 JIT 编译
)

 11、trainer.run(tgt_columns="labels") 启动了模型的训练过程,并指定了目标列。

  • trainer.run(): 这个方法启动了模型的训练过程。它会根据之前配置的训练参数(如模型、优化器、数据集、回调函数等)开始训练。

  • tgt_columns="labels": 这是一个参数,指定了数据集中哪个列作为模型的目标列(即标签列)。在这里,"labels" 表示数据集中用于训练和验证的目标列是 labels。这个列的值用于计算损失函数并进行模型的优化。

这种设置通常用于数据集中包含多个列的情况,其中一个列是模型训练的目标输出。在这个例子中,labels 列包含了分类任务中的标签。

trainer.run(tgt_columns="labels")
# 启动训练过程
# tgt_columns="labels" 指定了训练数据集中包含的目标列(标签列)
# 训练过程将使用这些目标列来计算损失和进行梯度更新

12、 设置并运行了模型的评估过程

  1. 创建 Evaluator 对象:

    • network=model:指定要评估的模型。
    • eval_dataset=dataset_test:指定用于评估的数据集。这里使用了 dataset_test 数据集进行评估。
    • metrics=metric:指定评估时使用的指标。在这里是准确率(Accuracy())。
  2. 运行评估:

    • evaluator.run(tgt_columns="labels"):启动模型的评估过程。
    • tgt_columns="labels":指定目标列(即数据集中用于计算评估指标的列)。在这里,"labels" 表示模型将使用这个列中的标签来计算准确率。

通过这种设置,Evaluator 对象会遍历 dataset_test 数据集,计算模型在测试集上的表现,并根据指定的评估指标(准确率)输出结果。

evaluator = Evaluator(network=model, eval_dataset=dataset_test, metrics=metric)
# 创建一个 Evaluator 对象,用于评估模型
# 参数解释:
# network=model: 要评估的模型
# eval_dataset=dataset_test: 用于评估的数据集
# metrics=metric: 评估过程中使用的指标(这里是准确率)

evaluator.run(tgt_columns="labels")
# 启动评估过程
# tgt_columns="labels" 指定了数据集中包含的目标列(标签列)
# 评估过程中使用这些目标列来计算评估指标(如准确率)

打卡

 

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 00:28:01       95 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 00:28:01       103 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 00:28:01       84 阅读
  4. Python语言-面向对象

    2024-07-22 00:28:01       93 阅读

热门阅读

  1. 计算并输出杨辉三角形的前10行

    2024-07-22 00:28:01       28 阅读
  2. 线程局部变量共享 -- 使用ThreadLocal解决该需求

    2024-07-22 00:28:01       22 阅读
  3. 内联汇编清楚变量指定位

    2024-07-22 00:28:01       26 阅读
  4. 信竞2024年csp-j模拟赛第二场赛后总结

    2024-07-22 00:28:01       31 阅读
  5. 《C++并发编程实战》笔记(三)

    2024-07-22 00:28:01       23 阅读
  6. 决策树:简单而强大的机器学习算法

    2024-07-22 00:28:01       27 阅读
  7. 过拟合和欠拟合的解决办法

    2024-07-22 00:28:01       29 阅读
  8. mac电脑显示隐藏文件

    2024-07-22 00:28:01       27 阅读
  9. 十、继承

    2024-07-22 00:28:01       25 阅读
  10. Dubbo 的服务降级

    2024-07-22 00:28:01       22 阅读
  11. iOS 语言基础&初探 Xcode 工具

    2024-07-22 00:28:01       26 阅读