手把手教你使用华为昇腾CANN技术栈完成经典的鸢尾花分类任务,体验完整的AI应用开发流程基于华为昇腾CANN的鸢尾

前言

随着人工智能产业的快速发展,端侧 AI 部署已成为落地 AI 应用的核心环节。华为昇腾 CANN(Compute Architecture for Neural Networks)作为昇腾 AI 芯片的异构计算架构,能够充分释放昇腾芯片的算力潜能,为 AI 模型的训练与端侧部署提供高效支撑。

核心理论基础

昇腾 CANN 架构解析
昇腾 CANN 是面向昇腾系列 AI 芯片的异构计算架构,向下对接昇腾芯片硬件,向上为应用层提供统一的编程接口,核心优势体现在:

  1. 异构计算调度:融合 CPU、昇腾 NPU(神经网络处理单元)的算力,自动完成任务拆分与调度,最大化算力利用率;
  2. 算子库优化:内置丰富的高性能 AI 算子,支持主流深度学习框架(TensorFlow/PyTorch)的算子适配,减少开发者底层优化成本;
  3. 端边云协同:提供统一的模型转换与部署工具链,支持训练好的模型快速适配昇腾端侧设备(如昇腾 310B、昇腾 200DK)。

昇腾 CANN 的核心组件及分工如下:

组件名称     核心功能
AscendCL 昇腾芯片的统一编程接口,支持模型推理、算子开发等
ATC(Ascend Tensor Compiler) 模型转换工具,将 ONNX/TensorFlow 等模型转换为昇腾芯片支持的 OM 模型
MindStudio 昇腾 AI 开发一站式 IDE,支持代码编写、调试、部署

1.项目概述与环境准备

1.1概述
在机器学习的世界里,有一个数据集被广泛提及,它就是鸢尾花数据集(Iris Dataset)。对于许多初学者来说,它是通往数据科学大门的“Hello World”。鸢尾花数据集是机器学习领域中一个非常著名且经典的数据集,由英国统计学家和生物学家罗纳德·费舍尔(Ronald Fisher)在1936年首次提出。这个数据集包含150个鸢尾花样本,每个样本有四个特征,分别是花萼(sepal)长度、花萼宽度、花瓣(petal)长度和花瓣宽度,以及它们所属的鸢尾花品种。150个鸢尾花样本包括三种不同的品种:山鸢尾(Setosa)、变色鸢尾(Versicolor)、维吉尼亚鸢尾(Virginica),每种品种各有50个样本。鸢尾花数据,数值数据单位为厘米(cm)。以下是三种鸢尾花图片。
为什么选鸢尾花数据?
鸢尾花数据集的特点:数据集的特征数量较少,只有4个特征,且这些特征都是数值型的,不用考虑涉及非数值型数据怎么处理问题,易于理解和处理,对入门学友好。且数据集中的样本数量适中,且数据没有缺失值和异常值,数据质量较高。
在机器学习中的应用价值:鸢尾花数据可以应用于分类,聚类(去掉标签数据),降维,数据预处理。机器学习入门:scikit-learn库的使用

1.2鸢尾花分类问题简介

鸢尾花分类是机器学习领域的"Hello World",数据集包含3种鸢尾花(Setosa、Versicolour、Virginica)的4个特征:

  • 花萼长度(sepal length)

  • 花萼宽度(sepal width)

  • 花瓣长度(petal length)

  • 花瓣宽度(petal width)

任务目标:基于 4 个特征实现鸢尾花类别的精准分类。

1.3 环境准备

昇腾 CANN 安装

安装依赖:

sudo apt-get install gcc g++ make cmake;


执行安装脚本:

./Ascend-cann-toolkit_6.0.RC1_linux-x86_64.run --install;


配置环境变量:

export ASCEND_HOME=/usr/local/Ascend
export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH
export LD_LIBRARY_PATH=$ASCEND_HOME/atc/lib64:$LD_LIBRARY_PATH

依赖库安装
 

pip install torch==1.12.0 torchvision==0.13.0 scikit-learn pandas numpy onnx==1.12.0

1.4 分类模型选型

鸢尾花分类属于简单的多分类任务,本文选择经典的全连接神经网络(MLP)作为基础模型,原因:

  • 结构简单,聚焦 CANN 核心流程而非模型调优;
  • 算子数量少,易观察 CANN 的算子优化效果;
  • 无复杂卷积操作,降低虚拟环境验证难度。

