mask(掩码、掩膜)是深度学习中的常见操作。简单而言,其相当于在原始张量上盖上一层掩膜,从而屏蔽或选择一些特定元素,因此常用于构建张量的过滤器(见下图)。

按照上述定义,非线性激活函数Relu(根据输出的正负区间进行简单粗暴的二分)、dropout机制(根据概率进行二分)都可以理解为泛化的mask操作。

从任务适应性上,mask在图像和自然语言处理中都广为应用,其应用包括但不局限于:图像兴趣区提取、图像屏蔽、图像结构特征提取、语句padding对齐的mask、语言模型中sequence mask等。

从使用mask的具体流程上,其可以作用于数据的预处理(如原始数据的过滤)、模型中间层(如relu、drop等)和模型损失计算上(如padding序列的损失忽略)。

尽管上述操作均可统称为mask,但其具体的算法实现细节需要根据实际需求进行设计,下面利用pytroch来实现几个典型的例子。

实例1:图像兴趣区提取

通过mask张量定义兴趣区(或非兴趣区)位置张量,将非兴趣区上的张量元素用0值填充。

import torcha = torch.randint(0, 255, (2, 3, 3))   # 两张单通道的图像张量
# tensor([[[ 77,  58, 134],
#         [ 83, 187,  36],
#         [103, 183, 138]],#        [[223,  19,   7],
#         [ 55, 167,  77],
#         [231, 223,  37]]])mask = = torch.tensor([[1, 0, 0], [0, 1, 0],  [0, 0, 1]]).bool()   # 1为感兴趣区域位置,0为非感兴趣,可将其值填为0a.masked_fill_(~mask, 0)      # 注意按照上述定义,需取反~
# tensor([[[ 77,   0,   0],
#         [  0, 187,   0],
#         [  0,   0, 138]],#        [[223,   0,   0],
#         [  0, 167,   0],
#         [  0,   0,  37]]])

实例2:文本Embedding层中对padding的处理

在NLP中,虽然CNN特征抽取器要求文本长度为定长,而RNN和Tranformer特征抽取器虽然可应对不定长的文本序列,但为了在batch维度上进行并行化处理,一般还是选择将文本进行长度对齐,即过长序列进行截断,而长度不足序列进行padding操作。padding操作只是数据维度上的对齐,其并不应该对整个网络的计算贡献任何东西,所以必须进行mask操作。

在pytorch中的词嵌入对象Embedding中,直接通过设定padding_idx参数,即可自动对指定的pad编号进行mask操作,即将padding_idx对象的词向量元素均设为0,从而使得该词对网络的正向传播和梯度反向传播均失活,从而达到了mask的目的。

import torch
import torch.nn as nna = torch.tensor([[1,2,3], [2,1,0]])   # 2段文本数据
net = nn.Embedding(num_embeddings=10, embedding_dim=5, padding_idx=0)  # 词嵌入层
b = net(a)   # 进行词嵌入
# tensor([[[-1.8167,  0.0701,  2.0281, -0.7096,  1.0128],
#          [ 2.3647,  1.0678,  0.0383,  0.3265, -0.1237],
#         [ 1.0633,  0.4248,  2.0323, -0.3140, -0.5124]],#        [[ 2.3647,  1.0678,  0.0383,  0.3265, -0.1237],
#         [-1.8167,  0.0701,  2.0281, -0.7096,  1.0128],
#         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000]]],
#       grad_fn=<EmbeddingBackward>)# 会发现padding=0处的张量均变为了0

下面来手动实现下上述功能:

import torch
import torch.nn as nna = torch.tensor([[1,2,3], [2,1,0]])
net = nn.Embedding(num_embeddings=10, embedding_dim=5)  # 并未设置padding_index参数
a_ = net(a)  # 观察结果,发现果然没有全为0的词向量mask = (a!=0).float().unsequeeze(-1)  # 手动得到mask张量,注意要升维b = a_ * mask   # 会发现得到了上述的效果
# tensor([[[ 0.2723, -0.2836,  0.0061,  1.0740, -1.1754],
#         [-0.6695, -0.9080,  0.7244,  0.3022,  0.5039],
#         [ 1.8236, -1.1954, -0.3024,  0.0857, -0.2242]],#        [[-0.6695, -0.9080,  0.7244,  0.3022,  0.5039],
#         [ 0.2723, -0.2836,  0.0061,  1.0740, -1.1754],
#         [ 0.0000,  0.0000,  0.0000, -0.0000, -0.0000]]],
#       grad_fn=<MulBackward0>)

