AllenNLP另外很重要的一点在于,它在torch的model的基础上添加了很多的方法,使得模型更加适用于NLP场景的使用。

AllenNLP设计模型的思想在于:

输出为dict格式,里面必须包含loss,其余则由我们自行决定。因此输出相比传统的pytorch模型,输出更加的丰富,我们可以把我们任何想要的信息都通过这个字典返回~

model.py文件有370多行,

大体上需要注意的是

  • __init__ 里要传入vocab与regularizer
  • get_regularization_penalty 得到类似L1或者L2正则的惩罚值。
  • get_parameters_for_histogram_tensorboard_logging 得到的值用于tensorboard
  • forward 最为关键的前向传播函数
  • forward_on_instance 在一条数据上进行eval
  • forward_on_instances在一堆数据上进行eval
  • decode 对答案进行解码,例如label等
  • get_metrics 返回模型的评估结果,如准确率
  • _get_prediction_device 预测得到GPU设备
  • _load 读取模型
  • load 调用_load函数
  • extend_embedder_vocab fintuning或者迁移学习时,扩充我们的词表与embedding矩阵

具体如下面代码~

# 设定并存储了一个best.th 的模型
# When training a model, many sets of weights are saved. By default we want to
# save/load this set of weights.
_DEFAULT_WEIGHTS = "best.th"class Model(torch.nn.Module, Registrable):"""This abstract class represents a model to be trained. Rather than relying completelyon the Pytorch Module, we modify the output spec of ``forward`` to be a dictionary.
Models built using this API are still compatible with other pytorch models and canbe used naturally as modules within other models - outputs are dictionaries, whichcan be unpacked and passed into other layers. One caveat to this is that if youwish to use an AllenNLP model inside a Container (such as nn.Sequential), you mustinterleave the models with a wrapper module which unpacks the dictionary intoa list of tensors.
In order for your model to be trained using the :class:`~allennlp.training.Trainer`api, the output dictionary of your Model must include a "loss" key, which will beoptimised during the training process.
Finally, you can optionally implement :func:`Model.get_metrics` in order to make useof early stopping and best-model serialization based on a validation metric in:class:`~allennlp.training.Trainer`. Metrics that begin with "_" will not be loggedto the progress bar by :class:`~allennlp.training.Trainer`."""_warn_for_unseparable_batches: Set[str] = set()# 必然是要传入一个词表的~def __init__(self,vocab: Vocabulary,regularizer: RegularizerApplicator = None) -> None:super().__init__()self.vocab = vocabself._regularizer = regularizer# 得到对某些层的参数的惩罚def get_regularization_penalty(self) -> Union[float, torch.Tensor]:"""Computes the regularization penalty for the model.Returns 0 if the model was not configured to use regularization."""if self._regularizer is None:return 0.0else:return self._regularizer(self)def get_parameters_for_histogram_tensorboard_logging( # pylint: disable=invalid-nameself) -> List[str]:"""Returns the name of model parameters used for logging histograms to tensorboard."""return [name for name, _ in self.named_parameters()]# 关键的forward函数,看英文注释便可def forward(self, *inputs) -> Dict[str, torch.Tensor]:  # pylint: disable=arguments-differ"""Defines the forward pass of the model. In addition, to facilitate easy training,this method is designed to compute a loss function defined by a user.
The input is comprised of everything required to perform atraining update, `including` labels - you define the signature here!It is down to the user to ensure that inference can be performedwithout the presence of these labels. Hence, any inputs not available atinference time should only be used inside a conditional block.
The intended sketch of this method is as follows::
def forward(self, input1, input2, targets=None):........output1 = self.layer1(input1)output2 = self.layer2(input2)output_dict = {"output1": output1, "output2": output2}if targets is not None:# Function returning a scalar torch.Tensor, defined by the user.loss = self._compute_loss(output1, output2, targets)output_dict["loss"] = lossreturn output_dict
Parameters----------inputs:Tensors comprising everything needed to perform a training update, `including` labels,which should be optional (i.e have a default value of ``None``).  At inference time,simply pass the relevant inputs, not including the labels.
Returns-------output_dict: ``Dict[str, torch.Tensor]``The outputs from the model. In order to train a model using the:class:`~allennlp.training.Trainer` api, you must provide a "loss" key pointing to ascalar ``torch.Tensor`` representing the loss to be optimized."""raise NotImplementedError# 很机制,干脆直接调用处理多个输入的方法def forward_on_instance(self, instance: Instance) -> Dict[str, numpy.ndarray]:"""Takes an :class:`~allennlp.data.instance.Instance`, which typically has raw text in it,converts that text into arrays using this model's :class:`Vocabulary`, passes those arraysthrough :func:`self.forward()` and :func:`self.decode()` (which by default does nothing)and returns the result.  Before returning the result, we convert any``torch.Tensors`` into numpy arrays and remove the batch dimension."""return self.forward_on_instances([instance])[0]# 这里非常重要!!!!!!!!!!# 我们自行做DIY完全可以按照这种思路来做!# 比如Batch的操作~!def forward_on_instances(self,instances: List[Instance]) -> List[Dict[str, numpy.ndarray]]:"""Takes a list of  :class:`~allennlp.data.instance.Instance`s, converts that text intoarrays using this model's :class:`Vocabulary`, passes those arrays through:func:`self.forward()` and :func:`self.decode()` (which by default does nothing)and returns the result.  Before returning the result, we convert any``torch.Tensors`` into numpy arrays and separate thebatched output into a list of individual dicts per instance. Note that typicallythis will be faster on a GPU (and conditionally, on a CPU) than repeated calls to:func:`forward_on_instance`.
Parameters----------instances : List[Instance], requiredThe instances to run the model on.
Returns-------A list of the models output for each instance."""batch_size = len(instances)with torch.no_grad():cuda_device = self._get_prediction_device()# 将我们的instances原本不等长# 变成一个batch,这样 之后 就可以使用padding等操作dataset = Batch(instances)# 使用index_instances,词表,将我们的instance变成数值化dataset.index_instances(self.vocab)# 使用as_tensor_dict方法,将数据变成tensormodel_input = util.move_to_device(dataset.as_tensor_dict(), cuda_device)# 调用模型decode方法~,将数值化的结果再反解回 文本outputs = self.decode(self(**model_input))# 将batch拆解成 一个个单独的实例,并且返回numpy的格式instance_separated_output: List[Dict[str, numpy.ndarray]] = [{} for _ in dataset.instances]for name, output in list(outputs.items()):if isinstance(output, torch.Tensor):# NOTE(markn): This is a hack because 0-dim pytorch tensors are not iterable.# This occurs with batch size 1, because we still want to include the loss in that case.if output.dim() == 0:output = output.unsqueeze(0)if output.size(0) != batch_size:self._maybe_warn_for_unseparable_batches(name)continueoutput = output.detach().cpu().numpy()elif len(output) != batch_size:self._maybe_warn_for_unseparable_batches(name)continuefor instance_output, batch_element in zip(instance_separated_output, output):instance_output[name] = batch_elementreturn instance_separated_output# 解码部分def decode(self, output_dict: Dict[str, torch.Tensor]) -> Dict[str, torch.Tensor]:"""Takes the result of :func:`forward` and runs inference / decoding / whateverpost-processing you need to do your model.  The intent is that ``model.forward()`` shouldproduce potentials or probabilities, and then ``model.decode()`` can take those results andrun some kind of beam search or constrained inference or whatever is necessary.  This doesnot handle all possible decoding use cases, but it at least handles simple kinds ofdecoding.
This method `modifies` the input dictionary, and also `returns` the same dictionary.
By default in the base class we do nothing.  If your model has some special decoding step,override this method."""# pylint: disable=no-self-usereturn output_dict# 返回模型的评估结果def get_metrics(self, reset: bool = False) -> Dict[str, float]:"""Returns a dictionary of metrics. This method will be called by:class:`allennlp.training.Trainer` in order to compute and use model metrics for earlystopping and model serialization.  We return an empty dictionary here rather than raisingas it is not required to implement metrics for a new model.  A boolean `reset` parameter ispassed, as frequently a metric accumulator will have some state which should be resetbetween epochs. This is also compatible with :class:`~allennlp.training.Metric`s. Metricsshould be populated during the call to ``forward``, with the:class:`~allennlp.training.Metric` handling the accumulation of the metric until thismethod is called."""# pylint: disable=unused-argument,no-self-usereturn {}def _get_prediction_device(self) -> int:"""This method checks the device of the model parameters to determine the cuda_devicethis model should be run on for predictions.  If there are no parameters, it returns -1.
Returns-------The cuda device this model should run on for predictions."""devices = {util.get_device_of(param) for param in self.parameters()}if len(devices) > 1:devices_string = ", ".join(str(x) for x in devices)raise ConfigurationError(f"Parameters have mismatching cuda_devices: {devices_string}")elif len(devices) == 1:return devices.pop()else:return -1def _maybe_warn_for_unseparable_batches(self, output_key: str):"""This method warns once if a user implements a model which returns a dictionary withvalues which we are unable to split back up into elements of the batch. This is controlledby a class attribute ``_warn_for_unseperable_batches`` because it would be extremely verboseotherwise."""if  output_key not in self._warn_for_unseparable_batches:logger.warning(f"Encountered the {output_key} key in the model's return dictionary which ""couldn't be split by the batch size. Key will be ignored.")# We only want to warn once for this key,# so we set this to false so we don't warn again.self._warn_for_unseparable_batches.add(output_key)@classmethoddef _load(cls,config: Params,serialization_dir: str,weights_file: str = None,cuda_device: int = -1) -> 'Model':"""Instantiates an already-trained model, based on the experimentconfiguration and some optional overrides."""weights_file = weights_file or os.path.join(serialization_dir, _DEFAULT_WEIGHTS)# Load vocabulary from filevocab_dir = os.path.join(serialization_dir, 'vocabulary')# If the config specifies a vocabulary subclass, we need to use it.vocab_params = config.get("vocabulary", Params({}))vocab_choice = vocab_params.pop_choice("type", Vocabulary.list_available(), True)vocab = Vocabulary.by_name(vocab_choice).from_files(vocab_dir)model_params = config.get('model')# The experiment config tells us how to _train_ a model, including where to get pre-trained# embeddings from. We're now _loading_ the model, so those embeddings will already be# stored in our weights. We don't need any pretrained weight file anymore, and we don't# want the code to look for it, so we remove it from the parameters here.remove_pretrained_embedding_params(model_params)model = Model.from_params(vocab=vocab, params=model_params)# If vocab+embedding extension was done, the model initialized from from_params# and one defined by state dict in weights_file might not have same embedding shapes.# Eg. when model embedder module was transferred along with vocab extension, the# initialized embedding weight shape would be smaller than one in the state_dict.# So calling model embedding extension is required before load_state_dict.# If vocab and model embeddings are in sync, following would be just a no-op.# 拓展embedding的vocabularymodel.extend_embedder_vocab()model_state = torch.load(weights_file, map_location=util.device_mapping(cuda_device))model.load_state_dict(model_state)# Force model to cpu or gpu, as appropriate, to make sure that the embeddings are# in sync with the weightsif cuda_device >= 0:model.cuda(cuda_device)else:model.cpu()return model@classmethoddef load(cls,config: Params,serialization_dir: str,weights_file: str = None,cuda_device: int = -1) -> 'Model':"""Instantiates an already-trained model, based on the experimentconfiguration and some optional overrides.
Parameters----------config: ParamsThe configuration that was used to train the model. It should definitelyhave a `model` section, and should probably have a `trainer` sectionas well.serialization_dir: str = NoneThe directory containing the serialized weights, parameters, and vocabularyof the model.weights_file: str = NoneBy default we load the weights from `best.th` in the serializationdirectory, but you can override that value here.cuda_device: int = -1By default we load the model on the CPU, but if you want to load itfor GPU usage you can specify the id of your GPU hereReturns-------model: ModelThe model specified in the configuration, loaded with the serializedvocabulary and the trained weights."""# Peak at the class of the model.model_type = config["model"] if isinstance(config["model"], str) else config["model"]["type"]# Load using an overridable _load method.# This allows subclasses of Model to override _load.# pylint: disable=protected-accessreturn cls.by_name(model_type)._load(config, serialization_dir, weights_file, cuda_device)# 扩充词表def extend_embedder_vocab(self, embedding_sources_mapping: Dict[str, str] = None) -> None:"""Iterates through all embedding modules in the model and assures it can embedwith the extended vocab. This is required in fine-tuning or transfer learningscenarios where model was trained with original vocabulary but duringfine-tuning/transfer-learning, it will have it work with extended vocabulary(original + new-data vocabulary).
Parameters----------embedding_sources_mapping : Dict[str, str], (optional, default=None)Mapping from model_path to pretrained-file path of the embeddingmodules. If pretrained-file used at time of embedding initializationisn't available now, user should pass this mapping. Model path ispath traversing the model attributes upto this embedding module.Eg. "_text_field_embedder.token_embedder_tokens"."""# self.named_modules() gives all sub-modules (including nested children)# The path nesting is already separated by ".": eg. parent_module_name.child_module_nameembedding_sources_mapping = embedding_sources_mapping or {}for model_path, module in self.named_modules():if hasattr(module, 'extend_vocab'):pretrained_file = embedding_sources_mapping.get(model_path, None)module.extend_vocab(self.vocab,extension_pretrained_file=pretrained_file,model_path=model_path)def remove_pretrained_embedding_params(params: Params):if isinstance(params, Params):  # The model could possible be a string, for example.keys = params.keys()if 'pretrained_file' in keys:del params['pretrained_file']for value in params.values():if isinstance(value, Params):remove_pretrained_embedding_params(value)