2. 数据准备与预处理

2.1 数据集加载与探索

首先加载鸢尾花数据集,并完成数据划分、标准化等预处理:

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
import matplotlib.pyplot as plt

class IrisDataProcessor:
    def __init__(self):
        self.scaler = StandardScaler()
        self.label_encoder = LabelEncoder()
        
    def load_and_explore_data(self):
        """加载并探索鸢尾花数据集"""
        # 加载数据
        iris = load_iris()
        X = iris.data  # 特征数据
        y = iris.target  # 标签数据
        feature_names = iris.feature_names
        target_names = iris.target_names
        
        print("数据集基本信息:")
        print(f"特征数量: {X.shape[1]}")
        print(f"样本数量: {X.shape[0]}")
        print(f"特征名称: {feature_names}")
        print(f"类别名称: {target_names}")
        print(f"类别分布: {np.bincount(y)}")
        
        return X, y, feature_names, target_names
    
    def preprocess_data(self, X, y, test_size=0.2, random_state=42):
        """数据预处理"""
        # 标准化特征
        X_scaled = self.scaler.fit_transform(X)
        
        # 编码标签(虽然已经是数值,这里为了通用性)
        y_encoded = self.label_encoder.fit_transform(y)
        
        # 划分训练集和测试集
        X_train, X_test, y_train, y_test = train_test_split(
            X_scaled, y_encoded, test_size=test_size, 
            random_state=random_state, stratify=y
        )
        
        print(f"训练集大小: {X_train.shape}")
        print(f"测试集大小: {X_test.shape}")
        
        return X_train, X_test, y_train, y_test
    
    def visualize_data(self, X, y, feature_names, target_names):
        """数据可视化"""
        plt.figure(figsize=(15, 10))
        
        # 特征分布直方图
        for i in range(4):
            plt.subplot(2, 3, i+1)
            for class_id in range(3):
                plt.hist(X[y == class_id, i], alpha=0.7, label=target_names[class_id])
            plt.xlabel(feature_names[i])
            plt.ylabel('Frequency')
            plt.legend()
        
        # 特征相关性热力图
        plt.subplot(2, 3, 5)
        df = pd.DataFrame(X, columns=feature_names)
        correlation_matrix = df.corr()
        plt.imshow(correlation_matrix, cmap='coolwarm', interpolation='nearest')
        plt.colorbar()
        plt.xticks(range(len(feature_names)), feature_names, rotation=45)
        plt.yticks(range(len(feature_names)), feature_names)
        plt.title('Feature Correlation')
        
        plt.tight_layout()
        plt.show()

# 使用示例
if __name__ == "__main__":
    processor = IrisDataProcessor()
    X, y, feature_names, target_names = processor.load_and_explore_data()
    X_train, X_test, y_train, y_test = processor.preprocess_data(X, y)
    processor.visualize_data(X, y, feature_names, target_names)

3. PyTorch模型设计与训练

3.1 神经网络模型设计

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import torch.nn.functional as F

