AI备忘录 - 网络模型
type: channel
link: https://www.aiuai.cn/category/models/
items: sd-webui-controlnet 细节增强 tile model
items: StableDiffusion两种模型序列化格式
items: Pytorch - 图像分类库timm快速使用
items: CLIP - 图像文本多模态模型
items: 卷积神经网络通透阐释[转]
items: 计算机视觉之视频理解TSM
items: 计算机视觉之经典分类网络结构
items: Transformer-逐步说明与实现
items: RNN与LSTM简析
items: TF-Serving - Docker部署

sd-webui-controlnet 细节增强 tile model
type: item
date: 2023-05-27T13:24:00+08:00
description: https://github.com/lllyasviel/ControlNet-v1-1-nightly#controlnet-11-tiletile modelcontrol_v11f1e_sd15_tile, from https://huggingface.co/lllyasviel/ControlNet-v1-1/tree/maintile model 能够生成新的图像细节，并忽略原图里的已有图像细节，因此，该模型可以用于移除不好的细节，添加改善后的细节. 例如，移除由于图像缩放所引起的模糊.参考：超分但，并不是超分模型.其主要有两个功能：忽略图片的细节，生成新的细节若 local tile semantics 和 prompts 不匹配，则忽略 global prompts，并采用 local context 来引导 diffusion 生成.如果原图像本身已经有很好的细节，仍然可以采用 tile model 替换图像细节. Stable Diffusion's I2I 可以实现类似作用，但 tile model 更易于保持图像的整体结构，只改变细节，即使 denosing strength =1.0.ControlNet tile model，对于给定 tile，其首先识别 tile 里所包含的东西，并增强其识别到的语义的影响；且，当 内容与 prompts 不匹配时，降低 global prompts 的影响.sd-webui-controlnet tile modelhttps://github.com/Mikubill/sd-webui-controlnet/issues/1033使用方式：it can do 2x, 4x, or 8x super resolutionit can add, or change, or re-generate image details in an imageit can fix, refine, and improve bad image details obtained by any other super resolution methods like bad details or blurring from RealESRGANit can guide SD to diffuse in tiles, "one beautiful girl" will not generate 16 girls if you use 16 tiles and denoising strength 1.0.it can finish unfinished artwork drafts if those drafts are drawn by color blocksPreprocessor:The preprocessor can be none or tile_resample (tile_resample is just a resizing to make your image smaller if you want more variations)Hint:do not forget to try different control modes - it can produce interesting effectsthis model supports resolution 768 or 1024 well. You can try it if you find SD's 512 is too small and blur.

StableDiffusion两种模型序列化格式
type: item
date: 2023-04-10T19:38:00+08:00
description: https://huggingface.co/docs/diffusers/using-diffusers/using_safetensors.ckpt 和 .safetensors[1] - .ckpt 文件是用 pickle 序列化的，可能包含恶意代码，不信任的模型来源，加载 .ckpt 可能存在安全问题.https://docs.python.org/zh-cn/3/library/pickle.html构建恶意的 pickle 数据来 在解封时执行任意代码 是可能的。 绝对不要对不信任来源的数据和可能被篡改过的数据进行解封。处理不信任数据时，更安全的序列化格式如 json 可能更为适合。[2] - .safetensors 文件是用 numpy 保存的，只包含张量数据，没有任何代码，加载 .safetensors 更安全和快速.为了将 .ckpt 文件转换为 .safetensors 文件，需要先加载 .ckpt 中的数据，然后用 numpy 保存为 .safetensors.safetensorsdoc: https://huggingface.co/docs/safetensors/index模型加载import torch import safetensors.torch import os def load_state_dict(ckpt_path, location='cpu'): _, extension = os.path.splitext(ckpt_path) if extension.lower() == ".safetensors": state_dict = safetensors.torch.load_file(ckpt_path, device=location) else: state_dict = get_state_dict(torch.load( ckpt_path, map_location=torch.device(location))) state_dict = get_state_dict(state_dict) print(f'Loaded state_dict from [{ckpt_path}]') return state_dict def get_state_dict(d): return d.get('state_dict', d)

