PyTorch自定义CPU 算子-Transformer架构实现与应用

答案仓库败北了

自定义基于 PyTorch 的 CPU 算子

实验目的

掌握如何在 PyTorch 中新增自定义的 mysigmoid 算子。具体包括:

  1. 熟悉 PyTorch 整体设计机理;
  2. 通过在 PyTorch 框架中添加自定义的 mysigmoid 算子,加深对 PyTorch 算子实现机 制的理解,以在 PyTorch 中添加自定义 CPU 算子为例,为后续在 PyTorch 中添加自定义的 DLP 算子奠定基础。

实验环境

硬件平台:MLU 云平台环境(只使用CPU)。

软件环境:编程框架 PyTorch、Python 3 及相关的扩展库 Pillow、Numpy、Scipy。

运行环境:

镜像收藏:mlu370_ubuntu22.04-student-1.22.1 :v4.2

实验内容

基于第4.2节实时风格迁移推理实验,我们将其中的 Sigmoid 算子替换为自定义的 mysigmoid 算子。该实验不仅涉及使用 C++ 扩展的方式实现 mysigmoid 算子的添加,还需要在推 理文件中调用 mysigmoid 算子,并进行测试。

实验目录:

/opt/code_chap_4/exp_4_4_mysigmoid/

代码补全

sigmoid算子的 C++ 实现

mysigmoid.cpp

算子编译

setup.py

利用 Python 中提供的 Setuptools 模块完成编译流程,将包含算子的 C++ 文件, 编译为一个动态链接库(在 Linux 平台是一个.so 后缀文件),可以让 Python 调用其中实现的函数功能

要注意的一点是后面导入这个算子的时候,因为import默认只在当前目录下找库,但是算子又在op_mysigmoid目录下,跟测试文件隔了一层,import找不到。说是可以通过移动文件位置或者pip安装库来解决,但是交上去的文件也不知道评测的时候会怎么处理,感觉最好还是手动扩展一下path

1
2
3
4
5
6
7
# 导入自定义连接库
import os
import sys
current_dir = os.path.dirname(os.path.abspath(__file__))
module_path = os.path.join(current_dir, 'op_mysigmoid')
sys.path.append(module_path)
import mysigmoid_cpp

算子测试

test_mysigmoid.py

替换4.2节实时风格迁移推理实验的sigmoid算子

evaluate_cpu.py

先将4.2节的代码贴过来,然后替换成mysigmoid算子

几个注意点,和4.2节的代码不一样的地方:

一些文件夹的位置和之前实验不一样了,需要修改

1
2
3
4
5
6
7
8
9
10
11
12
13
class COCODataSet(Dataset):

def __init__(self):
super(COCODataSet, self).__init__()
self.zip_files = ZipFile('../data/train2014_small.zip')
---
if __name__ == '__main__':
---
# TODO: 从/models文件夹下加载网络参数到g_net中
g_net.load_state_dict(torch.load('../models/fst.pth', map_location='cpu'))
---
save_image(torch.cat((image_c, image_g), dim=3), f'../out/cpu/{i}.jpg')
print("TEST RESULT PASS!\n")

去掉网络结构里的sigmoid部分,因为后面forward的时候会调用自定义的sigmoid

1
2
3
4
class TransNet(nn.Module):
def __init__(self):
#TODO: sigmoid激活函数
nn.Sigmoid() # 去掉这行

main里最后有个break

1
2
3
    save_image(torch.cat((image_c, image_g), dim=3), f'../out/cpu/{i}.jpg')
break # 记得加上
print("TEST RESULT PASS!\n")

运行

全部补全之后

1
2
3
4
5
6
# 进行算子编译生成动态链接库。看到so pass就过了
python setup.py build_ext --inplace、
# 进行算子测试
python test_mysigmoid.py
# 进行模型推理
python evaluate_cpu.py

Transformer 架构实现与应用

实验目的

掌握 Transformer 模型的核心原理与 PyTorch 实现方法。通过模块化编程、模型搭建与 推理评估,深入理解 Transformer 的工作机制,并具备在 PyTorch 中实现复杂深度学习模型 的能力。具体包括:

  1. 理解 Transformer 模型的整体架构,包括编码器-解码器结构及其关键组件;
  2. 掌握位置编码、多头注意力、前馈神经网络等核心模块的原理与实现方法;
  3. 熟悉在 PyTorch 中完成 Transformer 模型搭建与推理的流程;
  4. 能够在 DLP 上完成翻译任务的性能验证,并具备基础的模型分析能力。

实验环境

硬件平台:MLU 云平台环境

软件环境:编程框架 PyTorch、计算加速库 CNNL、云端开发工具集 CNToolkit、Python3 及相关的扩展库。

数据集:IWSLT2016 ,国际机器翻译公开基准数据集

运行环境:

镜像收藏:mlu370_ubuntu22.04-student-1.22.1 :v4.2

实验目录:

/opt/code_chap_4/exp_4_5 _transformer/

代码补全

Transformer 基本单元模块实现

modules.py

词嵌入模块

层归一化模块

位置编码模块

多头注意力机制模块

前馈神经网络模块

标签平滑模块

Transformer 翻译模型构建

AttModel.py

模块实现了一个基于 Transformer 结构的 Seq2Seq 模型,可用于机器翻译等任务。模型由编码器和解码器两部分组成,调用 了基本单元模块中的嵌入模块、层归一化模块、位置编码模块、多头注意力机制模块、前 馈神经网络模块以及标签平滑模块。

Transformer 翻译模型评估

环境与依赖导入模块

模型推理与结果评估模块

程序入口与参数配置模块

device的问题

参与同一次运算的 tensor 必须在同一个 device 上,但是有些tensor默认是在cpu的。需要加一行,把它放到和 queries 同一个设备上。有三个地方需要

1
2
3
4
5
6
7
8
9
10
11
12
key_masks = torch.sign(torch.abs(torch.sum(keys, dim=-1)))  # (N, T_k)
key_masks = key_masks.repeat(self.num_heads, 1) # (h*N, T_k)
key_masks = torch.unsqueeze(key_masks, 1).repeat(1, queries.size()[1], 1) # (h*N, T_q, T_k)
key_masks = key_masks.to(queries.device)

masks = Variable(torch.unsqueeze(tril, 0).repeat(outputs.size()[0], 1, 1))
masks = masks.to(outputs.device)

query_masks = torch.sign(torch.abs(torch.sum(queries, dim=-1)))
query_masks = query_masks.repeat(self.num_heads, 1)
query_masks = torch.unsqueeze(query_masks, 2).repeat(1, 1, keys.size()[1])
query_masks = query_masks.to(outputs.device)

运行

1
2
3
4
# 在CPU上 运 行
bash run_transformer_cpu.sh
# 在DLP上 运 行
bash run_transformer_mlu.sh