class IrisNet(nn.Module):
    """简单的全连接神经网络用于鸢尾花分类"""
    def __init__(self, input_size=4, hidden_size=16, num_classes=3):
        super(IrisNet, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.fc2 = nn.Linear(hidden_size, hidden_size)
        self.fc3 = nn.Linear(hidden_size, num_classes)
        self.dropout = nn.Dropout(0.2)
        
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

class ModelTrainer:
    def __init__(self, model, learning_rate=0.01):
        self.model = model
        self.criterion = nn.CrossEntropyLoss()
        self.optimizer = optim.Adam(model.parameters(), lr=learning_rate)
        
    def train(self, train_loader, val_loader, epochs=100):
        """训练模型"""
        train_losses = []
        val_accuracies = []
        
        for epoch in range(epochs):
            # 训练阶段
            self.model.train()
            total_loss = 0
            for batch_x, batch_y in train_loader:
                self.optimizer.zero_grad()
                outputs = self.model(batch_x)
                loss = self.criterion(outputs, batch_y)
                loss.backward()
                self.optimizer.step()
                total_loss += loss.item()
            
            # 验证阶段
            self.model.eval()
            correct = 0
            total = 0
            with torch.no_grad():
                for batch_x, batch_y in val_loader:
                    outputs = self.model(batch_x)
                    _, predicted = torch.max(outputs.data, 1)
                    total += batch_y.size(0)
                    correct += (predicted == batch_y).sum().item()
            
            accuracy = 100 * correct / total
            avg_loss = total_loss / len(train_loader)
            
            train_losses.append(avg_loss)
            val_accuracies.append(accuracy)
            
            if (epoch + 1) % 20 == 0:
                print(f'Epoch [{epoch+1}/{epochs}], Loss: {avg_loss:.4f}, Accuracy: {accuracy:.2f}%')
        
        return train_losses, val_accuracies
    
    def evaluate(self, test_loader):
        """评估模型性能"""
        self.model.eval()
        correct = 0
        total = 0
        all_predictions = []
        all_labels = []
        
        with torch.no_grad():
            for batch_x, batch_y in test_loader:
                outputs = self.model(batch_x)
                _, predicted = torch.max(outputs.data, 1)
                total += batch_y.size(0)
                correct += (predicted == batch_y).sum().item()
                
                all_predictions.extend(predicted.cpu().numpy())
                all_labels.extend(batch_y.cpu().numpy())
        
        accuracy = 100 * correct / total
        print(f'测试集准确率: {accuracy:.2f}%')
        
        return accuracy, all_predictions, all_labels

# 训练模型
def train_iris_model(X_train, X_test, y_train, y_test):
    # 转换为PyTorch张量
    X_train_tensor = torch.FloatTensor(X_train)
    y_train_tensor = torch.LongTensor(y_train)
    X_test_tensor = torch.FloatTensor(X_test)
    y_test_tensor = torch.LongTensor(y_test)
    
    # 创建数据加载器
    train_dataset = TensorDataset(X_train_tensor, y_train_tensor)
    test_dataset = TensorDataset(X_test_tensor, y_test_tensor)
    
    train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size=8, shuffle=False)
    
    # 创建模型和训练器
    model = IrisNet(input_size=4, hidden_size=16, num_classes=3)
    trainer = ModelTrainer(model, learning_rate=0.01)
    
    # 训练模型
    print("开始训练模型...")
    train_losses, val_accuracies = trainer.train(train_loader, test_loader, epochs=100)
    
    # 评估模型
    accuracy, predictions, labels = trainer.evaluate(test_loader)
    
    return model, trainer, train_losses, val_accuracies

# 使用示例
if __name__ == "__main__":
    processor = IrisDataProcessor()
    X, y, feature_names, target_names = processor.load_and_explore_data()
    X_train, X_test, y_train, y_test = processor.preprocess_data(X, y)
    
    model, trainer, losses, accuracies = train_iris_model(X_train, X_test, y_train, y_test)import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import torch.nn.functional as F