Pytorch - 图像分类库timm快速使用
type: item
date: 2022-02-05T18:30:00+08:00
description: 原文：Getting Started with PyTorch Image Models (timm): A Practitioner’s Guide - 2022.02.02Github： rwightman/pytorch-image-modelsPyTorch Image Models（timm） 是一个优秀的图像分类 Python 库，其包含了大量的图像模型（Image Models）、Optimizers、Schedulers、Augmentations 等等.timm 提供了参考的 training 和 validation 脚本，用于复现在 ImageNet 上的训练结果；以及更多的 官方文档 和 timmdocs project.https://rwightman.github.io/pytorch-image-models/https://fastai.github.io/timmdocs/但，由于 timm 的功能之多，所以在定制使用时很难知道如何入手. 这里主要进行概述.pip install timm==0.5.41. Modelstimm 提供了大量的模型结构集合，而且很多模型都包含了预训练权重，或 PyTorch 训练、或从Jax和TensorFlow中移植，很方便下载使用.模型列表：https://paperswithcode.com/lib/timm查看模型列表：#打印 timm 提供的模型列表 print(timm.list_models()) print(len(timm.list_models())) #739 #带有预训练权重的模型列表 print(timm.list_models(pretrained=True)) print(len(timm.list_models(pretrained=True))) #592其中，timm.list_models() 函数：list_models(filter='', module='', pretrained=False, exclude_filters='', name_matches_cfg=False)查看特定族模型，如：print(timm.list_models('gluon_resnet*')) print(timm.list_models('*resnext*', 'resnet') ) print(timm.list_models('resnet*', pretrained=True))1.1. create_model 一般用法timm 创建模型最简单的方式是采用 create_model.以 Resnet-D 模型为例（Bag of Tricks for Image Classification For Convolutional Neural Networks paper），其是Resnet 的一种变形，其采用 average pool 进行下采样.model = timm.create_model('resnet50d', pretrained=True) print(model) #查看模型配置参数 print(model.default_cfg) ''' {'url': 'https://github.com/rwightman/pytorch-image-models/releases/download/v0.1-weights/resnet50d_ra2-464e36ba.pth', 'num_classes': 1000, 'input_size': (3, 224, 224), 'pool_size': (7, 7), 'crop_pct': 0.875, 'interpolation': 'bicubic', 'mean': (0.485, 0.456, 0.406), 'std': (0.229, 0.224, 0.225), 'first_conv': 'conv1.0', 'classifier': 'fc', 'architecture': 'resnet50d'} '''1.2. create_model 修改输入通道timm models 有个非常有用的特点，其可以处理任意通道数量的输入图像. 这是很多其他库所不具备的. 其实现原理可参考：https://fastai.github.io/timmdocs/models#So-how-is-timm-able-to-load-these-weights?model = timm.create_model('resnet50d', pretrained=True, in_chans=1) print(model) #test, single cha…