实例3:padding的损失计算问题

对于文本序列中的NLP,其中<padding>-token位置处的损失不应该计入,具体而言就是最终的损失应当是一个mask-mean的计算过程。

在pytorch中的损失计算对象CrossEntropyLoss等中,直接通过设定ignore_index参数,即可自动忽略<padding>处的损失计算。

下面是pytorch中的一个简单的例子:

import torch
import torch.nn as nntargets = torch.tensor([1, 2, 0])  # 某个时间步batch中各样本的labels
preds = torch.tensor([[1.4, 0.5, 1.1], [0.7, 0.4, 0.2], [2.4, 0.2, 1.4]])   # 某个时间步的batch*predscriterion1 = nn.CrossEntropyLoss()   # 不屏蔽padding
criterion2 = nn.CrossEntropyLoss(ignore_index=0)   # 不屏蔽paddingloss1 = criterion1(preds, targets)
# 返回  tensor(1.1362)loss2 = criterion2(preds, targets)
# 返回  tensor(1.5088) , 例子中该损失只考虑了2个样本

下面,手动实现下该机制:

import torch
import torch.nn as nn
import torch.nn.functional as Ftargets = torch.tensor([1, 2, 0])  # 某个时间步batch中各样本的labels
preds = torch.tensor([[1.4, 0.5, 1.1], [0.7, 0.4, 0.2], [2.4, 0.2, 1.4]])   # 某个时间步的batch*predsdef pad_loss(pred, target,  pad_index=None):if pad_index == None:    # 不考虑padding的maskmask = torch.ones_like(target, dtype=torch.float)else:mask = (target != pad_index).float()nopd = mask.sum().item()   # 实际计算的样本label数target = torch.zeros(pred.shape).scatter(dim=1, index=target.unsqueeze(-1), source=torch.tensor(1))  # 对labels进行one-hot编码target_ = target * mask.unsqueeze(-1)   # 对labels进行maskloss = -(F.log_softmax(pred, dim=-1) * target_.float()).sum()/nopd   # NLL损失return lossloss1 = pad_loss(preds, preds)
# 返回  tensor(1.1362)loss2 = pad_loss(preds, preds, pad_index=0)
# 返回  tensor(1.5088)

实例4:self-attention对padding的处理

Transformer中提出的self-attention机制可以通过文本内部两两元素进行信息的提取,在其中计算各score的softmax权重时,不能将padding处的文本考虑进来(因为这些文本并不存在)。所以在进行softmax前需要进行mask操作(如下图)。

其具体策略是,将padding的文本处的score设定为负的极大值,这样最终的权重接近于0,从而这些文本不会对attention后生成的向量其作用。

import torch
import torch.nn as nn
import torch.nn.functional as Fa = torch.tensor([2,1,0])   # 文本序列
score = torch.tensor([1.2, 2.3, 4])   #  score结果mask = (a == 0).bool()   # 生成mask
score_ = F.softmax(score.masked_fill(mask, -np.inf), dim=-1)   # padding处填充-inf,从而对softmax结果没影响
# tensor([0.2497, 0.7503, 0.0000])

实例5:序列生成模型中对后续未知文本的处理
在Transformer中Decoder部分的self-attention处,由于是模型的目的在于序列生成,所以无论在训练过程中需要特意将后续文本进行mask,不让模型看到。

此时的mask操作称为针对序列的sequence mask,其以文本序列长度为单位,生成一个上三角矩阵矩阵,其中上三角元素为0,其余元素为1,表示在当前word处(即矩阵的对角元)模型看不到后面的words。

import numpy as np
import torch def sequence_mask(size):mask_shape = (size, size)return torch.from_numpy(np.tril(np.ones(mask_shape),k=0))

实例6:mask的联合操作

比如在Transformer的Decoder中self-attention中,既需要对<pad>进行mask,也需要对后续序列进行mask,此时就需要对两个mask进行&位运算,以迭加效果。

def combine_mask(batch_text, inpad_index=0):"""batch_text: 文本batch, Batch * Sequence """pad_mask = batch_text != inpad_index    # Batch * Sequencesequence_len = batch_text.shape[1]   # 时间步长sequence_mask = torch.tensor(np.tril(np.ones((sequence_len, sequence_len)), k=0)).byte()  # Sequence * Sequencemask = pad_mask.unsqueeze(-2) & sequence_mask    # Batch * Sequence * Sequence 注意将pad_mask升维return mask

