document_object_model_range

===== 介绍 =====
Range标识了一定范围Document,DocumentFragment或Attr的内容。它是连续的,可以通过选择一对边界点内的内容描述。

并不是每一个Range都对应一个选择,而每一次选择都会返回一个Range。

Range接口提供了比DOM对节点操作更高层次的接口,当然这些最后都转化成了节点的操作,这意味着Range接口可以直接由节点操作完成。


===== 定义和表示 =====
==== 位置(Position) ====
文档的两种表达方式,包括标记的源码表示和DOM树结构表示。以下是与Position相关概念的定义。

Range是由边界点(boundary-point)组成的,而边界点由容器(container)和偏移(offset)定义。容器的父节点是边界点的父容器(ancestor container)。如果容器是Attr, Document, DocumentFragment, Element或EntityReference节点,那么偏移就在容器的子节点中。如果容器是CharacterData, Comment或ProcessingInstruction,那么偏移是容器中字符串间隙。

一个Range的两个边界点必须拥有相同的父容器,即是Document, DocumentFragment或Attr。共同的父容器称为Range的根容器(root container),包含Range根容器的DOM树称为Range的内容树(context tree)

边界点不能在标签内部。

{{:tech:rangeexample.gif?|}}

Range与容器和偏移相关的属性

  readonly attribute Node startContainer;
  readonly attribute long startOffset;
  readonly attribute Node endContainer;
  readonly attribute long endOffset;
==== 选择和部分选择(Selection and Partial Selection) ====
选择的内容可以包括连续节点或者是文本。

当节点被部分选择时,它仅仅是一个边界点的父容器。
==== 规范 ====
本文中document都是通过文本方式表示,通过粗体表示被Range选中的内容。

<FOO>A**BC<BAR>DEF**</BAR></FOO>

如果边界点重合,则使用^表示。

<FOO>A^BC<BAR>DEF</BAR></FOO>
===== 构建Range ====
Range可以通过DocumentRange的接口createRange创建。

  interface DocumentRange {
    Range createRange();
  }

初始的Range两个边界点都指向文档的起始点。被特定文档创建的Range只能选择该文档的内容。
===== 重设位置 =====
Range提供以下接口重设边界点。
  void setStart(in Node parent, in long offset)
                        raises(RangeException);
  void setEnd(in Node parent, in long offset)
                raises(RangeException);
下面方式可以通过相对位置重设边界点,此时容器成为了node的父节点。
  void setStartBefore(in Node node);
                              raises(RangeException);
  void setStartAfter(in Node node);
                       raises(RangeException);
  void setEndBefore(in Node node);
                      raises(RangeException);
  void setEndAfter(in Node node);
                     raises(RangeException);
以下方法可以设置Range在起始边界点还是在结束边界点collapse
  void collapse(in boolean toStart);
以下属性检测Range是否发生collapse
  readonly attribute boolean collapsed;
以下方法选定特定节点或其内容
  void selectNode(in Node n);
  void selectNodeContents(in Node n);

===== 比较边界点 =====
  short compareBoundaryPoints(in CompareHow how, in Range sourceRange) raises(RangeException);
CompareHow只能是以下四个值
  * START_TO_START
  * START_TO_END
  * END_TO_END
  * END_TO_START
结果返回-1,0,1分别对应位置在前面,等于,后面

对于边界点位置的比较可能有几种情况
  * 容器相同
  * 它们的容器不在节点树同一个高度上,同时也不是包含关系
  * 它们的容器在节点树上存在包含关系
针对不同情况,先后关系的比较有不同定义。同时需要注意的是,在文本表示的文档上具有相同位置的边界点,可能在节点树中有不同的含义。
===== 删除内容 =====
  void deleteContents();
以下是示例

  * <FOO>A**B<MOO>CD</MOO>**CD</FOO>  ⇒  <FOO>A^CD</FOO>

  * <FOO>A<MOO>B**C</MOO>D**E</FOO>  ⇒  <FOO>A<MOO>B</MOO>^E</FOO>

  * <FOO>X**Y<BAR>Z**W</BAR>Q</FOO>  ⇒  <FOO>X^<BAR>W</BAR>Q</FOO>

  * <FOO><BAR1>A**B</BAR1><BAR2/><BAR3>C**D</BAR3></FOO>  ⇒  <FOO><BAR1>A</BAR1>^<BAR3>D</BAR3>
