入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删。

目录

一、用途

二、代码解析

1、__init__

A、参数意义

B、对查询表的设定

C、对模型的一些其他设定(包括对权重,是否填充等等)

D、分别获取分布式训练中给每个进程开始词和结束词的index列表

E、获得相应的初始化权重参数矩阵

2、forward

A、判断输入的词的index是否在进程index中

B、构建输入词在该进程中的index列表,同时对是否全在该范围内进行标识

C、获取嵌入词

D、标识记录并进行数据汇总


一、用途

转化为词向量咯

二、代码解析

这一部分在mpu/layers.py里的VocabParallelEmbedding类里实现

1、__init__

def __init__(self, num_embeddings, embedding_dim,init_method=init.xavier_normal_):super(VocabParallelEmbedding, self).__init__()

A、参数意义

num_embeddings查询表(词典)的大小(即有多少个词);

embedding_dim每个查询向量的维度(即为每个词创建一个多少维的向量来表示);

init_method初始化权重方法————这里初始化为服从正态分布

B、对查询表的设定

        # Keep the input dimensions.self.num_embeddings = num_embeddingsself.embedding_dim = embedding_dim

C、对模型的一些其他设定(包括对权重,是否填充等等)

        # Set the detauls for compatibility.self.padding_idx = None#padding_idx选择了不填充self.max_norm = None#max_norm权重约束————这里选择了最大范数不做约束self.norm_type = 2.#norm_type指定利用2范数计算。self.scale_grad_by_freq = False#scale_grad_by_freq根据单词在mini-batch(一个batchsize)中出现的频率,对梯度进行放缩.这里不启用。self.sparse = False#这里不启用专门处理稀疏张量的模块self._weight = None

(1)padding_idx——自然语言中使用批处理时候, 每个句子的长度并不一定是等长的, 这时候就需要对较短的句子进行padding。这里默认选择了不填充

(2)max_norm权重约束——最大范数:如果嵌入向量的范数超过了这个界限,就要进行再归一化。这里默认不做约束

(3)norm_type指定利用什么范数计算,并用于对比max_norm,这里选择2范数。

(4)scale_grad_by_freq根据单词在mini-batch(一个batchsize)中出现的频率,对梯度进行放缩

(5)sparse:torch.sparse是一个专门处理稀疏张量的模块。(通常,张量会按一定的顺序连续地进行存取。但是,对于一个存在很多空值的稀疏张量来说,顺序存储的效率显得较为低下)只有足够稀疏的张量使用这种方式进行存储才能获得更高的效率。——这里不启用。

补充说明:sparse中,有意义的值被称为specified elements,而无意义的值(空值,通常为0,但是也可以是其他值)则被称为fill value。

(6)_weight:这个好像没什么用啊(如果他有什么用处的话可不可以在评论区里吱我一声呀,谢谢啦~)

D、分别获取分布式训练中给每个进程开始词和结束词的index列表

        #分别获取分布式训练中给每个进程开始词和结束词的index列表self.vocab_start_index, self.vocab_end_index = \VocabUtility.vocab_range_from_global_vocab_size(self.num_embeddings, get_model_parallel_rank(),get_model_parallel_world_size())

这里调用了mpu/utils.py里的VocabUtility类中的vocab_range_from_global_vocab_size方法,mpu/initialize.py里的get_model_parallel_rank函数和get_model_parallel_world_size函数。

(1)VocabUtility类中的vocab_range_from_global_vocab_size方法

    @staticmethod#参数设定:global_vocab_size——词典中词的数量;rank——模型并行组的进程标识(模型并行组中每个进程都有唯一标识符);world_size——分布式组中的进程数def vocab_range_from_global_vocab_size(global_vocab_size, rank, world_size):per_partition_vocab_size = divide(global_vocab_size, world_size)#得到一个进程里有多少词return VocabUtility.vocab_range_from_per_partition_vocab_size(per_partition_vocab_size, rank, world_size)

✨参数设定:

  • global_vocab_size——词典中词的数量
  • rank——模型并行组的进程标识(模型并行组中每个进程都有唯一标识符)
  • world_size——分布式组中的进程数

✨divide函数(mpu/utils.py里)——就是实现个保证可以整除,这里为了得到一个进程中的词数量

def ensure_divisibility(numerator, denominator):"""Ensure that numerator is divisible by the denominator."""assert numerator % denominator == 0, '{} is not divisible by {}'.format(numerator, denominator)def divide(numerator, denominator):"""Ensure that numerator is divisible by the denominator and returnthe division value."""ensure_divisibility(numerator, denominator)#调用上面的函数:判断是否整除return numerator // denominator #直接进行一个强制整除返回