浅析深度学习中的mask操作相关推荐

  1. 深度学习中的mask操作

    mask(掩码.掩膜)是深度学习中的常见操作.简单而言,其相当于在原始张量上盖上一层掩膜,从而屏蔽或选择一些特定元素,因此常用于构建张量的过滤器(见下图). 按照上述定义,非线性激活函数Relu(根据 ...

  2. 深度学习中的卷积操作

    本文从信号处理中的互相关运算引入深度学习中的卷积. 然后介绍了不同的卷积类型,以及如何在pytorch中使用这些卷积层. (在看pytorch文档中的Conv1D/2D/3D的时候感到比较困惑,又很好 ...

  3. 浅析深度学习中Batch Size大小对训练过程的影响

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者丨陈志远@知乎(已授权) 来源丨https://zhuanlan ...

  4. 任奎:人工智能算法安全浅析——深度学习中的对抗攻击与防御

    2020-05-19 19:52:46 任奎 随着计算机产业发展带来的计算性能与处理能力的大幅提高,人工智能在音视频识别.自然语言处理和博弈论等领域得到了广泛应用.在此背景下,确保人工智能的核心--深 ...

  5. 浅析深度学习中优化方法

    目前而言,深度学习是机器学习的发展前沿,一般针对大数据量的学习目标.其优化方法来源于基本的机器学习的优化方法,但也有所不同. 下面,小结一下,其基础是随机梯度下降的方法,但是为了学习的自适应性,做了如 ...

  6. 经验 | 深度学习中从基础综述、论文笔记到工程经验、训练技巧

    点上方蓝字计算机视觉联盟获取更多干货 在右上方 ··· 设为星标 ★,与你不见不散 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:本文授权转自知乎作者跑者小越,https://zhuanla ...

  7. [转载] python实现语义分割_使用Keras实现深度学习中的一些语义分割模型

    参考链接: Keras中的深度学习-数据预处理 Keras-Sematic-Segmentation 使用Keras实现深度学习中的一些语义分割模型. 配置 tensorflow 1.13.1+ten ...

  8. 深度学习中Attention Mechanism详细介绍:原理、分类及应用

    Attention是一种用于提升基于RNN(LSTM或GRU)的Encoder + Decoder模型的效果的的机制(Mechanism),一般称为Attention Mechanism.Attent ...

  9. 一文看尽深度学习中的各种注意力机制(1998-2020年)

    导读 视觉注意力机制是人类视觉所特有的一种大脑信号处理机制,而深度学习中的注意力机制正是借鉴了人类视觉的注意力思维方式.一般来说,人类在观察外界环境时会迅速的扫描全景,然后根据大脑信号的处理快速的锁定 ...

最新文章

  1. thttpd安装与调试
  2. 人工智能不再是未来,机器学习靠什么来实现?
  3. 【组队学习】【33期】动手学数据分析
  4. 基于 OpenCV 的表格文本内容提取
  5. Google Expeditions项目今年获得AR支持
  6. 做科研没人带,发不了文章怎么办?
  7. Go interface 类型转换原理剖析
  8. (筆記) 如何使用ModelSim作前仿真與後仿真? (SOC) (Quartus II) (ModelSim)
  9. CentOS6.x安装zabbix
  10. e480 黑苹果_记一次黑苹果PC装机全过程
  11. php网页象棋源码,JS小游戏之象棋暗棋源码详解_javascript技巧
  12. 为什么公交Wi-Fi还不如地铁上普及?
  13. 从零开始学android:环境搭建
  14. Chrome 屏蔽广告
  15. python中ospathjoin_python-在Windows上与os.path.join混合斜杠
  16. JS图片显示与隐藏案例
  17. Bilateral Filtering(双边滤波)
  18. connection_reset解决方案
  19. Pg sql 创建自动增长列及修改序列当前值
  20. 最新版akamai2.0逆向分析爬虫破盾风控绕过tls指纹

热门文章

  1. 【hash】兔子与兔子(C++)
  2. 大数据在医疗领域的应用
  3. OracleORA错误解决方案
  4. Eclipse的配置使用
  5. Python脚本-自动连接校园网
  6. 【附源码】计算机毕业设计java在线学习交流平台设计与实现
  7. Rancher2.6 Monitoring Grafana 对接 LDAP
  8. 高德地图API 添加标点 自定义标点
  9. MACD与OBV结合,用OBV进行改进MACD指标公式
  10. GreenPlum-6 最简步骤安装