===== 提取内容 =====
  DocumentFragment extractContents();

  * <FOO>A**B<MOO>CD</MOO>**CD</FOO>  -->  B<MOO>CD</MOO>
  * <FOO>A<MOO>B**C</MOO>D**E</FOO>  -->  <MOO>C<MOO>D
  * <FOO>X**Y<BAR>Z**W</BAR>Q</FOO>  -->  Y<BAR>Z</BAR>
  * <FOO><BAR1>A**B</BAR1><BAR2/><BAR3>C**D</BAR3></FOO> -->  <BAR1>B</BAR1><BAR2/><BAR3>C</BAR3>
===== 复制内容 =====
  DocumentFragment cloneContents();
===== 插入内容 =====
  void insertNode(in Node n) raises(RangeException);
在text节点插入节点会导致text节点的分裂
===== 装饰内容 =====
  void surroundContents(in Node newParent);
示例
  Before:
    <BAR>AB<MOO>C</MOO>DE</BAR>
 
  After surroundContents(FOO):
    <BAR>A<FOO>B<MOO>C</MOO>D</FOO>E</BAR>
当Range包含部分选择的非文本节点时,会产生异常
===== 其他成员 =====
克隆Range对象
  Range cloneRange();
获得边界点的最近父容器
  readonly attribute Node commonAncestorContainer;
获得选中对象的字符表示
  DOMString toString();
===== 文档变化时Range的修改 =====
文档变化时Range所作的变化依照以下两个原则
  * 所有的Range依然有效
  * 尽可能选择相同的区域
事实上,伴随文档改变导致的Range改变可以看成是一系列的Range操作,包括插入和删除。
==== 插入 ====
仅当插入节点和边界点拥有相同容器并且偏移小于边界点偏移时,才产生Range边界点的修改
==== 删除 ====
详细见[[http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Deletions]]示例
===== 相关资料 =====
W3C DOM-Level-2-Traversal-Range ranges [[http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html]]
### PyTorch Implementation of BERT-CasRel Model for Relation Extraction The CasRel model is designed to address the challenges associated with document-level relation extraction, particularly focusing on capturing complex dependencies between entities within documents. This section explains how this can be implemented using PyTorch and integrates insights from various research findings. #### Overview of BERT-CasRel Architecture CasRel employs a cascaded tagging mechanism that allows simultaneous prediction of subject-object pairs while considering their contextual relationships[^1]. The core idea behind CasRel lies in its ability to jointly extract multiple relations by leveraging pre-trained language models like BERT, which excel at understanding deep semantic structures present in text data. To implement such functionality effectively: - **Model Definition**: Define the architecture where BERT serves as the backbone encoder responsible for generating rich embeddings representing input sequences. - **Dataset Preparation**: Prepare datasets compatible with the expected format required by the defined model structure. Given that dataset design closely follows what the model expects as inputs/outputs, ensuring alignment here becomes crucial[^4]. Below demonstrates an example code snippet illustrating key components involved when implementing the BERT-CasRel model using PyTorch: ```python import torch from transformers import BertTokenizer, BertModel class BertCasRel(torch.nn.Module): def __init__(self, num_relations=53): # Example number of possible relations super(BertCasRel, self).__init__() self.bert = BertModel.from_pretrained('bert-base-chinese') hidden_size = self.bert.config.hidden_size # Subject tagger layers self.subject_start_fc = torch.nn.Linear(hidden_size, 1) self.subject_end_fc = torch.nn.Linear(hidden_size, 1) # Object tagger layers per each type of relationship self.object_taggers = torch.nn.ModuleList([ torch.nn.Sequential( torch.nn.Linear(hidden_size, 2), torch.nn.Softmax(dim=-1)) for _ in range(num_relations)]) def forward(self, token_ids, attention_mask=None): outputs = self.bert(input_ids=token_ids, attention_mask=attention_mask)[0] subj_starts_logits = self.subject_start_fc(outputs).squeeze(-1) subj_ends_logits = self.subject_end_fc(outputs).squeeze(-1) obj_tags_list = [] for object_tagger in self.object_taggers: obj_tags = object_tagger(outputs) obj_tags_list.append(obj_tags) return { 'subj_starts': subj_starts_logits, 'subj_ends': subj_ends_logits, 'obj_tags': torch.stack(obj_tags_list, dim=1)} tokenizer = BertTokenizer.from_pretrained('bert-base-chinese') # Dummy Input Data Creation dummy_input_text = ["公司A收购了公司B"] encoded_inputs = tokenizer(dummy_input_text, padding=True, truncation=True, max_length=128, return_tensors="pt") model = BertCasRel() output = model(**encoded_inputs) print(output['subj_starts'].shape) # Shape should match batch size * sequence length ``` This implementation showcases defining both subject start/end predictors along with separate binary classifiers for identifying objects related through specific types of relations. By stacking these predictions across all potential relation categories, one obtains comprehensive annotations over entire texts.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值