pytorch移植华为mindspore记录

news2024/11/25 5:00:39

因为某个需求,需要把原来pytorch的神经网络移植到华为的mindspore上
这边记录下遇到的坑
附上mindspore的官方教程:
https://mindspore.cn/tutorials/zh-CN/r2.0/advanced/compute_graph.html

这边附上需要移植的网络,以tensorflow和pytorch的形式移植

import numpy as np

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Embedding, Conv1D, multiply, GlobalMaxPool1D, Input, Activation


def Malconv(max_len=200000, win_size=500, vocab_size=256):
    inp = Input((max_len,))
    emb = Embedding(vocab_size, 8)(inp)

    conv1 = Conv1D(kernel_size=win_size, filters=128, strides=win_size, padding='same')(emb)
    conv2 = Conv1D(kernel_size=win_size, filters=128, strides=win_size, padding='same')(emb)
    a = Activation('sigmoid', name='sigmoid')(conv2)

    mul = multiply([conv1, a])
    a = Activation('relu', name='relu')(mul)
    p = GlobalMaxPool1D()(a)
    d = Dense(64)(p)
    out = Dense(1, activation='sigmoid')(d)

    return Model(inp, out)

pytorch是这种写法:

from typing import Optional
import torch
import torch.nn as nn
import mindspore.nn as nn
from torch import Tensor


class MalConv(nn.Module):
    """The MalConv model.

    References:
        - Edward Raff et al. 2018. Malware Detection by Eating a Whole EXE.
          https://arxiv.org/abs/1710.09435
    """

    def __init__(
        self,
        num_classes: int = 2,
        *,
        num_embeddings: int = 257,
        embedding_dim: int = 8,
        channels: int = 128,
        kernel_size: int = 512,
        stride: int = 512,
        padding_idx: Optional[int] = 256,
    ) -> None:
        super().__init__()

        self.num_classes = num_classes

        # By default, num_embeddings (257) = byte (0-255) + padding (256).
        self.embedding = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx)

        self.conv1 = nn.Conv1d(embedding_dim, channels, kernel_size=kernel_size, stride=stride, bias=True)
        self.conv2 = nn.Conv1d(embedding_dim, channels, kernel_size=kernel_size, stride=stride, bias=True)

        self.max_pool = nn.AdaptiveMaxPool1d(1)

        self.fc = nn.Sequential(
            nn.Flatten(),
            nn.Linear(channels, channels),
            nn.ReLU(inplace=True),
            nn.Linear(channels, num_classes),
        )

    def _embed(self, x: Tensor) -> Tensor:
        # Perform embedding.
        x = self.embedding(x)

        # Treat embedding dimension as channel.
        x = x.permute(0, 2, 1)
        return x

    def _forward_embedded(self, x: Tensor) -> Tensor:
        # Perform gated convolution.
        x = self.conv1(x) * torch.sigmoid(self.conv2(x))

        # Perform global max pooling.
        x = self.max_pool(x)

        x = self.fc(x)
        return x

    def forward(self, x: Tensor) -> Tensor:
        x = self._embed(x)
        x = self._forward_embedded(x)
        return x

先看看mindspore怎么安装:
https://mindspore.cn/install

我先安装的是cpu版本的,顺便一提看着有三个版本,实际你能用的只有2.0.0版本,1.10.1里连pytorch的卷积nn.Conv1d都没有,Nightly更是连介绍这东西是啥的文档都没有。
在这里插入图片描述

pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.0.0rc1/MindSpore/unified/x86_64/mindspore-2.0.0rc1-cp37-cp37m-linux_x86_64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述
安装完后,先看看介绍,mindspore是啥,最重要的先查看与pytorch的典型区别
https://www.mindspore.cn/docs/zh-CN/r2.0/migration_guide/typical_api_comparision.html