class IrisNet(nn.Module):
    """简单的全连接神经网络用于鸢尾花分类"""
    def __init__(self, input_size=4, hidden_size=16, num_classes=3):
        super(IrisNet, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.fc2 = nn.Linear(hidden_size, hidden_size)
        self.fc3 = nn.Linear(hidden_size, num_classes)
        self.dropout = nn.Dropout(0.2)
        
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

class ModelTrainer:
    def __init__(self, model, learning_rate=0.01):
        self.model = model
        self.criterion = nn.CrossEntropyLoss()
        self.optimizer = optim.Adam(model.parameters(), lr=learning_rate)
        
    def train(self, train_loader, val_loader, epochs=100):
        """训练模型"""
        train_losses = []
        val_accuracies = []
        
        for epoch in range(epochs):
            # 训练阶段
            self.model.train()
            total_loss = 0
            for batch_x, batch_y in train_loader:
                self.optimizer.zero_grad()
                outputs = self.model(batch_x)
                loss = self.criterion(outputs, batch_y)
                loss.backward()
                self.optimizer.step()
                total_loss += loss.item()
            
            # 验证阶段
            self.model.eval()
            correct = 0
            total = 0
            with torch.no_grad():
                for batch_x, batch_y in val_loader:
                    outputs = self.model(batch_x)
                    _, predicted = torch.max(outputs.data, 1)
                    total += batch_y.size(0)
                    correct += (predicted == batch_y).sum().item()
            
            accuracy = 100 * correct / total
            avg_loss = total_loss / len(train_loader)
            
            train_losses.append(avg_loss)
            val_accuracies.append(accuracy)
            
            if (epoch + 1) % 20 == 0:
                print(f'Epoch [{epoch+1}/{epochs}], Loss: {avg_loss:.4f}, Accuracy: {accuracy:.2f}%')
        
        return train_losses, val_accuracies
    
    def evaluate(self, test_loader):
        """评估模型性能"""
        self.model.eval()
        correct = 0
        total = 0
        all_predictions = []
        all_labels = []
        
        with torch.no_grad():
            for batch_x, batch_y in test_loader:
                outputs = self.model(batch_x)
                _, predicted = torch.max(outputs.data, 1)
                total += batch_y.size(0)
                correct += (predicted == batch_y).sum().item()
                
                all_predictions.extend(predicted.cpu().numpy())
                all_labels.extend(batch_y.cpu().numpy())
        
        accuracy = 100 * correct / total
        print(f'测试集准确率: {accuracy:.2f}%')
        
        return accuracy, all_predictions, all_labels

# 训练模型
def train_iris_model(X_train, X_test, y_train, y_test):
    # 转换为PyTorch张量
    X_train_tensor = torch.FloatTensor(X_train)
    y_train_tensor = torch.LongTensor(y_train)
    X_test_tensor = torch.FloatTensor(X_test)
    y_test_tensor = torch.LongTensor(y_test)
    
    # 创建数据加载器
    train_dataset = TensorDataset(X_train_tensor, y_train_tensor)
    test_dataset = TensorDataset(X_test_tensor, y_test_tensor)
    
    train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size=8, shuffle=False)
    
    # 创建模型和训练器
    model = IrisNet(input_size=4, hidden_size=16, num_classes=3)
    trainer = ModelTrainer(model, learning_rate=0.01)
    
    # 训练模型
    print("开始训练模型...")
    train_losses, val_accuracies = trainer.train(train_loader, test_loader, epochs=100)
    
    # 评估模型
    accuracy, predictions, labels = trainer.evaluate(test_loader)
    
    return model, trainer, train_losses, val_accuracies

# 使用示例
if __name__ == "__main__":
    processor = IrisDataProcessor()
    X, y, feature_names, target_names = processor.load_and_explore_data()
    X_train, X_test, y_train, y_test = processor.preprocess_data(X, y)
    
    model, trainer, losses, accuracies = train_iris_model(X_train, X_test, y_train, y_test)

4. 模型转换:PyTorch → ONNX → OM(ATC工具)

4.1 导出为ONNX格式

昇腾 ATC 工具不直接支持 PyTorch 的.pth 模型,需先转换为 ONNX 格式:

def export_to_onnx(model, input_size=4, onnx_path="iris_model.onnx"):
    """将PyTorch模型导出为ONNX格式"""
    # 设置为评估模式
    model.eval()
    
    # 创建示例输入
    dummy_input = torch.randn(1, input_size)
    
    # 导出模型
    torch.onnx.export(
        model,
        dummy_input,
        onnx_path,
        export_params=True,
        opset_version=11,
        input_names=['input'],
        output_names=['output'],
        dynamic_axes={
            'input': {0: 'batch_size'},
            'output': {0: 'batch_size'}
        }
    )
    print(f"模型已导出为: {onnx_path}")
    
    return onnx_path

# 导出训练好的模型
onnx_path = export_to_onnx(model)

4.2 使用ATC工具转换为OM模型

#!/bin/bash
# convert_model.sh - 使用ATC工具转换模型

# 设置环境变量(根据实际安装路径调整)
# source /usr/local/Ascend/ascend-toolkit/set_env.sh

# 使用ATC转换ONNX模型为昇腾OM模型
atc \
--model=iris_model.onnx \
--framework=5 \
--output=iris_model_ascend \
--soc_version=Ascend310 \
--input_shape="input:1,4" \
--input_format=ND \
--output_type=FP32 \
--log=info \
--op_select_implmode=high_precision

echo "模型转换完成: iris_model_ascend.om"

5. AscendCL推理实现

5.1 基于CANN的推理引擎(模拟器模式)

