以下文章来源于英特尔物联网,作者武卓,李翊玮


文章作者:武卓, 李翊玮

最近人工智能领域最火爆的话题非 chatGPT 以及最新发布的 GPT-4 模型莫属了。这两个生成式 AI 模型在问答、搜索、文本生成领域展现出的强大能力,每每让使用过它们的每个用户瞠目结舌、感叹不已。说到以上这两个 GPT 模型,相信大家也听说过、它们的 “超能力”来自于它们自身的超大模型尺寸,每运行一次 AI 推理都需要巨大的算力在背后来做支持,显然在本地设备上要运行这样的超大模型是不太可能的。

然而你知道吗,跟它们同属 GPT 模型家族的 GPT-2 模型在 OpenVINO™ 开源工具套件的优化和加速下,在装有11代英特尔处理器 N5105 2.0-2.9GHz (Jasper Lake) 的这样不足千元的 AI 开发板上就能运行文本生成任务的推理。

关于 GPT-2 请访问:

Language Models are Unsupervised Multitask Learners

(d4mucfpksywv.cloudfront)

1

AI 爱克斯开发板

AI 产品原型设计好伙伴

AIxBoard(爱克斯板)开发板是专为支持入门级边缘AI应用程序和设备而设计。能够满足人工智能学习、开发、实训等应用场景。

该开发板是类树莓派的 x86 主机,可支持 Linux Ubuntu 及完整版 Windows 操作系统。板载一颗英特尔4核处理器,最高运行频率可达2.9 GHz,且内置核显(iGPU),板载 64GB eMMC 存储及 LPDDR4x 2933MHz(4GB/6GB/8GB) ,内置蓝牙和 Wi-Fi 模组,支持 USB 3.0 、HDMI 视频输出、3.5mm音频接口,1000Mbps 以太网口。完全可把它作为一台 mini 小电脑来看待,且其可集成一块 Arduino Leonardo 单片机,可外拓各种传感器模块。

此外,其接口与 Jetson Nano 载板兼容,GPIO 与树莓派兼容,能够最大限度地复用树莓派、 Jetson Nano 等生态资源,无论是摄像头物体识别, 3D 打印,还是 CNC 实时插补控制都能稳定运行。可作为边缘计算引擎用于人工智能产品验证、开发;也可以作为域控核心用于机器人产品开发。

x86 架构使支持完整的 Windows 系统,不需要特殊优化就能直接获得 Visual Studio 、 OpenVINO™ 、 OpenCV 等最强大的软件支持,最成熟的开发生态,数百万的开源项目,给你的创意提供更多助力。无论你是一个 DIY 的狂热爱好者、交互设计师还是机器人专家, AI 爱克斯开发板都是你理想的伙伴!

下面,就让我们通过以下手把手的教程,来看看这样的推理是怎么样在边缘 AI 开发板上运行起来的吧。

2

如何安装

首先,需要在 AI 开发板上安装 OpenVINO™  Notebooks 运行环境。由于 AI 开发板上自带 Windows 操作系统,因此可以参考以下具体步骤在 Windows 上进行 OpenVINO™ Notebooks 运行环境的安装。

https://github/openvinotoolkit/openvino_notebooks/wiki/Windows

当然 AI 开发板也非常方便的支持将系统刷成 Linux 系统,如果您是 Linux 用户可点击此链接:

https://github/openvinotoolkit/openvino_notebooks/wiki/Ubuntu

总体而言,通过以下三个安装步骤即可完成所有安装步骤,接着就可以加载所有的 notebooks 代码示例了。

安装 Python 3.10.x(或 Python3.7,3.8或3.9版本)

并创建一个虚拟环境

python3 -m venv openvino_env
openvino_env\Scripts\activate

向右滑动查看完整代码

对目录实施 Git 克隆 