这里点名批评下mindspore,看到这部分我自己都气笑了,在使用mindspore的时候它很贴心的告诉你 import mindspore.nn as nn 就可以代替import torch.nn as nn,听上去是不是很方便?要是完全函数名方法名重合那确实方便,但是很多时候这些函数名不完全一样,比如:
mindspore里名字变了但是功能没变,mindspore里名词没变,功能没变,但是参数变了,mindspore里名词没变参数没变但是功能变了,最后一种是最讨厌的,比如:

在这里插入图片描述
这个dropout和你原来使用的dropout是相反的没想到吧!如果不看文档直接掉坑里去
mindspore说我改动了一些方法,只有这样你才知道你用的是mindspore!

首先是搭建网络,原来的网络不算复杂,先看看mindspore的官方文档:
https://www.mindspore.cn/tutorials/zh-CN/r1.10/beginner/model.html
看看它写的样例网络:

Copyclass Network(nn.Cell):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.dense_relu_sequential = nn.SequentialCell(
            nn.Dense(28*28, 512),
            nn.ReLU(),
            nn.Dense(512, 512),
            nn.ReLU(),
            nn.Dense(512, 10)
        )

    def construct(self, x):
        x = self.flatten(x)
        logits = self.dense_relu_sequential(x)
        return logits

看上去很像pytorch的网络,类似于把forward换成了construct
这里需要提一点,mindspore介绍里说的是图构建的时候会自动构建图,说是自动计算梯度啥的,不需要backward和优化器的step方法这样,我个人感觉是直接把forward换成construct了,但是这部分我没完全理解透,如果后面有变更我会再修改

我修改后的网络长这样:
首先原来继承的nn.module变成了cell类,这个是mindspore自己写的类,然后是一些替换,把forward换成construct,Linear换成Dense,Conv1d里的bias参数需要换成have_bias
关于api的替换最好还是查下官方的映射文档:
https://www.mindspore.cn/docs/zh-CN/r2.0/note/api_mapping/pytorch_api_mapping.html

from typing import Optional
import mindspore.nn as nn
from mindspore import Tensor
import mindspore

class MalConv(nn.Cell):
    """The MalConv model.

    References:
        - Edward Raff et al. 2018. Malware Detection by Eating a Whole EXE.
          https://arxiv.org/abs/1710.09435
    """

    def __init__(
        self,
        num_classes: int = 2,
        *,
        num_embeddings: int = 257,
        embedding_dim: int = 8,
        channels: int = 128,
        kernel_size: int = 512,
        stride: int = 512,
        padding_idx: Optional[int] = 256,
    ) -> None:
        super().__init__()

        self.num_classes = num_classes

        # By default, num_embeddings (257) = byte (0-255) + padding (256).
        self.embedding = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx)

        self.conv1 = nn.Conv1d(embedding_dim, channels, kernel_size=kernel_size, stride=stride, has_bias=True)
        self.conv2 = nn.Conv1d(embedding_dim, channels, kernel_size=kernel_size, stride=stride, has_bias=True)

        self.maxpool = nn.AdaptiveMaxPool1d(1)

        self.fc = nn.SequentialCell(
            nn.Flatten(),
            nn.Dense(channels, channels),
            nn.ReLU(),
            nn.Dense(channels, num_classes),
            nn.Sigmoid()
        )

    def _embed(self, x: Tensor) -> Tensor:
        # Perform embedding.
        x = self.embedding(x)

        # Treat embedding dimension as channel.
        x = x.permute(0, 2, 1)
        return x

    def _forward_embedded(self, x: Tensor) -> Tensor:
        # Perform gated convolution.
        x = self.conv1(x) * mindspore.ops.sigmoid(self.conv2(x))

        # Perform global max pooling.
        x = self.maxpool(x)

        x = self.fc(x)
        return x

    def construct(self, x: Tensor) -> Tensor:
        x = self._embed(x)
        x = self._forward_embedded(x)
        return x
print(MalConv())

然后是需要构建数据集,这里我用了原来的数据集代码,和构建pytorch数据集的方法类似,我之前也写过一篇如何构建pytorch数据集的博客
https://blog.csdn.net/qq_43199509/article/details/127534962

