• 技术干货|昇思MindSpore NLP模型迁移之Roberta ——情感分析任务


    熟悉 BERT 模型的小伙伴对于 Roberta 模型肯定不陌生了。Roberta 模型在 BERT 模型的基础上进行了一定的改进,主要改进点有以下几个部分:

    1. 训练语料:BERT只使用 16 GB 的Book Corpus数据集和英语维基百科进行训练,Roberta增加了 CC-NEWS 、OPEN WEB TEXT、STORIES 等语料,一共有 160 GB 的纯文本。

    2. Batch Size:Roberta模型在训练中使用了更大的Batch Size -> [256 ~ 8000]。

    3. 训练时间:Roberta模型使用 1024 块 V100 的 GPU 训练了整整 1 天的时间,模型参数量和训练时间更加多和更加长。

    同时Roberta在具体的训练方法上也有所改进:

    1. 动态 MASK 机制

    2. 去除了 NSP 任务

    3. Tokenizer部分更换成 BPE 算法,分词这一点和 GPT-2 十分相似

    Roberta 源码(huggingface):

    https://huggingface.co/roberta-base

    Roberta论文:

    https://arxiv.org/abs/1907.11692

    这里我们采用了华为开发的 MindSpore 框架,并且选择了 Pytorch 版本 Roberta 模型进行模型迁移。欢迎大家一起参与到 MindSpore 开源社区的开发中来!

    前言

    本文环境:

    系统:Ubuntu 18

    GPU:RTX 3090

    MindSpore版本:1.3

    数据集:SST-2(情感分析任务)

    SST-2 数据集定义:

    这是一个二分类的数据集,训练集和验证集的句子所对应的标签是0或1

    模型权重转换

    我们需要将 Pytorch 版本的 Roberta 权重转换成 MindSpore 适用的权重,这里提供一个转换的思路。主要可以参考官网的API映射文档进行改写。

    官网链接:转换映射

    (https://www.mindspore.cn/docs/migration_guide/zh-CN/r1.5/api_mapping/pytorch_api_mapping.html)

    1. def torch_to_ms(model, torch_model):
    2. """
    3. Updates mobilenetv2 model mindspore param's data from torch param's data.
    4. Args:
    5. model: mindspore model
    6. torch_model: torch model
    7. """
    8. print("start load")
    9. # load torch parameter and mindspore parameter
    10. torch_param_dict = torch_model
    11. ms_param_dict = model.parameters_dict()
    12. count = 0
    13. for ms_key in ms_param_dict.keys():
    14. ms_key_tmp = ms_key.split('.')
    15. if ms_key_tmp[0] == 'roberta_embedding_lookup':
    16. count += 1
    17. update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.word_embeddings.weight', ms_key)
    18. elif ms_key_tmp[0] == 'roberta_embedding_postprocessor':
    19. if ms_key_tmp[1] == "token_type_embedding":
    20. count += 1
    21. update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.token_type_embeddings.weight', ms_key)
    22. elif ms_key_tmp[1] == "full_position_embedding":
    23. count += 1
    24. update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.position_embeddings.weight',
    25. ms_key)
    26. elif ms_key_tmp[1] =="layernorm":
    27. if ms_key_tmp[2]=="gamma":
    28. count += 1
    29. update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.LayerNorm.weight',
    30. ms_key)
    31. else:
    32. count += 1
    33. update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.LayerNorm.bias',
    34. ms_key)
    35. elif ms_key_tmp[0] == "roberta_encoder":
    36. if ms_key_tmp[3]=='attention':
    37. par = ms_key_tmp[4].split('_')[0]
    38. count += 1
    39. update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.'+ms_key_tmp[2]+'.'+ms_key_tmp[3]+'.'
    40. +'self.'+par+'.'+ms_key_tmp[5],
    41. ms_key)
    42. elif ms_key_tmp[3]=='attention_output':
    43. if ms_key_tmp[4]=='dense':
    44. count += 1
    45. update_torch_to_ms(torch_param_dict, ms_param_dict,
    46. 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.'+ms_key_tmp[4]+'.'+ms_key_tmp[5],
    47. ms_key)
    48. elif ms_key_tmp[4]=='layernorm':
    49. if ms_key_tmp[5]=='gamma':
    50. count += 1
    51. update_torch_to_ms(torch_param_dict, ms_param_dict,
    52. 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.LayerNorm.weight',
    53. ms_key)
    54. else:
    55. count += 1
    56. update_torch_to_ms(torch_param_dict, ms_param_dict,
    57. 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.LayerNorm.bias',
    58. ms_key)
    59. elif ms_key_tmp[3]=='intermediate':
    60. count += 1
    61. update_torch_to_ms(torch_param_dict, ms_param_dict,
    62. 'encoder.layer.' + ms_key_tmp[2] + '.intermediate.dense.'+ms_key_tmp[4],
    63. ms_key)
    64. elif ms_key_tmp[3]=='output':
    65. if ms_key_tmp[4]=='dense':
    66. count += 1
    67. update_torch_to_ms(torch_param_dict, ms_param_dict,
    68. 'encoder.layer.' + ms_key_tmp[2] + '.output.dense.'+ms_key_tmp[5],
    69. ms_key)
    70. else:
    71. if ms_key_tmp[5]=='gamma':
    72. count += 1
    73. update_torch_to_ms(torch_param_dict, ms_param_dict,
    74. 'encoder.layer.' + ms_key_tmp[2] + '.output.LayerNorm.weight',
    75. ms_key)
    76. else:
    77. count += 1
    78. update_torch_to_ms(torch_param_dict, ms_param_dict,
    79. 'encoder.layer.' + ms_key_tmp[2] + '.output.LayerNorm.bias',
    80. ms_key)
    81. if ms_key_tmp[0]=='dense':
    82. if ms_key_tmp[1]=='weight':
    83. count += 1
    84. update_torch_to_ms(torch_param_dict, ms_param_dict,
    85. 'pooler.dense.weight',
    86. ms_key)
    87. else:
    88. count += 1
    89. update_torch_to_ms(torch_param_dict, ms_param_dict,
    90. 'pooler.dense.bias',
    91. ms_key)
    92. save_checkpoint(model, "./model/roberta-base.ckpt")
    93. print(count)
    94. print("finish load")

    这里值得注意的是转换的参数一定要对应的上,不然在后续权重加载中会出现权重加载失败,或是训练过程中loss值降不下去的情况!转换完后可以试着打印对应参数的 key 值防止错漏。

    这样我们就获得了转换出来的roberta.ckpt文件用于加载权重。这里的权重文件一定要和tensorflow的权重文件进行区分!

    数据处理

    对于数据的输入这一块,MindSpore和Pytorch也是存在差异的。这里我们直接使用自己准备的dataset部分,这里面封装了多种NLP任务的数据集处理方式,可以将数据集转换成mindrecord形式,然后用于模型的训练和验证。下面跟着笔者继续去了解一下吧!

    1. """
    2. SST-2 dataset
    3. """
    4. from typing import Union, Dict, List
    5. import mindspore.dataset as ds
    6. from ..base_dataset import CLSBaseDataset
    7. class SST2Dataset(CLSBaseDataset):
    8. """
    9. SST2 dataset.
    10. Args:
    11. paths (Union[str, Dict[str, str]], Optional): Dataset file path or Dataset directory path, default None.
    12. tokenizer (Union[str]): Tokenizer function, default 'spacy'.
    13. lang (str): Tokenizer language, default 'en'.
    14. max_size (int, Optional): Vocab max size, default None.
    15. min_freq (int, Optional): Min word frequency, default None.
    16. padding (str): Padding token, default `<pad>`.
    17. unknown (str): Unknown token, default `<unk>`.
    18. buckets (List[int], Optional): Padding row to the length of buckets, default None.
    19. Examples:
    20. >>> sst2 = SST2Dataset(tokenizer='spacy', lang='en')
    21. # sst2 = SST2Dataset(tokenizer='spacy', lang='en', buckets=[16,32,64])
    22. >>> ds = sst2()
    23. """
    24. def __init__(self, paths: Union[str, Dict[str, str]] = None,
    25. tokenizer: Union[str] = 'spacy', lang: str = 'en', max_size: int = None, min_freq: int = None,
    26. padding: str = '<pad>', unknown: str = '<unk>',
    27. buckets: List[int] = None):
    28. super(SST2Dataset, self).__init__(sep='\t', name='SST-2')
    29. self._paths = paths
    30. self._tokenize = tokenizer
    31. self._lang = lang
    32. self._vocab_max_size = max_size
    33. self._vocab_min_freq = min_freq
    34. self._padding = padding
    35. self._unknown = unknown
    36. self._buckets = buckets
    37. def __call__(self) -> Dict[str, ds.MindDataset]:
    38. self.load(self._paths)
    39. self.process(tokenizer=self._tokenize, lang=self._lang, max_size=self._vocab_max_size,
    40. min_freq=self._vocab_min_freq, padding=self._padding,
    41. unknown=self._unknown, buckets=self._buckets)
    42. return self.mind_datasets
    1. from mindtext.dataset.classification import SST2Dataset
    2. #对SST-2情感分析的数据集进行处理 如果本来缓存就有只需要直接读缓存
    3. dataset = SST2Dataset(paths='./mindtext/dataset/SST-2',
    4. tokenizer="roberta-base",
    5. max_length=128,
    6. truncation_strategy=True,
    7. columns_list=['input_ids', 'attention_mask','label'],
    8. test_columns_list=['input_ids', 'attention_mask'],
    9. batch_size=64 )
    10. ds = dataset() #生成对应的train、dev的mindrecord文件
    11. ds = dataset.from_cache( columns_list=['input_ids', 'attention_mask','label'],
    12. test_columns_list=['input_ids', 'attention_mask'],
    13. batch_size=64
    14. )
    15. dev_dataset = ds['dev'] #取出转成mindrecord的验证集用于验证

    生成出来的mindrecord文件,一个是 .mindrecord文件 一个是 .mindrecord.db文件,值得注意的是我们不能随意去修改它们的名字,两个文件是存在着一定的映射关系,如果强行去修改它们名字会出现读取不了mindrecord文件的错误!

    还有进行数据处理的参数一定要和模型输入的参数一致,例如我们Roberta模型输入的参数是['input_ids', 'attention_mask','label']。

    模型的主体架构

    项目架构图:

    架构方面我们主要是参考的fastnlp的划分方式。将模型划分为Encoder、Embedding、Tokenizer三个部分,后续会进一步的优化模型的架构。

    1.Embedding

    1. """Roberta Embedding."""
    2. import logging
    3. from typing import Tuple
    4. import mindspore.nn as nn
    5. from mindspore import Tensor
    6. from mindspore.train.serialization import load_checkpoint, load_param_into_net
    7. from mindtext.modules.encoder.roberta import RobertaModel, RobertaConfig
    8. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    9. logger = logging.getLogger(__name__)
    10. class RobertaEmbedding(nn.Cell):
    11. """
    12. This is a class that loads pre-trained weight files into the model.
    13. """
    14. def __init__(self, roberta_config: RobertaConfig, is_training: bool = False):
    15. super(RobertaEmbedding, self).__init__()
    16. self.roberta = RobertaModel(roberta_config, is_training)
    17. def init_robertamodel(self,roberta):
    18. """
    19. Manual initialization BertModel
    20. """
    21. self.roberta=roberta
    22. def from_pretrain(self, ckpt_file):
    23. """
    24. Load the model parameters from checkpoint
    25. """
    26. param_dict = load_checkpoint(ckpt_file)
    27. load_param_into_net(self.roberta, param_dict)
    28. def construct(self, input_ids: Tensor, input_mask: Tensor)-> Tuple[Tensor, Tensor]:
    29. """
    30. Returns the result of the model after loading the pre-training weights
    31. Args:
    32. input_ids:A vector containing the transformation of characters into corresponding ids.
    33. input_mask:the mask for input_ids.
    34. Returns:
    35. sequence_output:the sequence output .
    36. pooled_output:the pooled output of first token:cls..
    37. """
    38. sequence_output, pooled_output, _ = self.roberta(input_ids, input_mask)
    39. return sequence_output, pooled_output

    这部分主要用来加载预训练好的权重,在前文我们就得到了mindrecord形式的权重文件。

    2.Encoder

    1. class RobertaModel(nn.Cell):
    2. """
    3. Used from mindtext.modules.encoder.roberta with Roberta
    4. Args:
    5. config (Class): Configuration for RobertaModel.
    6. is_training (bool): True for training mode. False for eval mode.
    7. use_one_hot_embeddings (bool): Specifies whether to use one hot encoding form.
    8. Default: False.
    9. """
    10. def __init__(self,
    11. config: RobertaConfig,
    12. is_training: bool,
    13. use_one_hot_embeddings: bool = False):
    14. super().__init__()
    15. config = copy.deepcopy(config)
    16. if not is_training:
    17. config.hidden_dropout_prob = 0.0
    18. config.attention_probs_dropout_prob = 0.0
    19. self.seq_length = config.seq_length
    20. self.hidden_size = config.hidden_size
    21. self.num_hidden_layers = config.num_hidden_layers
    22. self.embedding_size = config.hidden_size
    23. self.token_type_ids = None
    24. self.compute_type = numbtpye2mstype(config.compute_type)
    25. self.last_idx = self.num_hidden_layers - 1
    26. output_embedding_shape = [-1, self.seq_length, self.embedding_size]
    27. self.roberta_embedding_lookup = nn.Embedding(
    28. vocab_size=config.vocab_size,
    29. embedding_size=self.embedding_size,
    30. use_one_hot=use_one_hot_embeddings,
    31. embedding_table=TruncatedNormal(config.initializer_range))
    32. self.roberta_embedding_postprocessor = EmbeddingPostprocessor(
    33. embedding_size=self.embedding_size,
    34. embedding_shape=output_embedding_shape,
    35. use_token_type=False,
    36. token_type_vocab_size=config.type_vocab_size,
    37. use_one_hot_embeddings=use_one_hot_embeddings,
    38. max_position_embeddings=config.max_position_embeddings,
    39. dropout_prob=config.hidden_dropout_prob)
    40. self.roberta_encoder = RobertaTransformer(
    41. hidden_size=self.hidden_size,
    42. seq_length=self.seq_length,
    43. num_attention_heads=config.num_attention_heads,
    44. num_hidden_layers=self.num_hidden_layers,
    45. intermediate_size=config.intermediate_size,
    46. attention_probs_dropout_prob=config.attention_probs_dropout_prob,
    47. initializer_range=config.initializer_range,
    48. hidden_dropout_prob=config.hidden_dropout_prob,
    49. hidden_act=config.hidden_act,
    50. compute_type=self.compute_type,
    51. return_all_encoders=True)
    52. self.cast = P.Cast()
    53. self.dtype = numbtpye2mstype(config.dtype)
    54. self.cast_compute_type = SecurityCast()
    55. self.slice = P.StridedSlice()
    56. self.squeeze_1 = P.Squeeze(axis=1)
    57. self.dense = nn.Dense(self.hidden_size, self.hidden_size,
    58. activation="tanh",
    59. weight_init=TruncatedNormal(config.initializer_range))\
    60. .to_float(mstype.float32)
    61. self._create_attention_mask_from_input_mask = CreateAttentionMaskFromInputMask(config)
    62. def construct(self, input_ids: Tensor, input_mask: Tensor) -> Tuple[Tensor, Tensor, Tensor]:
    63. """Bidirectional Encoder Representations from Transformers.
    64. Args:
    65. input_ids:A vector containing the transformation of characters into corresponding ids.
    66. input_mask:the mask for input_ids.
    67. Returns:
    68. sequence_output:the sequence output .
    69. pooled_output:the pooled output of first token:cls.
    70. embedding_table:fixed embedding table.
    71. """
    72. # embedding
    73. embedding_tables = self.roberta_embedding_lookup.embedding_table
    74. word_embeddings = self.roberta_embedding_lookup(input_ids)
    75. embedding_output = self.roberta_embedding_postprocessor(input_ids,
    76. word_embeddings)
    77. # attention mask [batch_size, seq_length, seq_length]
    78. attention_mask = self._create_attention_mask_from_input_mask(input_mask)
    79. # roberta encoder
    80. encoder_output = self.roberta_encoder(self.cast_compute_type(embedding_output),
    81. attention_mask)
    82. sequence_output = self.cast(encoder_output[self.last_idx], self.dtype)
    83. # pooler
    84. batch_size = P.Shape()(input_ids)[0]
    85. sequence_slice = self.slice(sequence_output,
    86. (0, 0, 0),
    87. (batch_size, 1, self.hidden_size),
    88. (1, 1, 1))
    89. first_token = self.squeeze_1(sequence_slice)
    90. pooled_output = self.dense(first_token)
    91. pooled_output = self.cast(pooled_output, self.dtype)
    92. return sequence_output, pooled_output, embedding_tables

    这是我们的模型主体,这里我们将模型整体放入到了encoder文件下的roberta.py。我们可以看到encoder部分主要包括 encoder_output 和 sequence_output 两个部分。这里的部分实现我们是参照了 MindSpore ModelZoo 项目的 BERT 模型去实现的(小伙伴们在迁移模型时候可以登录MindSpore官网前去参考哦~),所以只需要简单的将几个重要的模块进行拼接就OK了,这几个模块包括:

    EncoderOutput:每个sub-layer加上残差连接和归一化的模块。

    RobertaAttention:单个多头自注意力层。

    RobertaEncoderCell:单个的RobertaEncoder层。

    RobertaTransformer:将多个RobertaEncoderCell拼接在一起,形成完整的roberta模块。

    这样可以大大减少我们模型架构的时间,也能更好的学习到MindSpore框架的使用。

    3.Tokenizer

    分词方面我们封装在dataset中。可以通过指定huggingface库中存在的预训练模型的名字来直接加载词表等文件!使用起来非常方便,详情可以回溯到数据处理部分的代码。如果想实现别的下游任务,但在dataset中没有的话,也可以使用我们实现的tokenlizer来用自己的方式去构建mindrecord形式的数据。

    1. def get_tokenizer(tokenize_method: str, lang: str = 'en'):
    2. """
    3. Get a tokenizer.
    4. Args:
    5. tokenize_method (str): Select a tokenizer method.
    6. lang (str): Tokenizer language, default English.
    7. Returns:
    8. function: A tokenizer function.
    9. """
    10. tokenizer_dict = {
    11. 'spacy': None,
    12. 'raw': _split,
    13. 'cn-char': _cn_split,
    14. }
    15. if tokenize_method == 'spacy':
    16. import spacy
    17. spacy.prefer_gpu()
    18. if lang != 'en':
    19. raise RuntimeError("Spacy only supports english")
    20. if parse_version(spacy.__version__) >= parse_version('3.0'):
    21. en = spacy.load('en_core_web_sm')
    22. else:
    23. en = spacy.load(lang)
    24. def _spacy_tokenizer(text):
    25. return [w.text for w in en.tokenizer(text)]
    26. tokenizer = _spacy_tokenizer
    27. elif tokenize_method in tokenizer_dict:
    28. tokenizer = tokenizer_dict[tokenize_method]
    29. else:
    30. raise RuntimeError(f"Only support {tokenizer_dict.keys()} tokenizer.")
    31. return tokenizer

    模型参数加载

    在模型主体的roberta.py文件中 RobertaConfig 模块可以加载yaml文件中的对应参数到 RobertaModel中去。以下是yaml文件的参数配置:

    1. seq_length: 128
    2. vocab_size: 50265
    3. hidden_size: 768
    4. bos_token_id: 0
    5. eos_token_id: 2
    6. num_hidden_layers: 12
    7. num_attention_heads: 12
    8. intermediate_size: 3072
    9. hidden_act: "gelu"
    10. hidden_dropout_prob: 0.1
    11. attention_probs_dropout_prob: 0.1
    12. max_position_embeddings: 514
    13. pad_token_id: 1
    14. type_vocab_size: 1
    15. initializer_range: 0.02
    16. use_relative_positions: False
    17. dtype: mstype.float32
    18. compute_type: mstype.float32

    模型训练

    接下来就是大家最期待的模型训练部分啦!我们首先要做的是将适用于 MindSpore 框架的权重参数加载到Roberta模型中去,同时初始化。可以看到,yaml 形式的超参数配置写入到RobertaModel 中并进行实例化,随后权重参数通过MindSpore内置的load_checkpoint和load_param_intonet函数加载进RobertaModel。这里我们不是直接进行加载,而是中间嵌套了一层RobertaEmbedding。而且需要注意的是训练时我们的 is_training 值设置为True,num_labels视具体下游任务要求设置。

    1. roberta_config_file = "./mindtext/config/test.yaml"
    2. roberta_config = RobertaConfig.from_yaml_file(roberta_config_file)
    3. rbm = RobertaModel(roberta_config, True)
    4. param_dict = load_checkpoint('./mindtext/pretrain/roberta-base-ms.ckpt')
    5. p = load_param_into_net(rbm, param_dict)
    6. em = RobertaEmbedding(roberta_config, True)
    7. em.initRobertaModel(rbm)
    8. roberta = RobertaforSequenceClassification(roberta_config, is_training=True, num_labels=2)
    9. roberta.init_embedding(em)

    模型权重加载完毕后,设置好学习率lr、训练轮数epoch、损失函数、优化器等等,就可以开始训练啦!这里我们根据论文提供的learning_rate来设置:3e-5。其次还使用了warm_up预热学习率,待模型趋于稳定后,再选择预先设置的学习率进行训练,使得模型收敛速度变得更快,模型效果更佳。epoch设为3轮。

    1. epoch_num = 3
    2. save_path = "./mindtext/pretrain/output/roberta-base_sst.ckpt"
    3. lr_schedule = RobertaLearningRate(learning_rate=3e-5,
    4. end_learning_rate=1e-5,
    5. warmup_steps=int(train_dataset.get_dataset_size() * epoch_num * 0.1),
    6. decay_steps=train_dataset.get_dataset_size() * epoch_num,
    7. power=1.0)
    8. params = roberta.trainable_params()
    9. optimizer = AdamWeightDecay(params, lr_schedule, eps=1e-8)

    一切准备好后,就进入训练阶段,最后将经过微调的模型参数保存至指定路径的ckpt文件中。

    1. def train(train_data, roberta, optimizer, save_path, epoch_num):
    2. update_cell = DynamicLossScaleUpdateCell(loss_scale_value=2 ** 32, scale_factor=2, scale_window=1000)
    3. netwithgrads = RobertaFinetuneCell(roberta, optimizer=optimizer, scale_update_cell=update_cell)
    4. callbacks = [TimeMonitor(train_data.get_dataset_size()), LossCallBack(train_data.get_dataset_size())]
    5. model = Model(netwithgrads)
    6. model.train(epoch_num, train_data, callbacks=callbacks, dataset_sink_mode=False)
    7. save_checkpoint(model.train_network, save_path)

    模型评估

    评估和训练的流程大致一样,读取转换成mindrecord形式的验证集,准备用作评估模型性能。

    1. dataset = SST2Dataset(paths='./mindtext/dataset/SST-2',
    2. tokenizer="roberta-base",
    3. max_length=128,
    4. truncation_strategy=True,
    5. columns_list=['input_ids', 'attention_mask','label'],
    6. test_columns_list=['input_ids', 'attention_mask'],
    7. batch_size=64 )
    8. ds = dataset.from_cache( columns_list=['input_ids', 'attention_mask','label'],
    9. test_columns_list=['input_ids', 'attention_mask'],
    10. batch_size=64
    11. )
    12. dev_dataset = ds['dev']

    接着加载超参数配置和模型权重文件,通过from_pretrain函数装载到Roberta模型中去。注意这里的下游任务也需指定 is_training 和 num_labels 两个参数值,根据具体任务设置。

    1. roberta_config_file = "./mindtext/conf/test.yaml"
    2. roberta_config = RobertaConfig.from_yaml_file(roberta_config_file)
    3. roberta = RobertaforSequenceClassification(roberta_config, is_training=False, num_labels=2, dropout_prob=0.0)
    4. model_path = "./mindtext/pretrain/output/roberta_trainsst2.ckpt"
    5. roberta.from_pretrain(model_path)

    最后就可以开始评估啦!该任务是一个文本二分类任务,模型预测标签和真实标签进行对比,模型精度为[0-1]之间的小数。

    1. def eval(eval_data, model):
    2. metirc = Accuracy('classification')
    3. metirc.clear()
    4. squeeze = mindspore.ops.Squeeze(1)
    5. for batch in tqdm(eval_data.create_dict_iterator(num_epochs=1), total=eval_data.get_dataset_size()):
    6. input_ids = batch['input_ids']
    7. input_mask = batch['attention_mask']
    8. label_ids = batch['label']
    9. inputs = {"input_ids": input_ids,
    10. "input_mask": input_mask
    11. }
    12. output = model(**inputs)
    13. sm = mindspore.nn.Softmax(axis=-1)
    14. output = sm(output)
    15. metirc.update(output, squeeze(label_ids))
    16. print(metirc.eval())

  • 相关阅读:
    Go HTTP 调用(下)
    试一试FineReport,教你玩转花样商业报表!
    Matlab数值计算(多项式插值)
    基于Windows 的 VS Code C/C++ 编译环境搭建
    vue3实现表格的分页以及确认消息弹窗
    Nginx反向代理与负载均衡与504错误
    动态规划算法实现------空间中的移动(路径)问题
    记一次:Python的学习笔记五(Django集成swagger)
    电脑重装系统后桌面图标如何调小尺寸
    将 WSL 安装到C盘以外的位置
  • 原文地址:https://blog.csdn.net/Kenji_Shinji/article/details/125479204