AllenNLP源码学习——Vocabulary
class _NamespaceDependentDefaultDict(defaultdict)
记录non_padded_namespaces(哪些namespace不需要pad,例如tags,labels),以及如何进行pad(padded_function),或者不pad(non_padded_function)
def missing(self, key: str): 处理
如果key在non_padded_namespaces中,返回_non_padded_function
如果key不在non_padded_namespaces中,返回_padded_function
defaultdict类的初始化函数接受一个类型作为参数,当所访问的键不存在的时候,可以实例化一个值作为默认值
defaultdict类除了接受类型名称作为初始化函数的参数之外,还可以使用任何不带参数的可调用函数,到时该函数的返回结果作为默认值,这样使得默认值的取值更加灵活。
defaultdict类中通过__missing__()实现默认值的功能,当访问不存在的键时,dict[key]会调用__missing__()方法取得默认值。
python中defaultdict方法的使用
class _TokenToIndexDefaultDict
从_NamespaceDependentDefaultDict派生,padded_function为lambda: {padding_token: 0, oov_token: 1}
,即pad(无意义的填充词)为0,oov(词典中没有的词)为1
class _IndexToTokenDefaultDict
从_NamespaceDependentDefaultDict派生,padded_function为lambda: {0: padding_token, 1: oov_token}
,即0为pad(无意义的填充词),1为oov(词典中没有的词)
以上两个词典实际为两层的词典,例如{"labels":{"@@PADDING@@":0,"@@UNKNOWN@@":1}}
,{"tokens":{"word":10}}
。
一个巧妙的地方在于,基类的__missing__()方法中,判断如果某个命名空间不在词典中,则在添加命名空间时,判断它是不是需要pad,如果需要pad,则先把{"@@PADDING@@":0,"@@UNKNOWN@@":1}设置为这个命名空间的值。
_read_pretrained_tokens(embeddings_file_uri: str)
从txt或者压缩文件(zip/tar/…)获得所有token,返回值tokens: List[str]
文件中存embedding的形式为word XXXXXX
,即词与对应的embedding中间有一个空格,一行是一个词的。
def pop_max_vocab_size(params: Params)
从配置中获得词典中值的数量,返回int或Dict[str, int](多个词典)
class Vocabulary(Registrable)
- 词汇表将字符串映射到整数,允许将字符串映射到词典外的标记(OOV)。
- 词汇表匹配特定的数据集,用它来判断哪些token是在词典内。
- 词汇表还允许使用多个不同的命名空间,因此可以将“a”作为单词和“a”作为单词使用单独的索引,因此可以使用此命名空间将标记和标签字符串映射到索引(通过Field.index方法)。统一地,class:
fields.field.Field
(各种Field的基类), 此类中的大多数方法都允许传入命名空间;默认使用’tokens’命名空间,可以省略命名空间参数,只使用默认值。 - 命名空间:Instance的key(根据Instance向词典添加元素时获得命名空间),Indexer的namespace属性(token转index时添加命名空间)
- Vocabulary类只是管理token与index的关系,OOV,PAD,而index,计数,转tensor的工作在Field类中进行。
构造参数
- counter: Dict[str, Dict[str, int]] = None,计数器,用来初始化内部两个词典,具体地,Dict[str(命名空间), Dict[str(词), int(数量)]] 。Vocabulary只是记录token和index的关系,用这个counter传入instance最终在Field进行计数。
- min_count: Dict[str, int] = None,对于某个词的计数少于一个值时,不加入词典;可以对不同的命名空间设置不同的最小值
- max_vocab_size: Union[int, Dict[str, int]] = None,限制词典最大词数;可以对不同的命名空间设置不同的最大值
- non_padded_namespaces: Iterable[str] = DEFAULT_NON_PADDED_NAMESPACES,默认为("*tags", “*labels”),命名空间为tags、labels或后缀是tags/labels,在后面的处理中,不进行pad
- pretrained_files: Optional[Dict[str, str]] = None,命名空间中的词都可以从已有的embedding文件获取。如果6为False,那么数据集中新出现的词会加入词典;如果为True,则词典中只用embedding文件中加载的词。
- only_include_pretrained_words: bool = False
- tokens_to_add: Dict[str, List[str]] = None,手动向命名空间添加词
- min_pretrained_embeddings: Dict[str, int] = None,如果不为None,则从命名空间对应的预训练embedding文件中取出前k个词,加入词典
词典
Vocabulary中用两个词典记录token到index,index到token。
他们是两层的词典,第一层是{命名空间:词典},第二层词典是token和index的对应。
self._token_to_index = _TokenToIndexDefaultDict
self._index_to_token = _IndexToTokenDefaultDict
方法
_extend():向初始化的Vocabulary传数据建立词典,或拓展已有的词典,把tokens填充进词典,需要注意的是,用来创建词典的词有三个来源:1.数据集(instances)得到的(counter),2.预训练词嵌入文件(pretrained_files), 3.手动添加的词(tokens_to_add),3是最后加入词典的。
如果数据集中得到token先用词数进行排序,因此出现多的词在前面。
预训练词嵌入文件在counter中没有出现的词,没有加入词典。
add_token_to_namespace(self, token: str, namespace: str = ‘tokens’):把单词(按顺序,而不是插入加入到指定的命名空间中,
建立词典
一、读取词典文件
def from_files(cls, directory: str) -> 'Vocabulary’
读取vocabulary目录下的所有文件,例如non_padded_namespaces.txt,tokens.txt,token_characters.txt。。。最后调用vocab.set_from_file(filename, is_padded, namespace=namespace)
,由一个个命名空间构造出词典。
def set_from_file(self,filename: str,is_padded: bool = True,oov_token: str = DEFAULT_OOV_TOKEN,namespace: str = "tokens")
filename为non_padded_namespaces.txt这些文件的路径
is_padded指这个命名空间是不是需要pad的(tags与labels为False),如果需要pad,则词典的0号位置为@@PADDING@@
oov_token用哪个词代表OOV词,默认为@@UNKNOWN@@,在txt文件中可以看到第一个位置是@@UNKNOWN@@,如果is_padded=True,则@@UNKNOWN@@在1号位置。
namespace表示在那个命名空间。
读取embedding文件是逐行进行的,加入到词典时也是按照顺序的,因此词典中的词与文件中词的顺序对应,用来进行词嵌入。
二、从实例(instances)创建词典
Instance(Mapping[str, Field]),Instance包含若干个Field,Field的count_vocab_items方法各自不同。
每个instance调用count_vocab_items
namespace_token_counts: Dict[str(命名空间), Dict[str(词), int(数量)]]instance.count_vocab_items(namespace_token_counts)-------------->count_vocab_items()内部调用每个field的count_vocab_items()for field in self.fields.values():field.count_vocab_items(counter)
例如TextField,类中包括List[Token],token_indexers: Dict[str, TokenIndexer]。
token_indexers可以将tokens进行不同的转换,例如cat可以转换为34,也可以根据字符转换为[23, 10, 18],还有其他的方式。。。
def count_vocab_items(self, counter: Dict[str, Dict[str, int]]):for indexer in self._token_indexers.values():for token in self.tokens:indexer.count_vocab_items(token, counter)
indexs下次单独学习,这里只是了解一下count_vocab_items做了什么。
以SingleIdTokenIndexer为例,在这里词作为一个整体。count_vocab_items方法中用一个计数器对单词进行计数,计数结果存在indexer设置的namespace中。
counter[self.namespace][text] += 1
三、配置文件创建词典
读取配置文件创建Vocabulary部分可以在trainer.py的TrainerPieces类的from_params方法中找到。
if recover and os.path.exists(os.path.join(serialization_dir, "vocabulary")):vocab = Vocabulary.from_files(os.path.join(serialization_dir, "vocabulary"))params.pop("vocabulary", {})else:vocab = Vocabulary.from_params(params.pop("vocabulary", {}),(instance for key, dataset in all_datasets.items()for instance in datasetif key in datasets_for_vocab_creation))
- 如果上次训练中断,这次训练设置-r,即恢复之前的训练,则词典通过Vocabulary.from_files读取建立好的词典文件建立。
- 如果直接建立词典,则先读取数据集,词典通过Vocabulary.from_params,把Vocabulary的参数和读取数据集得到的Instances传入from_params。在from_params中进行一系列参数设置,进入Vocabulary.from_instances,通过数据集,建立词典。
AllenNLP源码学习——Vocabulary相关推荐
- ERNIE源码学习与实践:为超越ChatGPT打下技术基础!
★★★ 本文源自AlStudio社区精品项目,[点击此处]查看更多精品内容 >>> ERNIE学习与实践:为超越ChatGPT打下技术基础! ERNIE是BERT相爱相杀的好基友,由 ...
- 文心ERNIE源码学习与实践:为超越ChatGPT打下技术基础!
ERNIE学习与实践:为超越ChatGPT打下技术基础! ERNIE是BERT相爱相杀的好基友,由ERNIE发展起来的文心大模型,是GPT3.0的强劲竞争对手,未来还会挑战ChatGPT的江湖地位! ...
- Shiro源码学习之二
接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...
- Shiro源码学习之一
一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...
- mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...
前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...
- vue实例没有挂载到html上,vue 源码学习 - 实例挂载
前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...
- 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制
Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...
- jQuery源码学习之Callbacks
jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...
- JDK源码学习笔记——Integer
一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...
最新文章
- python一年365天、初始水平值_2020年11月7日,20201107
- 软件工程导论 银行储蓄系统_独家:重庆农商行客户存款被盗刷 银行却责怪客户用卡不规范...
- 1_1 FactoryMode 工厂模式
- 记录: 开发中的2个线程的使用问题
- python——函数 11、命名空间
- 又拍云 php5月18号那,又拍云文档中心
- php config(),php config
- 微服务和数据库到底是什么关系?
- [20170604]12c Top Frequency histogram补充.txt
- stm32运行java_STM32之——3种启动方式学习
- 「leetcode」257. 二叉树的所有路径(详解)
- Android源码打patch
- Eastfax使用技巧
- Pandas的crosstab函数
- 每日一支TED——Ethan Nadelmann:为什么我们应该终止禁毒战争
- 产品经理如何建立和促进心理安全
- 2019年程序员最值得选择的100家互联网公司排名
- raid卷的作用_Raid卷详解
- Java SE 网络编程
- [编程题] 创造新世界
热门文章
- 计算机里的公共汽车(总线)
- vc应用程序——个性化的工具条图标
- 因为计算机中丢失pff,PFF文件扩展名 - 什么是.pff以及如何打开? - ReviverSoft
- faric区块链浏览器搭建
- RemoteViews的作用和工作原理
- mysql s1009_mysql 学习笔记
- 数据中心的基本模块包括服务器,模块化数据中心的主要组成部分
- 如何避免成为一个油腻的前端
- python3 字体颜色_python3使用xlwt时写入文档字体颜色和边框样式
- 树莓派CM4_3xPCIE扩展板(SSD+WIFI6+USB3.0+5G+4G)——SSD固态盘测速