# Bidirectional Encoder Representation from Transformers(BERT)

## 模型介绍
BERT的全称为Bidirectional Encoder Representation from Transformers，是一个预训练的语言表征模型。它强调了不再像以往一样采用传统的单向语言模型或者把两个单向语言模型进行浅层拼接的方法进行预训练，而是采用新的masked language model（MLM），以致能生成深度的双向语言表征。

## 模型结构
以往的预训练模型的结构会受到单向语言模型（从左到右或者从右到左）的限制，因而也限制了模型的表征能力，使其只能获取单方向的上下文信息。而BERT利用MLM进行预训练并且采用深层的双向Transformer组件（单向的Transformer一般被称为Transformer decoder，其每一个token（符号）只会attend到目前往左的token。而双向的Transformer则被称为Transformer encoder，其每一个token会attend到所有的token）来构建整个模型，因此最终生成能融合左右上下文信息的深层双向语言表征。

## 构建安装

在光源可拉取推理的docker镜像，BERT模型推理的镜像如下： 

```python
docker pull image.sourcefind.cn:5000/dcu/admin/base/custom:ort1.14.0_migraphx3.0.0-dtk22.10.1
```

### 安装Opencv依赖

```python
cd <path_to_migraphx_samples>
sh ./3rdParty/InstallOpenCVDependences.sh
```

### 修改CMakeLists.txt

- 如果使用ubuntu系统，需要修改CMakeLists.txt中依赖库路径：
  将"${CMAKE_CURRENT_SOURCE_DIR}/depend/lib64/"修改为"${CMAKE_CURRENT_SOURCE_DIR}/depend/lib/"

- **MIGraphX2.3.0及以上版本需要c++17**


### 安装OpenCV并构建工程

```
rbuild build -d depend
```

### 设置环境变量

将依赖库依赖加入环境变量LD_LIBRARY_PATH，在~/.bashrc中添加如下语句：

**Centos**:

```
export LD_LIBRARY_PATH=<path_to_migraphx_samples>/depend/lib64/:$LD_LIBRARY_PATH
```

**Ubuntu**:

```
export LD_LIBRARY_PATH=<path_to_migraphx_samples>/depend/lib/:$LD_LIBRARY_PATH
```

然后执行:

```
source ~/.bashrc
```

## 推理

本次采用经典的Bert模型完成问题回答任务，模型和分词文件下载链接：https://pan.baidu.com/s/1yc30IzM4ocOpTpfFuUMR0w, 提取码：8f1a, 将bertsquad-10.onnx文件和uncased_L-12_H-768_A-12分词文件保存在Resource\Models\NLP\Bert文件夹下。下面介绍如何运行python代码和C++代码示例，具体推理代码解析，在Doc目录中有详细说明。

### python版本推理

1.参考《MIGraphX教程》中的安装方法安装MIGraphX并设置好PYTHONPATH

2.安装依赖：

```python
# 进入migraphx samples工程根目录
cd <path_to_migraphx_samples> 

# 进入示例程序目录
cd Python/NLP/Bert

# 安装依赖
pip install -r requirements.txt
```

3.在Python/NLP/Bert目录下执行如下命令运行该示例程序：

```python
python bert.py
```

输出结果为：

<img src="./Doc/Images/Bert_05.png" style="zoom:100%;" align=middle>

输出结果中，问题id对应预测概率值最大的答案。

### C++版本推理

切换到build目录中，执行如下命令：

```python
cd ./build/
./MIGraphX_Samples
```

根据提示选择运行BERT模型的示例程序

```python
./MIGraphX_Samples 0
```

如下所示，会在当前界面中提示输入问题，根据问题得到预测答案

<img src="./Doc/Images/Bert_06.png" style="zoom:100%;" align=middle>

## 历史版本

https://developer.hpccube.com/codes/modelzoo/bert_migraphx

## 参考资料

https://github.com/ROCmSoftwarePlatform/AMDMIGraphX/tree/develop/examples/nlp/python_bert_squad