AllenNLP 用法总结相关推荐

  1. c语言中external,static关键字用法

    static用法: 在C中,static主要定义全局静态变量.定义局部静态变量.定义静态函数. 1.定义全局静态变量:在全局变量前面加上关键字static,该全局变量变成了全局静态变量.全局静态变量有 ...

  2. Pandas_transform的用法

    先来看一个实例问题. 如下销售数据中展现了三笔订单,每笔订单买了多种商品,求每种商品销售额占该笔订单总金额的比例.例如第一条数据的最终结果为:235.83 / (235.83+232.32+107.9 ...

  3. Python中yield和yield from的用法

    yield 后面接的是 future 对象 调用方 委托生成器 yield from 直接给出循环后的结果 yield from 委托者和子生成器直接通信 yield from 直接处理stopIte ...

  4. pytorch学习 中 torch.squeeze() 和torch.unsqueeze()的用法

    squeeze的用法主要就是对数据的维度进行压缩或者解压. 先看torch.squeeze() 这个函数主要对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的 ...

  5. python yield 和 yield from用法总结

    #例1. 简单输出斐波那契數列前 N 个数 #缺点:该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列 #要提高 fab 函数的可复用性,最好不要直接打印出数列,而 ...

  6. tf.nn.embedding_lookup()的用法

    函数: tf.nn.embedding_lookup( params, ids, partition_strategy='mod', name=None, validate_indices=True, ...

  7. OpenMP用法大全

    OpenMP基本概念 OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C.C++和Fortran.OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的 ...

  8. Dorado用法与示例

    Dorado用法与示例 dorado用后总结 一.dorado概念 dorado的产品全名是"dorado展现中间件".从产品形态上dorado由两部分组成,第一部分是一个具有AJ ...

  9. TensorFlow用法

    TensorFlow用法 什么是TensorFlow TensorFlow是一个开源软件库,用于使用数据流图进行数值计算.图中的节点表示数学运算,而图的边缘表示流动的多维数据数组(张量).这种灵活的体 ...

  10. TensorFlow Keras API用法

    TensorFlow Keras API用法 Keras 是与 TensorFlow 一起使用的更高级别的作为后端的 API.添加层就像添加一行代码一样简单.在模型架构之后,使用一行代码,可以编译和拟 ...

最新文章

  1. 追番必备,动漫角色也可以用人脸识别了
  2. ubuntu系统初始化
  3. 一键控制全屋设备,AI交互时代来临
  4. 分部类--重温篇[好处,示例]
  5. java component创建_spring--打印hello--注解component--自动创建对象
  6. Java并发编程(十)设计线程安全的类
  7. 真是O(1)吗?想清楚了没?
  8. 在Win7 64位注册ActiveX控件
  9. 没有CLOB类型却报ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB
  10. linux打印jvm内存堆栈_5款强大的JVM 性能调优监控工具
  11. python 定时器_python 线程之四:定时器(Timer),非阻塞
  12. matlab低通滤波器库函数代码_Matlab中模拟低通滤波器的函数
  13. 使用Python爬取mobi格式电纸书
  14. css知多少(7)——盒子模型
  15. 图像处理之:最大类间方差法法进行图像二值化处理
  16. 计算机仿真撤稿,LOL云顶之弈11.5天神裁决天使阵容攻略 新版本裁决天使运营思路...
  17. matplotlib简要画图
  18. matlab使用invfreqs出错,MATLAB实验2016剖析.doc
  19. 港科夜闻|香港科技大学参与共建「粤港水安全保障联合实验室」,开展水资源风险评估等方面交叉研究和成果转化...
  20. 单纯形法(simplex algorithm)

热门文章

  1. python导入鸢尾花数据集_python数据挖掘学习笔记】十九.鸢尾花数据集可视化、线性回归、决策树花样分析...
  2. adadelta算法_c – 尝试理解adadelta算法
  3. linux sata 3驱动下载,linux – SSD SATA3驱动器可能存在的问题
  4. 你画我猜游戏的java实现
  5. php超小免杀大马_最新过狗免杀php大马体积最小1KB吗
  6. mac卸载mysql
  7. abaqus Isight学习
  8. Mybatis拦截器
  9. 智能合约的形式化描述、分析和验证
  10. 【数字逻辑】学习笔记 第三章 Part2 逻辑函数的化简