(如果你还没有安装 Git ,请先去这里安装:

http://github/git-for-windows/git/releases/download/v2.35.1.windows.2/git-2.35.1.2-64-bit.exe)

git clone --depth=1 https://github/openvinotoolkit/openvino_notebooks.git
cd openvino_notebooks

向右滑动查看完整代码

安装所有的库和依赖项

pip install -r requirements.txt

向右滑动查看完整代码

运行 Jupyter Notebook

jupyter lab notebooks

向右滑动查看完整代码

3

在 AI 爱克斯开发板上利用 

OpenVINO™ 优化和部署 GPT2

接下来,就让我们看看在 AI 开发板上运行 GPT2 进行文本生成都有哪些主要步骤吧。

注意:以下步骤中的所有代码来自 OpenVINO™ Notebooks 开源仓库中的223-gpt2-text-prediction notebook 代码示例,您可以点击以下链接直达源代码:

https://github/openvinotoolkit/openvino_notebooks/blob/main/notebooks/223-gpt2-text-prediction/223-gpt2-text-prediction.ipynb

整个代码示例的运行流程如下图所示:

预处理

首先定义分词。本次文本生成任务的输入为一个自然语言的序列,在此基础上, GPT-2 模型会生成相关内容的长文本。由于自然语言处理模型通常将一个分词的列表作为标准输入,一个分词通常是将一个单词映射成的一个整数值。因此,为了提供正确的输入,我们使用词汇表文件来处理映射。首先让我们加载词汇表文件,代码如下:

# this function converts text to tokens
  def tokenize(text):
      """
      tokenize input text using GPT2 tokenizer
      
      Parameters:
        text, str - input text
      Returns:
        input_ids - np.array with input token ids
        attention_mask - np.array with 0 in place, where should be padding and 1 for places where original tokens are located, represents attention mask for model 
      """
      inputs = tokenizer(text, return_tensors="np")
      return inputs["input_ids"], inputs["attention_mask"]

向右滑动查看完整代码

其中, eos_token 是一个特殊的 token ,这意味着生成已经完成。我们存储此 token 的索引,以便在稍后阶段使用这个索引作为填充。

eos_token_id = tokenizer.eos_token_id

向右滑动查看完整代码

定义 Softmax 层。由于 GPT-2 模型推理的结果是以logits的形式呈现的,因此我们需要定义一个 softmax 函数,用于将前k个 logits 转换为概率分布,从而在选择最终的文本预测的结果时挑选概率最大的推理结果。

import numpy as np
  
  
  def softmax(x):
      e_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
      summation = e_x.sum(axis=-1, keepdims=True)
      return e_x / summation

向右滑动查看完整代码

确定最小序列长度。如果没有达到最小序列长度,下面的代码将降低 eos token 出现的概率。这将继续生成下一个单词的过程。

def process_logits(cur_length, scores, eos_token_id, min_length=0):
      """
      reduce probability for padded indicies
      
      Parameters:
        cur_length - current length of input sequence
        scores - model output logits
        eos_token_id - index of end of string token in mode vocab
        min_length - minimum length for appling postprocessing
      """
      if cur_length < min_length:
          scores[:, eos_token_id]
      return scores

向右滑动查看完整代码

Top-K 采样。在 Top-K 采样中,我们过滤了 K 个最有可能的下一个单词,并仅在这 K 个下一个词中重新分配概率质量。

def get_top_k_logits(scores, top_k):
      """
      perform top-k sampling
      
      Parameters:
        scores - model output logits
        top_k - number of elements with highest probability to select
      """
      filter_value = -float("inf")
      top_k = min(max(top_k, 1), scores.shape[-1])
      top_k_scores = -np.sort(-scores)[:, :top_k]
      indices_to_remove = scores < np.min(top_k_scores)
      filtred_scores = np.ma.array(scores, mask=indices_to_remove,
                                  fill_value=filter_value).filled()
      return filtred_scores

向右滑动查看完整代码

加载模型并转换为OpenVINO™ IR 格式

下载模型。

from transformers import GPT2Tokenizer, GPT2LMHeadModel


 tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
 pt_model = GPT2LMHeadModel.from_pretrained('gpt2')

向右滑动查看完整代码

运行结果如下图所示:

这里我们要使用开源在 HuggingFace 的 GPT-2 模型,需先将原始为 PyTorch 格式的模型,通过转换到 ONNX ,从而在 OpenVINO™ 中得到优化及推理加速。我们将使用 HuggingFace Transformer 库功能将模型导出到 ONNX 。有关 Transformer 导出到 ONNX 的更多信息,请参阅 HuggingFace 文档:

地址(复制到浏览器中打开)

https://huggingface.co/docs/transformers/serialization

转换为 ONNX 格式后的模型文件,再通过 OpenVINO™ 的模型优化器 MO 转换为 OpenVINO™ IR 格式的模型文件。

from pathlib import Path
from openvino.runtime import serialize
from openvino.tools import mo
from transformers.onnx import export, FeaturesManager


 
# define path for saving onnx model
onnx_path = Path("model/gpt2.onnx")
onnx_path.parent.mkdir(exist_ok=True)
  
  # define path for saving openvino model
  model_path = onnx_path.with_suffix(".xml")
  
  # get model onnx config function for output feature format casual-lm
  model_kind, model_onnx_config = FeaturesManager.check_supported_model_or_raise(pt_model, feature='causal-lm')
  
  # fill onnx config based on pytorch model config
  onnx_config = model_onnx_config(pt_model.config)
  
  # convert model to onnx
  onnx_inputs, onnx_outputs = export(tokenizer, pt_model, onnx_config, onnx_config.default_onnx_opset, onnx_path)
  
  # convert model to openvino
  ov_model = mo.convert_model(onnx_path, compress_to_fp16=True, input="input_ids[1,1..128],attention_mask[1,1..128]")
  
  # serialize openvino model
  serialize(ov_model, str(model_path))

向右滑动查看完整代码

接着加载 OpenVINO™ IR 格式的模型到 CPU 上进行推理:

from openvino.runtime import Core
  
  # initialize openvino core
  core = Core()
  
  # read the model and corresponding weights from file
  model = core.read_model(model_path)
  
  # compile the model for CPU devices
  compiled_model = corepile_model(model=model, device_name="CPU")
  
  # get output tensors
  output_key = compiled_model.output(0)

向右滑动查看完整代码

在 GPT-2 的情况下,我们将批大小( batch size )和序列长度( sequence length )作为输入,将批大小、序列长度和 vocab 大小作为输出。

定义文本生成主函数

接下来,我们定义文本生成的主函数

def generate_sequence(input_ids, attention_mask, max_sequence_length=128,
                        eos_token_id=eos_token_id, dynamic_shapes=True):
      """
      text prediction cycle.
      
      Parameters:
        input_ids: tokenized input ids for model
        attention_mask: attention mask for model
        max_sequence_length: maximum sequence length for stop iteration
        eos_token_ids: end of sequence index from vocab
        dynamic_shapes: use dynamic shapes for inference or pad model input to max_sequece_length
      Returns:
        predicted token ids sequence
      """
      while True:
          cur_input_len = len(input_ids[0])
          if not dynamic_shapes:
              pad_len = max_sequence_length - cur_input_len
              model_input_ids = np.concatenate((input_ids, [[eos_token_id] * pad_len]), axis=-1)
              model_input_attention_mask = np.concatenate((attention_mask, [[0] * pad_len]), axis=-1)
          else:
              model_input_ids = input_ids
              model_input_attention_mask = attention_mask
          outputs = compiled_model({"input_ids": model_input_ids, "attention_mask": model_input_attention_mask})[output_key]
          next_token_logits = outputs[:, cur_input_len - 1, :]
          # pre-process distribution
          next_token_scores = process_logits(cur_input_len,
                                            next_token_logits, eos_token_id)
          top_k = 20
          next_token_scores = get_top_k_logits(next_token_scores, top_k)
          # get next token id
          probs = softmax(next_token_scores)
          next_tokens = np.random.choice(probs.shape[-1], 1,
                                         p=probs[0], replace=True)
          # break the loop if max length or end of text token is reached
          if cur_input_len == max_sequence_length or next_tokens == eos_token_id:
              break
          else:
              input_ids = np.concatenate((input_ids, [next_tokens]), axis=-1)
              attention_mask = np.concatenate((attention_mask, [[1] * len(next_tokens)]), axis=-1)
      return input_ids

向右滑动查看完整代码

运行主函数,生成文本

最后,让我们来输入一句话,再由此让 GPT-2 模型在此基础上生成一段文本:

import time
  text = "Deep learning is a type of machine learning that uses neural networks"
  input_ids, attention_mask = tokenize(text)
  
  start = time.perf_counter()
  output_ids = generate_sequence(input_ids, attention_mask)
  end = time.perf_counter()
  output_text = " "
  # Convert IDs to words and make the sentence from it
  for i in output_ids[0]:
      output_text += tokenizer.convert_tokens_to_string(tokenizer._convert_id_to_token(i))
  print(f"Generation took {end - start:.3f} s")
  print("Input Text: ", text)
  print()
  print(f"Predicted Sequence:{output_text}")

向右滑动查看完整代码

运行结果如下图所示:

可以看到,即使是在我们这款千元不到的 AI 开发板上,运行 GPT-2 模型进行文本生成也是完全可以支持的。也由此可见,在边缘运行生成性的工作负载(比如我们这里介绍的文本生成)是一项完全可以实现的任务,而尽可能靠近数据产生地,也是人工智能可扩展性和可落地性的关键。

4

小结

整个的步骤就是这样!现在就开始跟着我们提供的代码和步骤,动手在你的边缘设备上尝试用 Open VINO™ 优化和加速 GPT-2 吧。

关于 OpenVINO™ 开源工具套件的详细资料,包括其中我们提供的三百多个经验证并优化的预训练模型的详细资料,请您点击:

https://www.intel/content/www/us/en/developer/tools/openvino-toolkit/overview.html

除此之外,为了方便大家了解并快速掌握 OpenVINO™ 的使用,我们还提供了一系列开源的 Jupyter notebook demo 。运行这些 notebook ,就能快速了解在不同场景下如何利用 OpenVINO™ 实现一系列、包括计算机视觉、语音及自然语言处理任务。

OpenVINO™  notebooks 的资源可以在 Github 这里下载安装:

https://github/openvinotoolkit/openvino_notebooks 

AIxBoard 爱克斯板_蓝蛙智能 (xzsteam) 购买链接及开发指南:

https://www.xzsteam/product_detail/2.html

通知和免责声明

Intel技术可能需要启用硬件、软件或服务激活。

任何产品或组件都不能绝对安全。

您的成本和结果可能有所不同。

©英特尔公司。Intel、Intel徽标和其他Intel标志是Intel Corporation或其子公司的商标。其他名称和品牌可能被称为他人的财产。

--END--

你也许想了解(点击蓝字查看)⬇️➡️ 以AI作画,祝她节日快乐;简单三步,OpenVINO™ 助你轻松体验AIGC
➡️ 还不知道如何用OpenVINO™作画?点击了解教程。➡️ 如何给开源项目做贡献? | 开发者节日福利➡️ 几行代码轻松实现对于PaddleOCR的实时推理,快来get!➡️ 使用OpenVINO 在“端—边—云”快速实现高性能人工智能推理➡️ 图片提取文字很神奇?试试三步实现OCR!➡️【Notebook系列第六期】基于Pytorch预训练模型,实现语义分割任务➡️使用OpenVINO™ 预处理API进一步提升YOLOv5推理性能
扫描下方二维码立即体验 
OpenVINO™ 工具套件 2022.3

点击 阅读原文 立即体验OpenVINO 2022.3

文章这么精彩,你有没有“在看”?

更多推荐

开发者实战 | 在AI爱克斯开发板上用OpenVINO™运行GPT-2模型