CLIP - 图像文本多模态模型
type: item
date: 2022-01-31T19:09:00+08:00
description: 多模态模型，这里主要是视觉和文本2个模态交互的模型。一般的思路是，分别对文本和视觉进行特征提取，得到embedding，然后进行early或者late fusion，再根据预训练任务进行参数更新。[1] - 视觉特征的提取直接提取视觉向量；目标检测，大多用的是Faster R-CNN，输出bounding box和对应位置；提取类别特征潜在问题：提取的信息有冗余和噪音，对下游任务有益的视觉信息没有被有效提取，和对应的文本信息有语义鸿沟，不好做视觉-文本对齐等。[2] - 文本特征的提取文本一般会用BERT等做初始化，大规模训练集会从头开始训练。Early fusion：特征提取后，一般是直接concat，进入transformer；Late fusion：特征提取后，模态内部再进行深度学习，再做模态交互。计算机视觉：计算机具有看到并理解其所看到的东西的能力，以类似于人类；自然语言处理：计算机具有理解语言的能力，以类似于人类的方式。CLIP 架起了计算机视觉与自然语言处理之间的桥梁.CLIPCLIP，Contrastive Language–Image Pre-training[1] - 双流模型，文本和视觉分别进入transformer encoder，经过线性投影计算不同图文对的相似度；[2] - 使用对比学习，将图片分类转换成图文匹配任务。用4亿对来自网络的图文数据集，将文本作为图像标签，进行训练。进行下游任务时，只需要提供和图上的concepts对应的文本描述，就可以进行zero-shot transfer。[3] - 输入图片到 CLIP 模型，可以返回与图片标题（描述）或摘要.数据：4亿个网络公开的图文对。为覆盖到更多的视觉concepts， 用了50w个query在搜索引擎搜索图片，一个query差不多有2w张图片。输入：一个batch有N个图像文本对；模型：对比学习，预测对图文数据，将图片分类任务转换成图文匹配任务：[1] - 双流，2个encoder分别处理文本和图片数据，text encoder使用Transformer，image encoder用了2种模型，ResNet和Vision Transformer(ViT)；5种ResNet：ResNet-50, ResNet-101, EfficientNet-style的ResNet，包括RN50x4, RN50x16, RN50x64；3种ViT：ViT-B/32, ViT-B/16, ViT-L/14；[2] - encoder representation直接线性投影到multi-modal embedding space；[3] - 计算2模态之间的cosine similarity，让N个匹配的图文对相似度最大，不匹配的图文对相似度最小；[4] - 对称的cross-entropy loss；[5] - 数据增强：对resized图片进行random square crop。[6] - 将分类模型转换成图文匹配任务，用文本来弱监督图片分类。实验Zero-shot Transfer图片分类的zero-shot指的是对未知类别进行推理。本文的zero-shot指的是对未知任务进行推理，通过zero-shot transfer衡量任务学习的能力。Visual N-Grams (Li et al., 2017) 是第一个将zero-shot transfer应用到图片分类任务上的模型。模型用于学习长度为1~5grams的共142806个visual n-grams，对输入的图片，最大化对应的n-grams的probability。同样的，CLIP在进行zero-shot transfer时，将数据集中的类别标签转换为文字描述，主要步骤如下：输入：一张图片 + 所有类别转换的文本（100个类别就是100个文本描述）；转换向量：经过2个encoder，分别输出image和text的feature embedding；计算cosine similarity；预测类别：multinomial logistic regression classifier。zero-shot prediction 代码zero-shot prediction基于输入的图片，在类别描述中检索，找到最合适的类别。"Ref：https://github.com/openai/CLIP" import os import clip import torch from torchvision.datasets import CIFAR100 # Load the model device = "cuda" if torch.cuda.is_available() else "cpu" mode…