官方文档:
https://www.mindspore.cn/tutorials/zh-CN/r2.0.0-alpha/beginner/dataset.html
在这里插入图片描述
附上我改后的代码:
需要注意mindspore的数据类型转换不像原来的pytorch那么兼容,如果报错提示数据类型不符合需要用类似np.int32(),np.astype(dtype=xxx)这些方法来对数据类型进行转换, 最后需要用GeneratorDataset来进行修饰,batch表示每次且多少个数据扔进pytorch进行训练,drop_remainder如果为False的话,最后剩下的数据如果小于batch大小的话会扔掉

dataset = ds.GeneratorDataset(MalConvDataSet(), column_names=["data", "label"])
dataset = dataset.batch(1, drop_remainder=True)
# 准备数据
from OSutils import getDataPath, loadJsonData
from ByteSequencesFeature import byte_sequences_feature
import numpy as np


def data_loader_multilabel(file_path: str, label_dict=None):
    """
    用于读取多标签的情况
    """
    if label_dict is None:
        label_dict = {}
    file_md5 = file_path.split('/')[-1]
    return byte_sequences_feature(file_path), label_dict.get(file_md5)


def data_loader(file_path: str, label_dict=None):
    """
    用于读取单标签的情况
    """
    if label_dict is None:
        label_dict = {}
    file_md5 = file_path.split('/')[-1]
    if file_md5 in label_dict:
        return byte_sequences_feature(file_path), 1
    else:
        return byte_sequences_feature(file_path), 0


def pred_data_loader(file_path: str, *args):
    """
    用于读取预测文件的情况
    """
    file_md5 = file_path.split('/')[-1]
    return byte_sequences_feature(file_path), file_md5


class MalConvDataSet(object):

    def __init__(self, black_samples_dir="black_samples/", white_samples_dir='white_samples/',
                 label_dict_path='label_dict.json', label_type="single", valid=False, valid_size=0.2, seed=207):

        self.file_list = getDataPath(black_samples_dir)
        self.loader = data_loader_multilabel

        if label_type == "single":
            self.loader = data_loader
            self.file_list += getDataPath(white_samples_dir)

        if label_type == "predict":
            self.label_dict = {}
            self.loader = pred_data_loader
        else:
            self.label_dict = loadJsonData(label_dict_path)
            np.random.seed(seed)
            np.random.shuffle(self.file_list)

        # 如果是需要测试集,就在原来的基础上分割
        # 因为设定了随机种子,所以分割的结果是一样的

        valid_cut = int((1 - valid_size) * len(self.file_list))
        if valid:
            self.file_list = self.file_list[valid_cut:]
        else:
            self.file_list = self.file_list[:valid_cut]

    def __getitem__(self, index):
        file_path = self.file_list[index]
        feature, label = self.loader(file_path, self.label_dict)
        return np.array(feature), np.int32(label)

    def __len__(self):
        return len(self.file_list)


if __name__ == "__main__":
    import mindspore.dataset as ds

    # corresponding to torch.utils.data.DataLoader(my_dataset)
    dataset = ds.GeneratorDataset(MalConvDataSet(), column_names=["data", "label"])
    dataset = dataset.batch(1, drop_remainder=True)

    for data in dataset:
        for data in data:
            print(data)

然后需要专门写个类配置启动环境,我这边用的是官方提供的模板,官方文档如下:
https://www.mindspore.cn/docs/zh-CN/r2.0.0-alpha/migration_guide/model_development/training_and_evaluation_procession.html?highlight=init_env

import mindspore as ms
from mindspore.communication.management import init, get_rank, get_group_size


class DefaultConfig(object):
    """
    设置默认的环境
    """
    seed = 1
    device_target = "CPU"
    context_mode = "graph"  # should be in ['graph', 'pynative']
    device_num = 1
    device_id = 0


