[{"data":1,"prerenderedAt":366},["ShallowReactive",2],{"content-query-EARrHBFtwD":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"cover":11,"type":12,"category":13,"body":14,"_type":360,"_id":361,"_source":362,"_file":363,"_stem":364,"_extension":365},"/technology-blogs/zh/2228","zh",false,"","MSAdapter，一款高效迁移PyTorch代码到昇思MindSpore生态的适配工具","AI框架作为人工智能创新的重要基础设施，正促进人工智能技术加速进步，助力众多行业智能化转型升级。然而因国产框架发展较晚，生态还未建立起来，推广国产框架生态变得异常艰难。","2023-04-10","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/04/13/ed28ba2422664bf39e4ec7692d9f6ea1.png","technology-blogs","实践",{"type":15,"children":16,"toc":357},"root",[17,25,31,40,45,50,55,60,65,77,89,98,103,133,140,145,153,161,166,176,181,189,197,209,217,225,233,241,249,257,265,273,281,289,297,305,313,318,325,333,338,345,350],{"type":18,"tag":19,"props":20,"children":22},"element","h1",{"id":21},"msadapter一款高效迁移pytorch代码到昇思mindspore生态的适配工具",[23],{"type":24,"value":8},"text",{"type":18,"tag":26,"props":27,"children":28},"p",{},[29],{"type":24,"value":30},"AI框架作为人工智能创新的重要基础设施，正促进人工智能技术加速进步，助力众多行业智能化转型升级。然而因国产框架发展较晚，生态还未建立起来，推广国产框架生态变得异常艰难。从2016-2023年Papers with Code里各框架使用占比可以看到，PyTorch占有着主导的地位。作为国内自研的AI融合框架，昇思MindSpore积极响应产业界需求，不断在效率提升、易用性、创新性以及使用体验方面推动AI框架持续演进。",{"type":18,"tag":26,"props":32,"children":33},{},[34],{"type":18,"tag":35,"props":36,"children":39},"img",{"alt":37,"src":38},"image.png","https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413021730.27531925479032816092261434393069:50540412032704:2400:017AE30C1BFCA535D7E788A07635695E21EAF0F56E7F009463A647919E70484C.png",[],{"type":18,"tag":26,"props":41,"children":42},{},[43],{"type":24,"value":44},"图1 深度学习框架生态",{"type":18,"tag":26,"props":46,"children":47},{},[48],{"type":24,"value":49},"为了帮助用户高效迁移PyTorch代码到昇思MindSpore生态，昇思MindSpore和鹏城实验室联合开发的一款昇思MindSpore生态适配工具——MSAdapter。它能帮助用户高效使用中国算力网——智算网络的昇腾算力，且在不改变原有PyTorch用户使用习惯下，将代码快速迁移到MindSpore生态上。",{"type":18,"tag":26,"props":51,"children":52},{},[53],{"type":24,"value":54},"MSAdapter的API完全参照PyTorch设计，用户仅需少量修改就能轻松地将PyTorch代码高效运行在昇腾上。目前MSAdapter已经适配torch、torch.nn、torch.nn.function、torch.linalg等800+接口；全面支持torchvision；并且在MSAdapterModelZoo中验证了70+主流PyTorch模型的迁移。",{"type":18,"tag":26,"props":56,"children":57},{},[58],{"type":24,"value":59},"MSAdapter已在OpenI启智社区开源，社区为大家提供了普惠NPU算力资源，欢迎大家使用。",{"type":18,"tag":26,"props":61,"children":62},{},[63],{"type":24,"value":64},"代码仓地址：",{"type":18,"tag":26,"props":66,"children":67},{},[68],{"type":18,"tag":69,"props":70,"children":74},"a",{"href":71,"rel":72},"https://openi.pcl.ac.cn/OpenI/MSAdapter%E3%80%82",[73],"nofollow",[75],{"type":24,"value":76},"https://openi.pcl.ac.cn/OpenI/MSAdapter。",{"type":18,"tag":26,"props":78,"children":79},{},[80,82],{"type":24,"value":81},"资源地址：",{"type":18,"tag":69,"props":83,"children":86},{"href":84,"rel":85},"https://openi.pcl.ac.cn/OpenI/MSAdapter/modelarts/notebook/create%E3%80%82",[73],[87],{"type":24,"value":88},"https://openi.pcl.ac.cn/OpenI/MSAdapter/modelarts/notebook/create。",{"type":18,"tag":26,"props":90,"children":91},{},[92],{"type":18,"tag":93,"props":94,"children":95},"strong",{},[96],{"type":24,"value":97},"MSAdapter整体设计",{"type":18,"tag":26,"props":99,"children":100},{},[101],{"type":24,"value":102},"为匹配用户习惯，MSAdapter设计目的是在用户不感知的情况下，能适配PyTorch代码运行在昇腾（Ascend）设备上。MSAdapter以PyTorch的接口为标准，为用户提供一套和PyTorch一样（接口和功能完全一致）的中高阶模型构建接口和数据处理接口。图2展示了MSAdapter的层次结构。其特点如下：",{"type":18,"tag":104,"props":105,"children":106},"ul",{},[107,113,118,123,128],{"type":18,"tag":108,"props":109,"children":110},"li",{},[111],{"type":24,"value":112},"轻量化封装",{"type":18,"tag":108,"props":114,"children":115},{},[116],{"type":24,"value":117},"接口和功能与PyTorch完全映射",{"type":18,"tag":108,"props":119,"children":120},{},[121],{"type":24,"value":122},"PyTorch代码少量修改可在Ascend运行",{"type":18,"tag":108,"props":124,"children":125},{},[126],{"type":24,"value":127},"支持昇思MindSpore原生接口",{"type":18,"tag":108,"props":129,"children":130},{},[131],{"type":24,"value":132},"高效性能",{"type":18,"tag":26,"props":134,"children":135},{},[136],{"type":18,"tag":35,"props":137,"children":139},{"alt":37,"src":138},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413021818.82748185468713754935494078813218:50540412032704:2400:E22E1714496092BFB13F9A5AEEEDD3CEDFCCE3773CE14D64CF503D28E17A44AD.png",[],{"type":18,"tag":26,"props":141,"children":142},{},[143],{"type":24,"value":144},"图2 MSAdapter接口层次",{"type":18,"tag":26,"props":146,"children":147},{},[148],{"type":18,"tag":93,"props":149,"children":150},{},[151],{"type":24,"value":152},"MSAdapter快速入门",{"type":18,"tag":26,"props":154,"children":155},{},[156],{"type":18,"tag":93,"props":157,"children":158},{},[159],{"type":24,"value":160},"1、安装MSAdapter",{"type":18,"tag":26,"props":162,"children":163},{},[164],{"type":24,"value":165},"通过pip安装",{"type":18,"tag":167,"props":168,"children":170},"pre",{"code":169},"pip install msadapter\n",[171],{"type":18,"tag":172,"props":173,"children":174},"code",{"__ignoreMap":7},[175],{"type":24,"value":169},{"type":18,"tag":26,"props":177,"children":178},{},[179],{"type":24,"value":180},"通过源码安装",{"type":18,"tag":167,"props":182,"children":184},{"code":183},"git clone https://git.openi.org.cn/OpenI/MSAdapter.git \ncd MSAdapter \npython setup.py install\n",[185],{"type":18,"tag":172,"props":186,"children":187},{"__ignoreMap":7},[188],{"type":24,"value":183},{"type":18,"tag":26,"props":190,"children":191},{},[192],{"type":18,"tag":93,"props":193,"children":194},{},[195],{"type":24,"value":196},"2、使用MSAdapter",{"type":18,"tag":26,"props":198,"children":199},{},[200,202],{"type":24,"value":201},"下面以AlexNet模型为例，训练CIFAR10数据集的PyTorch代码转到MSAdapter代码，完整的代码可以从MSAdapterModelZoo获取（",{"type":18,"tag":69,"props":203,"children":206},{"href":204,"rel":205},"https://openi.pcl.ac.cn/OpenI/MSAdapterModelZoo/src/branch/master/official/cv/alexnet%EF%BC%89",[73],[207],{"type":24,"value":208},"https://openi.pcl.ac.cn/OpenI/MSAdapterModelZoo/src/branch/master/official/cv/alexnet）",{"type":18,"tag":26,"props":210,"children":211},{},[212],{"type":18,"tag":93,"props":213,"children":214},{},[215],{"type":24,"value":216},"2.1 修改导入包",{"type":18,"tag":167,"props":218,"children":220},{"code":219},"# PyTorch  导入包\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader\nfrom torchvision import datasets, transforms\nfrom torchvision.transforms.functional import InterpolationMode\nimport argparse\n",[221],{"type":18,"tag":172,"props":222,"children":223},{"__ignoreMap":7},[224],{"type":24,"value":219},{"type":18,"tag":167,"props":226,"children":228},{"code":227},"## MSAdapter 导入包\n\nimport msadapter.pytorch as torch\nimport msadapter.pytorch.nn as nn\nfrom msadapter.pytorch.utils.data import DataLoader\nfrom msadapter.torchvision import datasets, transforms\nfrom msadapter.torchvision.transforms.functional import InterpolationMode\n\nimport mindspore as ms\nimport argparse\n",[229],{"type":18,"tag":172,"props":230,"children":231},{"__ignoreMap":7},[232],{"type":24,"value":227},{"type":18,"tag":26,"props":234,"children":235},{},[236],{"type":18,"tag":93,"props":237,"children":238},{},[239],{"type":24,"value":240},"2.2 数据处理（一致）",{"type":18,"tag":167,"props":242,"children":244},{"code":243},"# PyTorch  数据处理\n\ntransform = transforms.Compose([transforms.Resize((224, 224), interpolation=InterpolationMode.BICUBIC),\n                                transforms.ToTensor(),\n                                transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.247, 0.2435, 0.2616])\n                               ])\n",[245],{"type":18,"tag":172,"props":246,"children":247},{"__ignoreMap":7},[248],{"type":24,"value":243},{"type":18,"tag":167,"props":250,"children":252},{"code":251},"# MSAdapter 数据处理\ntransform = transforms.Compose([transforms.Resize((224, 224), interpolation=InterpolationMode.BICUBIC),\n                                transforms.ToTensor(),\n                                transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.247, 0.2435, 0.2616])\n                               ])\n",[253],{"type":18,"tag":172,"props":254,"children":255},{"__ignoreMap":7},[256],{"type":24,"value":251},{"type":18,"tag":26,"props":258,"children":259},{},[260],{"type":18,"tag":93,"props":261,"children":262},{},[263],{"type":24,"value":264},"2.3 模型定义（一致）",{"type":18,"tag":167,"props":266,"children":268},{"code":267},"#  PyTorch 模型定义\nclass AlexNet(nn.Module):\n    def __init__(self, num_classes: int = 10) -> None:\n        super(AlexNet, self).__init__()\n\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 64, (11, 11), (4, 4), (2, 2)),\n            nn.ReLU(),\n            nn.MaxPool2d((3, 3), (2, 2)),\n\n            nn.Conv2d(64, 192, (5, 5), (1, 1), (2, 2)),\n            nn.ReLU(),\n            nn.MaxPool2d((3, 3), (2, 2)),\n\n            nn.Conv2d(192, 384, (3, 3), (1, 1), (1, 1)),\n            nn.ReLU(),\n            nn.Conv2d(384, 256, (3, 3), (1, 1), (1, 1)),\n            nn.ReLU(),\n            nn.Conv2d(256, 256, (3, 3), (1, 1), (1, 1)),\n            nn.ReLU(),\n            nn.MaxPool2d((3, 3), (2, 2)),\n        )\n\n        self.avgpool = nn.AdaptiveAvgPool2d((6, 6))\n\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(256 * 6 * 6, 4096),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096, 4096),\n            nn.ReLU(),\n            nn.Linear(4096, num_classes),\n        )\n\n    def forward(self, x):\n        return self._forward_impl(x)\n\n    def _forward_impl(self, x):\n        out = self.features(x)\n        out = self.avgpool(out)\n        out = torch.flatten(out, 1)\n        out = self.classifier(out)\n        return out\n",[269],{"type":18,"tag":172,"props":270,"children":271},{"__ignoreMap":7},[272],{"type":24,"value":267},{"type":18,"tag":167,"props":274,"children":276},{"code":275},"# MSAdapter 模型定义\nclass AlexNet(nn.Module):\n    def __init__(self, num_classes: int = 10) -> None:\n        super(AlexNet, self).__init__()\n\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 64, (11, 11), (4, 4), (2, 2)),\n            nn.ReLU(),\n            nn.MaxPool2d((3, 3), (2, 2)),\n\n            nn.Conv2d(64, 192, (5, 5), (1, 1), (2, 2)),\n            nn.ReLU(),\n            nn.MaxPool2d((3, 3), (2, 2)),\n\n            nn.Conv2d(192, 384, (3, 3), (1, 1), (1, 1)),\n            nn.ReLU(),\n            nn.Conv2d(384, 256, (3, 3), (1, 1), (1, 1)),\n            nn.ReLU(),\n            nn.Conv2d(256, 256, (3, 3), (1, 1), (1, 1)),\n            nn.ReLU(),\n            nn.MaxPool2d((3, 3), (2, 2)),\n        )\n\n        self.avgpool = nn.AdaptiveAvgPool2d((6, 6))\n\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(256 * 6 * 6, 4096),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096, 4096),\n            nn.ReLU(),\n            nn.Linear(4096, num_classes),\n        )\n\n    def forward(self, x):\n        return self._forward_impl(x)\n\n    def _forward_impl(self, x):\n        out = self.features(x)\n        out = self.avgpool(out)\n        out = torch.flatten(out, 1)\n        out = self.classifier(out)\n        return out\n",[277],{"type":18,"tag":172,"props":278,"children":279},{"__ignoreMap":7},[280],{"type":24,"value":275},{"type":18,"tag":26,"props":282,"children":283},{},[284],{"type":18,"tag":93,"props":285,"children":286},{},[287],{"type":24,"value":288},"2.4 模型训练（训练部分自定义）",{"type":18,"tag":167,"props":290,"children":292},{"code":291},"# PyTorch 模型训练\ndef train(config_args):\n    train_images = datasets.CIFAR10('./', train=True, download=True, transform=transform)\n    train_data = DataLoader(train_images, batch_size=128, shuffle=True, num_workers=2, drop_last=True)\n\n    epochs = config_args.epoch\n    net = AlexNet().to(config_args.device)\n    criterion = nn.CrossEntropyLoss()\n    optimizer = torch.optim.SGD(net.parameters(), lr=0.01, momentum=0.9, weight_decay=0.0005)\n    net.train()\n    print(\"begin training ......\")\n    for i in range(epochs):\n        for X, y in train_data:\n            X, y = X.to(config_args.device), y.to(config_args.device)\n            out = net(X)\n            loss = criterion(out, y)\n            optimizer.zero_grad()\n            loss.backward()\n            optimizer.step()\n            print(\"---------------------->epoch:{}, loss:{:.6f}\".format(i, loss))\n    torch.save(net.state_dict(), config_args.save_path)\n",[293],{"type":18,"tag":172,"props":294,"children":295},{"__ignoreMap":7},[296],{"type":24,"value":291},{"type":18,"tag":167,"props":298,"children":300},{"code":299},"# MSAdapter 模型训练\ndef train(config_args):\n    train_images = datasets.CIFAR10('./', train=True, download=True, transform=transform)\n    train_data = DataLoader(train_images, batch_size=128, shuffle=True, num_workers=2, drop_last=True)\n\n    epochs = config_args.epoch\n    net = AlexNet().to(config_args.device)\n    criterion = nn.CrossEntropyLoss()\n    optimizer = ms.nn.SGD(net.trainable_params(), learning_rate=0.01, momentum=0.9, weight_decay=0.0005)\n    loss_net = ms.nn.WithLossCell(net, criterion)\n    train_net = ms.nn.TrainOneStepCell(loss_net, optimizer)\n    net.train()\n    print(\"begin training ......\")\n    for i in range(epochs):\n        for X, y in train_data:\n            res = train_net(X, y)\n            print(\"---------------------->epoch:{}, loss:{:.6f}\".format(i, res.asnumpy()))\n    torch.save(net.state_dict(), config_args.save_path)\n",[301],{"type":18,"tag":172,"props":302,"children":303},{"__ignoreMap":7},[304],{"type":24,"value":299},{"type":18,"tag":26,"props":306,"children":307},{},[308],{"type":18,"tag":93,"props":309,"children":310},{},[311],{"type":24,"value":312},"3、Ascend环境运行",{"type":18,"tag":26,"props":314,"children":315},{},[316],{"type":24,"value":317},"目前启智平台对外提供了普惠Ascend算力和昇思MindSpore2.0镜像，用户可以在自己的项目上使用这些资源。",{"type":18,"tag":26,"props":319,"children":320},{},[321],{"type":18,"tag":35,"props":322,"children":324},{"alt":37,"src":323},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413022030.37248093050180469524023027411078:50540412032704:2400:F16F5CABC339D1D07AB213D695FC666361C74D406CCFF660F751FEA2B3C0D593.png",[],{"type":18,"tag":26,"props":326,"children":327},{},[328],{"type":18,"tag":93,"props":329,"children":330},{},[331],{"type":24,"value":332},"加入MSAdapter SIG",{"type":18,"tag":26,"props":334,"children":335},{},[336],{"type":24,"value":337},"MSAdapter SIG汇聚了一大批MSAdapter开发者和用户，您可以从群里直接获得使用指导。欢迎加入我们一起开发和使用，提出宝贵意见！",{"type":18,"tag":26,"props":339,"children":340},{},[341],{"type":18,"tag":35,"props":342,"children":344},{"alt":37,"src":343},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413022053.51473154806159679708431607805493:50540412032704:2400:7F0FBED8F82C35B3602E4A88EB218D50C5F1786A1009BC3B436F49DA701F7AFD.png",[],{"type":18,"tag":26,"props":346,"children":347},{},[348],{"type":24,"value":349},"或添加小助手备注：MSAdapter SIG",{"type":18,"tag":26,"props":351,"children":352},{},[353],{"type":18,"tag":35,"props":354,"children":356},{"alt":37,"src":355},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413022120.71199091796926655938021493756367:50540412032704:2400:9163BD8113C978F253D0BFF8F19A63F9C3C8826F9B16701C928B5FA29EF57416.png",[],{"title":7,"searchDepth":358,"depth":358,"links":359},4,[],"markdown","content:technology-blogs:zh:2228.md","content","technology-blogs/zh/2228.md","technology-blogs/zh/2228","md",1776506121269]