卷积神经网络通透阐释[转]
type: item
date: 2022-01-09T13:38:00+08:00
description: 原文：从此明白了卷积神经网络（CNN）- 2021.11.05出处：SimpleAI - 微信公众号图示很赞，好文，记录，学习备忘.1. 引子-边缘检测看一个最简单的例子：“边界检测（edge detection）”，假设有这样的一张图片，大小8×8：图片中的数字代表该位置的像素值，像素值越大，颜色越亮，所以为了示意，把右边小像素的地方画成深色。图的中间两个颜色的分界线就是要检测的边界。怎么检测这个边界呢？可以设计这样的一个 滤波器（filter，也称为kernel），大小3×3：然后，用这个filter，往图片上“盖”，覆盖一块跟filter一样大的区域之后，对应元素相乘，然后求和。计算一个区域之后，就向其他区域挪动，接着计算，直到把原图片的每一个角落都覆盖到了为止。这个过程就是 “卷积”。（不用管卷积在数学上到底是指什么运算，只用知道在CNN中是怎么计算的。）这里的“挪动”，就涉及到一个步长了，假如步长是1，那么覆盖了一个地方之后，就挪一格，容易知道，总共可以覆盖6×6个不同的区域。那么，将这6×6个区域的卷积结果，拼成一个矩阵：可以发现这个图片，中间颜色浅，两边颜色深，这说明原图片中间的边界，在这里被反映出来了!从上面这个例子中发现，可以通过设计特定的filter，让它去跟图片做卷积，就可以识别出图片中的某些特征，比如边界。上面的例子是检测竖直边界，也可以设计出检测水平边界的，只用把刚刚的filter旋转90°即可。对于其他的特征，理论上只要经过精细的设计，总是可以设计出合适的filter的。CNN（convolutional neural network），主要就是通过一个个的filter，不断地提取特征，从局部的特征到总体的特征，从而进行图像识别等等功能。那么问题来了，怎么可能去设计这么多各种各样的filter呀？首先，都不一定清楚对于一大推图片，需要识别哪些特征；其次，就算知道了有哪些特征，想真的去设计出对应的filter，恐怕也并非易事，要知道，特征的数量可能是成千上万的。其实学过神经网络之后，就知道，这些filter，根本就不用去设计，每个filter中的各个数字，不就是参数吗，可以通过大量的数据，来 让机器自己去“学习”这些参数嘛。这，就是CNN的原理。2. CNN的基本概念2.1. Padding从上面的引子中可知，原图像在经过filter卷积之后，变小了，从(8,8)变成了(6,6)。假设再进行一次卷积，那大小就变成了(4,4)了。这样有啥问题呢？ 主要有两个问题：[1] - 每次卷积，图像都缩小，这样卷不了几次就没了；[2] - 相比于图片中间的点，图片边缘的点在卷积中被计算的次数很少。这样的话，边缘的信息就易于丢失。为了解决这个问题，可以采用padding的方法。每次卷积前，先给图片周围都补一圈空白，让卷积之后图片跟原来一样大，同时，原来的边缘也被计算了更多次。比如，把(8,8)的图片给补成(10,10)，那么经过(3,3)的filter之后，就是(8,8)，没有变。把上面这种“让卷积之后的大小不变”的padding方式，称为 “Same”方式，把不经过任何填白的，称为 “Valid”方式。这个是在使用一些框架的时候，需要设置的超参数。2.2. Stride前面所介绍的卷积，都是默认步长是1，但实际上，还可以设置步长为其他的值。比如，对于(8,8)的输入，用(3,3)的filter，如果stride=1，则输出为(6,6);如果stride=2，则输出为(3,3);（这里例子举得不大好，除不断就向下取整）2.3. PoolingPooling，是为了提取一定区域的主要特征，并减少参数数量，防止模型过拟合。比如下面的MaxPooling，采用了一个2×2的窗口，并取stride=2：除了MaxPooling,还有AveragePooling，顾名思义就是取那个区域的平均值。2.4. 对多通道（channels）图片的卷积这个需要单独提一下。彩色图像，一般都是RGB三个通道（channel）的，因此输入数据的维度一般有三个：（长，宽，通道）。 比如一个28×28的RGB图片，维度就是(28,28,3)。前面的引子中，输入图片是2维的(8,8)，filter是(3,3)，输出也是2维的(6,6)。如果输入图片是三维的呢（即增多了一个channels），比如是(8,8,3)，这个时候，filter的维度就要变成(3,3,3)了，它的 最后一维要跟输入的channel维度一致。这个时候的卷积，是三个channel的所有元素对应相乘后求和，也就是之前是9个乘积的和，现在是27个乘积的和。因此，输出的维度并不会变化。还是(6,6)。但是，一般情况下，会使用多了filters同时卷积，比如，如果同时使用4个filte…