✨VocabUtility类中的vocab_range_from_per_partition_vocab_size方法——获取进程开始词和结束词的index(这里的world_size应该是没有用的)

    #获取进程开始词和结束词的index#参数说明:per_partition_vocab_size——一个进程中词的数目;rank——每个进程的标识@staticmethoddef vocab_range_from_per_partition_vocab_size(per_partition_vocab_size,rank, world_size):index_f = rank * per_partition_vocab_size#计算每个进程开始词的表示indexindex_l = index_f + per_partition_vocab_size#计算每个进程组结束词的表示indexreturn index_f, index_l

(2)get_model_parallel_rank()——返回模型并行组的进程标识

#返回模型并行组的进程标识
def get_model_parallel_rank():"""Return my rank for the model parallel group."""return torch.distributed.get_rank(group=get_model_parallel_group())

(3)get_model_parallel_world_size()——返回分布式组中的进程数

#返回分布式组中的进程数
def get_model_parallel_world_size():"""Return world size for the model parallel group."""return torch.distributed.get_world_size(group=get_model_parallel_group())

(4)get_model_parallel_group()——判断是否有模型并行组,有则返回该模型并行组。

(get_model_parallel_rank()和get_model_parallel_world_size()都用到了这个函数

def get_model_parallel_group():"""Get the model parallel group the caller rank belongs to."""assert _MODEL_PARALLEL_GROUP is not None, \'model parallel group is not initialized'return _MODEL_PARALLEL_GROUP

E、获得相应的初始化权重参数矩阵

(1)获取每个进程词的数目(即输入的矩阵的行数)的列表

        #获取每个进程词的数目(即输入的矩阵的行数)self.num_embeddings_per_partition = self.vocab_end_index - \self.vocab_start_index

(2)调用torch.nn.parameter的Parameter类获得权重矩阵的格式

        #获得权重矩阵的格式self.weight = Parameter(torch.Tensor(self.num_embeddings_per_partition,self.embedding_dim))

(3)启用模型并行

        self.weight.model_parallel = True

(4)初始化权重矩阵

        #初始化权重矩阵_initialize_affine_weight(self.weight, self.num_embeddings, self.embedding_dim,self.num_embeddings_per_partition, 0, init_method)

这里调用了_initialize_affine_weight函数

#参数设定:weight——权重矩阵格式;output_size权重矩阵的行数;input_size权重矩阵的列数;per_partition_size记录每个进程的大小的列表;partition_dim进程深度(分割张量的维度);init_method初始化权重矩阵的方法;stride步幅;return_master_weight是否返回矩阵
def _initialize_affine_weight(weight, output_size, input_size,per_partition_size, partition_dim, init_method,stride=1, return_master_weight=False):"""Initialize affine weight for model parallel.Build the master weight on all processes and scatterthe relevant chunk."""

✨参数设定:

  • weight——权重矩阵格式;
  • output_size权重矩阵的行数;
  • input_size权重矩阵的列数;
  • per_partition_size记录每个进程的大小的列表;
  • partition_dim进程深度(分割张量的维度);
  • init_method初始化权重矩阵的方法;
  • stride步幅;
  • return_master_weight是否返回矩阵

✨获取进程数(每个进程组里有多少个进程)——默认情况下,只有一个进程组

    world_size = get_model_parallel_world_size()#获取进程数(每个进程组里有多少个进程)

✨若只有一个进程,直接按初始化方法初始化权重后结束

    if world_size == 1:init_method(weight)if return_master_weight:return weightreturn None

✨初始化一个output_size*input_size的矩阵

    master_weight = torch.empty(output_size, input_size,dtype=weight.dtype,requires_grad=False)init_method(master_weight)#用特定的初始化方法初始化该矩阵

✨按进程拆分矩阵

    per_partition_per_stride_size = divide(per_partition_size, stride)#得到一个进程每一份的大小(行数)weight_list = torch.split(master_weight, per_partition_per_stride_size,dim=partition_dim)#将权重矩阵分为per_partition_per_stride_size大小的几份——这里相当于按进程划分rank = get_model_parallel_rank()#获取模型并行组的进程标识my_weight_list = weight_list[rank::world_size]#以rank为起始以进程数为步长的权重列表

✨拼接

    with torch.no_grad():torch.cat(my_weight_list, dim=partition_dim, out=weight)#拼接,输出张量为weightif return_master_weight:return master_weightreturn None

2、forward

A、判断输入的词的index是否在进程index中

    def forward(self, input_):# Build the mask.input_mask = (input_ < self.vocab_start_index) | \(input_ >= self.vocab_end_index)#输入的index是否全在该进程index中(在为false)

B、构建输入词在该进程中的index列表,同时对是否全在该范围内进行标识

        masked_input = input_.clone() - self.vocab_start_index#得出input是在该进程中的第几个词masked_input[input_mask] = 0#标识输入的index是否全在该进程index中(第0元素为0说明全都在)

C、获取嵌入词

        output_parallel = F.embedding(masked_input, self.weight,self.padding_idx, self.max_norm,self.norm_type, self.scale_grad_by_freq,self.sparse)

D、标识记录并进行数据汇总

        # Mask the output embedding.output_parallel[input_mask, :] = 0.0#将标识的那一行全部变为0# Reduce across all the model parallel GPUs.output = reduce_from_model_parallel_region(output_parallel)#对所有进程内的数据进行汇总,并且让所有进程都获取最终结果return output

这里的reduce_from_model_parallel_region()调用了torch.distributed.all_reduce()函数。

原理如下:


欢迎大家在评论区中批评指正,谢谢~

CogView中的Word embeddings (parallel)相关推荐

  1. 吴恩达《序列模型》精炼笔记(2)-- NLP和Word Embeddings

    AI有道 不可错过的AI技术公众号 关注 1 Word Representation 上节课我们介绍过表征单词的方式是首先建立一个较大的词汇表(例如10000),然后使用one-hot的方式对每个单词 ...

  2. Coursera吴恩达《序列模型》课程笔记(2)-- NLP Word Embeddings

    红色石头的个人网站:redstonewill.com <Recurrent Neural Networks>是Andrw Ng深度学习专项课程中的第五门课,也是最后一门课.这门课主要介绍循 ...

  3. 通俗易懂的Word Embeddings

    通俗易懂的Word Embeddings   Word Embeddings是机器学习领域最酷的事情之一,因为它可以从海量的文本数据中挖掘出单词之间纷繁复杂的联系.例如你可以在不给定任何先验知识的情况 ...

  4. From Word Embeddings To Document Distances论文总结

    一.前言 最近阅读的论文From Word Embeddings To Document Distances.做一个小总结.作为一个NLP刚刚开始,而且还没有入门的小白,很多的概念都不懂,一点点的查吧 ...

  5. BERT Word Embeddings 教程

    本篇文章译自 Chris McCormick 的BERT Word Embeddings Tutorial 在这篇文章,我深入研究了由Google的Bert生成的word embeddings,并向您 ...

  6. 什么是Word Embeddings

    2019独角兽企业重金招聘Python工程师标准>>> 注:因为很喜欢一个博文,就把它部分翻译过来,原作者网名叫NSS.他的这篇博文的名字是: "An Intuitive ...

  7. Word embeddings in 2017: Trends and future directions (2017年里的词嵌入:趋势和未来方向)

    Word embeddings in 2017: Trends and future directions 原文作者:anonymous 原文地址:http://ruder.io/word-embed ...

  8. Task 4: Contextual Word Embeddings

    Contextual Word Embeddings 最想学习哪些内容,汇总如下: 变压器 (Transformers) BERT 问题解答 (QA) 文本生成和摘要 预训练的词向量:早年的Collo ...

  9. Artetxe2018CoNLL_Uncovering divergent linguistic information in word embeddings...

    Uncovering divergent linguistic information in word embeddings with lessons for intrinsic and extrin ...

最新文章

  1. php调用mysql查询结果_php - 在php脚本中处理select查询结果集
  2. Android之matrix类控制图片的旋转、缩放、移动
  3. YBTOJ洛谷P3195:玩具装箱(斜率优化dp)
  4. leetcode 1423. 可获得的最大点数(滑动窗口)
  5. Redis windows学习(二)——Redis持久化的AOF模式和RDB模式
  6. bzoj 5369: [Pkusc2018]最大前缀和
  7. docker探索-windows10 docker 使用 mysql(二)
  8. 奇怪,Python有的函数调用需要两对括号?(2)
  9. 结构型模式:Decorator 装饰模式
  10. python装饰器详解-python中的装饰器详解
  11. mvc创建连接mysql_五、 创建连接串连接本地数据库(ASP.NET MVC5 系列)
  12. linux怎么添加硬盘步骤,Linux 添加新硬盘方法
  13. USB启动盘制作工具精选 2012版
  14. Android毕设项目功能:商城列表与购物车展示(一)
  15. 乡镇特色产业发展情况调研报告
  16. 混频器/变频器的原理及分类
  17. Linu系统——基础知识1
  18. 基于Laravel开发的Diy手机壳在线定制系统源码
  19. 并发之Striped64(l累加器)
  20. 软件测试转行做产品经理,转型产品经理,测试工程师的出路!

热门文章

  1. php move_uploaded_file liunx,PHP move_uploaded_file() 函数(将上传的文件移动到新位置)
  2. 计算机组装电源线排,主机箱背部走线技巧 组装电脑走背线与理线教程
  3. Android_学习系列(33)--App应用之提交到各大市场渠道
  4. 丰收互联蓝牙key怎么开机_信用社蓝牙key怎么用
  5. 电脑看网页视频没声音, 其他的都有声音
  6. C# List排序简介及四种方法介绍-附代码
  7. centos复制文件夹到指定目录
  8. JS定时器,距离XX天还有XX的倒计时
  9. 《啥是佩奇》怎么就刷屏了?
  10. 看漫画微信小程序源码/独立端漫画小程序源码