import numpy as np
import acl
import ctypes
import sys
import os

class AscendIrisClassifier:
    """基于AscendCL模拟器的鸢尾花分类器(无硬件验证版)"""
    
    def __init__(self, model_path):
        self.model_path = model_path
        self.device_id = 0  # 虚拟设备ID
        self.context = None
        self.model_id = None
        self.model_desc = None
        
    def init_resource(self):
        """初始化AscendCL资源(模拟器模式)"""
        try:
            # 1. 初始化ACL(仅加载框架,无硬件交互)
            ret = acl.init()
            if ret != 0:
                raise Exception(f"ACL初始化失败: {ret}")
            print("ACL框架初始化成功(模拟器模式)")
            
            # 2. 绑定虚拟设备(无物理芯片仅验证API调用)
            ret = acl.rt.set_device(self.device_id)
            if ret != 0:
                raise Exception(f"虚拟设备绑定失败: {ret}")
            print(f"虚拟设备 {self.device_id} 绑定成功")
            
            # 3. 创建上下文(核心API验证)
            self.context, ret = acl.rt.create_context(self.device_id)
            if ret != 0:
                raise Exception(f"上下文创建失败: {ret}")
            print("计算上下文创建成功")
            
            # 4. 加载OM模型(仅验证模型格式合法性)
            self.model_id, ret = acl.mdl.load_from_file(self.model_path)
            if ret != 0:
                raise Exception(f"OM模型加载失败: {ret}")
            print(f"OM模型加载成功: {self.model_path}")
            
            # 5. 解析模型描述(核心学习点:获取模型输入输出信息)
            self.model_desc = acl.mdl.create_desc()
            ret = acl.mdl.get_desc(self.model_desc, self.model_id)
            if ret != 0:
                raise Exception(f"模型描述解析失败: {ret}")
            
            # 6. 解析模型输入输出维度(无硬件核心学习内容)
            self._parse_model_io()
            print("AscendCL资源初始化完成(模拟器模式)")
            
        except Exception as e:
            print(f"初始化失败: {e}")
            self.release_resource()
            sys.exit(1)
    
    def _parse_model_io(self):
        """解析模型输入输出信息(无硬件核心学习点)"""
        # 获取输入信息
        input_num = acl.mdl.get_num_inputs(self.model_desc)
        input_dim = acl.mdl.get_input_dims(self.model_desc, 0)
        input_size = acl.mdl.get_input_size_by_index(self.model_desc, 0)
        print(f"【模型解析】输入数量: {input_num} | 输入维度: {input_dim} | 输入大小: {input_size} bytes")
        
        # 获取输出信息
        output_num = acl.mdl.get_num_outputs(self.model_desc)
        for i in range(output_num):
            output_dim = acl.mdl.get_output_dims(self.model_desc, i)
            output_size = acl.mdl.get_output_size_by_index(self.model_desc, i)
            print(f"【模型解析】输出 {i} | 维度: {output_dim} | 大小: {output_size} bytes")
    
    def simulate_predict(self, features):
        """模拟推理(仅验证输入预处理+数据格式适配,无实际计算)"""
        try:
            # 预处理输入(与训练端保持一致)
            input_data = self._preprocess_input(features)
            print(f"【模拟推理】输入形状: {input_data.shape} | 数据类型: {input_data.dtype}")
            
            # 验证输入与模型维度匹配(核心校验逻辑)
            input_dim = acl.mdl.get_input_dims(self.model_desc, 0)
            model_input_shape = [dim for dim in input_dim[0]['dims']]
            if list(input_data.shape) != model_input_shape:
                raise Exception(f"输入维度不匹配!模型要求: {model_input_shape}, 实际: {input_data.shape}")
            
            print("【模拟推理】输入格式验证通过(无硬件跳过实际计算)")
            # 模拟输出(返回占位符,仅展示格式)
            pred_class = np.argmax(np.random.rand(1, 3), axis=1)
            confidence = np.max(np.random.rand(1, 3), axis=1)
            return pred_class, confidence
            
        except Exception as e:
            print(f"模拟推理失败: {e}")
            return None, None
    
    def _preprocess_input(self, features):
        """预处理输入特征(与训练端标准化逻辑一致)"""
        if not isinstance(features, np.ndarray):
            features = np.array(features, dtype=np.float32)
        if len(features.shape) == 1:
            features = features.reshape(1, -1)
        
        # 加载训练端保存的标准化参数
        mean = np.load("scaler_mean.npy")
        std = np.load("scaler_std.npy")
        features = (features - mean) / std
        
        return features.astype(np.float32)
    
    def release_resource(self):
        """释放资源(模拟器模式)"""
        try:
            if self.model_desc:
                acl.mdl.destroy_desc(self.model_desc)
            if self.model_id:
                acl.mdl.unload(self.model_id)
            if self.context:
                acl.rt.destroy_context(self.context)
            
            acl.rt.reset_device(self.device_id)
            acl.finalize()
            print("资源释放完成(模拟器模式)")
        except Exception as e:
            print(f"资源释放异常: {e}")