计算机视觉之视频理解TSM
type: item
date: 2021-09-11T18:23:00+08:00
description: 出处：Paddle文档平台 - TSM1. TSM 简介视频流的爆炸性增长为以高精度和低成本执行视频理解任务带来了挑战。传统的2D CNN计算成本低，但无法捕捉视频特有的时间信息；3D CNN可以得到良好的性能，但计算量庞大，部署成本高。作者提出了一种通用且有效的时间偏移模块（Temporal Shift Module，TSM），它通过沿时间维度移动部分通道来促进相邻帧间的信息交换，同时它可以插入到2D CNN中实现零计算和零参数的时间建模，以此兼具2D卷积的高效与3D卷积的高性能。2. 模型介绍2.1. Intuition首先考虑一个正常的卷积操作，以核大小为3的一维卷积为例。假设卷积的权重为 $W = (w_1, w_2, w_3)$，输入 $X$ 是一个1D无限长的向量，则卷积操作 $Y = Conv(W,X)$ 可被表示为：$$ Y_i = w_1X_{i-1} + w_2X_i + w_3X_{i+1} $$将卷积操作解耦为两步，位移和乘法累加。对输入 $X$ 进行 $-1, 0, +1$ 的位移，具体表示为：$$ X^{-1}_{i} = X_{i - 1}, \quad X^{0}_{i} = X_i, \quad X^{+1}_{i} = X_{i+1} $$乘法累加可表示为：$$ Y = w_1X^{-1} + w_2X^0 + w_3X^{+1} $$第一步位移是不需要时间成本的，第二步乘法累加需要更大的计算消耗，但是TSM将乘法累加部分合并在了2D卷积中，因此它和基本的2D CNN网络相比不存在额外开销。图1 Temporal Shift moduleTemporal Shift Module(TSM) 如 图1 所示，在 图1 a 中，作者描述了一个具有C通道和T帧的张量，图片中每一行不同颜色代表在不同时间点的特征，沿时间维度，我们将一部分通道移动-1，另一部分通道移动+1，其余部分不动（如 图1 b 所示）。对于在线视频识别，作者也提供了在线版本的TSM（如 图1c 所示），由于在在线识别模式中，我们不能获得未来帧，因此只进行单一方向的移动。2.2. 简易的空间移动会带来什么问题虽然时间位移的原理很简单，但作者发现直接将空间位移策略应用于时间维度并不能提供高性能和效率。具体来说，如果简单的转移所有通道，则会带来两个问题：[1] - 由于大量数据移动而导致的效率下降问题。位移操作不需要计算但是会涉及数据移动，数据移动增加了硬件上的内存占用和推理延迟，作者观察到在视频理解网络中，当使用naive shift策略时，CPU延迟增加13.7%，GPU延迟增加12.4%，使整体推理变慢。[2] - 空间建模能力变差导致性能下降，由于部分通道被转移到相邻帧，当前帧不能再访问通道中包含的信息，这可能会损失2D CNN主干的空间建模能力。与TSN基线相比，使用naive shift会降低2.6%的准确率。2.3. TSM模块为了解决naive shift的两个问题，TSM给出了相应的解决方法。[1] - 减少数据移动。 为了研究数据移动的影响，作者测量了TSM模型在不同硬件设备上的推理延迟，作者移动了不同比例的通道数并测量了延迟，位移方式分为无位移、部分位移（位移1/8、1/4、1/2的通道）和全部位移，使用ResNet-50主干和8帧输入测量模型。作者观察到，如果移动所有的通道，那么延迟开销将占CPU推理时间的13.7%（如 图2 a 所示），如果只移动一小部分通道，如1/8，则可将开销限制在3%左右。图2 不同比例的通道位移下延迟与准确率对比[2] - 保持空间特征学习能力。 一种简单的TSM使用方法是将其直接插入到每个卷基层或残差模块前，如 图3 a 所示，这种方法被称为 in-place shift，但是它会损失主干模型的空间特征学习能力，尤其当我们移动大量通道时，存储在通道中的当前帧信息会随着通道移动而丢失。为解决这个问题，作者提出了另一种方法，即将TSM放在残差模块的残差分支中，这种方法被称为 residual TSM，如 图3 b 所示，它可以解决退化的空间特征学习问题，因为原始的激活信息在时间转移后仍可通过identity映射访问。 图3 In-place TSM 和 Residual TSM为检验上述假设，作者在 Kinetics 数据集上比较了 In-place TSM 和 Residual TSM 的性能。在 图2 b 中我们可以看到，对于所有比例的位移，Residual TSM 都具有更好的性能。同时，作者发现，性能与位移通道的比例有关：如果比例太小，则时间推理的能力可能不足以处理复杂的时间关系；如果太大，则会损害空间特征学习能力，选择1/4的通道偏移时，性能会达到峰值。2.4. TSM 视频…