def init_env(cfg=None):
    """初始化运行时环境."""
    if cfg is None:
        cfg = DefaultConfig()
    ms.set_seed(cfg.seed)
    # 如果device_target设置是None,利用框架自动获取device_target,否则使用设置的。
    if cfg.device_target != "None":
        if cfg.device_target not in ["Ascend", "GPU", "CPU"]:
            raise ValueError(f"Invalid device_target: {cfg.device_target}, "
                             f"should be in ['None', 'Ascend', 'GPU', 'CPU']")
        ms.set_context(device_target=cfg.device_target)

    # 配置运行模式,支持图模式和PYNATIVE模式
    if cfg.context_mode not in ["graph", "pynative"]:
        raise ValueError(f"Invalid context_mode: {cfg.context_mode}, "
                         f"should be in ['graph', 'pynative']")
    context_mode = ms.GRAPH_MODE if cfg.context_mode == "graph" else ms.PYNATIVE_MODE
    ms.set_context(mode=context_mode)

    cfg.device_target = ms.get_context("device_target")
    # 如果是CPU上运行的话,不配置多卡环境
    if cfg.device_target == "CPU":
        cfg.device_id = 0
        cfg.device_num = 1
        cfg.rank_id = 0

    # 设置运行时使用的卡
    if hasattr(cfg, "device_id") and isinstance(cfg.device_id, int):
        ms.set_context(device_id=cfg.device_id)

    if cfg.device_num > 1:
        # init方法用于多卡的初始化,不区分Ascend和GPU,get_group_size和get_rank方法只能在init后使用
        init()
        print("run distribute!", flush=True)
        group_size = get_group_size()
        if cfg.device_num != group_size:
            raise ValueError(f"the setting device_num: {cfg.device_num} not equal to the real group_size: {group_size}")
        cfg.rank_id = get_rank()
        ms.set_auto_parallel_context(parallel_mode=ms.ParallelMode.DATA_PARALLEL, gradients_mean=True)
        if hasattr(cfg, "all_reduce_fusion_config"):
            ms.set_auto_parallel_context(all_reduce_fusion_config=cfg.all_reduce_fusion_config)
    else:
        cfg.device_num = 1
        cfg.rank_id = 0
        print("run standalone!", flush=True)


if __name__ == "__main__":
    init_env()

最后就是启动环境,加载数据集和开始训练,我这边用了较少的训练集发现网络没有收敛,不知道是数据太少还是我迁移的时候少加了东西,我代码是这么写的:

from mindspore.train import Model, LossMonitor, TimeMonitor, CheckpointConfig, ModelCheckpoint
from mindspore import nn
import mindspore.dataset as ds
from MalConv import MalConv as Net
from MalConvDataSet import MalConvDataSet
from SetEnvironment import init_env
import mindspore

def train_net():
    # 初始化运行时环境
    init_env()
    # 二分类任务
    task_type = "single"
    num_classes = 2

    # 多分类任务
    # task_type="multilabel"
    # num_classes=103

    total_step = 1
    max_step = 300
    display_step = 1
    test_step = 1000
    learning_rate = 0.0001
    log_file_path = 'train_log_' + task_type + '.txt'
    use_gpu = False
    model_path = 'Malconv_' + task_type + '.model'
    black_samples_dir = "black_samples/"
    white_samples_dir = 'white_samples/'
    label_dict_path = 'label_dict.json'
    valid_size = 0.2
    # 构造数据集对象
    dataset_ori = ds.GeneratorDataset(
        MalConvDataSet(black_samples_dir=black_samples_dir, white_samples_dir=white_samples_dir,
                       label_dict_path=label_dict_path, label_type=task_type, valid=False,
                       valid_size=valid_size, seed=207), shuffle=True, column_names=["data", "label"])
    dataset=dataset_ori.batch(2,drop_remainder=False)
    # 网络模型,和任务有关
    net = Net()
    # 损失函数,和任务有关
    loss = nn.CrossEntropyLoss()
    # 优化器实现,和任务有关
    optimizer = nn.Adam(net.trainable_params(), learning_rate)
    # 封装成Model
    model = Model(net, loss_fn=loss, metrics={'top_1_accuracy', 'top_5_accuracy'})
    # checkpoint保存
    config_ck = CheckpointConfig(save_checkpoint_steps=dataset.get_dataset_size(),
                                 keep_checkpoint_max=5)
    ckpt_cb = ModelCheckpoint(prefix="resnet", directory="./checkpoint", config=config_ck)
    # 模型训练,1轮
    model.train(1, dataset, callbacks=[LossMonitor(), TimeMonitor()])
    for each in dataset:
        print("data:",each[0],each[1])
        each_predict=model.predict(each[0])
        print("predict:",each_predict)