5.2 完整的使用示例(无硬件验证版)

def main():
    """主函数:昇腾CANN全流程学习示例(无硬件版)"""
    
    # 1. 数据准备
    print("=== 步骤1: 数据准备 ===")
    # 复用之前的IrisDataProcessor逻辑(仅保留数据加载+预处理)
    processor = IrisDataProcessor()
    X, y, feature_names, target_names = processor.load_and_explore_data()
    X_train, X_test, y_train, y_test = processor.preprocess_data(X, y)
    
    # 2. 模型训练
    print("\n=== 步骤2: 模型训练 ===")
    model, trainer, losses, accuracies = train_iris_model(X_train, X_test, y_train, y_test)
    
    # 3. 导出为ONNX
    print("\n=== 步骤3: ONNX模型导出 ===")
    onnx_path = export_to_onnx(model)
    
    # 4. ATC转换OM模型(模拟器模式)
    print("\n=== 步骤4: ATC模型转换(模拟器模式) ===")
    print("执行命令: atc --model=iris_mlp.onnx --framework=5 --output=iris_model_ascend --soc_version=Ascend310B1 --simulate=1")
    print("OM模型转换完成(仅验证格式合法性)")
    
    # 5. AscendCL模拟器验证
    print("\n=== 步骤5: AscendCL API验证(模拟器模式) ===")
    classifier = AscendIrisClassifier("iris_model_ascend.om")
    classifier.init_resource()
    
    # 模拟推理(仅验证输入格式+维度匹配)
    test_samples = [
        [5.1, 3.5, 1.4, 0.2],  # Setosa
        [6.7, 3.0, 5.2, 2.3],  # Virginica
        [5.9, 3.0, 4.2, 1.5],  # Versicolour
    ]
    
    print("\n模拟推理验证:")
    for i, sample in enumerate(test_samples):
        predicted_class, confidence = classifier.simulate_predict(sample)
        if predicted_class is not None:
            print(f"样本 {i+1}: {sample}")
            print(f"  输入格式验证: 通过 | 模拟预测类别索引: {predicted_class[0]}")
    
    # 6. 清理资源
    classifier.release_resource()

if __name__ == "__main__":
    main()

总结

通过本实战项目,我们完整地展示了昇腾 CANN 生态的核心学习流程(无硬件也能掌握):

  1. 数据准备:加载、探索和预处理经典的鸢尾花数据集,为模型训练奠定基础;
  2. 模型训练:使用 PyTorch 构建轻量化 MLP 分类器,保证模型与 CANN 算子兼容;
  3. 模型转换:通过 ONNX 中间格式 + ATC 工具,掌握昇腾专属 OM 模型的转换逻辑(模拟器验证);
  4. API 验证:基于 AscendCL 接口,掌握昇腾推理的核心流程(资源初始化、模型解析、输入校验)。

本项目聚焦昇腾 CANN 的 “软件层核心逻辑”,避开物理硬件依赖,所掌握的模型适配、算子兼容、ATC 转换等能力,可无缝迁移到有昇腾芯片的场景。在此基础上,你可进一步学习 CANN 自定义算子开发、模型量化等进阶内容,逐步掌握昇腾生态的核心开发能力。

欢迎加入CANN社区:https://atomgit.com/cann

Logo

CANN开发者社区旨在汇聚广大开发者,围绕CANN架构重构、算子开发、部署应用优化等核心方向,展开深度交流与思想碰撞,携手共同促进CANN开放生态突破!

更多推荐