计算机视觉之经典分类网络结构
type: item
date: 2021-09-06T21:55:00+08:00
description: 出处：[Paddle文档平台 - 图像分类1. LeNet1.1. 模型介绍LeNet是最早的卷积神经网络之一[1]，其被提出用于识别手写数字和机器印刷字符。1998年，Yann LeCun第一次将LeNet卷积神经网络应用到图像分类上，在手写数字识别任务中取得了巨大成功。算法中阐述了图像中像素特征之间的相关性能够由参数共享的卷积操作所提取，同时使用卷积、下采样（池化）和非线性映射这样的组合结构，是当前流行的大多数深度图像识别网络的基础。1.2. 模型结构LeNet通过连续使用卷积和池化层的组合提取图像特征，其架构如 图1 所示，这里展示的是用于MNIST手写体数字识别任务中的LeNet-5模型：图1 LeNet模型网络结构示意图[1] - 第一模块：包含5×5的6通道卷积和2×2的池化。卷积提取图像中包含的特征模式（激活函数使用Sigmoid），图像尺寸从28减小到24。经过池化层可以降低输出特征图对空间位置的敏感性，图像尺寸减到12。[2] - 第二模块：和第一模块尺寸相同，通道数由6增加为16。卷积操作使图像尺寸减小到8，经过池化后变成4。[3] - 第三模块：包含4×4的120通道卷积。卷积之后的图像尺寸减小到1，但是通道数增加为120。将经过第3次卷积提取到的特征图输入到全连接层。第一个全连接层的输出神经元的个数是64，第二个全连接层的输出神经元个数是分类标签的类别数，对于手写数字识别的类别数是10。然后使用Softmax激活函数即可计算出每个类别的预测概率。提示：卷积层的输出特征图如何当作全连接层的输入使用呢？卷积层的输出数据格式是$[N, C, H, W]$，在输入全连接层的时候，会自动将数据拉平，也就是对每个样本，自动将其转化为长度为$K$的向量，其中$K = C \times H \times W$，一个mini-batch的数据维度变成了$N\times K$的二维向量。1.3. 模型实现LeNet网络的实现代码如下：#! -*- coding:utf-8 -*- import paddle import numpy as np from paddle.nn import Conv2D, MaxPool2D, Linear import paddle.nn.functional as F # 定义 LeNet 网络结构 class LeNet(paddle.nn.Layer): def __init__(self, num_classes=1): super(LeNet, self).__init__() # 创建卷积和池化层 # 创建第1个卷积层 self.conv1 = Conv2D(in_channels=1, out_channels=6, kernel_size=5) self.max_pool1 = MaxPool2D(kernel_size=2, stride=2) # 尺寸的逻辑：池化层未改变通道数；当前通道数为6 # 创建第2个卷积层 self.conv2 = Conv2D(in_channels=6, out_channels=16, kernel_size=5) self.max_pool2 = MaxPool2D(kernel_size=2, stride=2) # 创建第3个卷积层 self.conv3 = Conv2D(in_channels=16, out_channels=120, kernel_size=4) # 尺寸的逻辑：输入层将数据拉平[B,C,H,W] -> [B,C*H*W] # 输入size是[28,28]，经过三次卷积和两次池化之后，C*H*W等于120 self.fc1 = Linear(in_features=120, out_features=64) # 创建全连接层，第一个全连接层的输出神经元个数为64， 第二个全连接层输出神经元个数为分类标签的类别数 self.fc2 = Linear(in_features=64, out_features=num_classes) # 网络的前向计算过程 def forward(self, x): x = self.conv1(x) # 每个卷积层使用Sigmoid激活函数，后面跟着一个2x2的池化 x = F.sigmoid(x) x = self.max_pool1(x) x = F.sigmoid(x) x = self.conv2(x) x = self.max_pool2(x) x = self.conv3(x) # 尺寸的逻辑：输入层将数据拉平[B,C,H,W] -> [B,C*H*W] x = paddle.reshape(x, [x.shape[0], -1]) x = self.fc1(x) x…

Transformer-逐步说明与实现
type: item
date: 2021-05-23T20:40:00+08:00
description: 主要参考：[1] - Illustrated Guide to Transformers- Step by Step Explanation-2020.05.01[2] - Github - hyunwoongko/transformerTransformer 结构如图：两层编码器+两层解码器组成的Transformer结构如图：1. Attention 机制Attention 机制使得 Transformer 能够获取非常长的记忆力(extremely long term memory).Transformer 能够参与(attend)或关注(focus)所有先前所生成的 tokens.token(符号): 包括单词和标点tokenization(分词)：词语是什么->['词语', '是', '什么']基于示例，假如想要采用生成式 Transformer 写一部科幻小说，采用 Hugging Face 实现的 Write With Transformer 即可. 给定模型输入，模型会自动生成其余部分.输入：“As Aliens entered our planet”.Transformer输出： “and began to colonized Earth, a certain group of extraterrestrials began to manipulate our society through their influences of a certain number of the elite to keep and iron grip over the populace.”虽然生成的故事有点黑暗，但有意思的是模型如何生成的故事. 当模型逐个单词生成文本时，其可以参与或关注与生成的单词相关的单词. 这种能够知道哪些单词被参与的能力是通过反向传播的训练过程中学会的.图：在逐个生成单词的过程中，Attention 机制关注于不同的 tokens.RNN(Recurrent neural networks) 也具有捕捉先前输入的能力. 但是，Attention 机制的能力在于，其不在受限于短时记忆. RNN 的参考窗口更短，当故事变长时，RNN 将无法访问序列中较早生成的单词. 且，对于GRU(Gated Recurrent Units) 和 LSTM(Long-short Term Memory)，虽然能够具有更大的容量来实现长期记忆，并因此具有更长的参考窗口，但其存在和 RNN 类似的问题.而，Attention 机制，从理论上将，如果具有足够的计算资源，其具有无限的参考窗口，因此能够在生成文本的同时，使用故事的全部上下文信息.图： Attention, RNN’s, GRU’s 和 LSTM 的假设参考窗口2. Attention Is All You Need 逐步说明Attention Is All You NeedTransformers 基于 Attention 的 encoder-decoder 结构，如图：图：Transformer模型概括来说，编码器将输入序列映射为抽象的连续表示形式，这种表示形式能够保留所有已经学习到的输入信息. 然后，解码器采用这种连续表示，并逐步生成单个输出，同时还接收先前的输出.这里逐步说明，并给出参考实现，示例：输入：“Hi how are you”Transformer输出：“I am fine”2.1. Input EmbeddingsTransformer的第一步是，将输入送人 word embdding 层. word embedding 层可以看作是一个查询表(lookup table)，以获取每个单词的学习向量表示形式. 神经网络的学习是通过数字进行的，因此每个单词都被映射到具有连续值的向量来表示该单词.图：将 Words 转化为 Input Embeddings实现如：models/embedding/token_embeddings.pyfrom torch import nn class TokenEmbedding(nn.Embedding): """ Token Embedding using torch.nn they will dense representation of word using weighted matrix """ def __init__(self, vocab_size, d_model): """ class for token embedding that included positional information :param vocab_size: size of vocabulary :param d_mode…

RNN与LSTM简析
type: item
date: 2021-04-24T18:40:00+08:00
description: 关于 RNN 和 LSTM 比较经典的基础知识及图例.1. RNNRNN，循环神经网络，其结构如：图：RNN 包含循环结构如图，神经网络 $A$，某个输入 $x_t$，对应输出值 $h_t$. RNN 可以是信息从当前状态传递到下一状态.数据传递效果：RNN 可以看作是同一神经网络的多次复制，每个神经网络模块将信息传递到下一个神经网络. RNN 的展开如图：图：RNN 网络展开形式，链式结构RNN 动图版：1.1. RNN 一般结构给定函数 $f:h',y=f(h,x)$，这里暂时忽略偏置bias，如图：其中，[1] - $x$ 为当前状态的输入[2] - $h$ 表示接收到的上一个节点网络的输入[3] - $y$ 为当前节点状态的输出[4] - $h'$ 为传递到下一个节点网络的输出. $h$ 和 $h'$ 是具有相同维度的向量.[5] - $\sigma$ 为激活函数，一般是 tanh 函数，以及会加一个偏置 $b$. 由图可知，输出 $h'$ 与 $x$ 和 $h$ 的值相关，而 $y$ 一般使用 $h'$ 送入到一个线性层(如，这里是维度映射)，在使用 softmax 激活函数进行分类，得到输出值.RNN 的标准结构如图：其中，函数 $f$ 是各个节点网络所共享的.RNN中，将过去的输出和当前的输入链接到一起，通过tanh来控制两者的输出，它只考虑最近时刻的状态. 在RNN中有两个输入和一个输出.单个RNN模块传递，动图：RNN 还可细分为，单输入序列输出、序列输入单输出、序列输入序列输出(分等长和不等长)等一系列结构.1.1.1. tanh 函数tanh 激活函数用于调节在神经网络中传递的值，它会将输入值压缩到-1 到 1 之间.1.2. RNN - PyTorchPytorch 模块 - torch.nn.RNNCell一个 RNN Cell 模块可以表示为：$$ h' = tanh(W_{ih}x + b_{ih} + W_{hh}h + b_{hh}) $$其中，$h'$ 是输出的下一个隐状态.函数定义为：torch.nn.RNNCell(input_size, hidden_size, bias=True, nonlinearity='tanh')其中，[1] - input_size - 输入 x 中的期望特征数[2] - hidden_size - 隐状态 h 的特征数[3] - bias - 若为 False，则不适用偏置权重 $b_{ih}$ 和 $b_{hh}$[4] - nonlinearity - 采用的非线性函数，tanh 或 relu.函数使用示例：rnn = nn.RNNCell(10, 20) input = torch.randn(6, 3, 10) hx = torch.randn(3, 20) output = [] for i in range(6): hx = rnn(input[i], hx) output.append(hx)1.3. Long-Term 依赖问题RNN 的关键点之一，是可以用来连接先前的信息到当前的任务上，例如使用先前信息来推测对当前状态的理解. 两种场景：[1] - 先前信息与预测信息之间的间隔非常小此种场景，RNN 可以学会使用先前信息. 仅仅需要知道先前的信息来执行当前的任务.例如，对于一个语言模型用来基于先前的词来预测下一个词，如果预测 "the clouds are in the sky" 最后的词，其并不需要任何其他的上下文. 因此下一个词很显然就应该是 sky.图：不太长的先前信息和位置间隔.[2] - 更复杂的场景，先前信息和当前预测的位置间隔比较大随着信息间隔不断增大时，RNN 会丧失学习到连接如此远的信息的能力.例如，预测 "I grew up in France... I speak fluent French" 最后的词. 当前的信息建议下一个词可能是一种语言的名字，但是如果弄清楚是什么语言，需要先前提到的离当前位置很远的 France 的上下文信息.图：较长的先前信息和位置间隔RNN 存在梯度消失问题，通常可以采用两种解决办法：[1] - 选取更好的激活函数，如ReLU函数.[2] - 改变传播网络结构，如LSTM.2. LSTMLSTM，Long short-term memory，长短期记忆. 是 RNN 的一种改进，主要为了解决长序列训练过程中的梯度小时问题，使得 RNN 具有更好更强的记忆能力.如图：图：LSTM 结构，类似于 RNN，各重复模块包含四种交互.LSTM 为了能记住长期的状态，在RNN的基础上增加了一路输入和一路输出，增加的这一路就是细胞状态，也就是图中最上面的一条通路.2.1. LSTM 图例上图中，包含的…

TF-Serving - Docker部署
type: item
date: 2021-03-01T21:11:00+08:00
description: Github - tensorflow/servinghttps://github.com/tensorflow/serving/tree/master/tensorflow_serving/g3doc1. TF Serving 示例#拉取镜像 # docker docker pull tensorflow/serving # nvidia-docker docker pull tensorflow/serving:latest-gpu # git clone https://github.com/tensorflow/serving # Location of demo models TESTDATA="$(pwd)/serving/tensorflow_serving/servables/tensorflow/testdata" # Start TensorFlow Serving container and open the REST API port docker run -t --rm -p 8501:8501 \ -v "$TESTDATA/saved_model_half_plus_two_cpu:/models/half_plus_two" \ -e MODEL_NAME=half_plus_two \ tensorflow/serving & # Query the model using the predict API curl -d '{"instances": [1.0, 2.0, 5.0]}' \ -X POST http://localhost:8501/v1/models/half_plus_two:predict # Returns => { "predictions": [2.5, 3.0, 4.5] }2. TF Serving 参数TF Serving 运行示例：docker run -p 8501:8501 \ --mount type=bind,source=/path/to/local/saved_model/,target=/models/model_name \ -t tensorflow/serving \ -e MODEL_NAME=model_name --model_base_path=/models/model_name/ --per_process_gpu_memory_fraction=0.5 #或 docker run -t --rm -p 8501:8501 \ -v /path/to/local/saved_model/:/models/model_name \ -e MODEL_NAME=test-model tensorflow/serving:1.15.0 &[1] - -p 8501:8501 - 服务端口[2] - -t - 指定镜像[3] - --mount - 挂载路径，其中type=bind是选择挂载模式，注：中间不能有空格. source 是模型在机器中的绝对存储路径，target 是模型容器中存储路径[4] - per_process_gpu_memory_fraction 是设定运行时所需的GPU显存资源最大不允许超过的比率的设定值；[5] - model_name 命名3. 参考[1] - Tensorflow笔记：通过tf.Serving+Docker部署 - 2020.04.14[2] - TensorFlow Serving with Docker