if __name__ == '__main__':
    train_net()

反正跑是能跑,要是有新发现或者发现错误我会回来更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/518531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode 链表OJ分享

目录 删除排序链表中的重复元素回文链表剑指Offer 06.从尾到头打印链表复制带随机指针的链表 删除排序链表中的重复元素 链接: link 题目描述: 题目思路: 本题思路使用双指针,以示例二为例如下图: 如果head->val等于next-&…

ihateniggers:针对Python开发者的Windows远控木马分析

背景 墨菲安全实验室在持续监测开源软件仓库中的投毒行为,5 月 9 日起发现 4 个包含 “ihateniggers” 远程控制木马的 Python 包被 nagogygmail.com 邮箱关联的账号发布到 PyPI 仓库,试图针对Windows系统下 Python 开发者进行攻击。木马利用了discord、…

各种顺序表和链表的实现代码

目录 一、什么是线性表 二、顺序表 2.1什么是顺序表 2.2静态顺序表的代码实现 2.3动态顺序表的代码实现 三、链表 3.1什么是链表 3.2不带头单向不循环链表的代码实现 3.3带头双向循环链表的代码实现 四、顺序表和链表的区别 一、什么是线性表 线性表是n个具有相同特性…

(十五)数据编辑——图形编辑①

数据编辑——图形编辑① 数据编辑包括几何数据和属性数据的编辑。几何数据的编辑主要是针对图形的操作,即图形编辑,包括平行线复制、缓冲区生成、镜面反射、图层合并、结点操作、拓扑编辑等。属性编辑主要包括图层要素属性的添加、删除、修改、复制、粘…

谷歌落子,我们对中国大模型的期待应该是什么?

对中国大模型厂商而言,市场期待的,也恰是这些真正可落地的应用和实践。这些实践可以在社交,在电商,在低代码,在供应链,也更可以在一个个中国产业数字化转型的新洼地。 作者|思杭 皮爷 出品|产业家 在微软G…

裸辞5个月,面试了37家公司,终于.....

上半年裁员,下半年裸辞,有不少人高呼裸辞后躺平真的好快乐!但也有很多人,裸辞后的生活五味杂陈。 面试37次终于找到心仪工作 因为工作压力大、领导PUA等各种原因,今年2月下旬我从一家互联网小厂裸辞,没想…

执行增删改查时的结果处理

查询最终走到PreparedStatementHandler类的query方法,执行查询后调用DefaultResultSetHandler类的handleResultSets方法 1.处理返回的普通实体类 DefaultResultSetHandler类的handleResultSets方法 继续本类的handleResultSet方法 通过 handleRowValues 方法来…

设计一个可靠的自动化测试框架需要考虑哪些问题呢?

随着软件开发的日益普及,自动化测试框架逐渐成为了保障软件质量的必备工具。然而,如何设计一个可靠的自动化测试框架并不是一件简单的事情,需要考虑多方面的问题。本文将从需求分析、架构设计、测试用例编写等多个角度,介绍设计一…

【SpringMVC】| SpringMVC拦截器

目录 一:SpringMVC拦截器 1. 拦截器介绍 2. HandlerInterceptor接口分析 3. 自定义拦截器实现权限验证 一:SpringMVC拦截器 SpringMVC 中的 Interceptor 拦截器,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理…

C++面向对象(黑马程序员)

内存分区模型 #include<iostream> using namespace std;//栈区数据注意事项&#xff1a;不要返回局部变量的地址 //栈区的数据由编译器管理开辟和释放int* func(int b) //形参数据也会放在栈区 {b 100;int a 10; //局部变量存放在栈区&#xff0c;栈区的数据在函数执…

Qt创建项目 No suitable kits found.

最近因为要写.net6项目&#xff0c;而更新了Visual Studio&#xff0c;后来再使用Qt的时候发现不能编译了。 调整后&#xff0c;发现新建项目显示“No suitable kits found”错误。 网上也看了很多的解决方案&#xff0c;但都不得要领&#xff0c;也都没有解决。 ----------…

Java-Redis持久化之AOF操作

Java-Redis持久化之AOF操作 1.AOF(append only file)2.请你用自己的话说一说 AOF的过程?3.配置如何开启AOF操作4.AOF的优点和缺点: 1.AOF(append only file) 将我们所有的命令都记录下来保存到文件&#xff0c;恢复的时候把这个文件都执行一遍。 2.请你用自己的话说一说 AOF…

【Vue】学习笔记-全局事件总线

全局事件总线(GlobalEventBus) 一种可以在任意组件通信的方式&#xff0c;本质上就是一个对象&#xff0c;它必须满足以下条件 所有的组件对象都必须能看见他这个对象必须能够使用$ on $ emit $ off方法取绑定、触发和解绑事件 使用步骤 定义全局事件总线 //创建VUE new V…

WPF中的用户控件和自定义控件详解

总目录 文章目录 总目录一、什么是用户控件和自定义控件1 用户控件和自定义控件2 相关知识点2 用户控件和自定义控件的适用场景 二、用户控件的使用1.通过依赖属性和路由事件封装用户控件的案例2.通过依赖属性命令依赖属性封装用户控件的案例3.只对外提供属性不对外提供操作的用…

USBCAN卡和台达AS228T通信

AS228R 如图 A.把CAN卡固定上 B.接一个120欧的终端电阻 C.把来可的USBCAN卡的CANH和CANL分别接入AS228R的CANH和CANL. CAN 接口及网络拓扑 10.2.4.1 CAN 网络实体信号的定义及数据格式 CAN 信号为差分信号&#xff0c;信号电压为 CAN和 CAN-之间的电压差&#xff0c;CAN 和…

怎样删除hao123(浏览器首页被篡改了)

有时候我们打开浏览器发现首页被hao123 ,或者2345 这些浏览器给篡改了 或者打开的时候直接打开2个.这个时候想要删除它们,其他它们本身就是网页的,没有应用 在卸载的地方就不用了,它们就嵌套你的浏览器里面,打开的时候启动了他们, 下面说下方法 1 查看浏览器在什么方法下载…

第3天学习Docker-Docker部署常见应用(MySQL、Tomcat、Nginx、Redis、Centos)

前提须知&#xff1a; &#xff08;1&#xff09;搜索镜像命令 格式&#xff1a;docker search 镜像名 &#xff08;2&#xff09;设置Docker镜像加速器 详见文章&#xff1a;Docker设置ustc的镜像源&#xff08;镜像加速器&#xff09; 1、部署MySQL 拉取镜像&#xff08;这…

Radius:针对Rollup生态的Trustless Shared Sequencing层

1. 引言 前序博客&#xff1a; Rollup去中心化Rollup DecentralizationAztec 征集 Rollup Sequencer去中心化提案 Rollup中单一中心化sequencer的问题在于&#xff1a; 审查MEV extraction MEV extraction的问题不在于中心化本身&#xff0c;而在于sequencer具有操纵交易顺…

CN学术期刊《西部素质教育》简介及投稿邮箱

《西部素质教育》&#xff08;半月刊&#xff09;创刊于2015年&#xff0c;是由青海人民出版社有限责任公司主管/主办的教育类学术期刊&#xff0c;本刊恪守“追踪教育研究前沿&#xff0c;关注教育实践热点&#xff0c;探索创新教育理念&#xff0c;传播教育教学信息&#xff…

测试外包干了4年,我废了...

这是来自一位粉丝的投稿内容如下&#xff1a; 先说一下自己的个人情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某外包公司&#xff0c;干了接近4年的软件测试外包工作&#xff0c;马上2023年秋招了&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在…