• The source code for the experiment mentioned in this article is available on GitHub.

    I was studying chapter 9 of D2L recently on natural language processing (NLP) using recurrent neural networks (RNN). To validate and further reinforce my understanding of the concepts presented in the chapter, I decided to train a word-level language model from scratch based on the King James Version (KJV) of the Christian Bible.

    Various factors informed my decision to use the Bible as the data source for my more realistic (compared to the toy example in D2L) NLP deep learning experiment.

    1. The Bible is among one of the English books with the most words, surpassed only by a few select novels. This makes it a prime candidate for performing word-level analysis and deep learning as opposed to shorter texts such as The Time Machine by H. G. Wells
    2. Growing up in a community with moderate Christian influence, the Bible was familiar to me compared to novels that I may not have read or even heard of
    3. The raw Bible text taken straight from Open Bible was already sufficiently structured and well formatted, perfect for practicing how to create and implement simple data pre-processing pipelines without ingesting structured CSV data directly

    With the problem statement defined, I proceeded to develop a Python script to train my Elman RNN-based language model on the entire corpus of the KJV Bible. With the help of DeepSeek, I was able to quickly clarify the key concepts required to implement the model training pipeline with Huawei’s Ascend-optimized deep learning framework known as MindSpore and quickly triage and debug issues which otherwise would have wasted me precious hours or days chasing them.

    As an aside, I started migrating from Jupyter notebooks to plain Python scripts on my Orange Pi AIpro (20T) recently. While Jupyter notebooks made it easy to visualize the results from my deep learning experiments and explain my work to myself and others via inline text, using them effectively meant I had to keep my browser open for the entire duration of the experiment and wait for the entire training pipeline to finish. This was fine for short experiments lasting up to an hour but quickly proved unwieldy with more complex neural networks such as ResNet and DenseNet which easily took hours or even days to complete. Migrating to a vanilla Python approach enabled me to run my deep learning pipelines in the background with convenient command-line tools such as tmux, checking on the progress occasionally with MLflow without keeping the monitor attached.

    With my NLP pipeline humming along, I was set to celebrate the success of training my first word-level language model from scratch using a dataset I selected and prepared. Little did I know that this was just the start of my debugging journey …

    A classic textbook example of overfitting, or is it?

    I divided the full text of the KJV Bible directly with an 80-20 ratio with 80% of the text for my training set and the remaining 20% for my validation set. What caveats can you think of that could render this approach flawed or suboptimal? 😉

    Within the first few hours of training my language model, the training loss and perplexity was steadily decreasing over time. However, the validation loss (perplexity) quickly reached its optimum at the 2nd epoch, with the loss steadily increasing thereafter.

    Since I used a 2-layer Elman RNN without regularization techniques such as weight decay, momentum and dropout, I initially assumed it to be a classic textbook example of overfitting. After all, my network was deep in both the conventional and time-oriented sense – it had 2 stacked recurrent layers and the model was trained on sequences of 32 consecutive words. While the Bible contains many words for a mere human, such a dataset is considered tiny by today’s standards of training LLMs such as ChatGPT and DeepSeek.

    Training loss on the Old Testament
    Validation loss on the New Testament

    With these metrics and my initial hypothesis in mind, I asked DeepSeek for tips and tricks to reduce overfitting. Not surprisingly, it gave the following general recommendations typical for most deep learning tasks.

    1. Reduce the learning rate
    2. Add weight decay and momentum
    3. Apply dropout within the stacked RNN layers
    4. Reduce the number of units of hidden state within the stacked RNN – I used 256, DeepSeek recommended 128 or fewer

    I decided to adopt (1) and (2) as a starting point to introduce regularization and mitigate overfitting.

    Mitigating overfitting with abysmal results

    With the 2nd run of my NLP pipeline using weight decay and momentum as my primary technique to combat overfitting, the training and validation losses actually surged initially before following a steady decline after 5 or so epochs. Both the training and validation losses followed this same general pattern which suggested that the regularization techniques were kicking in. Unfortunately, the overall performance of my model was abysmal compared to my initial run.

    1. During my initial run, the optimal results were obtained at the end of the 2nd epoch with the training perplexity reduced to around 50 and the validation perplexity remaining around 200
    2. By the end of the 2nd run, my training perplexity stabilized at around 90 while my validation perplexity remained at around 1500

    Considering the vocabulary of the KJV Bible consisted of around 5600 unique words after removing infrequent words appearing less than 5 times throughout the entire text, my updated model was only performing marginally better than random guessing on the validation set! What was going on? Surely the adoption of regularization techniques such as weight decay and momentum, even if ineffective, should not exacerbate overfitting?

    The “Aha!” moment

    On a Friday evening, a crucial detail on how the Bible is structured surfaced in my mind. Unlike typical English novels which follow a consistent vocabulary and writing style throughout the entire book, the Bible is divided into 2 major sections, each with its own distinct vocabulary, style and phrasing.

    1. The Old Testament focuses primarily on the Ten Commandments and the chosen people, with adherence to the Law and discipline as its recurring theme
    2. The New Testament on the other hand focuses on belief and salvation, with love, forgiveness and understanding as its recurring theme

    With this key observation in mind, I asked DeepSeek what percentage of words across the entire KJV Bible belong to the Old vs. New Testaments. Unsurprisingly, the numbers coincided heavily with my naive 80-20 train/test split.

    1. The Old Testament accounts for approximately 77% of total words within the KJV Bible
    2. In contrast, the New Testament accounts for just under 23% of total words within the KJV Bible

    Simply put, my model was effectively trained to recognize phrases from the Old Testament but asked to predict phrases from the New Testament, both of which are characterized by distinct vocabulary and writing styles, a classic example of distribution shift. The regularization techniques only served to widen the gap since the sliver of New Testament phrases which made it to the training set were forgotten after a dozen or so epochs through regularization.

    The solution? Shuffle the phrases across the entire Bible before applying the 80-20 train/test split. With this simple optimization, the training and validation perplexities both stabilize near the 20-30 range over 20+ epochs, without compromising on the learning rate or applying regularization techniques such as dropout.

    Training loss on KJV full text
    Validation loss on KJV full text

    Lesson learned – spend time understanding the data you are dealing with before rushing to train your next model!

    Concluding remarks and going further

    This was an interesting albeit unexpected lesson in data preprocessing and handling with designing and implementing deep learning experiments.

    I hope you enjoyed reading this article as much as I did authoring it and stay tuned for updates 😉

  • The source code for this article is available on GitHub.

    I recently purchased the GMKtec NucBox K11 Mini PC for building my AI homelab and support my ongoing journey on MLOps and deep learning. This blog post explains my motivations for building my AI homelab, the difficulties I encountered along the way, the design decisions I made to arrive at my current setup and my next steps once the OrangePi AI Studio Pro extension dock is available.

    A big thank you to my employer Enfinity Solutions for arranging the Mini PC purchase and making this all possible!

    NucBox K11 Mini PC

    Background and motivation

    Back in January 2026, I purchased the OrangePi AIpro (20T) to kickstart my deep learning journey with Dive into Deep Learning (D2L) based on the MindSpore deep learning framework and CANN ecosystem optimized for Huawei’s Ascend AI processors.

    My initial goal was to familiarize myself with the concepts of machine learning and gain hands-on experience training and fine-tuning modern deep neural networks such as those based on the Transformer architecture commonly found in LLMs like ChatGPT and DeepSeek.

    While the OrangePi AIpro (20T) helped me get through the basics of deep learning, the 20 TOPS AI computing power of the Ascend 310B1 edge inferencing NPU chip quickly revealed its limitations. Within 3 months of starting my deep learning journey (2026-03 to 2026-05), I got from training my very first linear neural network to training modern CNNs such as ResNet predating the current generative / agentic AI era. However, even training the simplest variation ResNet18 on a simple dataset such as Fashion MNIST took about 1-2 hours to complete.

    It soon became clear that I would need to upgrade my current hardware setup to continue my deep learning journey, hence my purchase of the AI Studio Pro extension dock in 2026-06 featuring 2 Ascend 310P4 NPUs offering a total of 352 TOPS / 176 TFLOPS of AI processing power. The extension dock alone does not provide a complete AI computing environment and must be paired with a standard x86 PC such as the NucBox K11 which I also purchased.

    Unfortunately, the AI Studio Pro is currently in great demand with limited stock so I am still waiting for it to be available at the time of writing. In the meantime, my NucBox K11 arrived and the remainder of this blog post describes my existing AI homelab setup on the NucBox K11 with its current limitations.

    Design considerations and trade-offs

    The major goals for building my AI homelab are as below.

    1. Familiarize myself with the MindSpore deep learning framework and CANN ecosystem lead by Huawei which is quickly dominating the Chinese domestic market and displacing NVIDIA’s CUDA ecosystem
    2. Learn the basics of training and fine-tuning large language models (LLMs) based on the Transformer architecture used in popular foundation models such as ChatGPT and DeepSeek
    3. Familiarize myself with the operational aspects of deep learning known as MLOps – how to deploy, manage and scale deep learning workloads in a production-ready environment such as Kubernetes
    4. Spin up Jupyter notebooks for rapid experimentation with varying hardware resources and popular deep learning frameworks such as PyTorch and MindSpore pre-installed, without manually creating Python virtual environments and managing package dependencies across projects

    With the following goals in mind, the components used in my AI homelab and the trade-offs considered are described below.

    Kubernetes as the base environment with K3s

    Modern AI workloads are tailored to container-native environments such as Kubernetes. Furthermore, containers provide a standardized operating environment with pre-installed software for my Jupyter notebooks, obviating the need to manage Python virtual environments and package dependencies across projects manually. As such, Kubernetes was the natural starting point for building my AI homelab.

    Since I’m running Kubernetes on a single PC with no high-availability (HA) requirements and which needs to be stopped and started quickly, K3s was the natural choice for my Kubernetes distribution. With K3s, setting up Kubernetes was a breeze and its lightweight, un-opinionated nature enables me to deploy just the right components for my use case, giving more headroom for my deep learning workloads.

    Argo CD for managing my platform components with GitOps

    My AI homelab requires multiple components installed, spread across various Kustomize manifests and Helm charts. Installing them manually with ad-hoc kubectl and helm commands makes it difficult to keep track of what was installed and makes it difficult to reliably upgrade these components when new security fixes and features are available.

    As such, I decided to adopt a GitOps workflow to manage these components transparently and prevent configuration drift. This left me with 2 choices: Argo CD or Flux. Both are mature GitOps solutions each with its own advantages. I went with the former since the web UI is more mature and Argo CD is the go-to GitOps solution by leading enterprise Kubernetes distributions such as Rancher and OpenShift. Plus, I took the DO380 v4.14 course by Red Hat in late 2025 which covered enterprise Argo CD deployment practices such as the App of Apps pattern. I simply wanted to give it a try and see how it goes 😉

    Check out my Argo CD GitOps repository: DonaldKellett/my-ascend-gitops

    Argo CD login page
    Argo CD dashboard

    Rancher system-upgrade-controller for managing Kubernetes upgrades

    While K3s is easy to upgrade manually, it’s better to automate it for more consistent and reliable results. Rancher provides a system-upgrade-controller to manage K3s upgrades automatically via Plan custom resources.

    An added benefit of managing K3s upgrades with Plan custom resources is that it can be managed declaratively via GitOps and the current running K3s version v1.35.5+k3s1 is explicitly documented in the GitOps repository.

    Bitnami Sealed Secrets for secrets management

    A major pain point of implementing GitOps without a proper secrets management solution is that:

    1. Either the base64-encoded Kubernetes secrets are pushed directly to the GitOps repository which is as good as publishing them in plaintext, or
    2. The Kubernetes secrets are omitted from the GitOps repository with no additional offsite copy in case the cluster is unavailable or compromised

    There are 2 mainstream solutions for managing Kubernetes secrets in production.

    1. External Secrets Operator (ESO): delegates secrets to an external secrets provider outside Kubernetes such as AWS KMSAzure Key Vault and HashiCorp Vault / OpenBao
    2. Bitnami Sealed Secrets: automatically manages the lifecycle of encryption keys in Kubernetes and uses them to encrypt Kubernetes secrets via SealedSecret custom resources

    Since I want my AI homelab to be as self-contained as possible with minimal dependency on external services, Sealed Secrets was the most appropriate option for my use case. Instead of creating Kubernetes secrets directly on the cluster, the Secret manifest is generated on the client side only and passed to the kubeseal CLI to generate the corresponding SealedSecret containing the encrypted secret. The SealedSecret is then pushed to the GitOps repository which can only be decrypted with the pre-existing keys on our local cluster and the custom resource owns the corresponding Kubernetes secret after decryption.

    cert-manager for TLS certificate management

    cert-manager is the de-facto solution for managing TLS certificates in Kubernetes. No other solution comes close 😉

    Without cert-manager, the flow for generating signed TLS certificates for HTTPS is manual and error-prone.

    1. Generate a root CA certificate-key pair with the OpenSSL CLI openssl and store it safely. This only needs to be done once
    2. Use openssl to generate a TLS certificate-key pair for our web server manually, valid for the list of DNS hostnames and IP addresses under the Subject Alternative Name (SAN) field
    3. Create a Kubernetes TLS secret manually containing the web server certificate-key pair in (2)
    4. Reference the Kubernetes TLS secret in (3) in the corresponding Ingress resource

    The openssl CLI is known for its complexity and verbosity with many configurable options. I still can’t remember the exact options available and have to ~~ask Gemini~~ Google search to recall the exact command line options used (-:

    It’s also easy to silently omit a critical option such as forgetting to include the SAN, in which case the web server simply refuses to present the TLS certificate leading to vague errors which are difficult to diagnose and troubleshoot.

    With cert-manager, I just generate the root CA-key pair once and use it to define my ClusterIssuer. With the ClusterIssuer defined, I can request TLS Certificates through custom resources referencing my ClusterIssuer and get the corresponding TLS secret automatically and ready for use.

    With external-facing production services, cert-manager can also automate ACME challenges paired with ExternalDNS to request and sign certificates from a trusted provider such as Let’s Encrypt. Since my AI homelab is only available internally, I decided Let’s Encrypt certificates would be overkill and manually defining my ClusterIssuer with my custom root CA was sufficient for my use case.

    ExternalDNS for managing DNS within my home network

    The default CoreDNS instance is only available within Kubernetes for intra-cluster DNS resolution. Without ExternalDNS integration with a supported provider such as Amazon Route 53 or Cloudflare DNS, DNS records for services exposed via Ingress or Gateway API resources must be created manually for external users to reach them properly.

    With the goal of making my homelab self-sufficient, relying on an external DNS provider did not make sense and would only increase the cost and operational complexity. Fortunately, ExternalDNS supports CoreDNS with etcd backend as an “external” DNS provider for self-hosted setups.

    Instead of modifying the existing in-cluster CoreDNS and Kubernetes etcd backend, separate CoreDNS and etcd instances were deployed to a dedicated namespace external-dns for serving “external” DNS traffic within my home network. My setup is based on the official CoreDNS with etcd backend tutorial with the below modifications.

    1. Deploy to external-dns namespace instead of default
    2. Remove the etcd NodePort service since it’s exposed in the tutorial for testing purposes only
    3. Expose the “external” CoreDNS as a LoadBalancer service with the default port 53/udp. This allows other devices on my home network such as my Redmi Book 14 laptop running Fedora Workstation 44 to use it to resolve hostnames of the form *.internal.donaldsebleung.com generated by ExternalDNS

    To allow my laptop to seamlessly access the services from my AI homelab while ensuring uninterrupted Internet access even when my NucBox K11 is powered off, I configured a split-horizon DNS setup on my laptop via the drop-in configuration file /etc/systemd/resolved.conf.d/99-split-dns.conf shown below.

    [Resolve]
    DNS=192.168.0.125
    Domains=~internal.donaldsebleung.com

    This instructs systemd-resolved to query the “external” CoreDNS running on my NucBox K11 for lab addresses ending in internal.donaldsebleung.com while retaining the default DHCP-provided DNS configuration for Internet DNS queries. The output from resolvectl status is shown below.

    Global
    Protocols: LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported
    resolv.conf mode: stub
    Current DNS Server: 192.168.0.125
    DNS Servers: 192.168.0.125
    DNS Domain: ~internal.donaldsebleung.com
    Link 2 (wlp0s20f3)
    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
    Protocols: +DefaultRoute LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported
    Current DNS Server: 192.168.0.1
    DNS Servers: 192.168.0.1
    Default Route: yes

    JupyterHub for self-service notebook provisioning

    All the services mentioned so far are core infrastructure components which do not directly enable me to provision Jupyter notebooks on demand. For that, I chose JupyterHub which is directly supported by the upstream Jupyter project. The Kubernetes distribution of JupyterHub is also known as Zero to JupyterHub with Kubernetes (Z2JH).

    A major advantage of JupyterHub is that it’s dedicated to provisioning standardized, reproducible notebook environments and nothing else which is exactly what I need. This keeps my setup lightweight and resource-efficient, leaving more headroom for my actual deep learning workloads.

    In contrast, Kubeflow provides services encompassing the entire MLOps lifecycle including a model registry, model serving with KServe and KFP for running distributed training pipelines, none of which I need at the moment. It’s also very heavyweight and requires special attention to deploy in a production-ready configuration as opposed to a one-off demo. That’s why I decided to go with JupyterHub as opposed to Kubeflow in the end.

    JupyterHub login page
    JupyterHub PyTorch CPU-only notebook

    Concluding remarks and going further

    Setting up this AI homelab was great fun and actually useful for supporting my MLOps and deep learning journey as opposed to the one-off demos I’ve been used to over the past few years. The only issue is that I can only train simple neural networks like LeNet without hardware acceleration provided by the AI Studio Pro extension dock. This means I will have to wait until the extension dock is available to run interesting AI/ML workloads relevant to modern deep learning.

    Once my AI Studio Pro arrives, my next steps would be to:

    1. Install the Ascend Device Plugin and Ascend Docker Runtime from Huawei’s MindCluster project to manage the Ascend 310P4 NPUs in Kubernetes
    2. Create custom notebook images with MindSpore and CANN pre-installed and update JupyterHub to allow selecting various notebook images and resource specifications
    3. With the previous steps complete, continue on my MLOps and deep learning journey following the remaining chapters in the D2L textbook

    I hope you enjoyed reading this blog post as much as I did authoring it and stay tuned for updates! 😉

    + , , , , , , ,
  • The source code for this article is available on: GitHubGitCode.

    Kubeflow transforms Kubernetes into a self-service platform for AI practitioners and data scientists alike. It incorporates both established and emerging cloud and AI-native projects such as IstioEnvoy and Knative to support the entire MLOps lifecycle: data cleaning and preprocessing, model training, validation and serving etc. Originally developed by Google to run TensorFlow on Kubernetes, it is now a CNCF Incubating project.

    Kubeflow Community Distribution (KCD) is the official community version of Kubeflow designed to run on vanilla Kubernetes. It is available as a Kustomization which can be installed manually with kubectl or declaratively via GitOps with Argo CD or Flux.

    Follow me through this article as we bootstrap Kubeflow on K3s with GPU support, leveraging the App of Apps pattern with Argo CD to deploy KCD 26.03.1 together with NVIDIA GPU Operator 26.3.2 and validating our installation with a GPU-enabled PyTorch notebook.

    Prerequisites

    Proficiency with Linux and Kubernetes is assumed. Familiarity with AI/ML-related concepts and tools such as Jupyter notebooks, Python programming and PyTorch is recommended but not required.

    Lab environment

    The instructions in this lab were validated on Huawei Cloud with a standalone pi2.2xlarge.4 Elastic Cloud Server (ECS) instance. The ECS instance had 8 vCPUs and 32G memory with a single 128G system disk and 1 NVIDIA Tesla T4 datacenter GPU.

    The operating system image is based on Ubuntu 22.04 LTS (Jammy Jellyfish). All commands were executed directly as the root user.

    Preparing our node for Kubeflow

    The following steps were performed to ensure our ECS instance runs Kubeflow smoothly.

    Increase the inotify resource limits

    By default, the fs.inotify.max_user_instances sysctl is set to 128 which is quickly exhausted when multiple pods are deployed on the same node. We increase it to 8192 along with a related option fs.inotify.max_user_watches which is also increased from around 250k to 1Mi.

    Add the following lines to /etc/sysctl.d/99-increase-inotify-limits.conf and reload them with sysctl --system.

    fs.inotify.max_user_instances=8192
    fs.inotify.max_user_watches=1048576

    Install Go 1.26.4

    Go is required to build and deploy the Argo CD Operator from source. Version 0.18.0 of the operator is the latest version at the time of writing which supports building with Go 1.26.

    Follow the official instructions to download and install Go on Linux. Ensure /usr/local/go/bin is in your PATH.

    pushd $(mktemp -d)
    wget https://go.dev/dl/go1.26.4.linux-amd64.tar.gz
    rm -rf /usr/local/go && tar -C /usr/local -xzf go1.26.4.linux-amd64.tar.gz
    echo "export PATH=\$PATH:/usr/local/go/bin" | tee "$HOME/.profile"
    source "$HOME/.profile"
    popd

    Update the NVIDIA drivers and load the UVM module

    Modern versions of CUDA starting from 12.x require NVIDIA driver versions 5xx and above. Our ECS instance had the deprecated NVIDIA driver version 4xx installed which is not supported by CUDA 12.x / 13.x and causes the CUDA validation step in the NVIDIA GPU Operator deployment to fail.

    Uninstall all outdated NVIDIA drivers with the command below.

    apt purge -y '*nvidia*' && apt autoremove --purge -y

    Now install the latest supported drivers with ubuntu-drivers autoinstall.

    ubuntu-drivers autoinstall

    For the NVIDIA GPU Operator to work properly, we also need to load the Unified Virtual Memory (UVM) module. Configure the module to load on system boot by creating a file /etc/modules-load.d/99-nvidia-uvm.conf with the following content.

    nvidia-uvm

    Reboot the system to take effect. Ensure the module is loaded by verifying that the below command returns at least 1 non-empty line of output.

    lsmod | grep nvidia_uvm

    Installing K3s and increasing the pod limit

    K3s is a lightweight Kubernetes distribution optimized for edge environments. We’ll use K3s for our lab since it’s dead simple to install and get running on a single server.

    Install version v1.35.5+k3s1 of K3s with the official installer. We’ll also increase the per-node pod limit from 110 to 250 since a fresh Kubeflow installation alone consists of approximately 70 pods.

    curl -sfL https://get.k3s.io | \
    INSTALL_K3S_VERSION="v1.35.5+k3s1" sh -s - server \
    --kubelet-arg="max-pods=250"

    Now wait for our node to become ready.

    kubectl wait \
    --for=condition=Ready \
    node \
    --all \
    --timeout=300s

    Deploying the Argo CD Operator and cluster-wide Argo CD instance

    The Argo CD Operator enables us to define Argo CD instances declaratively as Kubernetes custom resources. We’ll deploy v0.18.0 of the operator directly from the GitHub repository: argoproj-labs/argocd-operator

    Clone version v0.18.0 of the operator and deploy it with make deploy.

    git clone -b v0.18.0 https://github.com/argoproj-labs/argocd-operator.git
    pushd argocd-operator/
    make deploy

    By default, each Argo CD instance is scoped to its own namespace. Since we’re installing both the NVIDIA GPU Operator and Kubeflow as platform components, let’s set the ARGOCD_CLUSTER_CONFIG_NAMESPACES=argocd environment variable on our operator workload. The variable instructs the Argo CD Operator to treat the Argo CD instance in the argocd namespace as a cluster-wide instance, allowing it to manage cluster-scoped resources such as ClusterRoles and ClusterRoleBindings. We’ll deploy our cluster-wide Argo CD instance in a later step.

    kubectl -n argocd-operator-system set env \
    deploy/argocd-operator-controller-manager \
    ARGOCD_CLUSTER_CONFIG_NAMESPACES=argocd \
    -c manager

    Wait for our operator deployment to become ready.

    kubectl -n argocd-operator-system wait \
    --for=condition=Available \
    deploy/argocd-operator-controller-manager \
    --timeout=300s

    Create our argocd namespace and declare our cluster-wide Argo CD instance. The default configuration should suffice so we leave the spec empty.

    kubectl create ns argocd
    kubectl -n argocd create -f - << EOF
    ---
    apiVersion: argoproj.io/v1beta1
    kind: ArgoCD
    metadata:
    name: argocd
    spec: {}
    EOF

    Wait for the cluster Argo CD instance to be reconciled and its workloads to be available.

    kubectl -n argocd wait \
    --for=condition=Reconciled \
    argocd.argoproj.io/argocd \
    --timeout=300s
    kubectl -n argocd wait \
    --for=condition=Available \
    deploy \
    --all \
    --timeout=300s

    Leave the project directory.

    popd

    Bootstrapping Kubeflow with GPU support using the App of Apps pattern

    The App of Apps pattern is the practice of defining a parent Argo CD application which manages 0 or more child Argo CD applications. The parent application is managed by the platform team which oversees the entire Kubernetes environment. Each child application represents a deliverable unit or workload. It represents either an individual platform component owned by the respective infrastructure team or a self-contained application comprised of a collection of microservices owned by the respective application team.

    For example:

    1. The parent application argocd-apps is managed by the platform engineering team which oversees the entire Kubernetes infrastructure
    2. A child application cilium manages the Cilium CNI critical to cluster operations. It is managed by the network team
    3. Another child application tekton manages Tekton which powers the developers’ CI/CD pipelines. It is managed by the DevOps team
    4. 2 child applications, bookinfo and star-wars, manage the Bookinfo and Star Wars applications respectively, each in their own dedicated namespace. They are managed by 2 separate application teams with each team responsible for their own app

    Here, we employ the App of Apps pattern to bootstrap 2 platform components for our quick demo.

    1. NVIDIA GPU Operator: enables Kubernetes workloads to request GPUs for model training and inference
    2. Kubeflow: an open source platform enabling self-service for AI/ML practitioners and data scientists alike

    Clone the GitHub repository and make it our working directory: DonaldKellett/kubeflow-gitops-demo

    git clone https://github.com/DonaldKellett/kubeflow-gitops-demo.git
    pushd kubeflow-gitops-demo/

    Build the Kustomization under bootstrap/overlays/v1/ and deploy the generated manifests to the argocd namespace using server-side apply.

    kubectl kustomize bootstrap/overlays/v1/ | \
    kubectl -n argocd apply -f - --server-side

    Wait at most 30 minutes for both components to report as Healthy. Due to a known issue kubeflow/community-distribution#3205, the metadata-grpc-deployment workload in the kubeflow namespace may be stuck in a CrashLoopBackOff state, causing our kubeflow application to remain stuck in the Degraded state indefinitely.

    As long as the metadata-grpc-deployment is the only workload with this issue, it should not affect our quick demo with a GPU-enabled PyTorch notebook as our final validation step. Nevertheless, if it bothers you, consider fixing it manually or simply tearing down and re-creating the lab environment from scratch.

    kubectl -n argocd wait \
    --for=jsonpath='{.status.health.status}'=Healthy \
    applications.argoproj.io \
    --all \
    --timeout=1800s

    Logging in to the Kubeflow dashboard

    With our Kubeflow platform ready, follow the official instructions in kubeflow/community-distribution. Use kubectl port-forward to expose the Kubeflow dashboard at port 8080/tcp.

    kubectl port-forward svc/istio-ingressgateway -n istio-system 8080:80

    Visit http://localhost:8080/ which displays the Kubeflow landing page.

    Kubeflow landing page

    Click the “Sign in with Dex” button and fill in the default login credentials below.

    1. Username: user@example.com
    2. Password: 12341234
    Kubeflow login page

    You are redirected to the Kubeflow dashboard. Congratulations on getting Kubeflow up and running!

    Kubeflow dashboard

    Validating our installation with a GPU-enabled PyTorch notebook

    Let’s create a Kubeflow notebook with PyTorch and CUDA installed. CUDA enables us to leverage NVIDIA GPUs in our PyTorch deep learning experiments to speed up model training and inference.

    Inspect the sample Notebook custom resource and the corresponding workspace PVC under samples/pytorch-gpu-example.yaml. It creates the Notebook resource and PVC under the kubeflow-user-example-com data science project (namespace) owned by the user@example.com user.

    Notice the nvidia.com/gpu=1 field under .spec.template.spec.containers[].resources.{requests,limits} which requests 1 NVIDIA GPU from our Kubernetes cluster. This enables our PyTorch notebook with CUDA installed to access the underlying GPU hardware resource.

    ---
    apiVersion: kubeflow.org/v1
    kind: Notebook
    metadata:
    name: pytorch-gpu-example
    namespace: kubeflow-user-example-com
    spec:
    template:
    spec:
    containers:
    - name: pytorch-gpu-example
    image: ghcr.io/kubeflow/kubeflow/notebook-servers/jupyter-pytorch-cuda:v1.11.0
    resources:
    requests:
    cpu: "2"
    memory: 8Gi
    nvidia.com/gpu: "1"
    limits:
    cpu: "2"
    memory: 8Gi
    nvidia.com/gpu: "1"
    env:
    - name: NOTEBOOK_ARGS
    value: |-
    --ServerApp.port=8888
    --ServerApp.token=''
    --ServerApp.password=''
    --ServerApp.base_url=/notebook/kubeflow-user-example-com/pytorch-gpu-example
    --ServerApp.quit_button=False
    volumeMounts:
    - name: pytorch-gpu-example-volume
    mountPath: /home/jovyan
    readinessProbe:
    httpGet:
    path: /notebook/kubeflow-user-example-com/pytorch-gpu-example/api
    port: notebook-port
    livenessProbe:
    httpGet:
    path: /notebook/kubeflow-user-example-com/pytorch-gpu-example/api
    port: notebook-port
    ports:
    - containerPort: 8888
    name: notebook-port
    volumes:
    - name: pytorch-gpu-example-volume
    persistentVolumeClaim:
    claimName: pytorch-gpu-example-pvc
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: pytorch-gpu-example-pvc
    namespace: kubeflow-user-example-com
    spec:
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
    storage: 10Gi

    Deploy it to our cluster.

    kubectl create -f samples/pytorch-gpu-example.yaml

    Now wait at most 15 minutes for our notebook to be ready. The notebook image is a few GiB in size so the initial pull may take around 5 minutes to complete depending on your network bandwidth and Docker Hub rate limits.

    kubectl -n kubeflow-user-example-com wait \
    --for=condition=Ready \
    pod/pytorch-gpu-example-0 \
    --timeout=900s

    Visit http://localhost:8080/notebook/kubeflow-user-example-com/pytorch-gpu-example/ in your browser, then upload the sample notebook samples/00-pytorch-gpu-example.ipynb to the JupyterLab UI which contains the following Python code written with PyTorch.

    import torch
    has_gpu = torch.cuda.is_available()
    print(f'GPU acceleration is{'' if has_gpu else ' NOT'} available in this notebook!')
    device = torch.device('cuda') if has_gpu else torch.device('cpu')
    A = torch.randn(2, 2, device=device)
    B = torch.randn(2, 2, device=device)
    C = A @ B
    C, C.device
    GPU-enabled PyTorch notebook

    Click the Run button to the top left of the window and you should get the following output. The exact numbers may vary between consecutive runs.

    GPU acceleration is available in this notebook!
    (tensor([[-0.2708, -1.2782],
    [ 1.0428, 4.2339]], device='cuda:0'),
    device(type='cuda', index=0))

    Congratulations, you created your first PyTorch deep learning experiment with GPU acceleration enabled!

    Exit the project directory.

    popd

    Demo

    View the demo on Asciinema.

    A command-line walkthrough of this lab is included below.

    Concluding remarks and going further

    Kubeflow is the de-facto standard for managing the entire MLOps lifecycle on Kubernetes. Nevertheless, given the weight and complexity of Kubeflow, it may not be wise to deploy and manage upstream Kubeflow directly for production teams and workloads.

    To convert this quick demo into a production-ready Kubeflow deployment, consider:

    1. Securing the Kubeflow dashboard with TLS
    2. Configuring enterprise authentication and RBAC for proper multi-tenancy
    3. Upgrade to a vendor-backed distribution of Kubeflow such as Charmed Kubeflow or Red Hat OpenShift AI (RHOAI). Their enterprise support options free your MLOps and data science teams from the undifferentiated heavy lifting of managing Kubeflow itself, enabling them to focus on the actual AI/ML workloads which deliver actual business value

    I hope you enjoyed following through this article as much as I did authoring it and stay tuned for updates 😉

    + , , , , , , , ,
  • The notebook source code for this experiment is available on GitHub.

    MLflow is the largest open source AI engineering platform for agents, LLMs, and ML models.” It was originally developed by Databricks and joined the Linux Foundation in June 2020.

    MLflow enables data scientists and ML engineers to manage and visualize their model training pipelines through a unified platform. At the heart of MLflow are 2 key concepts.

    1. Experiment: a collection of model training pipelines useful for cross-evaluating the performance of different models and hyperparameters on the the same problem domain. For example, an experiment called fashion-mnist-linear compares the performance of training the same linear classifier with varying learning rates.
    2. Run: a single instance of a model training pipeline within an experiment. For example, our first run in fashion-mnist-linear trains a linear classifier with a learning rate of 0.01.

    MLflow enables tracking the hyperparameters selected and metrics generated in each run through 2 key components.

    1. MLflow Tracking Server: the server-side component that stores and visualizes the data. It can be deployed as a standalone server with pipx / uvx, as a Docker container or on Kubernetes.
    2. MLflow client: provided through the mlflow Python package, it allows model training pipelines to connect to an MLflow tracking server and log hyperparameters, metrics and ONNX models.

    Follow me through this notebook experiment as we deploy our first MLflow tracking server with Docker and create our first experiment with 2 runs, allowing us to visualize and compare the effects of tuning the learning rate on training our linear classifier with the Fashion MNIST dataset.

    Prerequisites

    For the optimal experience, familiarity with Linux, Python, Jupyter, and key ML concepts such as would be had from going through the first 4 chapters of D2L is recommended.

    Hardware and software used in this lab

    This notebook experiment was tested on the OrangePi AIpro (20T) development board featuring a single Ascend 310B NPU device.

    The software versions used in this notebook are listed below.

    1. Ubuntu 22.04 LTS
    2. Python 3.12
    3. MindSpore 2.9.0
    4. CANN 9.0.0
    5. MLflow 3.13.0
    6. ONNX 1.21.0
    7. ONNX Runtime 1.26.0
    !npu-smi info
    +--------------------------------------------------------------------------------------------------------+
    | npu-smi 23.0.0 Version: 23.0.0 |
    +-------------------------------+-----------------+------------------------------------------------------+
    | NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page) |
    | Chip Device | Bus-Id | AICore(%) Memory-Usage(MB) |
    +===============================+=================+======================================================+
    | 0 310B1 | Alarm | 0.0 50 15 / 15 |
    | 0 0 | NA | 0 5840 / 23673 |
    +===============================+=================+======================================================+
    !cat requirements.txt
    absl-py==2.4.0
    attrs==26.1.0
    cloudpickle==3.1.2
    decorator==5.2.1
    jupyterlab==4.5.7
    jupyterlab-git==0.53.0
    jupyter-resource-usage==1.2.1
    loguru==0.7.3
    matplotlib==3.10.9
    mindspore==2.9.0
    mlflow==3.13.0
    ml-dtypes==0.5.4
    msguard==0.0.8
    onnx==1.21.0
    onnxruntime==1.26.0
    openpyxl==3.1.5
    opentelemetry-exporter-otlp-proto-grpc==1.33.1
    opentelemetry-exporter-otlp-proto-http==1.33.1
    pandas~=2.2
    plotly>=5.11.0
    pydantic==2.13.4
    sympy==1.14.0
    tornado==6.5.5
    %pip install -r requirements.txt
    Requirement already satisfied: absl-py==2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 1)) (2.4.0)
    Requirement already satisfied: attrs==26.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 2)) (26.1.0)
    Requirement already satisfied: cloudpickle==3.1.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 3)) (3.1.2)
    Requirement already satisfied: decorator==5.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 4)) (5.2.1)
    Requirement already satisfied: jupyterlab==4.5.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 5)) (4.5.7)
    Requirement already satisfied: jupyterlab-git==0.53.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 6)) (0.53.0)
    Requirement already satisfied: jupyter-resource-usage==1.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 7)) (1.2.1)
    Requirement already satisfied: loguru==0.7.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 8)) (0.7.3)
    Requirement already satisfied: matplotlib==3.10.9 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 9)) (3.10.9)
    Requirement already satisfied: mindspore==2.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 10)) (2.9.0)
    Requirement already satisfied: mlflow==3.13.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 11)) (3.13.0)
    Requirement already satisfied: ml-dtypes==0.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 12)) (0.5.4)
    Requirement already satisfied: msguard==0.0.8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 13)) (0.0.8)
    Requirement already satisfied: onnx==1.21.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 14)) (1.21.0)
    Requirement already satisfied: onnxruntime==1.26.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 15)) (1.26.0)
    Requirement already satisfied: openpyxl==3.1.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 16)) (3.1.5)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-grpc==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 17)) (1.33.1)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-http==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 18)) (1.33.1)
    Requirement already satisfied: pandas~=2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 19)) (2.3.3)
    Requirement already satisfied: plotly>=5.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 20)) (6.8.0)
    Requirement already satisfied: pydantic==2.13.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 21)) (2.13.4)
    Requirement already satisfied: sympy==1.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 22)) (1.14.0)
    Requirement already satisfied: tornado==6.5.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 23)) (6.5.5)
    Requirement already satisfied: async-lru>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.3.0)
    Requirement already satisfied: httpx<1,>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.28.1)
    Requirement already satisfied: ipykernel!=6.30.0,>=6.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (7.2.0)
    Requirement already satisfied: jinja2>=3.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.1.6)
    Requirement already satisfied: jupyter-core in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (5.9.1)
    Requirement already satisfied: jupyter-lsp>=2.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.3.1)
    Requirement already satisfied: jupyter-server<3,>=2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.19.0)
    Requirement already satisfied: jupyterlab-server<3,>=2.28.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.28.0)
    Requirement already satisfied: notebook-shim>=0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.4)
    Requirement already satisfied: packaging in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (26.2)
    Requirement already satisfied: setuptools>=41.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (82.0.1)
    Requirement already satisfied: traitlets in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (5.15.1)
    Requirement already satisfied: jupyterlab-git-core>=0.52.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (0.53.0)
    Requirement already satisfied: prometheus-client in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 7)) (0.25.0)
    Requirement already satisfied: psutil>=5.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 7)) (7.2.2)
    Requirement already satisfied: pyzmq>=19 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 7)) (27.1.0)
    Requirement already satisfied: contourpy>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (1.3.3)
    Requirement already satisfied: cycler>=0.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (0.12.1)
    Requirement already satisfied: fonttools>=4.22.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (4.63.0)
    Requirement already satisfied: kiwisolver>=1.3.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (1.5.0)
    Requirement already satisfied: numpy>=1.23 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (1.26.4)
    Requirement already satisfied: pillow>=8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (12.2.0)
    Requirement already satisfied: pyparsing>=3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (3.3.2)
    Requirement already satisfied: python-dateutil>=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (2.9.0.post0)
    Requirement already satisfied: protobuf>=3.13.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (5.29.6)
    Requirement already satisfied: asttokens>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (3.0.1)
    Requirement already satisfied: scipy>=1.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (1.17.1)
    Requirement already satisfied: astunparse>=1.6.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (1.6.3)
    Requirement already satisfied: safetensors>=0.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (0.7.0)
    Requirement already satisfied: dill>=0.3.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (0.4.1)
    Requirement already satisfied: mlflow-skinny==3.13.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (3.13.0)
    Requirement already satisfied: mlflow-tracing==3.13.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (3.13.0)
    Requirement already satisfied: Flask-CORS<7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (6.0.3)
    Requirement already satisfied: Flask<4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (3.1.3)
    Requirement already satisfied: aiohttp<4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (3.14.0)
    Requirement already satisfied: alembic!=1.10.0,<2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (1.18.4)
    Requirement already satisfied: cryptography<49,>=43.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (48.0.0)
    Requirement already satisfied: docker<8,>=4.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (7.1.0)
    Requirement already satisfied: graphene<4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (3.4.3)
    Requirement already satisfied: gunicorn<27 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (26.0.0)
    Requirement already satisfied: huey<4,>=2.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (3.0.1)
    Requirement already satisfied: pyarrow<25,>=4.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (24.0.0)
    Requirement already satisfied: scikit-learn<2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (1.9.0)
    Requirement already satisfied: skops<1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (0.14.0)
    Requirement already satisfied: sqlalchemy<3,>=1.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow==3.13.0->-r requirements.txt (line 11)) (2.0.50)
    Requirement already satisfied: typing_extensions>=4.7.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from onnx==1.21.0->-r requirements.txt (line 14)) (4.15.0)
    Requirement already satisfied: flatbuffers in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from onnxruntime==1.26.0->-r requirements.txt (line 15)) (25.12.19)
    Requirement already satisfied: et-xmlfile in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from openpyxl==3.1.5->-r requirements.txt (line 16)) (2.0.0)
    Requirement already satisfied: deprecated>=1.2.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (1.3.1)
    Requirement already satisfied: googleapis-common-protos~=1.52 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (1.75.0)
    Requirement already satisfied: grpcio<2.0.0,>=1.63.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (1.81.0)
    Requirement already satisfied: opentelemetry-api~=1.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (1.33.1)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-common==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (1.33.1)
    Requirement already satisfied: opentelemetry-proto==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (1.33.1)
    Requirement already satisfied: opentelemetry-sdk~=1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (1.33.1)
    Requirement already satisfied: requests~=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 18)) (2.34.2)
    Requirement already satisfied: annotated-types>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 21)) (0.7.0)
    Requirement already satisfied: pydantic-core==2.46.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 21)) (2.46.4)
    Requirement already satisfied: typing-inspection>=0.4.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 21)) (0.4.2)
    Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from sympy==1.14.0->-r requirements.txt (line 22)) (1.3.0)
    Requirement already satisfied: cachetools<8,>=5.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (7.1.4)
    Requirement already satisfied: click<9,>=7.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (8.4.1)
    Requirement already satisfied: databricks-sdk<1,>=0.20.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (0.114.0)
    Requirement already satisfied: fastapi<1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (0.136.3)
    Requirement already satisfied: gitpython<4,>=3.1.9 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (3.1.50)
    Requirement already satisfied: importlib_metadata!=4.7.0,<10,>=3.7.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (8.6.1)
    Requirement already satisfied: python-dotenv<2,>=0.19.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (1.2.2)
    Requirement already satisfied: pyyaml<7,>=5.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (6.0.3)
    Requirement already satisfied: sqlparse<1,>=0.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (0.5.5)
    Requirement already satisfied: starlette<2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (1.2.1)
    Requirement already satisfied: uvicorn<1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (0.49.0)
    Requirement already satisfied: pytz>=2020.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pandas~=2.2->-r requirements.txt (line 19)) (2026.2)
    Requirement already satisfied: tzdata>=2022.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pandas~=2.2->-r requirements.txt (line 19)) (2026.2)
    Requirement already satisfied: narwhals>=1.15.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from plotly>=5.11.0->-r requirements.txt (line 20)) (2.22.1)
    Requirement already satisfied: aiohappyeyeballs>=2.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from aiohttp<4->mlflow==3.13.0->-r requirements.txt (line 11)) (2.6.2)
    Requirement already satisfied: aiosignal>=1.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from aiohttp<4->mlflow==3.13.0->-r requirements.txt (line 11)) (1.4.0)
    Requirement already satisfied: frozenlist>=1.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from aiohttp<4->mlflow==3.13.0->-r requirements.txt (line 11)) (1.8.0)
    Requirement already satisfied: multidict<7.0,>=4.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from aiohttp<4->mlflow==3.13.0->-r requirements.txt (line 11)) (6.7.1)
    Requirement already satisfied: propcache>=0.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from aiohttp<4->mlflow==3.13.0->-r requirements.txt (line 11)) (0.5.2)
    Requirement already satisfied: yarl<2.0,>=1.17.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from aiohttp<4->mlflow==3.13.0->-r requirements.txt (line 11)) (1.24.2)
    Requirement already satisfied: Mako in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from alembic!=1.10.0,<2->mlflow==3.13.0->-r requirements.txt (line 11)) (1.3.12)
    Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.9.0->-r requirements.txt (line 10)) (0.47.0)
    Requirement already satisfied: six<2.0,>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.9.0->-r requirements.txt (line 10)) (1.17.0)
    Requirement already satisfied: cffi>=2.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from cryptography<49,>=43.0.0->mlflow==3.13.0->-r requirements.txt (line 11)) (2.0.0)
    Requirement already satisfied: wrapt<3,>=1.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from deprecated>=1.2.6->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (2.2.1)
    Requirement already satisfied: urllib3>=1.26.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from docker<8,>=4.0.0->mlflow==3.13.0->-r requirements.txt (line 11)) (2.7.0)
    Requirement already satisfied: blinker>=1.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from Flask<4->mlflow==3.13.0->-r requirements.txt (line 11)) (1.9.0)
    Requirement already satisfied: itsdangerous>=2.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from Flask<4->mlflow==3.13.0->-r requirements.txt (line 11)) (2.2.0)
    Requirement already satisfied: markupsafe>=2.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from Flask<4->mlflow==3.13.0->-r requirements.txt (line 11)) (3.0.3)
    Requirement already satisfied: werkzeug>=3.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from Flask<4->mlflow==3.13.0->-r requirements.txt (line 11)) (3.1.8)
    Requirement already satisfied: graphql-core<3.3,>=3.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from graphene<4->mlflow==3.13.0->-r requirements.txt (line 11)) (3.2.11)
    Requirement already satisfied: graphql-relay<3.3,>=3.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from graphene<4->mlflow==3.13.0->-r requirements.txt (line 11)) (3.2.0)
    Requirement already satisfied: anyio in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.13.0)
    Requirement already satisfied: certifi in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2026.5.20)
    Requirement already satisfied: httpcore==1.* in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.0.9)
    Requirement already satisfied: idna in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.18)
    Requirement already satisfied: h11>=0.16 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.16.0)
    Requirement already satisfied: comm>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: debugpy>=1.6.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.8.21)
    Requirement already satisfied: ipython>=7.23.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (9.14.1)
    Requirement already satisfied: jupyter-client>=8.8.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (8.9.0)
    Requirement already satisfied: matplotlib-inline>=0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.2)
    Requirement already satisfied: nest-asyncio>=1.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.6.0)
    Requirement already satisfied: platformdirs>=2.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-core->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.10.0)
    Requirement already satisfied: argon2-cffi>=21.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: jupyter-events>=0.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.12.1)
    Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.5.4)
    Requirement already satisfied: nbconvert>=6.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (7.17.1)
    Requirement already satisfied: nbformat>=5.3.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (5.10.4)
    Requirement already satisfied: send2trash>=1.8.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.1.0)
    Requirement already satisfied: terminado>=0.8.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.18.1)
    Requirement already satisfied: websocket-client>=1.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.9.0)
    Requirement already satisfied: pexpect in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core>=0.52.0->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (4.9.0)
    Requirement already satisfied: nbdime~=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (4.0.4)
    Requirement already satisfied: babel>=2.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.18.0)
    Requirement already satisfied: json5>=0.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.14.0)
    Requirement already satisfied: jsonschema>=4.18.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.26.0)
    Requirement already satisfied: opentelemetry-semantic-conventions==0.54b1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-sdk~=1.33.1->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 17)) (0.54b1)
    Requirement already satisfied: charset_normalizer<4,>=2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests~=2.7->opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 18)) (3.4.7)
    Requirement already satisfied: joblib>=1.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from scikit-learn<2->mlflow==3.13.0->-r requirements.txt (line 11)) (1.5.3)
    Requirement already satisfied: threadpoolctl>=3.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from scikit-learn<2->mlflow==3.13.0->-r requirements.txt (line 11)) (3.6.0)
    Requirement already satisfied: prettytable>=3.9 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from skops<1->mlflow==3.13.0->-r requirements.txt (line 11)) (3.17.0)
    Requirement already satisfied: greenlet>=1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from sqlalchemy<3,>=1.4.0->mlflow==3.13.0->-r requirements.txt (line 11)) (3.5.1)
    Requirement already satisfied: argon2-cffi-bindings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: pycparser in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from cffi>=2.0.0->cryptography<49,>=43.0.0->mlflow==3.13.0->-r requirements.txt (line 11)) (3.0)
    Requirement already satisfied: google-auth~=2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from databricks-sdk<1,>=0.20.0->mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (2.53.0)
    Requirement already satisfied: annotated-doc>=0.0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from fastapi<1->mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (0.0.4)
    Requirement already satisfied: gitdb<5,>=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitpython<4,>=3.1.9->mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (4.0.12)
    Requirement already satisfied: zipp>=3.20 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from importlib_metadata!=4.7.0,<10,>=3.7.0->mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (4.1.0)
    Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.1.1)
    Requirement already satisfied: jedi>=0.18.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.20.0)
    Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.0.52)
    Requirement already satisfied: pygments>=2.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.20.0)
    Requirement already satisfied: stack_data>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.6.3)
    Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2025.9.1)
    Requirement already satisfied: referencing>=0.28.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.37.0)
    Requirement already satisfied: rpds-py>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2026.5.1)
    Requirement already satisfied: python-json-logger>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.1.0)
    Requirement already satisfied: rfc3339-validator in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.1.4)
    Requirement already satisfied: rfc3986-validator>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.1.1)
    Requirement already satisfied: beautifulsoup4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.14.3)
    Requirement already satisfied: bleach!=5.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (6.4.0)
    Requirement already satisfied: defusedxml in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.7.1)
    Requirement already satisfied: jupyterlab-pygments in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.3.0)
    Requirement already satisfied: mistune<4,>=2.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.2.1)
    Requirement already satisfied: nbclient>=0.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.11.0)
    Requirement already satisfied: pandocfilters>=1.4.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: colorama in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (0.4.6)
    Requirement already satisfied: fastjsonschema>=2.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbformat>=5.3.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.21.2)
    Requirement already satisfied: ptyprocess>=0.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pexpect->jupyterlab-git-core>=0.52.0->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (0.7.0)
    Requirement already satisfied: wcwidth in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from prettytable>=3.9->skops<1->mlflow==3.13.0->-r requirements.txt (line 11)) (0.8.0)
    Requirement already satisfied: webencodings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.5.1)
    Requirement already satisfied: tinycss2>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: smmap<6,>=3.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitdb<5,>=4.0.1->gitpython<4,>=3.1.9->mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (5.0.3)
    Requirement already satisfied: pyasn1-modules>=0.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from google-auth~=2.0->databricks-sdk<1,>=0.20.0->mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (0.4.2)
    Requirement already satisfied: parso<0.9.0,>=0.8.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jedi>=0.18.2->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.8.7)
    Requirement already satisfied: fqdn in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: isoduration in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (20.11.0)
    Requirement already satisfied: jsonpointer>1.13 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.1.1)
    Requirement already satisfied: rfc3987-syntax>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.1.0)
    Requirement already satisfied: uri-template in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.3.0)
    Requirement already satisfied: webcolors>=24.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (25.10.0)
    Requirement already satisfied: executing>=1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.2.1)
    Requirement already satisfied: pure-eval in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: soupsieve>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.8.4)
    Requirement already satisfied: pyasn1<0.7.0,>=0.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pyasn1-modules>=0.2.1->google-auth~=2.0->databricks-sdk<1,>=0.20.0->mlflow-skinny==3.13.0->mlflow==3.13.0->-r requirements.txt (line 11)) (0.6.3)
    Requirement already satisfied: lark>=1.2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.3.1)
    Requirement already satisfied: arrow>=0.15.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.4.0)
    [notice] A new release of pip is available: 25.0.1 -> 26.1.2
    [notice] To update, run: python -m pip install --upgrade pip
    Note: you may need to restart the kernel to use updated packages.
    import mindspore
    mindspore.set_device(device_target='Ascend', device_id=0)
    mindspore.run_check()
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    MindSpore version: 2.9.0
    The result of multiplication calculation is correct, MindSpore has been installed on platform [Ascend] successfully!

    Deploying MLflow Tracking Server with Docker

    The MLflow tracking server stores the runs, hyperparameters, metrics and artifacts of your experiments.

    Let’s deploy it with Docker Composemlflow server listens to port 5000 by default and requires the following persistent data stores.

    1. Backend store: stores metadata for runs, hyperparameters and metrics. By default, MLflow uses a SQlite DB mlflow.db under the current directory as the backend store. Here, we set the path to /data/mlflow.db
    2. Artifact store: stores large files such as ONNX models. By default, MLflow stores artifacts in a local ./mlruns directory. Here, we set the path to /data/artifacts

    We’ll use the latest version v3.13.0-full of the official MLflow docker image ghcr.io/mlflow/mlflow at the time of writing. To ensure our data persists across container restarts, let’s mount a Docker volume mlflow-data under the /data directory.

    !cat compose.yaml
    name: mlflow-environment
    services:
    mlflow-server:
    image: ghcr.io/mlflow/mlflow:v3.13.0-full
    container_name: mlflow-tracking-server
    hostname: mlflow-tracking-server
    restart: unless-stopped
    ports:
    - "5000:5000"
    volumes:
    - mlflow-data:/data
    command: >
    mlflow server
    --host 0.0.0.0
    --port 5000
    --backend-store-uri sqlite:////data/mlflow.db
    --artifacts-destination file:///data/artifacts
    --serve-artifacts
    --workers 4
    --allowed-hosts "*"
    --cors-allowed-origins "*"
    volumes:
    mlflow-data:
    name: mlflow-data

    The command we used to create and start our container with Compose is shown below for reference.

    docker compose up -d

    With the MLflow tracking server deployed, point your browser to http://localhost:5000/.

    from IPython.display import Image
    Image(filename='00-mlflow-mindspore-mlflow-homepage.jpg')
    MLflow homepage

    Loading and preprocessing the Fashion MNIST dataset

    The Fashion MNIST dataset serves as a quick sanity check that our model training pipeline is working correctly and that our neural network is able to learn features. The dataset is already mirrored on my website so let’s download and unpack it from there.

    import os
    dataset_dir = 'data/fashion/'
    os.makedirs(dataset_dir, exist_ok=True)
    import gzip
    import urllib.request
    prefix_url = 'https://donaldsebleung.com/assets/datasets/fashion-mnist'
    X_train_url = f'{prefix_url}/train-images-idx3-ubyte.gz'
    y_train_url = f'{prefix_url}/train-labels-idx1-ubyte.gz'
    X_test_url = f'{prefix_url}/t10k-images-idx3-ubyte.gz'
    y_test_url = f'{prefix_url}/t10k-labels-idx1-ubyte.gz'
    X_train_path = os.path.join(dataset_dir, 'train-images-idx3-ubyte')
    y_train_path = os.path.join(dataset_dir, 'train-labels-idx1-ubyte')
    X_test_path = os.path.join(dataset_dir, 't10k-images-idx3-ubyte')
    y_test_path = os.path.join(dataset_dir, 't10k-labels-idx1-ubyte')
    with urllib.request.urlopen(X_train_url) as response:
    with open(X_train_path, 'wb') as out_file:
    data_gzip = response.read()
    data = gzip.decompress(data_gzip)
    out_file.write(data)
    with urllib.request.urlopen(y_train_url) as response:
    with open(y_train_path, 'wb') as out_file:
    data_gzip = response.read()
    data = gzip.decompress(data_gzip)
    out_file.write(data)
    with urllib.request.urlopen(X_test_url) as response:
    with open(X_test_path, 'wb') as out_file:
    data_gzip = response.read()
    data = gzip.decompress(data_gzip)
    out_file.write(data)
    with urllib.request.urlopen(y_test_url) as response:
    with open(y_test_path, 'wb') as out_file:
    data_gzip = response.read()
    data = gzip.decompress(data_gzip)
    out_file.write(data)

    As usual, let’s load our training and validation sets with mindspore.dataset.FashionMnistDataset.

    import mindspore.dataset as ds
    train_ds = ds.FashionMnistDataset(dataset_dir=dataset_dir, usage='train', shuffle=True)
    test_ds = ds.FashionMnistDataset(dataset_dir=dataset_dir, usage='test', shuffle=True)

    Apply the usual transformations to our images and labels respectively. For each image, we:

    1. Resize each image to $28 \times 28$ pixels
    2. Rescale each grayscale pixel by a factor of $\frac{1}{255}$ to ensure pixel values lie within the range $[0, 1]$
    3. Reorder the dimensions from NHWC to NCHW format

    For each label, we:

    1. Apply one-hot encoding to our class labels

    Additionally, we cast the values to FP16 to avoid compatibility issues with FP32 matrix multiplication on the Ascend 310B NPU.

    import mindspore.dataset.vision as vision
    import mindspore.dataset.transforms as transforms
    from mindspore import dtype as mstype
    def transform_ds(dataset):
    image_transforms = [
    vision.Resize(size=(28, 28)),
    vision.Rescale(rescale=1/255, shift=0),
    vision.HWC2CHW(),
    transforms.TypeCast(data_type=mstype.float16)
    ]
    label_transforms = [
    transforms.OneHot(num_classes=10),
    transforms.TypeCast(data_type=mstype.float16)
    ]
    dataset = dataset.map(operations=image_transforms, input_columns='image')
    dataset = dataset.map(operations=label_transforms, input_columns='label')
    dataset = dataset.batch(batch_size=512, drop_remainder=False)
    return dataset
    train_ds = transform_ds(dataset=train_ds)
    test_ds = transform_ds(dataset=test_ds)

    Defining our neural network

    To keep things simple and focus on how MindSpore integrates with MLflow, we’ll simply flatten our images and apply a fully connected (FC) linear layer with 10 raw output logits corresponding to our 10 output label classes.

    Instead of subclassing mindspore.nn.Cell and defining the construct method manually, we can simply apply both operations (flattening + FC) sequentially with mindspore.nn.SequentialCell.

    import mindspore.nn as nn
    net = nn.SequentialCell([
    nn.Flatten(),
    nn.Dense(784, 10, dtype=mstype.float16)
    ])
    net
    SequentialCell(
    (0): Flatten()
    (1): Dense(input_channels=784, output_channels=10, has_bias=True)
    )

    Connecting to our MLflow tracking server

    Connecting to our MLflow tracking server is simple – pass in the URL to mlflow.set_tracking_uri and we’re done.

    import os
    MLFLOW_TRACKING_SERVER_HOST = os.getenv('MLFLOW_TRACKING_SERVER_HOST', 'localhost')
    MLFLOW_TRACKING_SERVER_PORT = os.getenv('MLFLOW_TRACKING_SERVER_PORT', '5000')
    MLFLOW_TRACKING_SERVER_URL = f'http://{MLFLOW_TRACKING_SERVER_HOST}:{MLFLOW_TRACKING_SERVER_PORT}'
    MLFLOW_TRACKING_SERVER_URL
    'http://localhost:5000'
    import mlflow
    mlflow.set_tracking_uri(MLFLOW_TRACKING_SERVER_URL)

    Creating our first MLflow experiment

    mlflow.set_experiment creates a new experiment with the given name or reuses an existing experiment with the same name if it already exists. It returns an Experiment object whose internal ID is available via the experiment_id property.

    experiment_name = 'fashion-mnist-linear'
    experiment = mlflow.set_experiment(experiment_name=experiment_name)
    print(f'Created MLflow experiment with name {experiment_name} and ID {experiment.experiment_id}')
    Created MLflow experiment with name fashion-mnist-linear and ID 1

    Our newly created experiment fashion-mnist-linear appears on the homepage of our MLflow tracking server under “Recent Experiments”.

    Image(filename='01-mlflow-mindspore-new-experiment.png')
    Our first MLflow experiment

    Defining our loss function and optimization algorithm

    Let’s use the standard activation + loss function and optimization algorithm for image classification problems.

    1. Activation + loss function: combined softmax cross-entropy loss using the log-sum-exp trick
    2. Optimization algorithm: minibatch stochaistic gradient descent (SGD) with a learning rate of 0.01. Common values for the learning rate typically lie within the range 1e-2 to 1e-4
    loss_fn = nn.SoftmaxCrossEntropyWithLogits(reduction='mean')
    loss_fn
    SoftmaxCrossEntropyWithLogits()
    optimizer = nn.SGD(params=net.trainable_params(), learning_rate=0.01)
    optimizer
    SGD()

    Abstracting the training loop with the MindSpore Model API

    So far, we have been defining our training loops manually with low-level functions such as mindspore.value_and_grad. While such manual work is useful initially for understanding the concepts behind deep learning such as backpropagation and gradient descent, as well as defining customized ML pipelines in advanced scenarios, the repetitive work quickly becomes tedious and time-consuming. Let’s be honest; most of the time we just want to quickly train our model and evaluate the results!

    Here’s where MindSpore’s Model API comes into play. Instead of manually defining our gradient function, per-step training logic and per-epoch training loop, we can simply wrap our neural network inside a mindspore.train.Model which provides many convenience methods for model training and evaluation as described below.

    1. mindspore.train.Model.train: trains our neural network against a training set train_dataset over the specified epoch number of epochs
    2. mindspore.train.Model.eval: evaluates our neural network against a validation set valid_dataset
    3. mindspore.train.Model.fit: combines both model training and validation within each epoch
    from mindspore.train import Model
    model = Model(network=net,
    loss_fn=loss_fn,
    optimizer=optimizer,
    metrics={'accuracy', 'loss'})
    model
    <mindspore.train.model.Model at 0xe7fecf89dd30>

    The train and fit methods optionally accept a list callbacks of objects representing callbacks invoked at the end of each training step. Each callback object inherits from the base class mindspore.train.Callback and defines methods invoked:

    1. At the start of the training pipeline
    2. After each training step
    3. After each training epoch
    4. At the end of the training pipeline

    Fortunately, for most common scenarios, importing and referencing the built in callbacks suffices. One such callback is mindspore.train.LossMonitor which simply reports the training loss at the end of each step, with an optional per_print_times parameter which adjusts the reporting to every $n$ training steps instead.

    from mindspore.train import LossMonitor
    callbacks = [LossMonitor(per_print_times=10)]
    callbacks
    [<mindspore.train.callback._loss_monitor.LossMonitor at 0xe7fecf89fec0>]

    Let’s train our model over 10 epochs.

    epochs = 10

    Logging MLflow run metrics and hyperparameters with custom callbacks

    We’ll use the following MLflow client methods to define our first run within the fashion-mnist-linear experiment, log metrics and hyperparameters and upload the trained ONNX model at the end of our training pipeline.

    1. mlflow.start_run: Starts a new run with the name specified in run_name. We’ll name our run with the format $DATETIME-lr_0.01 to specify that we are using a learning rate of 0.01 and avoid naming collisions between runs. MLflow experiment names are unique but runs within and across experiments can share the same human-readable name
    2. mlflow.log_params: logs to the MLflow tracking server the hyperparameters for this run as a dictionary of key-value pairs
    3. mlflow.log_metric: logs the specified metric such as training loss or validation accuracy at the specified step or epoch given by step
    4. mlflow.onnx.log_model: logs the provided ONNX model to the MLflow tracking server under a given name
    5. mlflow.end_run: signals to the MLflow tracking server that the current run has ended

    Since MLflow logging is not provided as a built-in callback, we define our subclass MLflowFashionMNISTCallback of mindspore.train.Callback and implement the following methods.

    1. __init__: the constructor. Here, we start the MLflow run within our experiment and log our hyperparameters
    2. on_train_begin: anything that must be executed at the start of the entire training pipeline that doesn’t fit cleanly within our constructor
    3. on_train_step_end: fetch and log the training loss at the end of each step
    4. on_train_epoch_end: fetch and log the validation accuracy and loss at the end of each epoch
    5. on_train_end: at the end of the training pipeline, export our ONNX model locally with mindspore.onnx.export then load it and log the model to our MLflow tracking server before ending the current run
    6. __del__: the destructor ensures the current run is properly terminated when our callback object is garbage collected
    import datetime
    import mindspore.ops as ops
    import onnx
    from mindspore.train import Callback
    class MLflowFashionMNISTCallback(Callback):
    def __init__(self, net, valid_dataset, learning_rate=0.01, version=1):
    super().__init__()
    self.net = net
    self.valid_dataset = valid_dataset
    self.learning_rate = learning_rate
    self.version = version
    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    run_name = f"{timestamp}-lr_{self.learning_rate}"
    self.run = mlflow.start_run(run_name=run_name)
    hyperparameters = {
    "learning_rate": self.learning_rate,
    "weight_decay": 0,
    "momentum": 0,
    "loss": "softmax_cross_entropy",
    "optimizer": "sgd",
    "batch_size": 512,
    "network_type": "linear",
    "epochs": 10
    }
    mlflow.log_params(hyperparameters)
    def on_train_begin(self, run_context):
    pass
    def on_train_step_end(self, run_context):
    cb_params = run_context.original_args()
    current_loss = cb_params.net_outputs.asnumpy().mean()
    mlflow.log_metric("train_loss", current_loss, step=cb_params.cur_step_num)
    def on_train_epoch_end(self, run_context):
    cb_params = run_context.original_args()
    if hasattr(cb_params, 'eval_results') and cb_params.eval_results:
    val_loss = cb_params.eval_results.get('loss', 0.0)
    val_accuracy = cb_params.eval_results.get('accuracy', 0.0)
    mlflow.log_metric('val_loss', val_loss, step=cb_params.cur_epoch_num)
    mlflow.log_metric('val_accuracy', val_accuracy, step=cb_params.cur_epoch_num)
    def on_train_end(self, run_context):
    onnx_path = f"fashion-mnist-linear-{self.version:02d}.onnx"
    dummy_input = ops.randn((1, 1, 28, 28), dtype=mstype.float16)
    mindspore.onnx.export(self.net,
    dummy_input,
    file_name=onnx_path,
    input_names=['image'],
    output_names=['label'])
    onnx_model = onnx.load(onnx_path)
    mlflow.onnx.log_model(
    onnx_model=onnx_model,
    name=f"fashion-mnist-linear-{self.version:02d}"
    )
    mlflow.end_run()
    def __del__(self):
    if hasattr(self, 'run') and self.run is not None:
    try:
    mlflow.end_run()
    except:
    pass

    Instantiate our custom callback and add it to our list of callbacks.

    callbacks.append(MLflowFashionMNISTCallback(net=net, valid_dataset=test_ds))
    callbacks
    [<mindspore.train.callback._loss_monitor.LossMonitor at 0xe7fecf89fec0>,
    <__main__.MLflowFashionMNISTCallback at 0xe7fecf89d4c0>]

    Now we are ready to train our model!

    model.fit(epoch=epochs,
    train_dataset=train_ds,
    valid_dataset=test_ds,
    callbacks=callbacks,
    dataset_sink_mode=False)
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:97: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:157: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    path string is NULLpath string is NULL.epoch: 1 step: 10, loss is 2.091796875
    epoch: 1 step: 20, loss is 1.939453125
    epoch: 1 step: 30, loss is 1.8232421875
    epoch: 1 step: 40, loss is 1.689453125
    epoch: 1 step: 50, loss is 1.6064453125
    epoch: 1 step: 60, loss is 1.541015625
    epoch: 1 step: 70, loss is 1.4658203125
    epoch: 1 step: 80, loss is 1.412109375
    epoch: 1 step: 90, loss is 1.392578125
    epoch: 1 step: 100, loss is 1.3486328125
    epoch: 1 step: 110, loss is 1.310546875
    Eval result: epoch 1, metrics: {'loss': 1.2708984375, 'accuracy': 0.6536}
    epoch: 2 step: 2, loss is 1.2724609375
    epoch: 2 step: 12, loss is 1.21484375
    epoch: 2 step: 22, loss is 1.171875
    epoch: 2 step: 32, loss is 1.177734375
    epoch: 2 step: 42, loss is 1.142578125
    epoch: 2 step: 52, loss is 1.1552734375
    epoch: 2 step: 62, loss is 1.078125
    epoch: 2 step: 72, loss is 1.0849609375
    epoch: 2 step: 82, loss is 1.0830078125
    epoch: 2 step: 92, loss is 1.099609375
    epoch: 2 step: 102, loss is 1.0712890625
    epoch: 2 step: 112, loss is 1.0498046875
    Eval result: epoch 2, metrics: {'loss': 1.035205078125, 'accuracy': 0.6736}
    epoch: 3 step: 4, loss is 0.99365234375
    epoch: 3 step: 14, loss is 0.95458984375
    epoch: 3 step: 24, loss is 0.94189453125
    epoch: 3 step: 34, loss is 0.97119140625
    epoch: 3 step: 44, loss is 0.93701171875
    epoch: 3 step: 54, loss is 0.94580078125
    epoch: 3 step: 64, loss is 0.95703125
    epoch: 3 step: 74, loss is 0.9619140625
    epoch: 3 step: 84, loss is 0.94873046875
    epoch: 3 step: 94, loss is 0.9208984375
    epoch: 3 step: 104, loss is 0.90380859375
    epoch: 3 step: 114, loss is 0.86865234375
    Eval result: epoch 3, metrics: {'loss': 0.92841796875, 'accuracy': 0.6913}
    epoch: 4 step: 6, loss is 0.9287109375
    epoch: 4 step: 16, loss is 0.912109375
    epoch: 4 step: 26, loss is 0.90576171875
    epoch: 4 step: 36, loss is 0.9296875
    epoch: 4 step: 46, loss is 0.8984375
    epoch: 4 step: 56, loss is 0.86669921875
    epoch: 4 step: 66, loss is 0.84716796875
    epoch: 4 step: 76, loss is 0.86376953125
    epoch: 4 step: 86, loss is 0.89599609375
    epoch: 4 step: 96, loss is 0.876953125
    epoch: 4 step: 106, loss is 0.8525390625
    epoch: 4 step: 116, loss is 0.9462890625
    Eval result: epoch 4, metrics: {'loss': 0.864404296875, 'accuracy': 0.7146}
    epoch: 5 step: 8, loss is 0.83837890625
    epoch: 5 step: 18, loss is 0.8369140625
    epoch: 5 step: 28, loss is 0.80810546875
    epoch: 5 step: 38, loss is 0.77490234375
    epoch: 5 step: 48, loss is 0.83251953125
    epoch: 5 step: 58, loss is 0.82666015625
    epoch: 5 step: 68, loss is 0.84716796875
    epoch: 5 step: 78, loss is 0.8232421875
    epoch: 5 step: 88, loss is 0.8623046875
    epoch: 5 step: 98, loss is 0.81201171875
    epoch: 5 step: 108, loss is 0.81787109375
    epoch: 5 step: 118, loss is 0.69775390625
    Eval result: epoch 5, metrics: {'loss': 0.8197265625, 'accuracy': 0.7331}
    epoch: 6 step: 10, loss is 0.82568359375
    epoch: 6 step: 20, loss is 0.72900390625
    epoch: 6 step: 30, loss is 0.7763671875
    epoch: 6 step: 40, loss is 0.81201171875
    epoch: 6 step: 50, loss is 0.7724609375
    epoch: 6 step: 60, loss is 0.76904296875
    epoch: 6 step: 70, loss is 0.787109375
    epoch: 6 step: 80, loss is 0.74560546875
    epoch: 6 step: 90, loss is 0.7890625
    epoch: 6 step: 100, loss is 0.771484375
    epoch: 6 step: 110, loss is 0.81201171875
    Eval result: epoch 6, metrics: {'loss': 0.7899169921875, 'accuracy': 0.7419}
    epoch: 7 step: 2, loss is 0.8076171875
    epoch: 7 step: 12, loss is 0.806640625
    epoch: 7 step: 22, loss is 0.7724609375
    epoch: 7 step: 32, loss is 0.80126953125
    epoch: 7 step: 42, loss is 0.7470703125
    epoch: 7 step: 52, loss is 0.7373046875
    epoch: 7 step: 62, loss is 0.763671875
    epoch: 7 step: 72, loss is 0.80126953125
    epoch: 7 step: 82, loss is 0.7763671875
    epoch: 7 step: 92, loss is 0.7744140625
    epoch: 7 step: 102, loss is 0.74755859375
    epoch: 7 step: 112, loss is 0.7529296875
    Eval result: epoch 7, metrics: {'loss': 0.7623291015625, 'accuracy': 0.7511}
    epoch: 8 step: 4, loss is 0.68505859375
    epoch: 8 step: 14, loss is 0.7529296875
    epoch: 8 step: 24, loss is 0.748046875
    epoch: 8 step: 34, loss is 0.74462890625
    epoch: 8 step: 44, loss is 0.7763671875
    epoch: 8 step: 54, loss is 0.7021484375
    epoch: 8 step: 64, loss is 0.71484375
    epoch: 8 step: 74, loss is 0.77587890625
    epoch: 8 step: 84, loss is 0.7080078125
    epoch: 8 step: 94, loss is 0.69482421875
    epoch: 8 step: 104, loss is 0.68505859375
    epoch: 8 step: 114, loss is 0.6904296875
    Eval result: epoch 8, metrics: {'loss': 0.7422607421875, 'accuracy': 0.757}
    epoch: 9 step: 6, loss is 0.65283203125
    epoch: 9 step: 16, loss is 0.68212890625
    epoch: 9 step: 26, loss is 0.705078125
    epoch: 9 step: 36, loss is 0.689453125
    epoch: 9 step: 46, loss is 0.7470703125
    epoch: 9 step: 56, loss is 0.74169921875
    epoch: 9 step: 66, loss is 0.791015625
    epoch: 9 step: 76, loss is 0.72314453125
    epoch: 9 step: 86, loss is 0.7080078125
    epoch: 9 step: 96, loss is 0.69384765625
    epoch: 9 step: 106, loss is 0.65283203125
    epoch: 9 step: 116, loss is 0.69873046875
    Eval result: epoch 9, metrics: {'loss': 0.724072265625, 'accuracy': 0.7631}
    epoch: 10 step: 8, loss is 0.64599609375
    epoch: 10 step: 18, loss is 0.69970703125
    epoch: 10 step: 28, loss is 0.7041015625
    epoch: 10 step: 38, loss is 0.67431640625
    epoch: 10 step: 48, loss is 0.71630859375
    epoch: 10 step: 58, loss is 0.66552734375
    epoch: 10 step: 68, loss is 0.6865234375
    epoch: 10 step: 78, loss is 0.69677734375
    epoch: 10 step: 88, loss is 0.7724609375
    epoch: 10 step: 98, loss is 0.7529296875
    epoch: 10 step: 108, loss is 0.63623046875
    epoch: 10 step: 118, loss is 0.66943359375
    Eval result: epoch 10, metrics: {'loss': 0.7093017578125, 'accuracy': 0.768}
    onnxruntime cpuid_info warning: Unknown CPU vendor. cpuinfo_vendor value: 0
    2026-06-07 23:38:21.468026834 [W:onnxruntime:Default, device_discovery.cc:283 GetGpuDevices] Failed to detect devices under "/sys/class/drm/card1": device_discovery.cc:93 ReadFileContents Failed to open file: "/sys/class/drm/card1/device/vendor"
    2026-06-07 23:38:21.468118293 [W:onnxruntime:Default, device_discovery.cc:283 GetGpuDevices] Failed to detect devices under "/sys/class/drm/card0": device_discovery.cc:93 ReadFileContents Failed to open file: "/sys/class/drm/card0/device/vendor"
    🏃 View run 20260607_233406-lr_0.01 at: http://localhost:5000/#/experiments/1/runs/05a1b50cf5344ef6b6024be54b5d8eac
    🧪 View experiment at: http://localhost:5000/#/experiments/1

    Let’s view the results of our experiment run. Navigate to the homepage of our MLflow tracking server and select “Model training > Experiments” to the top left, then select the experiment named fashion-mnist-linear.

    Image(filename='02-mlflow-mindspore-select-experiment.png')
    Select our MLflow experiment

    Click “Runs” in the menu to the left and click on the run name to inspect our latest run.

    Image(filename='03-mlflow-mindspore-experiment-select-run.png')
    Select our MLflow run

    The “Overview” tab displays the most recent metrics and hyperparameters for our run.

    Image(filename='04-mlflow-mindspore-run-metrics-hyperparameters.jpg')
    MLflow run hyperparameters

    The “Model metrics” tab contains pre-defined graphs for visualizing the training loss train_loss, validation accuracy val_accuracy and validation loss val_loss we logged in our training pipeline. No more manually computing and storing our metrics as tensors at the end of each training step just to convert them to Numpy arrays in the end for plotting our loss curve with Matplotlib!

    Image(filename='05-mlflow-mindspore-run-metrics-graphs.jpg')
    MLflow auto-generated plots for logged metrics

    The “Artifacts” tab includes our logged ONNX model which can be downloaded by clicking on the download button to the right.

    Image(filename='06-mlflow-mindspore-run-onnx-model.png')
    MLflow ONNX model artifact

    Creating a new MLflow run with different hyperparameters

    What use is an experiment tracking platform like MLflow if we can’t compare hyperparameters and metrics between runs? Let’s define a second run within our experiment and train our model with a learning rate of 0.1, all other hyperparameters being equal.

    A learning rate of 0.1 is considered very aggressive and can lead to massive overfitting for sufficiently complex deep networks. Fortunately, our model is just a simple linear classifier and using an aggresive learning rate should allow it to converge faster. Let’s validate our hypothesis by putting it all into action!

    train_ds = ds.FashionMnistDataset(dataset_dir=dataset_dir, usage='train', shuffle=True)
    test_ds = ds.FashionMnistDataset(dataset_dir=dataset_dir, usage='test', shuffle=True)
    train_ds = transform_ds(dataset=train_ds)
    test_ds = transform_ds(dataset=test_ds)
    net = nn.SequentialCell([
    nn.Flatten(),
    nn.Dense(784, 10, dtype=mstype.float16)
    ])
    net
    SequentialCell(
    (0): Flatten()
    (1): Dense(input_channels=784, output_channels=10, has_bias=True)
    )
    optimizer = nn.SGD(params=net.trainable_params(), learning_rate=0.1)
    optimizer
    SGD()
    model = Model(network=net,
    loss_fn=loss_fn,
    optimizer=optimizer,
    metrics={'accuracy', 'loss'})
    model
    <mindspore.train.model.Model at 0xe7feb2412480>
    callbacks = [
    LossMonitor(per_print_times=10),
    MLflowFashionMNISTCallback(net=net, valid_dataset=test_ds, learning_rate=0.1, version=2)
    ]
    callbacks
    [<mindspore.train.callback._loss_monitor.LossMonitor at 0xe7feb1f9f050>,
    <__main__.MLflowFashionMNISTCallback at 0xe7feb23d1910>]
    model.fit(epoch=epochs,
    train_dataset=train_ds,
    valid_dataset=test_ds,
    callbacks=callbacks,
    dataset_sink_mode=False)
    epoch: 1 step: 10, loss is 1.4189453125
    epoch: 1 step: 20, loss is 1.09375
    epoch: 1 step: 30, loss is 0.9716796875
    epoch: 1 step: 40, loss is 0.86962890625
    epoch: 1 step: 50, loss is 0.81396484375
    epoch: 1 step: 60, loss is 0.80810546875
    epoch: 1 step: 70, loss is 0.7412109375
    epoch: 1 step: 80, loss is 0.771484375
    epoch: 1 step: 90, loss is 0.71142578125
    epoch: 1 step: 100, loss is 0.728515625
    epoch: 1 step: 110, loss is 0.693359375
    Eval result: epoch 1, metrics: {'loss': 0.7176513671875, 'accuracy': 0.7601}
    epoch: 2 step: 2, loss is 0.67724609375
    epoch: 2 step: 12, loss is 0.6669921875
    epoch: 2 step: 22, loss is 0.693359375
    epoch: 2 step: 32, loss is 0.65966796875
    epoch: 2 step: 42, loss is 0.66162109375
    epoch: 2 step: 52, loss is 0.63330078125
    epoch: 2 step: 62, loss is 0.609375
    epoch: 2 step: 72, loss is 0.611328125
    epoch: 2 step: 82, loss is 0.60888671875
    epoch: 2 step: 92, loss is 0.5966796875
    epoch: 2 step: 102, loss is 0.67724609375
    epoch: 2 step: 112, loss is 0.64892578125
    Eval result: epoch 2, metrics: {'loss': 0.64521484375, 'accuracy': 0.7786}
    epoch: 3 step: 4, loss is 0.62060546875
    epoch: 3 step: 14, loss is 0.623046875
    epoch: 3 step: 24, loss is 0.58642578125
    epoch: 3 step: 34, loss is 0.60888671875
    epoch: 3 step: 44, loss is 0.57177734375
    epoch: 3 step: 54, loss is 0.537109375
    epoch: 3 step: 64, loss is 0.55810546875
    epoch: 3 step: 74, loss is 0.52978515625
    epoch: 3 step: 84, loss is 0.55224609375
    epoch: 3 step: 94, loss is 0.517578125
    epoch: 3 step: 104, loss is 0.53271484375
    epoch: 3 step: 114, loss is 0.60888671875
    Eval result: epoch 3, metrics: {'loss': 0.5850341796875, 'accuracy': 0.8014}
    epoch: 4 step: 6, loss is 0.552734375
    epoch: 4 step: 16, loss is 0.52294921875
    epoch: 4 step: 26, loss is 0.537109375
    epoch: 4 step: 36, loss is 0.52587890625
    epoch: 4 step: 46, loss is 0.59326171875
    epoch: 4 step: 56, loss is 0.52734375
    epoch: 4 step: 66, loss is 0.53662109375
    epoch: 4 step: 76, loss is 0.5263671875
    epoch: 4 step: 86, loss is 0.52001953125
    epoch: 4 step: 96, loss is 0.5546875
    epoch: 4 step: 106, loss is 0.54833984375
    epoch: 4 step: 116, loss is 0.56591796875
    Eval result: epoch 4, metrics: {'loss': 0.588037109375, 'accuracy': 0.7931}
    epoch: 5 step: 8, loss is 0.59619140625
    epoch: 5 step: 18, loss is 0.58447265625
    epoch: 5 step: 28, loss is 0.546875
    epoch: 5 step: 38, loss is 0.521484375
    epoch: 5 step: 48, loss is 0.5146484375
    epoch: 5 step: 58, loss is 0.481201171875
    epoch: 5 step: 68, loss is 0.50732421875
    epoch: 5 step: 78, loss is 0.51806640625
    epoch: 5 step: 88, loss is 0.537109375
    epoch: 5 step: 98, loss is 0.491455078125
    epoch: 5 step: 108, loss is 0.5322265625
    epoch: 5 step: 118, loss is 0.5615234375
    Eval result: epoch 5, metrics: {'loss': 0.55877685546875, 'accuracy': 0.8084}
    epoch: 6 step: 10, loss is 0.5224609375
    epoch: 6 step: 20, loss is 0.51318359375
    epoch: 6 step: 30, loss is 0.483154296875
    epoch: 6 step: 40, loss is 0.5771484375
    epoch: 6 step: 50, loss is 0.48193359375
    epoch: 6 step: 60, loss is 0.52734375
    epoch: 6 step: 70, loss is 0.480712890625
    epoch: 6 step: 80, loss is 0.5693359375
    epoch: 6 step: 90, loss is 0.51025390625
    epoch: 6 step: 100, loss is 0.5380859375
    epoch: 6 step: 110, loss is 0.55224609375
    Eval result: epoch 6, metrics: {'loss': 0.53516845703125, 'accuracy': 0.8199}
    epoch: 7 step: 2, loss is 0.52880859375
    epoch: 7 step: 12, loss is 0.55712890625
    epoch: 7 step: 22, loss is 0.5048828125
    epoch: 7 step: 32, loss is 0.5166015625
    epoch: 7 step: 42, loss is 0.5126953125
    epoch: 7 step: 52, loss is 0.5205078125
    epoch: 7 step: 62, loss is 0.49853515625
    epoch: 7 step: 72, loss is 0.4609375
    epoch: 7 step: 82, loss is 0.5341796875
    epoch: 7 step: 92, loss is 0.498291015625
    epoch: 7 step: 102, loss is 0.525390625
    epoch: 7 step: 112, loss is 0.515625
    Eval result: epoch 7, metrics: {'loss': 0.5278076171875, 'accuracy': 0.8173}
    epoch: 8 step: 4, loss is 0.4375
    epoch: 8 step: 14, loss is 0.496826171875
    epoch: 8 step: 24, loss is 0.50830078125
    epoch: 8 step: 34, loss is 0.435791015625
    epoch: 8 step: 44, loss is 0.55029296875
    epoch: 8 step: 54, loss is 0.46044921875
    epoch: 8 step: 64, loss is 0.5087890625
    epoch: 8 step: 74, loss is 0.50634765625
    epoch: 8 step: 84, loss is 0.485595703125
    epoch: 8 step: 94, loss is 0.463134765625
    epoch: 8 step: 104, loss is 0.513671875
    epoch: 8 step: 114, loss is 0.51318359375
    Eval result: epoch 8, metrics: {'loss': 0.52005615234375, 'accuracy': 0.8231}
    epoch: 9 step: 6, loss is 0.462890625
    epoch: 9 step: 16, loss is 0.4921875
    epoch: 9 step: 26, loss is 0.439208984375
    epoch: 9 step: 36, loss is 0.47412109375
    epoch: 9 step: 46, loss is 0.449462890625
    epoch: 9 step: 56, loss is 0.5068359375
    epoch: 9 step: 66, loss is 0.469482421875
    epoch: 9 step: 76, loss is 0.53369140625
    epoch: 9 step: 86, loss is 0.495849609375
    epoch: 9 step: 96, loss is 0.5166015625
    epoch: 9 step: 106, loss is 0.4453125
    epoch: 9 step: 116, loss is 0.473388671875
    Eval result: epoch 9, metrics: {'loss': 0.51754150390625, 'accuracy': 0.8234}
    epoch: 10 step: 8, loss is 0.4716796875
    epoch: 10 step: 18, loss is 0.443115234375
    epoch: 10 step: 28, loss is 0.444091796875
    epoch: 10 step: 38, loss is 0.49658203125
    epoch: 10 step: 48, loss is 0.46484375
    epoch: 10 step: 58, loss is 0.4501953125
    epoch: 10 step: 68, loss is 0.445556640625
    epoch: 10 step: 78, loss is 0.44091796875
    epoch: 10 step: 88, loss is 0.560546875
    epoch: 10 step: 98, loss is 0.475830078125
    epoch: 10 step: 108, loss is 0.529296875
    epoch: 10 step: 118, loss is 0.50732421875
    Eval result: epoch 10, metrics: {'loss': 0.50477294921875, 'accuracy': 0.8263}
    🏃 View run 20260607_233832-lr_0.1 at: http://localhost:5000/#/experiments/1/runs/93a7416379e44bac92709778fe156f44
    🧪 View experiment at: http://localhost:5000/#/experiments/1

    Check the results of our second run. The name takes the format of $DATETIME-lr_0.1 as defined by our custom callback via the learning_rate parameter.

    Image(filename='07-mlflow-mindspore-experiment-multiple-runs.jpg')
    Multiple runs in same MLflow experiment

    Notice the validation accuracy val_accuracy after 10 epochs is increased from around $77\%$ to over $82.5\%$. Indeed, with a simple linear model, overfitting is not a concern and the higher learning rate allows us to converge faster towards the maximum accuracy that can be achieved by such a rudimentary neural network.

    Image(filename='08-mlflow-mindspore-run-02-metrics-hyperparameters.jpg')
    MLflow metrics for 2nd run
    Image(filename='09-mlflow-mindspore-run-02-metrics-graphs.jpg')
    MLflow plots for 2nd run
    Image(filename='10-mlflow-mindspore-run-02-onnx-model.jpg')
    MLflow ONNX model artifact for 2nd run

    Concluding remarks and going further

    We saw how the MLflow open source AI engineering platform allows us to manage, track and compare ML experiments at scale. What we saw in this notebook experiment is just the tip of the iceberg and there’s plenty to be done to promote our MLflow demo from concept to production.

    1. Secure the MLflow tracking server with HTTPs
    2. Configure and implement proper access control for multi-tenant environments
    3. Ensure key components of our MLflow tracking server such as the backend and artifact stores are redundant and highly available
    4. Upgrade to an enterprise distribution of MLflow with vendor-backed commercial support such as Databricks Managed MLflow and fully-managed MLflow on Amazon SageMaker
    5. Integrate MLflow with the rest of your platform, processes and tooling for a complete, end-to-end MLOps experience

    I hope you enjoyed this notebook experiment as much as I did authoring it and stay tuned for updates 😉

  • The notebook source code for this article is available on GitHub.

    Transfer learning is the practice of adapting a pre-trained model for a new but related task. An example of transfer learning is low-rank adaptation (LoRA), a common technique in LLM fine-tuning.

    In this notebook experiment, let’s load ResNet-18 with MindCV for fine-tuning on the CIFAR-100 dataset. ResNet-18 is a modern CNN pre-trained on ImageNet which makes it suitable for our task as both datasets represent image classification tasks. Furthermore, ImageNet contains far more samples and categories than CIFAR-100, meaning the pre-trained filters from ImageNet should translate well to CIFAR-100 with minor adjustments.

    Prerequisites

    For the best experience following this notebook experiment, it’s recommended to go through the first 8 chapters of the D2L textbook or have equivalent experience with machine learning.

    Installing software packages and dependencies

    This notebook experiment was performed on the OrangePi AIpro (20T) development board. The software used in this notebook are listed below.

    1. Ubuntu 22.04 LTS
    2. Python 3.12
    3. MindSpore 2.9.0
    4. CANN 9.0.0
    5. MindCV commit 51b0636da1e38a44a52edf76cf314d1c7c18883a (2025-07-24)
    !cat requirements.txt
    absl-py==2.4.0
    attrs==26.1.0
    cloudpickle==3.1.2
    decorator==5.2.1
    git+https://github.com/mindspore-lab/mindcv.git@51b0636da1e38a44a52edf76cf314d1c7c18883a
    jupyterlab==4.5.7
    jupyterlab-git==0.53.0
    jupyter-resource-usage==1.2.1
    loguru==0.7.3
    matplotlib==3.10.9
    mindspore==2.9.0
    ml-dtypes==0.5.4
    msguard==0.0.8
    openpyxl==3.1.5
    opentelemetry-exporter-otlp-proto-grpc==1.33.1
    opentelemetry-exporter-otlp-proto-http==1.33.1
    pandas~=2.2
    plotly>=5.11.0
    pydantic==2.13.4
    sympy==1.14.0
    tornado==6.5.5
    %pip install -r requirements.txt
    Collecting git+https://github.com/mindspore-lab/mindcv.git@51b0636da1e38a44a52edf76cf314d1c7c18883a (from -r requirements.txt (line 5))
    Cloning https://github.com/mindspore-lab/mindcv.git (to revision 51b0636da1e38a44a52edf76cf314d1c7c18883a) to /tmp/pip-req-build-athjd9sc
    Running command git clone --filter=blob:none --quiet https://github.com/mindspore-lab/mindcv.git /tmp/pip-req-build-athjd9sc
    Running command git rev-parse -q --verify 'sha^51b0636da1e38a44a52edf76cf314d1c7c18883a'
    Running command git fetch -q https://github.com/mindspore-lab/mindcv.git 51b0636da1e38a44a52edf76cf314d1c7c18883a
    Resolved https://github.com/mindspore-lab/mindcv.git to commit 51b0636da1e38a44a52edf76cf314d1c7c18883a
    Installing build dependencies ... [?25ldone
    [?25h Getting requirements to build wheel ... [?25ldone
    [?25h Preparing metadata (pyproject.toml) ... [?25ldone
    [?25hRequirement already satisfied: absl-py==2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 1)) (2.4.0)
    Requirement already satisfied: attrs==26.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 2)) (26.1.0)
    Requirement already satisfied: cloudpickle==3.1.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 3)) (3.1.2)
    Requirement already satisfied: decorator==5.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 4)) (5.2.1)
    Requirement already satisfied: jupyterlab==4.5.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 6)) (4.5.7)
    Requirement already satisfied: jupyterlab-git==0.53.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 7)) (0.53.0)
    Requirement already satisfied: jupyter-resource-usage==1.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 8)) (1.2.1)
    Requirement already satisfied: loguru==0.7.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 9)) (0.7.3)
    Requirement already satisfied: matplotlib==3.10.9 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 10)) (3.10.9)
    Requirement already satisfied: mindspore==2.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 11)) (2.9.0)
    Requirement already satisfied: ml-dtypes==0.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 12)) (0.5.4)
    Requirement already satisfied: msguard==0.0.8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 13)) (0.0.8)
    Requirement already satisfied: openpyxl==3.1.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 14)) (3.1.5)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-grpc==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 15)) (1.33.1)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-http==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 16)) (1.33.1)
    Requirement already satisfied: pandas~=2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 17)) (2.3.3)
    Requirement already satisfied: plotly>=5.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 18)) (6.7.0)
    Requirement already satisfied: pydantic==2.13.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 19)) (2.13.4)
    Requirement already satisfied: sympy==1.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 20)) (1.14.0)
    Requirement already satisfied: tornado==6.5.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 21)) (6.5.5)
    Requirement already satisfied: async-lru>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.3.0)
    Requirement already satisfied: httpx<1,>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.28.1)
    Requirement already satisfied: ipykernel!=6.30.0,>=6.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (7.2.0)
    Requirement already satisfied: jinja2>=3.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (3.1.6)
    Requirement already satisfied: jupyter-core in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (5.9.1)
    Requirement already satisfied: jupyter-lsp>=2.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.3.1)
    Requirement already satisfied: jupyter-server<3,>=2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.18.2)
    Requirement already satisfied: jupyterlab-server<3,>=2.28.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.28.0)
    Requirement already satisfied: notebook-shim>=0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.2.4)
    Requirement already satisfied: packaging in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (26.2)
    Requirement already satisfied: setuptools>=41.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (82.0.1)
    Requirement already satisfied: traitlets in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 6)) (5.15.0)
    Requirement already satisfied: jupyterlab-git-core>=0.52.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (0.53.0)
    Requirement already satisfied: prometheus-client in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 8)) (0.25.0)
    Requirement already satisfied: psutil>=5.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 8)) (7.2.2)
    Requirement already satisfied: pyzmq>=19 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 8)) (27.1.0)
    Requirement already satisfied: contourpy>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (1.3.3)
    Requirement already satisfied: cycler>=0.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (0.12.1)
    Requirement already satisfied: fonttools>=4.22.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (4.63.0)
    Requirement already satisfied: kiwisolver>=1.3.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (1.5.0)
    Requirement already satisfied: numpy>=1.23 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (1.26.4)
    Requirement already satisfied: pillow>=8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (12.2.0)
    Requirement already satisfied: pyparsing>=3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (3.3.2)
    Requirement already satisfied: python-dateutil>=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 10)) (2.9.0.post0)
    Requirement already satisfied: protobuf>=3.13.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 11)) (5.29.6)
    Requirement already satisfied: asttokens>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 11)) (3.0.1)
    Requirement already satisfied: scipy>=1.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 11)) (1.17.1)
    Requirement already satisfied: astunparse>=1.6.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 11)) (1.6.3)
    Requirement already satisfied: safetensors>=0.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 11)) (0.7.0)
    Requirement already satisfied: dill>=0.3.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 11)) (0.4.1)
    Requirement already satisfied: et-xmlfile in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from openpyxl==3.1.5->-r requirements.txt (line 14)) (2.0.0)
    Requirement already satisfied: deprecated>=1.2.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (1.3.1)
    Requirement already satisfied: googleapis-common-protos~=1.52 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (1.75.0)
    Requirement already satisfied: grpcio<2.0.0,>=1.63.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (1.80.0)
    Requirement already satisfied: opentelemetry-api~=1.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (1.33.1)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-common==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (1.33.1)
    Requirement already satisfied: opentelemetry-proto==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (1.33.1)
    Requirement already satisfied: opentelemetry-sdk~=1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (1.33.1)
    Requirement already satisfied: requests~=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 16)) (2.34.2)
    Requirement already satisfied: annotated-types>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 19)) (0.7.0)
    Requirement already satisfied: pydantic-core==2.46.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 19)) (2.46.4)
    Requirement already satisfied: typing-extensions>=4.14.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 19)) (4.15.0)
    Requirement already satisfied: typing-inspection>=0.4.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 19)) (0.4.2)
    Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from sympy==1.14.0->-r requirements.txt (line 20)) (1.3.0)
    Requirement already satisfied: PyYAML>=5.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindcv==0.5.0->-r requirements.txt (line 5)) (6.0.3)
    Requirement already satisfied: tqdm in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindcv==0.5.0->-r requirements.txt (line 5)) (4.67.3)
    Requirement already satisfied: pytz>=2020.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pandas~=2.2->-r requirements.txt (line 17)) (2026.2)
    Requirement already satisfied: tzdata>=2022.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pandas~=2.2->-r requirements.txt (line 17)) (2026.2)
    Requirement already satisfied: narwhals>=1.15.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from plotly>=5.11.0->-r requirements.txt (line 18)) (2.21.2)
    Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.9.0->-r requirements.txt (line 11)) (0.47.0)
    Requirement already satisfied: six<2.0,>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.9.0->-r requirements.txt (line 11)) (1.17.0)
    Requirement already satisfied: wrapt<3,>=1.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from deprecated>=1.2.6->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (2.2.0)
    Requirement already satisfied: anyio in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (4.13.0)
    Requirement already satisfied: certifi in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2026.5.20)
    Requirement already satisfied: httpcore==1.* in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.0.9)
    Requirement already satisfied: idna in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (3.16)
    Requirement already satisfied: h11>=0.16 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.16.0)
    Requirement already satisfied: comm>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.2.3)
    Requirement already satisfied: debugpy>=1.6.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.8.20)
    Requirement already satisfied: ipython>=7.23.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (9.13.0)
    Requirement already satisfied: jupyter-client>=8.8.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (8.8.0)
    Requirement already satisfied: matplotlib-inline>=0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.2.2)
    Requirement already satisfied: nest-asyncio>=1.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.6.0)
    Requirement already satisfied: MarkupSafe>=2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jinja2>=3.0.3->jupyterlab==4.5.7->-r requirements.txt (line 6)) (3.0.3)
    Requirement already satisfied: platformdirs>=2.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-core->jupyterlab==4.5.7->-r requirements.txt (line 6)) (4.9.6)
    Requirement already satisfied: argon2-cffi>=21.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (25.1.0)
    Requirement already satisfied: jupyter-events>=0.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.12.1)
    Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.5.4)
    Requirement already satisfied: nbconvert>=6.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (7.17.1)
    Requirement already satisfied: nbformat>=5.3.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (5.10.4)
    Requirement already satisfied: send2trash>=1.8.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.1.0)
    Requirement already satisfied: terminado>=0.8.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.18.1)
    Requirement already satisfied: websocket-client>=1.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.9.0)
    Requirement already satisfied: pexpect in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core>=0.52.0->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (4.9.0)
    Requirement already satisfied: nbdime~=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (4.0.4)
    Requirement already satisfied: babel>=2.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.18.0)
    Requirement already satisfied: json5>=0.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.14.0)
    Requirement already satisfied: jsonschema>=4.18.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (4.26.0)
    Requirement already satisfied: importlib-metadata<8.7.0,>=6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-api~=1.15->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (8.6.1)
    Requirement already satisfied: opentelemetry-semantic-conventions==0.54b1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-sdk~=1.33.1->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (0.54b1)
    Requirement already satisfied: charset_normalizer<4,>=2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests~=2.7->opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 16)) (3.4.7)
    Requirement already satisfied: urllib3<3,>=1.26 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests~=2.7->opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 16)) (2.7.0)
    Requirement already satisfied: argon2-cffi-bindings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (25.1.0)
    Requirement already satisfied: zipp>=3.20 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from importlib-metadata<8.7.0,>=6.0->opentelemetry-api~=1.15->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 15)) (4.1.0)
    Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.1.1)
    Requirement already satisfied: jedi>=0.18.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.20.0)
    Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (3.0.52)
    Requirement already satisfied: pygments>=2.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.20.0)
    Requirement already satisfied: stack_data>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.6.3)
    Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2025.9.1)
    Requirement already satisfied: referencing>=0.28.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.37.0)
    Requirement already satisfied: rpds-py>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.30.0)
    Requirement already satisfied: python-json-logger>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (4.1.0)
    Requirement already satisfied: rfc3339-validator in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.1.4)
    Requirement already satisfied: rfc3986-validator>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.1.1)
    Requirement already satisfied: beautifulsoup4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (4.14.3)
    Requirement already satisfied: bleach!=5.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (6.3.0)
    Requirement already satisfied: defusedxml in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.7.1)
    Requirement already satisfied: jupyterlab-pygments in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.3.0)
    Requirement already satisfied: mistune<4,>=2.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (3.2.1)
    Requirement already satisfied: nbclient>=0.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.10.4)
    Requirement already satisfied: pandocfilters>=1.4.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.5.1)
    Requirement already satisfied: colorama in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (0.4.6)
    Requirement already satisfied: gitpython!=2.1.4,!=2.1.5,!=2.1.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (3.1.50)
    Requirement already satisfied: fastjsonschema>=2.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbformat>=5.3.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.21.2)
    Requirement already satisfied: ptyprocess>=0.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pexpect->jupyterlab-git-core>=0.52.0->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (0.7.0)
    Requirement already satisfied: webencodings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.5.1)
    Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.4.0)
    Requirement already satisfied: gitdb<5,>=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (4.0.12)
    Requirement already satisfied: parso<0.9.0,>=0.8.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jedi>=0.18.2->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.8.7)
    Requirement already satisfied: fqdn in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.5.1)
    Requirement already satisfied: isoduration in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (20.11.0)
    Requirement already satisfied: jsonpointer>1.13 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (3.1.1)
    Requirement already satisfied: rfc3987-syntax>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.1.0)
    Requirement already satisfied: uri-template in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.3.0)
    Requirement already satisfied: webcolors>=24.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (25.10.0)
    Requirement already satisfied: wcwidth in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.7.0)
    Requirement already satisfied: executing>=1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.2.1)
    Requirement already satisfied: pure-eval in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (0.2.3)
    Requirement already satisfied: cffi>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.0.0)
    Requirement already satisfied: soupsieve>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (2.8.3)
    Requirement already satisfied: pycparser in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (3.0)
    Requirement already satisfied: smmap<6,>=3.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitdb<5,>=4.0.1->gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 7)) (5.0.3)
    Requirement already satisfied: lark>=1.2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.3.1)
    Requirement already satisfied: arrow>=0.15.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 6)) (1.4.0)
    [notice] A new release of pip is available: 25.0.1 -> 26.1.1
    [notice] To update, run: python -m pip install --upgrade pip
    Note: you may need to restart the kernel to use updated packages.
    import mindspore
    mindspore.set_device(device_target='Ascend', device_id=0)
    mindspore.run_check()
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    MindSpore version: 2.9.0
    The result of multiplication calculation is correct, MindSpore has been installed on platform [Ascend] successfully!

    Loading and visualizing the CIFAR-100 dataset

    The mindcv.create_dataset allows us to load the CIFAR-100 dataset with a single line of code. Let’s take just the first 4 samples and visualize them with Matplotlib.

    import mindcv
    visual_ds = mindcv.create_dataset('cifar100', split='train', download=True)
    visual_ds = visual_ds.batch(batch_size=4)
    visual_ds
    <mindspore.dataset.engine.datasets.BatchDataset at 0xe7ff49ef0f50>

    Our dataset contains 3 columns.

    1. image: the image containing the object we wish to classify
    2. coarse_label: a coarse label indicating the broad category that our object belongs to, e.g. insects, flowers, or people. There are 20 coarse labels in CIFAR-100
    3. fine_label: a fine label indicating the precise category that our objects belongs to, e.g. bee, orchid or girl. There are 100 fine labels in CIFAR-100

    Since CIFAR-100 includes both coarse and fine labels with a hierarchical relationship between the two, i.e. we can’t have a flower which is a girl, it’s a canonical example of hierarchical classification.

    visual_ds.get_col_names()
    ['image', 'coarse_label', 'fine_label']

    Let’s inspect the shapes of our sample features and labels.

    X_samples, y0_samples, y1_samples = next(visual_ds.create_tuple_iterator())
    X_samples.shape, y0_samples.shape, y1_samples.shape
    ((4, 32, 32, 3), (4,), (4,))

    Below, we define mappings from the raw integer labels to their human-readable equivalents. This mapping is taken from the CIFAR-100 dataset on Hugging Face.

    y0_labels = [
    'aquatic_mammals',
    'fish',
    'flowers',
    'food_containers',
    'fruit_and_vegetables',
    'household_electrical_devices',
    'household_furniture',
    'insects',
    'large_carnivores',
    'large_man-made_outdoor_things',
    'large_natural_outdoor_scenes',
    'large_omnivores_and_herbivores',
    'medium_mammals',
    'non-insect_invertebrates',
    'people',
    'reptiles',
    'small_mammals',
    'trees',
    'vehicles_1',
    'vehicles_2'
    ]
    len(y0_labels)
    20
    y1_labels = [
    'apple',
    'aquarium_fish',
    'baby',
    'bear',
    'beaver',
    'bed',
    'bee',
    'beetle',
    'bicycle',
    'bottle',
    'bowl',
    'boy',
    'bridge',
    'bus',
    'butterfly',
    'camel',
    'can',
    'castle',
    'caterpillar',
    'cattle',
    'chair',
    'chimpanzee',
    'clock',
    'cloud',
    'cockroach',
    'couch',
    'cra',
    'crocodile',
    'cup',
    'dinosaur',
    'dolphin',
    'elephant',
    'flatfish',
    'forest',
    'fox',
    'girl',
    'hamster',
    'house',
    'kangaroo',
    'keyboard',
    'lamp',
    'lawn_mower',
    'leopard',
    'lion',
    'lizard',
    'lobster',
    'man',
    'maple_tree',
    'motorcycle',
    'mountain',
    'mouse',
    'mushroom',
    'oak_tree',
    'orange',
    'orchid',
    'otter',
    'palm_tree',
    'pear',
    'pickup_truck',
    'pine_tree',
    'plain',
    'plate',
    'poppy',
    'porcupine',
    'possum',
    'rabbit',
    'raccoon',
    'ray',
    'road',
    'rocket',
    'rose',
    'sea',
    'seal',
    'shark',
    'shrew',
    'skunk',
    'skyscraper',
    'snail',
    'snake',
    'spider',
    'squirrel',
    'streetcar',
    'sunflower',
    'sweet_pepper',
    'table',
    'tank',
    'telephone',
    'television',
    'tiger',
    'tractor',
    'train',
    'trout',
    'tulip',
    'turtle',
    'wardrobe',
    'whale',
    'willow_tree',
    'wolf',
    'woman',
    'worm'
    ]
    len(y1_labels)
    100

    Now we visualize our 4 samples with Matplotlib. The main reason we chose 4 samples instead of 10 as we have done before is because the names for some of these categories are rather long and it’s difficult to get Matplotlib to get them to display properly without overlapping text and images.

    import matplotlib.pyplot as plt
    fig, axes = plt.subplots(2, 2)
    for axis_idx, axis in enumerate(axes.flatten()):
    axis.set_title(f'{y0_labels[y0_samples[axis_idx]]}\n{y1_labels[y1_samples[axis_idx]]}')
    axis.imshow(X_samples[axis_idx])
    axis.axis('off')
    fig.tight_layout()
    fig.show()
    CIFAR-100 samples

    Preprocessing the CIFAR-100 dataset

    Let’s load both the training and validation sets this time and pass them through our standard data pre-processing pipeline.

    The inputs are transformed via our standard image-processing pipeline.

    1. Resize images to the desired resolution. Here we resize them to $64 \times 64$ pixels
    2. Rescale each pixel along each channel by a factor of $\frac{1}{255}$ so the resulting values reside in the range $[0, 1]$
    3. Reorder the dimensions from NHWC to NCHW format

    Let’s one-hot encode our labels as well. This applies to both the coarse and fine labels. We’ll split our training and validation sets into batches of $2 ^ 7 = 128$ samples for fine-tuning.

    train_ds = mindcv.create_dataset('cifar100', split='train', download=True)
    test_ds = mindcv.create_dataset('cifar100', split='test', download=True)
    import mindspore.dataset.vision as vision
    import mindspore.dataset.transforms as transforms
    from mindspore import dtype as mstype
    def transform_ds(dataset):
    image_transforms = [
    vision.Resize(size=(64, 64)),
    vision.Rescale(rescale=1/255, shift=0),
    vision.HWC2CHW()
    ]
    coarse_label_transforms = [
    transforms.OneHot(num_classes=20),
    transforms.TypeCast(data_type=mstype.float32)
    ]
    fine_label_transforms = [
    transforms.OneHot(num_classes=100),
    transforms.TypeCast(data_type=mstype.float32)
    ]
    dataset = dataset.map(operations=image_transforms, input_columns='image')
    dataset = dataset.map(operations=coarse_label_transforms, input_columns='coarse_label')
    dataset = dataset.map(operations=fine_label_transforms, input_columns='fine_label')
    dataset = dataset.batch(batch_size=128, drop_remainder=False)
    return dataset
    train_ds, test_ds = transform_ds(dataset=train_ds), transform_ds(dataset=test_ds)
    train_ds, test_ds
    (<mindspore.dataset.engine.datasets.BatchDataset at 0xe7feec15c230>,
    <mindspore.dataset.engine.datasets.BatchDataset at 0xe7feec15d7f0>)

    Loading ResNet-18 pretrained from ImageNet

    Although it appears undocumented, we can use list_models from MindCV with a wildcard name resnet* to list the available pre-trained ResNet models. We’ll use ResNet-18 so the fine-tuning process completes on our development board within a reasonable timeframe, e.g. 2 hours.

    resnet_pretrained = mindcv.list_models('resnet*', pretrained=True)
    resnet_pretrained
    ['resnet101',
    'resnet152',
    'resnet18',
    'resnet34',
    'resnet50',
    'resnetv2_101',
    'resnetv2_50']

    Load the pretrained model with mindcv.create_model.

    resnet18 = mindcv.create_model('resnet18', pretrained=True)
    resnet18
    ResNet(
    (conv1): Conv2d(input_channels=3, output_channels=64, kernel_size=(7, 7), stride=(2, 2), pad_mode=pad, padding=3, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec36a240>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=bn1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=bn1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=bn1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=bn1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (max_pool): MaxPool2d(kernel_size=3, stride=2, pad_mode=SAME)
    (layer1): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec369b20>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer1.0.bn1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer1.0.bn1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer1.0.bn1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer1.0.bn1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff2117b9e0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer1.0.bn2.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer1.0.bn2.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer1.0.bn2.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer1.0.bn2.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1490>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer1.1.bn1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer1.1.bn1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer1.1.bn1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer1.1.bn1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec15cfb0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer1.1.bn2.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer1.1.bn2.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer1.1.bn2.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer1.1.bn2.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    )
    (layer2): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=128, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff49e71550>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer2.0.bn1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer2.0.bn1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer2.0.bn1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer2.0.bn1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1d30>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer2.0.bn2.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer2.0.bn2.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer2.0.bn2.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer2.0.bn2.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=64, output_channels=128, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec0d3920>, bias_init=None, format=NCHW)
    (1): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer2.0.down_sample.1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer2.0.down_sample.1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer2.0.down_sample.1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer2.0.down_sample.1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec156de0>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer2.1.bn1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer2.1.bn1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer2.1.bn1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer2.1.bn1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff0c14f1d0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer2.1.bn2.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer2.1.bn2.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer2.1.bn2.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer2.1.bn2.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    )
    (layer3): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=128, output_channels=256, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec15d190>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer3.0.bn1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer3.0.bn1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer3.0.bn1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer3.0.bn1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec126750>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer3.0.bn2.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer3.0.bn2.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer3.0.bn2.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer3.0.bn2.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=128, output_channels=256, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1820>, bias_init=None, format=NCHW)
    (1): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer3.0.down_sample.1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer3.0.down_sample.1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer3.0.down_sample.1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer3.0.down_sample.1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec36b980>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer3.1.bn1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer3.1.bn1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer3.1.bn1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer3.1.bn1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff21118320>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer3.1.bn2.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer3.1.bn2.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer3.1.bn2.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer3.1.bn2.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    )
    (layer4): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=256, output_channels=512, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec0f9400>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer4.0.bn1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer4.0.bn1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer4.0.bn1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer4.0.bn1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec4c33e0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer4.0.bn2.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer4.0.bn2.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer4.0.bn2.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer4.0.bn2.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=256, output_channels=512, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec126330>, bias_init=None, format=NCHW)
    (1): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer4.0.down_sample.1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer4.0.down_sample.1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer4.0.down_sample.1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer4.0.down_sample.1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec2e5850>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer4.1.bn1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer4.1.bn1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer4.1.bn1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer4.1.bn1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec5b6a80>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=layer4.1.bn2.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=layer4.1.bn2.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=layer4.1.bn2.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=layer4.1.bn2.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    )
    (pool): GlobalAvgPooling()
    (classifier): Dense(input_channels=512, output_channels=1000, has_bias=True)
    )

    Adapting ResNet-18 for hierarchical classification with CIFAR-100

    For our hierarchical classification task, let’s reuse the stem and body from ResNet-18 and replace the original head consisting of a single classifier with 2 parallel FC layers – 1 for predicting the coarse labels and 1 for predicting the fine labels.

    We’ll then concatenate the $20 + 100$ logits from the coarse + fine predictions into a single tensor and return the result.

    import mindspore.nn as nn
    class MultiHeadResNet18(nn.Cell):
    def __init__(self, resnet18):
    super().__init__()
    self.backbone = nn.SequentialCell([
    resnet18.conv1,
    resnet18.bn1,
    resnet18.relu,
    resnet18.max_pool,
    resnet18.layer1,
    resnet18.layer2,
    resnet18.layer3,
    resnet18.layer4,
    resnet18.pool,
    nn.Flatten()
    ])
    self.coarse_classifier = nn.Dense(512, 20)
    self.fine_classifier = nn.Dense(512, 100)
    def construct(self, X):
    y_hat = self.backbone(X)
    coarse_logits = self.coarse_classifier(y_hat)
    fine_logits = self.fine_classifier(y_hat)
    return ops.concat((coarse_logits, fine_logits), axis=-1)
    multihead_resnet18 = MultiHeadResNet18(resnet18=resnet18)
    multihead_resnet18
    MultiHeadResNet18(
    (backbone): SequentialCell(
    (0): Conv2d(input_channels=3, output_channels=64, kernel_size=(7, 7), stride=(2, 2), pad_mode=pad, padding=3, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec36a240>, bias_init=None, format=NCHW)
    (1): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    (2): ReLU()
    (3): MaxPool2d(kernel_size=3, stride=2, pad_mode=SAME)
    (4): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec369b20>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.0.bn1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.0.bn1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.0.bn1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.0.bn1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff2117b9e0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.0.bn2.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.0.bn2.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.0.bn2.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.0.bn2.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1490>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.1.bn1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.1.bn1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.1.bn1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.1.bn1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec15cfb0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.1.bn2.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.1.bn2.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.1.bn2.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.1.bn2.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    )
    (5): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=128, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff49e71550>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.0.bn1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.0.bn1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.0.bn1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.0.bn1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1d30>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.0.bn2.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.0.bn2.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.0.bn2.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.0.bn2.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=64, output_channels=128, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec0d3920>, bias_init=None, format=NCHW)
    (1): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.0.down_sample.1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.0.down_sample.1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.0.down_sample.1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.0.down_sample.1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec156de0>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.1.bn1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.1.bn1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.1.bn1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.1.bn1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff0c14f1d0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.1.bn2.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.1.bn2.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.1.bn2.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.1.bn2.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    )
    (6): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=128, output_channels=256, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec15d190>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.0.bn1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.0.bn1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.0.bn1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.0.bn1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec126750>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.0.bn2.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.0.bn2.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.0.bn2.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.0.bn2.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=128, output_channels=256, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1820>, bias_init=None, format=NCHW)
    (1): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.0.down_sample.1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.0.down_sample.1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.0.down_sample.1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.0.down_sample.1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec36b980>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.1.bn1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.1.bn1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.1.bn1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.1.bn1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff21118320>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.1.bn2.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.1.bn2.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.1.bn2.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.1.bn2.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    )
    (7): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=256, output_channels=512, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec0f9400>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.0.bn1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.0.bn1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.0.bn1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.0.bn1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec4c33e0>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.0.bn2.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.0.bn2.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.0.bn2.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.0.bn2.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=256, output_channels=512, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec126330>, bias_init=None, format=NCHW)
    (1): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.0.down_sample.1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.0.down_sample.1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.0.down_sample.1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.0.down_sample.1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec2e5850>, bias_init=None, format=NCHW)
    (bn1): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.1.bn1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.1.bn1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.1.bn1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.1.bn1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    (relu): ReLU()
    (conv2): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec5b6a80>, bias_init=None, format=NCHW)
    (bn2): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.1.bn2.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.1.bn2.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.1.bn2.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.1.bn2.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    )
    (8): GlobalAvgPooling()
    (9): Flatten()
    )
    (coarse_classifier): Dense(input_channels=512, output_channels=20, has_bias=True)
    (fine_classifier): Dense(input_channels=512, output_channels=100, has_bias=True)
    )

    Let’s wrap our model with mindspore.amp.auto_mixed_precision to handle the type casting between FP32 and FP16 automatically. This saves us the effort of doing it manually.

    import mindspore.amp as amp
    multihead_resnet18_amp = amp.auto_mixed_precision(network=multihead_resnet18, amp_level='O2')
    multihead_resnet18_amp
    _OutputTo32(
    (_backbone): MultiHeadResNet18(
    (backbone): SequentialCell(
    (0): Conv2d(input_channels=3, output_channels=64, kernel_size=(7, 7), stride=(2, 2), pad_mode=pad, padding=3, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec36a240>, bias_init=None, format=NCHW)
    (1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    (2): ReLU()
    (3): MaxPool2d(kernel_size=3, stride=2, pad_mode=SAME)
    (4): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec369b20>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.0.bn1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.0.bn1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.0.bn1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.0.bn1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff2117b9e0>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.0.bn2.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.0.bn2.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.0.bn2.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.0.bn2.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1490>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.1.bn1.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.1.bn1.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.1.bn1.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.1.bn1.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=64, output_channels=64, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec15cfb0>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=64, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.4.1.bn2.gamma, shape=(64,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.4.1.bn2.beta, shape=(64,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.4.1.bn2.moving_mean, shape=(64,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.4.1.bn2.moving_variance, shape=(64,), dtype=Float32, requires_grad=False))
    )
    )
    )
    (5): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=64, output_channels=128, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff49e71550>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.0.bn1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.0.bn1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.0.bn1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.0.bn1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1d30>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.0.bn2.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.0.bn2.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.0.bn2.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.0.bn2.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=64, output_channels=128, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec0d3920>, bias_init=None, format=NCHW)
    (1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.0.down_sample.1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.0.down_sample.1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.0.down_sample.1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.0.down_sample.1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec156de0>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.1.bn1.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.1.bn1.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.1.bn1.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.1.bn1.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=128, output_channels=128, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff0c14f1d0>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=128, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.5.1.bn2.gamma, shape=(128,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.5.1.bn2.beta, shape=(128,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.5.1.bn2.moving_mean, shape=(128,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.5.1.bn2.moving_variance, shape=(128,), dtype=Float32, requires_grad=False))
    )
    )
    )
    (6): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=128, output_channels=256, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec15d190>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.0.bn1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.0.bn1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.0.bn1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.0.bn1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec126750>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.0.bn2.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.0.bn2.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.0.bn2.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.0.bn2.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=128, output_channels=256, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff211b1820>, bias_init=None, format=NCHW)
    (1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.0.down_sample.1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.0.down_sample.1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.0.down_sample.1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.0.down_sample.1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec36b980>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.1.bn1.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.1.bn1.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.1.bn1.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.1.bn1.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=256, output_channels=256, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7ff21118320>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=256, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.6.1.bn2.gamma, shape=(256,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.6.1.bn2.beta, shape=(256,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.6.1.bn2.moving_mean, shape=(256,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.6.1.bn2.moving_variance, shape=(256,), dtype=Float32, requires_grad=False))
    )
    )
    )
    (7): SequentialCell(
    (0): BasicBlock(
    (conv1): Conv2d(input_channels=256, output_channels=512, kernel_size=(3, 3), stride=(2, 2), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec0f9400>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.0.bn1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.0.bn1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.0.bn1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.0.bn1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec4c33e0>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.0.bn2.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.0.bn2.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.0.bn2.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.0.bn2.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    (down_sample): SequentialCell(
    (0): Conv2d(input_channels=256, output_channels=512, kernel_size=(1, 1), stride=(2, 2), pad_mode=same, padding=0, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec126330>, bias_init=None, format=NCHW)
    (1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.0.down_sample.1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.0.down_sample.1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.0.down_sample.1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.0.down_sample.1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    )
    )
    (1): BasicBlock(
    (conv1): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec2e5850>, bias_init=None, format=NCHW)
    (bn1): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.1.bn1.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.1.bn1.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.1.bn1.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.1.bn1.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    (relu): ReLU()
    (conv2): Conv2d(input_channels=512, output_channels=512, kernel_size=(3, 3), stride=(1, 1), pad_mode=pad, padding=1, dilation=(1, 1), group=1, has_bias=False, weight_init=<mindspore.common.initializer.HeUniform object at 0xe7feec5b6a80>, bias_init=None, format=NCHW)
    (bn2): _OutputTo16(
    (_backbone): BatchNorm2d(num_features=512, eps=1e-05, momentum=0.9, gamma=Parameter (name=backbone.7.1.bn2.gamma, shape=(512,), dtype=Float32, requires_grad=True), beta=Parameter (name=backbone.7.1.bn2.beta, shape=(512,), dtype=Float32, requires_grad=True), moving_mean=Parameter (name=backbone.7.1.bn2.moving_mean, shape=(512,), dtype=Float32, requires_grad=False), moving_variance=Parameter (name=backbone.7.1.bn2.moving_variance, shape=(512,), dtype=Float32, requires_grad=False))
    )
    )
    )
    (8): GlobalAvgPooling()
    (9): Flatten()
    )
    (coarse_classifier): Dense(input_channels=512, output_channels=20, has_bias=True)
    (fine_classifier): Dense(input_channels=512, output_channels=100, has_bias=True)
    )
    )

    Create a dummy RGB “image” of $64 \times 64$ pixels and inspect the output shape from our network. Since we have 20 raw logits for the coarse labels and 100 for the fine labels, we should output a total of $20 + 100 = 120$ logits per image.

    import mindspore.ops as ops
    X_rgb_64x64 = ops.randn(1, 3, 64, 64)
    y_hat = multihead_resnet18_amp(X_rgb_64x64)
    y_hat.shape
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:97: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:157: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-9.0.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:179: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    (1, 120)

    Defining our hierarchical loss function for CIFAR-100

    Let’s define our loss function. Since there is a hierarchical relationship between the coarse and fine labels, we should mirror this relationship in our loss function.

    1. Compute the softmax cross-entropy loss for the coarse predictions. Denote the loss as $l_{\text{coarse}}$
    2. Compute the softmax cross-entropy loss for the fine predictions. Denote the loss as $l_{\text{fine}}$
    3. Define the hierarchical loss as $l = l_{\text{coarse}} + \lambda \cdot l_{\text{fine}}$ where $\lambda$ is a hyperparameter in the range $[0, 1]$

    The idea is that we should penalize an incorrect prediction of the coarse label more severely compared to an incorrect prediction of the fine label. It might be easy for our model to mistake an apple for a pear but at least it shouldn’t mistake a person for a tree!

    For our purposes in this notebook experiment, let’s set $\lambda = 0.5$ to strike a balance between penalizing incorrect fine label predictions too heavily and ensuring that our model learns the fine labels quick enough within a limited number of epochs. We’ll fine-tune our model over 10 epochs as it takes just under 2 hours to do so with our OrangePi AIpro (20T) development board which is a marginally reasonable timeframe.

    class HierarchicalLoss(nn.Cell):
    def __init__(self, lambd=0.5, reduction='mean'):
    super().__init__()
    self.lambd = lambd
    self.reduction = reduction
    self.ce = nn.SoftmaxCrossEntropyWithLogits(reduction=reduction)
    def construct(self, logits, labels):
    coarse_logits, fine_logits = logits[:, :20], logits[:, 20:]
    coarse_labels, fine_labels = labels
    coarse_loss = self.ce(coarse_logits, coarse_labels)
    fine_loss = self.ce(fine_logits, fine_labels)
    return coarse_loss + self.lambd * fine_loss
    loss_fn = HierarchicalLoss(lambd=0.5, reduction='mean')
    loss_fn
    HierarchicalLoss(
    (ce): SoftmaxCrossEntropyWithLogits()
    )

    Model fine-tuning and evaluation

    Let’s use minibatch SGD as our optimizer with a learning rate of 1e-3 for faster convergence within 10 epochs. For a fine-tuning task like this one, 1e-3 is already considered aggressive as we risk destroying the pre-trained image filters. Usually, a learning rate of 1e-4 will suffice.

    optimizer = nn.SGD(params=multihead_resnet18_amp.trainable_params(), learning_rate=1e-3)
    optimizer
    SGD()

    Define our forward and gradient functions as usual.

    def forward(X, y):
    y_hat = multihead_resnet18_amp(X)
    loss = loss_fn(y_hat, y)
    return loss, y_hat
    grad_fn = mindspore.value_and_grad(fn=forward, grad_position=None, weights=optimizer.parameters, has_aux=True)

    Now define our training logic per batch and per epoch. This is mostly similar to what we’ve seen before except our dataset now returns 2 sets of labels (coarse and fine) instead of 1 which we must accommodate for.

    def train_batch(X_batch, y_batch):
    (loss, _), grads = grad_fn(X_batch, y_batch)
    optimizer(grads)
    return loss
    def train_epoch(epoch=0):
    print(f'Epoch {epoch} start')
    batch_count = train_ds.get_dataset_size()
    training_losses = []
    multihead_resnet18_amp.set_train()
    for batch_idx, (X_batch, y0_batch, y1_batch) in enumerate(train_ds.create_tuple_iterator()):
    loss = train_batch(X_batch, (y0_batch, y1_batch))
    if batch_idx % 20 == 0:
    print(f'Training loss: {loss.asnumpy():.4f} [{batch_idx}/{batch_count}]')
    training_losses.append(loss)
    print(f'Epoch {epoch} end')
    return training_losses

    Define the validation logic as well. Again, the only real difference is accommodating both the coarse and fine labels.

    def validate_epoch(epoch=0):
    validation_losses = []
    multihead_resnet18_amp.set_train(False)
    for X_batch, y0_batch, y1_batch in test_ds.create_tuple_iterator():
    batch_size = X_batch.shape[0]
    y_hat = multihead_resnet18_amp(X_batch)
    validation_loss = (batch_size, loss_fn(y_hat, (y0_batch, y1_batch)).item())
    validation_losses.append(validation_loss)
    val_samples_total = sum(batch_size for batch_size, _ in validation_losses)
    val_loss = sum(batch_size * batch_loss for batch_size, batch_loss in validation_losses) / val_samples_total
    print(f'Validation loss after epoch {epoch}: {val_loss:.4f}')
    return val_loss

    Fine-tune our model over 10 epochs. Be patient – this will take just under 2 hours to complete on our development board.

    training_losses = []
    validation_losses = []
    epochs = 10
    print(f'Fine-tuning our model over {epochs} epochs ...')
    for epoch in range(epochs):
    training_losses.extend(train_epoch(epoch=epoch))
    validation_losses.append(validate_epoch(epoch=epoch))
    training_losses, validation_losses = ops.stack(training_losses, axis=0), mindspore.Tensor(validation_losses)
    training_losses.shape, validation_losses.shape
    Fine-tuning our model over 10 epochs ...
    Epoch 0 start
    ..Training loss: 5.6848 [0/391]
    Training loss: 5.4499 [20/391]
    Training loss: 5.3580 [40/391]
    Training loss: 5.3982 [60/391]
    Training loss: 5.3181 [80/391]
    Training loss: 5.3137 [100/391]
    Training loss: 5.1766 [120/391]
    Training loss: 5.1904 [140/391]
    Training loss: 5.0723 [160/391]
    Training loss: 5.0245 [180/391]
    Training loss: 4.9998 [200/391]
    Training loss: 4.7842 [220/391]
    Training loss: 4.9190 [240/391]
    Training loss: 4.9942 [260/391]
    Training loss: 4.8681 [280/391]
    Training loss: 4.7217 [300/391]
    Training loss: 4.6198 [320/391]
    Training loss: 4.7625 [340/391]
    Training loss: 4.4851 [360/391]
    Training loss: 4.7031 [380/391]
    path string is NULLpath string is NULL.Epoch 0 end
    Validation loss after epoch 0: 4.5388
    Epoch 1 start
    Training loss: 4.4457 [0/391]
    Training loss: 4.5591 [20/391]
    Training loss: 4.3686 [40/391]
    Training loss: 4.4903 [60/391]
    Training loss: 4.4057 [80/391]
    Training loss: 4.2155 [100/391]
    Training loss: 4.1198 [120/391]
    Training loss: 4.1873 [140/391]
    Training loss: 4.2746 [160/391]
    Training loss: 4.1506 [180/391]
    Training loss: 4.1203 [200/391]
    Training loss: 4.1334 [220/391]
    Training loss: 3.8344 [240/391]
    Training loss: 3.9543 [260/391]
    Training loss: 3.8445 [280/391]
    Training loss: 4.1660 [300/391]
    Training loss: 3.8658 [320/391]
    Training loss: 3.9542 [340/391]
    Training loss: 3.7998 [360/391]
    Training loss: 3.7627 [380/391]
    Epoch 1 end
    Validation loss after epoch 1: 3.7990
    Epoch 2 start
    Training loss: 3.8752 [0/391]
    Training loss: 3.6399 [20/391]
    Training loss: 3.6589 [40/391]
    Training loss: 3.5796 [60/391]
    Training loss: 3.6930 [80/391]
    Training loss: 3.6689 [100/391]
    Training loss: 3.5086 [120/391]
    Training loss: 3.5895 [140/391]
    Training loss: 3.3900 [160/391]
    Training loss: 3.4246 [180/391]
    Training loss: 3.4555 [200/391]
    Training loss: 3.2600 [220/391]
    Training loss: 3.6037 [240/391]
    Training loss: 3.5174 [260/391]
    Training loss: 3.3731 [280/391]
    Training loss: 3.4723 [300/391]
    Training loss: 3.3939 [320/391]
    Training loss: 3.5425 [340/391]
    Training loss: 3.1965 [360/391]
    Training loss: 3.3080 [380/391]
    Epoch 2 end
    Validation loss after epoch 2: 3.3056
    Epoch 3 start
    Training loss: 3.1990 [0/391]
    Training loss: 3.2452 [20/391]
    Training loss: 3.1243 [40/391]
    Training loss: 3.3510 [60/391]
    Training loss: 3.2063 [80/391]
    Training loss: 3.0302 [100/391]
    Training loss: 3.1367 [120/391]
    Training loss: 3.1910 [140/391]
    Training loss: 3.1967 [160/391]
    Training loss: 2.9561 [180/391]
    Training loss: 3.0482 [200/391]
    Training loss: 3.2196 [220/391]
    Training loss: 2.9519 [240/391]
    Training loss: 3.2386 [260/391]
    Training loss: 2.8335 [280/391]
    Training loss: 3.0779 [300/391]
    Training loss: 2.8997 [320/391]
    Training loss: 3.1181 [340/391]
    Training loss: 3.0453 [360/391]
    Training loss: 2.8809 [380/391]
    Epoch 3 end
    Validation loss after epoch 3: 2.9454
    Epoch 4 start
    Training loss: 2.8008 [0/391]
    Training loss: 2.8289 [20/391]
    Training loss: 2.7191 [40/391]
    Training loss: 2.8720 [60/391]
    Training loss: 2.7193 [80/391]
    Training loss: 2.7098 [100/391]
    Training loss: 2.6996 [120/391]
    Training loss: 2.8685 [140/391]
    Training loss: 2.6722 [160/391]
    Training loss: 2.7407 [180/391]
    Training loss: 3.0916 [200/391]
    Training loss: 2.8873 [220/391]
    Training loss: 2.7637 [240/391]
    Training loss: 2.7557 [260/391]
    Training loss: 2.6343 [280/391]
    Training loss: 2.8405 [300/391]
    Training loss: 2.6399 [320/391]
    Training loss: 2.8021 [340/391]
    Training loss: 2.5994 [360/391]
    Training loss: 2.4809 [380/391]
    Epoch 4 end
    Validation loss after epoch 4: 2.7025
    Epoch 5 start
    Training loss: 2.7227 [0/391]
    Training loss: 2.7959 [20/391]
    Training loss: 2.5210 [40/391]
    Training loss: 2.6694 [60/391]
    Training loss: 2.6951 [80/391]
    Training loss: 2.5896 [100/391]
    Training loss: 2.4578 [120/391]
    Training loss: 2.5537 [140/391]
    Training loss: 2.7304 [160/391]
    Training loss: 2.5739 [180/391]
    Training loss: 2.5543 [200/391]
    Training loss: 2.5630 [220/391]
    Training loss: 2.2733 [240/391]
    Training loss: 2.3827 [260/391]
    Training loss: 2.2933 [280/391]
    Training loss: 2.4656 [300/391]
    Training loss: 2.4673 [320/391]
    Training loss: 2.4325 [340/391]
    Training loss: 2.3518 [360/391]
    Training loss: 2.3556 [380/391]
    Epoch 5 end
    Validation loss after epoch 5: 2.4836
    Epoch 6 start
    Training loss: 2.6754 [0/391]
    Training loss: 2.2903 [20/391]
    Training loss: 2.3814 [40/391]
    Training loss: 2.3325 [60/391]
    Training loss: 2.3894 [80/391]
    Training loss: 2.1230 [100/391]
    Training loss: 2.3667 [120/391]
    Training loss: 2.5547 [140/391]
    Training loss: 2.4975 [160/391]
    Training loss: 2.3667 [180/391]
    Training loss: 2.3595 [200/391]
    Training loss: 2.3678 [220/391]
    Training loss: 2.3864 [240/391]
    Training loss: 2.1519 [260/391]
    Training loss: 2.5530 [280/391]
    Training loss: 2.3646 [300/391]
    Training loss: 2.2571 [320/391]
    Training loss: 2.0247 [340/391]
    Training loss: 2.2899 [360/391]
    Training loss: 2.4016 [380/391]
    Epoch 6 end
    Validation loss after epoch 6: 2.3266
    Epoch 7 start
    Training loss: 2.0084 [0/391]
    Training loss: 2.3109 [20/391]
    Training loss: 2.3336 [40/391]
    Training loss: 2.2305 [60/391]
    Training loss: 2.1838 [80/391]
    Training loss: 2.2407 [100/391]
    Training loss: 2.1323 [120/391]
    Training loss: 2.1440 [140/391]
    Training loss: 2.2685 [160/391]
    Training loss: 2.1336 [180/391]
    Training loss: 2.1021 [200/391]
    Training loss: 2.1731 [220/391]
    Training loss: 2.1500 [240/391]
    Training loss: 2.1780 [260/391]
    Training loss: 2.0409 [280/391]
    Training loss: 2.0791 [300/391]
    Training loss: 2.1021 [320/391]
    Training loss: 2.0038 [340/391]
    Training loss: 2.1276 [360/391]
    Training loss: 2.0658 [380/391]
    Epoch 7 end
    Validation loss after epoch 7: 2.2192
    Epoch 8 start
    Training loss: 2.1134 [0/391]
    Training loss: 2.1615 [20/391]
    Training loss: 2.0193 [40/391]
    Training loss: 2.3047 [60/391]
    Training loss: 2.1270 [80/391]
    Training loss: 2.2316 [100/391]
    Training loss: 2.2435 [120/391]
    Training loss: 1.9793 [140/391]
    Training loss: 1.9127 [160/391]
    Training loss: 2.2763 [180/391]
    Training loss: 2.1120 [200/391]
    Training loss: 2.0741 [220/391]
    Training loss: 2.1669 [240/391]
    Training loss: 2.0715 [260/391]
    Training loss: 2.1798 [280/391]
    Training loss: 2.0331 [300/391]
    Training loss: 2.0233 [320/391]
    Training loss: 2.1274 [340/391]
    Training loss: 1.9132 [360/391]
    Training loss: 2.1143 [380/391]
    Epoch 8 end
    Validation loss after epoch 8: 2.0878
    Epoch 9 start
    Training loss: 2.0792 [0/391]
    Training loss: 1.9131 [20/391]
    Training loss: 2.0230 [40/391]
    Training loss: 2.1467 [60/391]
    Training loss: 1.7917 [80/391]
    Training loss: 2.1788 [100/391]
    Training loss: 1.7646 [120/391]
    Training loss: 1.7108 [140/391]
    Training loss: 1.9769 [160/391]
    Training loss: 2.1211 [180/391]
    Training loss: 1.9208 [200/391]
    Training loss: 1.9581 [220/391]
    Training loss: 2.2359 [240/391]
    Training loss: 1.7331 [260/391]
    Training loss: 1.9252 [280/391]
    Training loss: 1.9974 [300/391]
    Training loss: 1.9489 [320/391]
    Training loss: 2.2466 [340/391]
    Training loss: 1.7049 [360/391]
    Training loss: 1.8673 [380/391]
    Epoch 9 end
    Validation loss after epoch 9: 2.0185
    ((3910,), (10,))

    Let’s plot the training vs. validation loss with Matplotlib.

    import numpy as np
    batches_per_epoch = 391
    batches_x = np.arange(batches_per_epoch * epochs)
    epochs_x = np.arange(epochs) * batches_per_epoch + batches_per_epoch
    training_losses_y = training_losses.asnumpy()
    validation_losses_y = validation_losses.asnumpy()
    plt.figure(figsize=(8, 5))
    plt.plot(batches_x, training_losses_y, label='Training loss', linestyle='-')
    plt.plot(epochs_x, validation_losses_y, label='Validation loss', linestyle='--')
    plt.title('Training vs. validation losses')
    plt.xlabel('Batch number')
    plt.ylabel('Loss')
    plt.yscale('log')
    plt.grid(True, linestyle='--', alpha=0.6)
    plt.legend()
    plt.show()
    .
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:97: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:157: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:97: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:157: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    ..
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:97: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:157: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:97: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:157: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    ...
    Training vs. validation loss

    Finally, let’s evaluate the accuracy of our model with 3 metrics.

    1. Coarse accuracy: the proportion of coarse labels which our model predicted correctly
    2. Fine accuracy: same as (1) but for fine labels
    3. Hierarchical accuracy: the true accuracy, each prediction is considered correct only if both the coarse and fine predictions match their corresponding labels
    multihead_resnet18_amp.set_train(False)
    coarse_accs, fine_accs, true_accs = [], [], []
    for X_batch, y0_batch, y1_batch in test_ds.create_tuple_iterator():
    batch_size = X_batch.shape[0]
    y_hat = multihead_resnet18_amp(X_batch)
    y0_hat, y1_hat = y_hat[:, :20], y_hat[:, 20:]
    y0_hat, y1_hat = ops.argmax(y0_hat, dim=1), ops.argmax(y1_hat, dim=1)
    y0_batch, y1_batch = ops.argmax(y0_batch, dim=1), ops.argmax(y1_batch, dim=1)
    y0_correct, y1_correct = (y0_hat == y0_batch).sum().item(), (y1_hat == y1_batch).sum().item()
    y0_acc, y1_acc = y0_correct / batch_size, y1_correct / batch_size
    coarse_accs.append((batch_size, y0_acc))
    fine_accs.append((batch_size, y1_acc))
    y_hat, y_batch = ops.stack((y0_hat, y1_hat), axis=1), ops.stack((y0_batch, y1_batch), axis=1)
    y_correct = ops.amin((y_hat == y_batch).astype(dtype=mstype.int32), axis=1).sum().item()
    y_acc = y_correct / batch_size
    true_accs.append((batch_size, y_acc))
    val_samples_total = sum(batch_size for batch_size, _ in true_accs)
    coarse_acc = sum(batch_size * y0_acc for batch_size, y0_acc in coarse_accs) / val_samples_total
    fine_acc = sum(batch_size * y1_acc for batch_size, y1_acc in fine_accs) / val_samples_total
    true_acc = sum(batch_size * y_acc for batch_size, y_acc in true_accs) / val_samples_total
    print(f'Coarse accuracy: {coarse_acc:.4f}')
    print(f'Fine accuracy: {fine_acc:.4f}')
    print(f'True accuracy: {true_acc:.4f}')
    .Coarse accuracy: 0.6987
    Fine accuracy: 0.4645
    True accuracy: 0.4251

    The coarse accuracy is close to $70\%$ and the hierarchical accuracy is over $40\%$ – not bad!

    Concluding remarks and going further

    We saw in this notebook experiment how to load ResNet-18 with pre-trained weights using MindCV and use it for transfer learning by fine-tuning the pre-trained model on the CIFAR-100 dataset using MindSpore.

    While fine-tuning a modern CNN such as ResNet-18 is interesting in its own right, it’s nevertheless just the tip of the iceberg in the field of transfer learning and we have yet to explore practical techniques of transfer learning relevant to modern deep learning. As we continue in our deep learning journey, we’ll likely cover LLM parameter-efficient fine-tuning (PEFT) techniques such as LoRA in a future notebook experiment. PEFT enables modern ML practitioners to quickly adapt an existing LLM to a specific domain by freezing the original model weights and attaching a small set of new weights for training, greatly reducing the time, effort and resources required for LLM fine-tuning.

    I hope you enjoyed following through this notebook experiment as much as I did authoring it and stay tuned for updates 😉

    + , , , , , ,
  • The notebook source code for this article is available on GitHub.

    Last time we saw how to upgrade the MindSpore 2.4.10 + CANN 8.0.0 pre-included with the Ubuntu 22.04 desktop image for OrangePi AIpro (20T) to MindSpore 2.8.0 + CANN 8.5.0.

    MindSpore 2.9.0 + CANN 9.0.0 were released on May 2026 with the following major highlights, among others.

    1. Native support for Ascend 950PR inference-optimized NPUs which the DeepSeek-V4 series LLMs were optimized on
    2. Addition of 2 DeepSeek Sparse Attention (DSA) interfaces under mindspore.ops:
      1. mindspore.ops.sparse_flash_attention
      2. mindspore.ops.lightning_indexer

    This notebook article outlines the process of upgrading from MindSpore 2.8.0 + CANN 8.5.0 on the OrangePi AIpro (20T) development board to the latest MindSpore 2.9.0 + CANN 9.0.0 as of May 2026. We assume you have already replaced Conda from the provided Ubuntu 22.04 desktop image with pyenv for modern, efficient Python virtual environment management.

    Uninstalling CANN 8.5.0

    The steps to uninstall CANN 8.5.0 should be performed outside of any existing Python virtual environment created by pyenv.

    The following uninstallation scripts are provided by CANN 8.5.0 which should be executed with the order given below.

    1. Uninstalll NNAL: /usr/local/Ascend/nnal/atb/latest/scripts/uninstall.sh
    2. Uninstall kernels: /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/script/ops_uninstall.sh
    3. Uninstall the toolkit library: /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/script/uninstall.sh

    These scripts must be run as root. Furthermore, if the log file /var/log/cann_atb_log/cann_atb_install.log does not already exist, make sure it is created and available as the NNAL uninstallation script expects it at that location.

    sudo mkdir -p /var/log/cann_atb_log/
    sudo touch /var/log/cann_atb_log/cann_atb_install.log

    Now run each uninstallation script with root privileges in order.

    sudo /usr/local/Ascend/nnal/atb/latest/scripts/uninstall.sh
    sudo /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/script/ops_uninstall.sh
    sudo /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/script/uninstall.sh

    Remember to clear the /usr/local/Ascend/ascend-toolkit directory as well.

    sudo rm -rvf /usr/local/Ascend/ascend-toolkit/*

    Installing CANN 9.0.0

    The steps to install CANN 9.0.0 should be performed outside of any existing Python virtual environment created by pyenv.

    Download the following .run installers for ARM64 architecture from the CANN community download page.

    1. Toolkit library: Ascend-cann-toolkit_9.0.0_linux-aarch64.run
    2. Kernels (ops) library for Ascend 310B series NPUs: Ascend-cann-310b-ops_9.0.0_linux-aarch64.run
    3. Neural network accelerator library (NNAL): Ascend-cann-nnal_9.0.0_linux-aarch64.run
    from IPython.display import Image
    Image(filename='00-install-cann-900.png')
    png

    Now run each installer with root privileges following the order outlined above. For each set of libraries, answer Y when prompted to accept the Huawei license agreement.

    sudo ./Ascend-cann-toolkit_9.0.0_linux-aarch64.run --install
    sudo ./Ascend-cann-310b-ops_9.0.0_linux-aarch64.run --install
    sudo ./Ascend-cann-nnal_9.0.0_linux-aarch64.run --install

    Once the CANN 9.0.0 libraries are installed, ensure your ~/.bashrc includes the following lines which sets the environment variables required to use CANN 9.0.0. Restart your shell to take effect.

    source /usr/local/Ascend/cann/set_env.sh
    source /usr/local/Ascend/nnal/atb/set_env.sh

    Installing MindSpore 2.9.0

    The steps to install MindSpore 2.9.0 should be performed within a Python virtual environment created by pyenv. The supported Python versions are Python 3.9 through 3.12. We will use Python 3.12 here as an example.

    With CANN 9.0.0 installed and working, let’s go ahead and install MindSpore 2.9.0 and dependent packages. The required packages and associated versions are listed below.

    !cat requirements.txt
    absl-py==2.4.0
    attrs==26.1.0
    cloudpickle==3.1.2
    decorator==5.2.1
    jupyterlab==4.5.7
    jupyterlab-git==0.53.0
    jupyter-resource-usage==1.2.1
    loguru==0.7.3
    matplotlib==3.10.9
    mindspore==2.9.0
    ml-dtypes==0.5.4
    msguard==0.0.8
    openpyxl==3.1.5
    opentelemetry-exporter-otlp-proto-grpc==1.33.1
    opentelemetry-exporter-otlp-proto-http==1.33.1
    pandas~=2.2
    plotly>=5.11.0
    pydantic==2.13.4
    sympy==1.14.0
    tornado==6.5.5

    Install them with Pip.

    %pip install -r requirements.txt
    Requirement already satisfied: absl-py==2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 1)) (2.4.0)
    Requirement already satisfied: attrs==26.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 2)) (26.1.0)
    Requirement already satisfied: cloudpickle==3.1.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 3)) (3.1.2)
    Requirement already satisfied: decorator==5.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 4)) (5.2.1)
    Requirement already satisfied: jupyterlab==4.5.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 5)) (4.5.7)
    Requirement already satisfied: jupyterlab-git==0.53.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 6)) (0.53.0)
    Requirement already satisfied: jupyter-resource-usage==1.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 7)) (1.2.1)
    Requirement already satisfied: loguru==0.7.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 8)) (0.7.3)
    Requirement already satisfied: matplotlib==3.10.9 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 9)) (3.10.9)
    Requirement already satisfied: mindspore==2.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 10)) (2.9.0)
    Requirement already satisfied: ml-dtypes==0.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 11)) (0.5.4)
    Requirement already satisfied: msguard==0.0.8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 12)) (0.0.8)
    Requirement already satisfied: openpyxl==3.1.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 13)) (3.1.5)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-grpc==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 14)) (1.33.1)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-http==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 15)) (1.33.1)
    Requirement already satisfied: pandas~=2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 16)) (2.3.3)
    Requirement already satisfied: plotly>=5.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 17)) (6.7.0)
    Requirement already satisfied: pydantic==2.13.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 18)) (2.13.4)
    Requirement already satisfied: sympy==1.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 19)) (1.14.0)
    Requirement already satisfied: tornado==6.5.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 20)) (6.5.5)
    Requirement already satisfied: async-lru>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.3.0)
    Requirement already satisfied: httpx<1,>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.28.1)
    Requirement already satisfied: ipykernel!=6.30.0,>=6.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (7.2.0)
    Requirement already satisfied: jinja2>=3.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.1.6)
    Requirement already satisfied: jupyter-core in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (5.9.1)
    Requirement already satisfied: jupyter-lsp>=2.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.3.1)
    Requirement already satisfied: jupyter-server<3,>=2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.18.2)
    Requirement already satisfied: jupyterlab-server<3,>=2.28.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.28.0)
    Requirement already satisfied: notebook-shim>=0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.4)
    Requirement already satisfied: packaging in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (26.2)
    Requirement already satisfied: setuptools>=41.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (82.0.1)
    Requirement already satisfied: traitlets in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.7->-r requirements.txt (line 5)) (5.15.0)
    Requirement already satisfied: jupyterlab-git-core>=0.52.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (0.53.0)
    Requirement already satisfied: prometheus-client in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 7)) (0.25.0)
    Requirement already satisfied: psutil>=5.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 7)) (7.2.2)
    Requirement already satisfied: pyzmq>=19 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.1->-r requirements.txt (line 7)) (27.1.0)
    Requirement already satisfied: contourpy>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (1.3.3)
    Requirement already satisfied: cycler>=0.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (0.12.1)
    Requirement already satisfied: fonttools>=4.22.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (4.62.1)
    Requirement already satisfied: kiwisolver>=1.3.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (1.5.0)
    Requirement already satisfied: numpy>=1.23 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (1.26.4)
    Requirement already satisfied: pillow>=8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (12.2.0)
    Requirement already satisfied: pyparsing>=3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (3.3.2)
    Requirement already satisfied: python-dateutil>=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 9)) (2.9.0.post0)
    Requirement already satisfied: protobuf>=3.13.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (5.29.6)
    Requirement already satisfied: asttokens>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (3.0.1)
    Requirement already satisfied: scipy>=1.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (1.17.1)
    Requirement already satisfied: astunparse>=1.6.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (1.6.3)
    Requirement already satisfied: safetensors>=0.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (0.7.0)
    Requirement already satisfied: dill>=0.3.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.9.0->-r requirements.txt (line 10)) (0.4.1)
    Requirement already satisfied: et-xmlfile in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from openpyxl==3.1.5->-r requirements.txt (line 13)) (2.0.0)
    Requirement already satisfied: deprecated>=1.2.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (1.3.1)
    Requirement already satisfied: googleapis-common-protos~=1.52 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (1.75.0)
    Requirement already satisfied: grpcio<2.0.0,>=1.63.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (1.80.0)
    Requirement already satisfied: opentelemetry-api~=1.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (1.33.1)
    Requirement already satisfied: opentelemetry-exporter-otlp-proto-common==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (1.33.1)
    Requirement already satisfied: opentelemetry-proto==1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (1.33.1)
    Requirement already satisfied: opentelemetry-sdk~=1.33.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (1.33.1)
    Requirement already satisfied: requests~=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 15)) (2.33.1)
    Requirement already satisfied: annotated-types>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 18)) (0.7.0)
    Requirement already satisfied: pydantic-core==2.46.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 18)) (2.46.4)
    Requirement already satisfied: typing-extensions>=4.14.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 18)) (4.15.0)
    Requirement already satisfied: typing-inspection>=0.4.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pydantic==2.13.4->-r requirements.txt (line 18)) (0.4.2)
    Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from sympy==1.14.0->-r requirements.txt (line 19)) (1.3.0)
    Requirement already satisfied: pytz>=2020.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pandas~=2.2->-r requirements.txt (line 16)) (2026.2)
    Requirement already satisfied: tzdata>=2022.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pandas~=2.2->-r requirements.txt (line 16)) (2026.2)
    Requirement already satisfied: narwhals>=1.15.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from plotly>=5.11.0->-r requirements.txt (line 17)) (2.21.0)
    Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.9.0->-r requirements.txt (line 10)) (0.47.0)
    Requirement already satisfied: six<2.0,>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.9.0->-r requirements.txt (line 10)) (1.17.0)
    Requirement already satisfied: wrapt<3,>=1.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from deprecated>=1.2.6->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (2.1.2)
    Requirement already satisfied: anyio in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.13.0)
    Requirement already satisfied: certifi in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2026.4.22)
    Requirement already satisfied: httpcore==1.* in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.0.9)
    Requirement already satisfied: idna in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.13)
    Requirement already satisfied: h11>=0.16 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.25.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.16.0)
    Requirement already satisfied: comm>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: debugpy>=1.6.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.8.20)
    Requirement already satisfied: ipython>=7.23.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (9.13.0)
    Requirement already satisfied: jupyter-client>=8.8.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (8.8.0)
    Requirement already satisfied: matplotlib-inline>=0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.2)
    Requirement already satisfied: nest-asyncio>=1.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.6.0)
    Requirement already satisfied: MarkupSafe>=2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jinja2>=3.0.3->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.0.3)
    Requirement already satisfied: platformdirs>=2.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-core->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.9.6)
    Requirement already satisfied: argon2-cffi>=21.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: jupyter-events>=0.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.12.1)
    Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.5.4)
    Requirement already satisfied: nbconvert>=6.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (7.17.1)
    Requirement already satisfied: nbformat>=5.3.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (5.10.4)
    Requirement already satisfied: send2trash>=1.8.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.1.0)
    Requirement already satisfied: terminado>=0.8.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.18.1)
    Requirement already satisfied: websocket-client>=1.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.9.0)
    Requirement already satisfied: pexpect in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core>=0.52.0->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (4.9.0)
    Requirement already satisfied: nbdime~=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (4.0.4)
    Requirement already satisfied: babel>=2.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.18.0)
    Requirement already satisfied: json5>=0.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.14.0)
    Requirement already satisfied: jsonschema>=4.18.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.26.0)
    Requirement already satisfied: importlib-metadata<8.7.0,>=6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-api~=1.15->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (8.6.1)
    Requirement already satisfied: opentelemetry-semantic-conventions==0.54b1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from opentelemetry-sdk~=1.33.1->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (0.54b1)
    Requirement already satisfied: charset_normalizer<4,>=2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests~=2.7->opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 15)) (3.4.7)
    Requirement already satisfied: urllib3<3,>=1.26 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests~=2.7->opentelemetry-exporter-otlp-proto-http==1.33.1->-r requirements.txt (line 15)) (2.7.0)
    Requirement already satisfied: argon2-cffi-bindings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: zipp>=3.20 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from importlib-metadata<8.7.0,>=6.0->opentelemetry-api~=1.15->opentelemetry-exporter-otlp-proto-grpc==1.33.1->-r requirements.txt (line 14)) (3.23.1)
    Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.1.1)
    Requirement already satisfied: jedi>=0.18.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.20.0)
    Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.0.52)
    Requirement already satisfied: pygments>=2.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.20.0)
    Requirement already satisfied: stack_data>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.6.3)
    Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2025.9.1)
    Requirement already satisfied: referencing>=0.28.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.37.0)
    Requirement already satisfied: rpds-py>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.30.0)
    Requirement already satisfied: python-json-logger>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.1.0)
    Requirement already satisfied: pyyaml>=5.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (6.0.3)
    Requirement already satisfied: rfc3339-validator in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.1.4)
    Requirement already satisfied: rfc3986-validator>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.1.1)
    Requirement already satisfied: beautifulsoup4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (4.14.3)
    Requirement already satisfied: bleach!=5.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (6.3.0)
    Requirement already satisfied: defusedxml in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.7.1)
    Requirement already satisfied: jupyterlab-pygments in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.3.0)
    Requirement already satisfied: mistune<4,>=2.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.2.1)
    Requirement already satisfied: nbclient>=0.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.10.4)
    Requirement already satisfied: pandocfilters>=1.4.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: colorama in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (0.4.6)
    Requirement already satisfied: gitpython!=2.1.4,!=2.1.5,!=2.1.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (3.1.50)
    Requirement already satisfied: fastjsonschema>=2.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbformat>=5.3.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.21.2)
    Requirement already satisfied: ptyprocess>=0.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pexpect->jupyterlab-git-core>=0.52.0->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (0.7.0)
    Requirement already satisfied: webencodings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.5.1)
    Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.4.0)
    Requirement already satisfied: gitdb<5,>=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (4.0.12)
    Requirement already satisfied: parso<0.9.0,>=0.8.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jedi>=0.18.2->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.8.7)
    Requirement already satisfied: fqdn in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: isoduration in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (20.11.0)
    Requirement already satisfied: jsonpointer>1.13 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.1.1)
    Requirement already satisfied: rfc3987-syntax>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.1.0)
    Requirement already satisfied: uri-template in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.3.0)
    Requirement already satisfied: webcolors>=24.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (25.10.0)
    Requirement already satisfied: wcwidth in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.7.0)
    Requirement already satisfied: executing>=1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.2.1)
    Requirement already satisfied: pure-eval in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: cffi>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.0.0)
    Requirement already satisfied: soupsieve>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (2.8.3)
    Requirement already satisfied: pycparser in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (3.0)
    Requirement already satisfied: smmap<6,>=3.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitdb<5,>=4.0.1->gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git-core[nbdime]>=0.52.0->jupyterlab-git==0.53.0->-r requirements.txt (line 6)) (5.0.3)
    Requirement already satisfied: lark>=1.2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.3.1)
    Requirement already satisfied: arrow>=0.15.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.7->-r requirements.txt (line 5)) (1.4.0)
    [notice] A new release of pip is available: 25.0.1 -> 26.1
    [notice] To update, run: python -m pip install --upgrade pip
    Note: you may need to restart the kernel to use updated packages.

    Now run the verification script below to confirm that MindSpore 2.9.0 is installed successfully. We use mindspore.set_device in place of mindspore.set_context since the latter is deprecated and will be removed in a future version of MindSpore.

    import mindspore
    mindspore.set_device(device_target='Ascend')
    mindspore.run_check()
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-9.0.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    MindSpore version: 2.9.0
    The result of multiplication calculation is correct, MindSpore has been installed on platform [Ascend] successfully!

    We can safely ignore any warnings generated as long as there are no lines starting with [ERROR] or [CRITICAL], in which case kindly consult the Ascend forum for assistance. Usually, absent any hardware issues, such error messages are caused by overly restrictive permissions in the CANN-related directories which can be fixed by relaxing the directory permissions appropriately.

    The expected output from a successful MindSpore 2.9.0 installation is repeated below.

    MindSpore version: 2.9.0
    The result of multiplication calculation is correct, MindSpore has been installed on platform [Ascend] successfully!

    Concluding remarks and going further

    We saw in this article how to install and use the latest versions of MindSpore and CANN on the OrangePi AIpro (20T) development board.

    I hope you enjoyed following through this article as much as I did writing it and stay tuned for updates 😉

    + , , , ,
  • The notebook source code for this article is available on GitHub.

    PyTorch is an open source deep learning framework in Python originally developed by Meta, now hosted under the vendor-neutral PyTorch Foundation. It is the de-facto industry standard for training modern deep learning models and large language models (LLMs). Like most other deep learning frameworks, PyTorch natively supports accelerating machine learning workloads on NVIDIA GPUs through its CUDA ecosystem without the need for special plugins or adapters.

    The torch-npu plugin developed by the Huawei Ascend community enables AI/ML engineers to migrate machine learning workloads from NVIDIA GPUs to Ascend NPUs seamlessly with minimal changes to existing code and processes. With the high-level model training logic in PyTorch unchanged, the CANN kernels library is used in place of CUDA and Ascend NPUs are used for hardware acceleration in place of NVIDIA GPUs.

    This notebook experiment serves as a gentle introduction to migrating deep learning models written in PyTorch to the Ascend ecosystem, using the Fashion MNIST dataset as our motivating example.

    Prerequisites

    The content in this notebook experiment builds upon the first 6 chapters of Dive into Deep Learning, also known as D2L.

    Python version and dependencies

    This notebook experiment runs on Python 3.11 with the following Python package dependencies.

    1. PyTorch 2.8.0
    2. TorchVision 0.23.0
    3. PyYAML 6.0.3
    4. setuptools 82.0.1
    5. torch-npu 2.8.0
    6. CANN 8.5.0
    7. Matplotlib 3.10.9
    8. ONNX 1.21.0
    9. onnxscript 0.7.0
    !cat requirements.txt
    absl-py==2.4.0
    attrs==25.4.0
    cloudpickle==3.1.2
    decorator==5.2.1
    jupyterlab==4.5.6
    jupyterlab-git==0.52.0
    jupyter-resource-usage==1.2.0
    matplotlib==3.10.9
    ml-dtypes==0.5.4
    onnx==1.21.0
    onnxscript==0.7.0
    torch==2.8.0
    torch-npu==2.8.0
    pyyaml==6.0.3
    scipy==1.17.1
    setuptools==82.0.1
    sympy==1.14.0
    torchvision==0.23.0
    tornado==6.5.5
    %pip install -r requirements.txt
    Requirement already satisfied: absl-py==2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 1)) (2.4.0)
    Requirement already satisfied: attrs==25.4.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 2)) (25.4.0)
    Requirement already satisfied: cloudpickle==3.1.2 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 3)) (3.1.2)
    Requirement already satisfied: decorator==5.2.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 4)) (5.2.1)
    Requirement already satisfied: jupyterlab==4.5.6 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 5)) (4.5.6)
    Requirement already satisfied: jupyterlab-git==0.52.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 6)) (0.52.0)
    Requirement already satisfied: jupyter-resource-usage==1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 7)) (1.2.0)
    Requirement already satisfied: matplotlib==3.10.9 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 8)) (3.10.9)
    Requirement already satisfied: ml-dtypes==0.5.4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 9)) (0.5.4)
    Requirement already satisfied: onnx==1.21.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 10)) (1.21.0)
    Requirement already satisfied: onnxscript==0.7.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 11)) (0.7.0)
    Requirement already satisfied: torch==2.8.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 12)) (2.8.0)
    Requirement already satisfied: torch-npu==2.8.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 13)) (2.8.0)
    Requirement already satisfied: pyyaml==6.0.3 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 14)) (6.0.3)
    Requirement already satisfied: scipy==1.17.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 15)) (1.17.1)
    Requirement already satisfied: setuptools==82.0.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 16)) (82.0.1)
    Requirement already satisfied: sympy==1.14.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 17)) (1.14.0)
    Requirement already satisfied: torchvision==0.23.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 18)) (0.23.0)
    Requirement already satisfied: tornado==6.5.5 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from -r requirements.txt (line 19)) (6.5.5)
    Requirement already satisfied: async-lru>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.3.0)
    Requirement already satisfied: httpx<1,>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.28.1)
    Requirement already satisfied: ipykernel!=6.30.0,>=6.5.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (7.2.0)
    Requirement already satisfied: jinja2>=3.0.3 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.1.6)
    Requirement already satisfied: jupyter-core in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (5.9.1)
    Requirement already satisfied: jupyter-lsp>=2.0.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.3.1)
    Requirement already satisfied: jupyter-server<3,>=2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.17.0)
    Requirement already satisfied: jupyterlab-server<3,>=2.28.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.28.0)
    Requirement already satisfied: notebook-shim>=0.2 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.4)
    Requirement already satisfied: packaging in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (26.2)
    Requirement already satisfied: traitlets in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (5.14.3)
    Requirement already satisfied: nbdime~=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (4.0.4)
    Requirement already satisfied: nbformat in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (5.10.4)
    Requirement already satisfied: pexpect in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (4.9.0)
    Requirement already satisfied: prometheus-client in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 7)) (0.25.0)
    Requirement already satisfied: psutil>=5.6 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 7)) (7.2.2)
    Requirement already satisfied: pyzmq>=19 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 7)) (27.1.0)
    Requirement already satisfied: contourpy>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (1.3.3)
    Requirement already satisfied: cycler>=0.10 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (0.12.1)
    Requirement already satisfied: fonttools>=4.22.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (4.62.1)
    Requirement already satisfied: kiwisolver>=1.3.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (1.5.0)
    Requirement already satisfied: numpy>=1.23 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (2.4.4)
    Requirement already satisfied: pillow>=8 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (12.2.0)
    Requirement already satisfied: pyparsing>=3 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (3.3.2)
    Requirement already satisfied: python-dateutil>=2.7 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from matplotlib==3.10.9->-r requirements.txt (line 8)) (2.9.0.post0)
    Requirement already satisfied: protobuf>=4.25.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from onnx==1.21.0->-r requirements.txt (line 10)) (7.34.1)
    Requirement already satisfied: typing_extensions>=4.7.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from onnx==1.21.0->-r requirements.txt (line 10)) (4.15.0)
    Requirement already satisfied: onnx_ir<2,>=0.1.16 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from onnxscript==0.7.0->-r requirements.txt (line 11)) (0.2.1)
    Requirement already satisfied: filelock in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from torch==2.8.0->-r requirements.txt (line 12)) (3.29.0)
    Requirement already satisfied: networkx in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from torch==2.8.0->-r requirements.txt (line 12)) (3.6.1)
    Requirement already satisfied: fsspec in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from torch==2.8.0->-r requirements.txt (line 12)) (2026.3.0)
    Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from sympy==1.14.0->-r requirements.txt (line 17)) (1.3.0)
    Requirement already satisfied: anyio in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.13.0)
    Requirement already satisfied: certifi in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2026.4.22)
    Requirement already satisfied: httpcore==1.* in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.0.9)
    Requirement already satisfied: idna in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.13)
    Requirement already satisfied: h11>=0.16 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.16.0)
    Requirement already satisfied: comm>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: debugpy>=1.6.5 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.8.20)
    Requirement already satisfied: ipython>=7.23.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (9.13.0)
    Requirement already satisfied: jupyter-client>=8.8.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (8.8.0)
    Requirement already satisfied: matplotlib-inline>=0.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.1)
    Requirement already satisfied: nest-asyncio>=1.4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.6.0)
    Requirement already satisfied: MarkupSafe>=2.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jinja2>=3.0.3->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.0.3)
    Requirement already satisfied: platformdirs>=2.5 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-core->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.9.6)
    Requirement already satisfied: argon2-cffi>=21.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: jupyter-events>=0.11.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.12.1)
    Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.5.4)
    Requirement already satisfied: nbconvert>=6.4.4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (7.17.1)
    Requirement already satisfied: overrides>=5.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (7.7.0)
    Requirement already satisfied: send2trash>=1.8.2 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.1.0)
    Requirement already satisfied: terminado>=0.8.3 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.18.1)
    Requirement already satisfied: websocket-client>=1.7 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.9.0)
    Requirement already satisfied: babel>=2.10 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.18.0)
    Requirement already satisfied: json5>=0.9.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.14.0)
    Requirement already satisfied: jsonschema>=4.18.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.26.0)
    Requirement already satisfied: requests>=2.31 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.33.1)
    Requirement already satisfied: colorama in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (0.4.6)
    Requirement already satisfied: gitpython!=2.1.4,!=2.1.5,!=2.1.6 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (3.1.47)
    Requirement already satisfied: pygments in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (2.20.0)
    Requirement already satisfied: fastjsonschema>=2.15 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbformat->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (2.21.2)
    Requirement already satisfied: six>=1.5 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from python-dateutil>=2.7->matplotlib==3.10.9->-r requirements.txt (line 8)) (1.17.0)
    Requirement already satisfied: ptyprocess>=0.5 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from pexpect->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (0.7.0)
    Requirement already satisfied: argon2-cffi-bindings in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: gitdb<5,>=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (4.0.12)
    Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.1.1)
    Requirement already satisfied: jedi>=0.18.2 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.19.2)
    Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.0.52)
    Requirement already satisfied: stack_data>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.6.3)
    Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2025.9.1)
    Requirement already satisfied: referencing>=0.28.4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.37.0)
    Requirement already satisfied: rpds-py>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.30.0)
    Requirement already satisfied: python-json-logger>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.1.0)
    Requirement already satisfied: rfc3339-validator in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.1.4)
    Requirement already satisfied: rfc3986-validator>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.1.1)
    Requirement already satisfied: beautifulsoup4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.14.3)
    Requirement already satisfied: bleach!=5.0.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (6.3.0)
    Requirement already satisfied: defusedxml in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.7.1)
    Requirement already satisfied: jupyterlab-pygments in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.3.0)
    Requirement already satisfied: mistune<4,>=2.0.3 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.2.0)
    Requirement already satisfied: nbclient>=0.5.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.10.4)
    Requirement already satisfied: pandocfilters>=1.4.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: charset_normalizer<4,>=2 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.4.7)
    Requirement already satisfied: urllib3<3,>=1.26 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.6.3)
    Requirement already satisfied: webencodings in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.5.1)
    Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.4.0)
    Requirement already satisfied: smmap<6,>=3.0.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from gitdb<5,>=4.0.1->gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (5.0.3)
    Requirement already satisfied: parso<0.9.0,>=0.8.4 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jedi>=0.18.2->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.8.6)
    Requirement already satisfied: fqdn in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: isoduration in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (20.11.0)
    Requirement already satisfied: jsonpointer>1.13 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.1.1)
    Requirement already satisfied: rfc3987-syntax>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.1.0)
    Requirement already satisfied: uri-template in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.3.0)
    Requirement already satisfied: webcolors>=24.6.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (25.10.0)
    Requirement already satisfied: wcwidth in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.6.0)
    Requirement already satisfied: executing>=1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.2.1)
    Requirement already satisfied: asttokens>=2.1.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.0.1)
    Requirement already satisfied: pure-eval in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: cffi>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.0.0)
    Requirement already satisfied: soupsieve>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.8.3)
    Requirement already satisfied: pycparser in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.0)
    Requirement already satisfied: lark>=1.2.2 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.3.1)
    Requirement already satisfied: arrow>=0.15.0 in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.4.0)
    Requirement already satisfied: tzdata in /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2026.2)
    [notice] A new release of pip is available: 24.0 -> 26.1
    [notice] To update, run: python -m pip install --upgrade pip
    Note: you may need to restart the kernel to use updated packages.

    Confirming that NPU acceleration is available

    The torch.npu.is_available method reports whether Ascend NPU acceleration is available.

    import torch
    import torch_npu
    torch.npu.is_available()
    /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages/torch_npu/utils/collect_env.py:58: UserWarning: Warning: The /usr/local/Ascend/cann-8.5.0 owner does not match the current owner.
    warnings.warn(f"Warning: The {path} owner does not match the current owner.")
    /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages/torch_npu/utils/collect_env.py:58: UserWarning: Warning: The /usr/local/Ascend/cann-8.5.0/aarch64-linux/ascend_toolkit_install.info owner does not match the current owner.
    warnings.warn(f"Warning: The {path} owner does not match the current owner.")
    /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages/torch_npu/utils/collect_env.py:58: UserWarning: Warning: The /usr/local/Ascend/cann-8.5.0 owner does not match the current owner.
    warnings.warn(f"Warning: The {path} owner does not match the current owner.")
    /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages/torch_npu/utils/collect_env.py:58: UserWarning: Warning: The /usr/local/Ascend/cann-8.5.0/aarch64-linux/ascend_toolkit_install.info owner does not match the current owner.
    warnings.warn(f"Warning: The {path} owner does not match the current owner.")
    /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages/torch_npu/__init__.py:309: UserWarning: On the interactive interface, the value of TASK_QUEUE_ENABLE is set to 0 by default. Do not set it to 1 to prevent some unknown errors
    warnings.warn("On the interactive interface, the value of TASK_QUEUE_ENABLE is set to 0 by default. \
    True

    Warnings can be safely ignored unless you see messages starting with [ERROR] or [CRITICAL] in which case consult the Ascend forum for assistance.

    As shown in the output above, NPU acceleration is available on our OrangePi AIpro (20T) development board which includes a single Ascend 310B1 NPU chip and core.

    We can also get the number of available NPUs with torch.npu.device_count and the current device ID with torch.npu.current_device.

    torch.npu.device_count()
    1
    torch.npu.current_device()
    0

    Our OrangePi AIpro (20T) development board has a single NPU chip and core so PyTorch returns 1 for the device count and 0 for the current device ID as expected.

    Let’s verify the results from PyTorch with the npu-smi command-line utility.

    !npu-smi info
    +--------------------------------------------------------------------------------------------------------+
    | npu-smi 23.0.0 Version: 23.0.0 |
    +-------------------------------+-----------------+------------------------------------------------------+
    | NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page) |
    | Chip Device | Bus-Id | AICore(%) Memory-Usage(MB) |
    +===============================+=================+======================================================+
    | 0 310B1 | Alarm | 0.0 53 24 / 24 |
    | 0 0 | NA | 0 7630 / 23673 |
    +===============================+=================+======================================================+

    As reported above, we have a single Ascend 310B1 NPU chip and core on our development board.

    Copying tensors to device memory

    PyTorch tensors reside in main memory by default. Main memory is also commonly known as random access memory (RAM) or CPU RAM.

    Let’s create a $2 \times 2$ matrix with torch.randn and query its device attribute to confirm that our tensor resides in main memory.

    A = torch.randn(2, 2)
    A, A.device
    (tensor([[ 0.0325, 0.2070],
    [-0.4967, -1.5113]]),
    device(type='cpu'))

    The device attribute returns device(type='cpu') which confirms our tensor is residing in main memory. In many cases, we’ll want to copy our tensor to NPU device memory. This allows us to perform computationally intensive operations such as matrix multiplication directly on the NPU device to speed up the model training process.

    Let’s use the npu method on our tensor to move it to (NPU) device memory and confirm that the device attribute on our tensor is updated appropriately.

    A = A.npu()
    A, A.device
    [W501 10:43:25.136407353 compiler_depend.ts:164] Warning: Device do not support double dtype now, dtype cast replace with float. (function operator())
    .
    (tensor([[ 0.0325, 0.2070],
    [-0.4967, -1.5113]], device='npu:0'),
    device(type='npu', index=0))

    The device attribute of our resulting tensor now reports device(type='npu', index=0), confirming that it is now copied to device memory.

    Initializing tensors directly to device memory

    Instead of creating our tensors in main memory only to copy them to device memory, we can initialize our tensors directly to device memory. This spares us the overhead of copying our data across different devices which poses non-trivial communication overhead.

    Use torch.device to construct an object representing our NPU device, then specify it in the device parameter of tensor constructors such as torch.randn. Alternatively, we can specify the device parameter during tensor initialization as the string 'npu:0' directly – both are functionally equivalent.

    npu_0 = torch.device('npu:0')
    npu_0
    device(type='npu', index=0)
    M0 = torch.randn(2, 2, device=npu_0)
    M1 = torch.randn(2, 2, device='npu:0')
    M0, M1, M0.device, M1.device
    (tensor([[-0.1831, 0.7490],
    [-0.2751, 0.5227]], device='npu:0'),
    tensor([[ 0.7776, -1.0241],
    [-0.6603, 0.9278]], device='npu:0'),
    device(type='npu', index=0),
    device(type='npu', index=0))

    Let’s multiply the 2 matrices with the @ operator. As both matrices are on the same NPU device with index 0, the product also automatically resides on the same NPU device memory.

    M = M0 @ M1
    M, M.device
    (tensor([[-0.6370, 0.8825],
    [-0.5591, 0.7667]], device='npu:0'),
    device(type='npu', index=0))

    Automatic migration of PyTorch CUDA code to Ascend

    Imagine you have a deep learning project written in PyTorch leveraging NVIDIA’s CUDA framework for GPU acceleration. Your codebase may already be riddled with CUDA calls like such: X.cuda()

    To migrate your codebase to run on Ascend NPUs, you would normally need to refactor the codebase manually to replace the CUDA calls to npu calls: X.cuda() $\rightarrow$ X.npu(). While this in itself is relatively straightforward, it is nevertheless grunt work producing no business value which you would rather avoid.

    Fortunately, the torch_npu.contrib module provides the transfer_to_npu submodule which you can import by adding a single line to your existing codebase. It automatically intercepts CUDA calls and converts them to NPU calls under the hood.

    Let’s see it in action!

    from torch_npu.contrib import transfer_to_npu
    torch.cuda.is_available()
    /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages/torch_npu/contrib/transfer_to_npu.py:347: ImportWarning:
    *************************************************************************************************************
    The torch.Tensor.cuda and torch.nn.Module.cuda are replaced with torch.Tensor.npu and torch.nn.Module.npu now..
    The torch.cuda.DoubleTensor is replaced with torch.npu.FloatTensor cause the double type is not supported now..
    The backend in torch.distributed.init_process_group set to hccl now..
    The torch.cuda.* and torch.cuda.amp.* are replaced with torch.npu.* and torch.npu.amp.* now..
    The device parameters have been replaced with npu in the function below:
    torch.logspace, torch.randint, torch.hann_window, torch.rand, torch.full_like, torch.ones_like, torch.rand_like, torch.randperm, torch.arange, torch.frombuffer, torch.normal, torch._empty_per_channel_affine_quantized, torch.empty_strided, torch.empty_like, torch.scalar_tensor, torch.tril_indices, torch.bartlett_window, torch.ones, torch.sparse_coo_tensor, torch.randn, torch.kaiser_window, torch.tensor, torch.triu_indices, torch.as_tensor, torch.zeros, torch.randint_like, torch.full, torch.eye, torch._sparse_csr_tensor_unsafe, torch.empty, torch._sparse_coo_tensor_unsafe, torch.blackman_window, torch.zeros_like, torch.range, torch.sparse_csr_tensor, torch.randn_like, torch.from_file, torch._cudnn_init_dropout_state, torch._empty_affine_quantized, torch.linspace, torch.hamming_window, torch.empty_quantized, torch._pin_memory, torch.load, torch.set_default_device, torch.get_device_module, torch.sparse_compressed_tensor, torch.Tensor.new_empty, torch.Tensor.new_empty_strided, torch.Tensor.new_full, torch.Tensor.new_ones, torch.Tensor.new_tensor, torch.Tensor.new_zeros, torch.Tensor.to, torch.Tensor.pin_memory, torch.nn.Module.to, torch.nn.Module.to_empty
    *************************************************************************************************************
    warnings.warn(msg, ImportWarning)
    /home/HwHiAiUser/.pyenv/versions/3.11.15/envs/orangepiaipro-20t/lib/python3.11/site-packages/torch_npu/contrib/transfer_to_npu.py:276: RuntimeWarning: torch.jit.script and torch.jit.script_method will be disabled by transfer_to_npu, which currently does not support them, if you need to enable them, please do not use transfer_to_npu.
    warnings.warn(msg, RuntimeWarning)
    True
    torch.cuda.device_count(), torch.cuda.current_device()
    (1, 0)
    gpu_0 = torch.device('cuda:0')
    gpu_0
    device(type='cuda', index=0)
    P0 = torch.randn(2, 2, device=gpu_0)
    P1 = torch.randn(2, 2, device='cuda:0')
    P0, P1, P0.device, P1.device
    (tensor([[-3.4023, -1.1358],
    [-1.0057, 0.0248]], device='npu:0'),
    tensor([[-0.8602, -0.5356],
    [-0.5590, 0.0599]], device='npu:0'),
    device(type='npu', index=0),
    device(type='npu', index=0))
    P = P0 @ P1
    P, P.device
    (tensor([[3.5616, 1.7543],
    [0.8512, 0.5401]], device='npu:0'),
    device(type='npu', index=0))

    With our PyTorch CUDA codebase seamlessly migrated to Ascend NPU, let’s see a more realistic example in action – training a multilayer perceptron (MLP) model on the Fashion MNIST dataset. We’ll use CUDA calls throughout our motivating example to demonstrate that none of your existing code needs to be manually migrated – what worked on NVIDIA GPUs will continue to work on Ascend NPUs as-is!

    Training a deep neural network on the Fashion MNIST dataset

    Let’s train a deep neural network on the Fashion MNIST dataset. Before that, let’s load the dataset and visualize a few samples to understand what kind of data we’re working with.

    This example is based on the official Training with PyTorch tutorial but we won’t be using convolutional neural networks (CNNs) here since they are covered in chapter 7 of D2L which we haven’t reached yet. Instead, we’ll just use a simple MLP model with multiple fully connected layers and dropout.

    Visualizing the dataset

    The torchvision.datasets.FashionMNIST class optionally downloads the dataset if download=True, then loads the dataset as PIL images and applies the transformation(s) defined in the transform parameter.

    Let’s set train=True which fetches the training set and apply torchvision.transforms.ToTensor to convert the images to PyTorch tensors.

    from torchvision import datasets, transforms
    data_dir = 'data/'
    visualize_data = datasets.FashionMNIST(root=data_dir,
    train=True,
    transform=transforms.ToTensor(),
    download=True)

    Next, we need to load and batch the data with torch.utils.data.DataLoader. Let’s specify a batch size of 10 and take just the first batch, visualizing the images and labels with Matplotlib.

    from torch.utils.data import DataLoader
    visualize_loader = DataLoader(visualize_data, batch_size=10, shuffle=True)
    X_samples, y_samples = next(iter(visualize_loader))
    X_samples.shape, y_samples.shape, X_samples.device, y_samples.device
    (torch.Size([10, 1, 28, 28]),
    torch.Size([10]),
    device(type='cpu'),
    device(type='cpu'))

    Note that the loaded samples reside in main memory. That’s fine since we’re just visualizing the images with Matplotlib – no need to use our Ascend NPU for now.

    X_samples, y_samples = X_samples.numpy(), y_samples.numpy()
    X_samples = X_samples.transpose(0, 2, 3, 1) # Convert CHW format back to HWC
    X_samples.shape, y_samples.shape
    ((10, 28, 28, 1), (10,))
    import matplotlib.pyplot as plt
    LABELS = [
    'T-shirt/top',
    'Trouser',
    'Pullover',
    'Dress',
    'Coat',
    'Sandal',
    'Shirt',
    'Sneaker',
    'Bag',
    'Ankle boot'
    ]
    fig, axes = plt.subplots(2, 5)
    for axis_idx, axis in enumerate(axes.flatten()):
    axis.set_title(LABELS[y_samples[axis_idx]])
    axis.imshow(X_samples[axis_idx])
    axis.axis('off')
    fig.tight_layout()
    fig.show()
    Fashion MNIST images and labels

    Loading and transforming our dataset

    Now we know what our data looks like, let’s load and transform it in a format suitable for training our model.

    The images are transformed via the following 3-step process, which is all handled automatically with the torchvision.transforms.ToTensor transformation we saw earlier.

    1. Resize all images to $28 \times 28$ pixels
    2. Rescale all channels from integer in range $[0, 255]$ to float in range $[0, 1]$
    3. Change the shape of each image from format (height, width, channels) to (channels, height, width)

    Unlike MindSpore 2.8.0, PyTorch recommends we keep the labels as class indices without one-hot encoding for optimized computation of the torch.nn.CrossEntropyLoss we’ll see later.

    train_data = datasets.FashionMNIST(root=data_dir,
    train=True,
    transform=transforms.ToTensor())
    test_data = datasets.FashionMNIST(root=data_dir,
    train=False,
    transform=transforms.ToTensor())

    For training, we’ll split our data in batches of $2^9=512$ samples. For validation, we’ll use a single batch of $10,000$ samples.

    train_loader = DataLoader(train_data, batch_size=512, shuffle=True)
    test_loader = DataLoader(test_data, batch_size=10000, shuffle=True)

    Defining our neural network, optimizer, activation and loss functions

    Here’s the neural network we’ll be using.

    1. Flatten the images to $28 \times 28 \times 1 = 784$ features
    2. 1st hidden layer with $784$ input channels and $2^{10}=1024$ output channels, ReLU activation
    3. 1st dropout layer with $p = 0.3$
    4. 2nd hidden layer with $1024$ input channels and $2^9=512$ output channels, ReLU activation
    5. 2nd dropout layer with $p = 0.2$
    6. Fully connected layer with $512$ input channels and $10$ output channels

    We’ll also copy our model to device memory using the to method. Confirm that our resulting model is in device memory by accessing its parameters with the parameters method which returns an iterator.

    import torch.nn as nn
    model = nn.Sequential(
    nn.Flatten(),
    nn.Linear(784, 1024),
    nn.ReLU(),
    nn.Dropout(0.3),
    nn.Linear(1024, 512),
    nn.ReLU(),
    nn.Dropout(0.2),
    nn.Linear(512, 10)
    ).to(gpu_0)
    model, next(model.parameters()).device
    (Sequential(
    (0): Flatten(start_dim=1, end_dim=-1)
    (1): Linear(in_features=784, out_features=1024, bias=True)
    (2): ReLU()
    (3): Dropout(p=0.3, inplace=False)
    (4): Linear(in_features=1024, out_features=512, bias=True)
    (5): ReLU()
    (6): Dropout(p=0.2, inplace=False)
    (7): Linear(in_features=512, out_features=10, bias=True)
    ),
    device(type='npu', index=0))

    Use torch.nn.CrossEntropyLoss for our loss function. It combines softmax activation and cross-entropy loss under the hood using the LogSumExp trick to prevent numerical underflow and overflow.

    criterion = nn.CrossEntropyLoss()
    criterion
    CrossEntropyLoss()

    For the optimizer, use torch.optim.SGD with the following hyperparameters.

    1. Learning rate: 0.01
    2. Weight decay: 1e-3
    3. Momentum: 0.9
    import torch.optim as optim
    optimizer = optim.SGD(params=model.parameters(), lr=0.01, weight_decay=1e-3, momentum=0.9)
    optimizer
    SGD (
    Parameter Group 0
    dampening: 0
    differentiable: False
    foreach: None
    fused: None
    lr: 0.01
    maximize: False
    momentum: 0.9
    nesterov: False
    weight_decay: 0.001
    )

    With our neural network, combined activation + loss function, optimizer and hyperparameters defined, it’s time to define our training loop.

    Training our neural network

    Let’s train our model over 20 epochs. We define the per-batch and per-epoch training logic as below.

    def train_batch(X_batch, y_batch):
    optimizer.zero_grad()
    y_hat = model(X_batch)
    loss = criterion(y_hat, y_batch)
    loss.backward()
    optimizer.step()
    return loss.item()
    def train_epoch(epoch=0):
    training_losses = []
    print(f'Epoch {epoch} start')
    model.train(True)
    batch_count = len(train_loader)
    for batch_idx, (X_batch, y_batch) in enumerate(train_loader):
    loss = train_batch(X_batch.to(gpu_0), y_batch.to(gpu_0))
    if batch_idx % 10 == 0:
    print(f'Training loss: {loss:.4f} [{batch_idx}/{batch_count}]')
    training_losses.append(loss)
    print(f'Epoch {epoch} end')
    return training_losses

    Define our validation logic at the end of each epoch as well.

    def validate_epoch(epoch=0):
    model.eval()
    validation_loss = None
    with torch.no_grad():
    X_test, y_test = next(iter(test_loader))
    y_hat = model(X_test.to(gpu_0))
    validation_loss = criterion(y_hat, y_test.to(gpu_0))
    validation_loss = validation_loss.item()
    print(f'Validation loss at epoch {epoch}: {validation_loss:.4f}')
    return validation_loss

    Now train our model using the utility functions defined above.

    epochs = 20
    training_losses = []
    validation_losses = []
    for epoch in range(epochs):
    training_losses.extend(train_epoch(epoch=epoch))
    validation_losses.append(validate_epoch(epoch=epoch))
    len(training_losses), len(validation_losses)
    Epoch 0 start
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/common/context/op_context.py:38: DeprecationWarning: currentThread() is deprecated, use current_thread() instead
    return _contexts.setdefault(threading.currentThread().ident, [])
    ..Training loss: 2.3067 [0/118]
    Training loss: 2.2449 [10/118]
    Training loss: 2.1330 [20/118]
    Training loss: 1.9472 [30/118]
    Training loss: 1.6020 [40/118]
    Training loss: 1.3151 [50/118]
    Training loss: 1.1242 [60/118]
    Training loss: 0.9828 [70/118]
    Training loss: 0.9193 [80/118]
    Training loss: 0.9016 [90/118]
    Training loss: 0.8678 [100/118]
    Training loss: 0.8293 [110/118]
    ..Epoch 0 end
    Validation loss at epoch 0: 0.7749
    Epoch 1 start
    Training loss: 0.7629 [0/118]
    Training loss: 0.7416 [10/118]
    Training loss: 0.7207 [20/118]
    Training loss: 0.7641 [30/118]
    Training loss: 0.7532 [40/118]
    Training loss: 0.7241 [50/118]
    Training loss: 0.7039 [60/118]
    Training loss: 0.6603 [70/118]
    Training loss: 0.7116 [80/118]
    Training loss: 0.5626 [90/118]
    Training loss: 0.6959 [100/118]
    Training loss: 0.6535 [110/118]
    Epoch 1 end
    Validation loss at epoch 1: 0.6184
    Epoch 2 start
    Training loss: 0.7138 [0/118]
    Training loss: 0.5561 [10/118]
    Training loss: 0.5997 [20/118]
    Training loss: 0.6026 [30/118]
    Training loss: 0.5982 [40/118]
    Training loss: 0.5553 [50/118]
    Training loss: 0.6269 [60/118]
    Training loss: 0.6159 [70/118]
    Training loss: 0.6426 [80/118]
    Training loss: 0.5798 [90/118]
    Training loss: 0.6270 [100/118]
    Training loss: 0.6189 [110/118]
    Epoch 2 end
    Validation loss at epoch 2: 0.5488
    Epoch 3 start
    Training loss: 0.5850 [0/118]
    Training loss: 0.5595 [10/118]
    Training loss: 0.5223 [20/118]
    Training loss: 0.5472 [30/118]
    Training loss: 0.5331 [40/118]
    Training loss: 0.5496 [50/118]
    Training loss: 0.5380 [60/118]
    Training loss: 0.5581 [70/118]
    Training loss: 0.5393 [80/118]
    Training loss: 0.5286 [90/118]
    Training loss: 0.5057 [100/118]
    Training loss: 0.5996 [110/118]
    Epoch 3 end
    Validation loss at epoch 3: 0.5119
    Epoch 4 start
    Training loss: 0.5086 [0/118]
    Training loss: 0.5163 [10/118]
    Training loss: 0.5191 [20/118]
    Training loss: 0.4908 [30/118]
    Training loss: 0.4604 [40/118]
    Training loss: 0.5194 [50/118]
    Training loss: 0.5331 [60/118]
    Training loss: 0.4916 [70/118]
    Training loss: 0.5372 [80/118]
    Training loss: 0.5035 [90/118]
    Training loss: 0.5856 [100/118]
    Training loss: 0.4825 [110/118]
    Epoch 4 end
    Validation loss at epoch 4: 0.4875
    Epoch 5 start
    Training loss: 0.4477 [0/118]
    Training loss: 0.4837 [10/118]
    Training loss: 0.4735 [20/118]
    Training loss: 0.4469 [30/118]
    Training loss: 0.4205 [40/118]
    Training loss: 0.4833 [50/118]
    Training loss: 0.4881 [60/118]
    Training loss: 0.4871 [70/118]
    Training loss: 0.4963 [80/118]
    Training loss: 0.5154 [90/118]
    Training loss: 0.4818 [100/118]
    Training loss: 0.4846 [110/118]
    Epoch 5 end
    Validation loss at epoch 5: 0.4772
    Epoch 6 start
    Training loss: 0.4566 [0/118]
    Training loss: 0.4809 [10/118]
    Training loss: 0.4806 [20/118]
    Training loss: 0.4843 [30/118]
    Training loss: 0.4679 [40/118]
    Training loss: 0.4649 [50/118]
    Training loss: 0.5032 [60/118]
    Training loss: 0.5153 [70/118]
    Training loss: 0.4867 [80/118]
    Training loss: 0.4000 [90/118]
    Training loss: 0.4270 [100/118]
    Training loss: 0.4309 [110/118]
    Epoch 6 end
    Validation loss at epoch 6: 0.4598
    Epoch 7 start
    Training loss: 0.4656 [0/118]
    Training loss: 0.3989 [10/118]
    Training loss: 0.4370 [20/118]
    Training loss: 0.4929 [30/118]
    Training loss: 0.4629 [40/118]
    Training loss: 0.4670 [50/118]
    Training loss: 0.4424 [60/118]
    Training loss: 0.4256 [70/118]
    Training loss: 0.4454 [80/118]
    Training loss: 0.4492 [90/118]
    Training loss: 0.4566 [100/118]
    Training loss: 0.4117 [110/118]
    Epoch 7 end
    Validation loss at epoch 7: 0.4521
    Epoch 8 start
    Training loss: 0.4429 [0/118]
    Training loss: 0.3813 [10/118]
    Training loss: 0.4334 [20/118]
    Training loss: 0.4130 [30/118]
    Training loss: 0.4505 [40/118]
    Training loss: 0.3780 [50/118]
    Training loss: 0.4415 [60/118]
    Training loss: 0.4462 [70/118]
    Training loss: 0.4231 [80/118]
    Training loss: 0.4326 [90/118]
    Training loss: 0.4013 [100/118]
    Training loss: 0.3960 [110/118]
    Epoch 8 end
    Validation loss at epoch 8: 0.4310
    Epoch 9 start
    Training loss: 0.4525 [0/118]
    Training loss: 0.4325 [10/118]
    Training loss: 0.4027 [20/118]
    Training loss: 0.4604 [30/118]
    Training loss: 0.4497 [40/118]
    Training loss: 0.3951 [50/118]
    Training loss: 0.4039 [60/118]
    Training loss: 0.4220 [70/118]
    Training loss: 0.4026 [80/118]
    Training loss: 0.3540 [90/118]
    Training loss: 0.3990 [100/118]
    Training loss: 0.4156 [110/118]
    Epoch 9 end
    Validation loss at epoch 9: 0.4340
    Epoch 10 start
    Training loss: 0.3414 [0/118]
    Training loss: 0.4657 [10/118]
    Training loss: 0.4249 [20/118]
    Training loss: 0.3894 [30/118]
    Training loss: 0.4244 [40/118]
    Training loss: 0.3674 [50/118]
    Training loss: 0.4154 [60/118]
    Training loss: 0.3856 [70/118]
    Training loss: 0.4114 [80/118]
    Training loss: 0.3649 [90/118]
    Training loss: 0.4157 [100/118]
    Training loss: 0.4477 [110/118]
    Epoch 10 end
    Validation loss at epoch 10: 0.4197
    Epoch 11 start
    Training loss: 0.4068 [0/118]
    Training loss: 0.3972 [10/118]
    Training loss: 0.3927 [20/118]
    Training loss: 0.4212 [30/118]
    Training loss: 0.4322 [40/118]
    Training loss: 0.4423 [50/118]
    Training loss: 0.3696 [60/118]
    Training loss: 0.3813 [70/118]
    Training loss: 0.4295 [80/118]
    Training loss: 0.3709 [90/118]
    Training loss: 0.4422 [100/118]
    Training loss: 0.3961 [110/118]
    Epoch 11 end
    Validation loss at epoch 11: 0.4135
    Epoch 12 start
    Training loss: 0.3441 [0/118]
    Training loss: 0.3853 [10/118]
    Training loss: 0.4168 [20/118]
    Training loss: 0.3616 [30/118]
    Training loss: 0.4245 [40/118]
    Training loss: 0.4083 [50/118]
    Training loss: 0.3639 [60/118]
    Training loss: 0.3572 [70/118]
    Training loss: 0.3499 [80/118]
    Training loss: 0.3522 [90/118]
    Training loss: 0.4522 [100/118]
    Training loss: 0.4074 [110/118]
    Epoch 12 end
    Validation loss at epoch 12: 0.4052
    Epoch 13 start
    Training loss: 0.4312 [0/118]
    Training loss: 0.3718 [10/118]
    Training loss: 0.3873 [20/118]
    Training loss: 0.3425 [30/118]
    Training loss: 0.3640 [40/118]
    Training loss: 0.3701 [50/118]
    Training loss: 0.3879 [60/118]
    Training loss: 0.3433 [70/118]
    Training loss: 0.4181 [80/118]
    Training loss: 0.3484 [90/118]
    Training loss: 0.3870 [100/118]
    Training loss: 0.3533 [110/118]
    Epoch 13 end
    Validation loss at epoch 13: 0.3984
    Epoch 14 start
    Training loss: 0.4387 [0/118]
    Training loss: 0.3737 [10/118]
    Training loss: 0.3873 [20/118]
    Training loss: 0.3481 [30/118]
    Training loss: 0.3841 [40/118]
    Training loss: 0.3389 [50/118]
    Training loss: 0.4040 [60/118]
    Training loss: 0.3406 [70/118]
    Training loss: 0.3931 [80/118]
    Training loss: 0.3658 [90/118]
    Training loss: 0.4006 [100/118]
    Training loss: 0.3896 [110/118]
    Epoch 14 end
    Validation loss at epoch 14: 0.3926
    Epoch 15 start
    Training loss: 0.3780 [0/118]
    Training loss: 0.3658 [10/118]
    Training loss: 0.3828 [20/118]
    Training loss: 0.4214 [30/118]
    Training loss: 0.3526 [40/118]
    Training loss: 0.3215 [50/118]
    Training loss: 0.3454 [60/118]
    Training loss: 0.3830 [70/118]
    Training loss: 0.4121 [80/118]
    Training loss: 0.3796 [90/118]
    Training loss: 0.3582 [100/118]
    Training loss: 0.3394 [110/118]
    Epoch 15 end
    Validation loss at epoch 15: 0.3928
    Epoch 16 start
    Training loss: 0.3898 [0/118]
    Training loss: 0.3741 [10/118]
    Training loss: 0.3795 [20/118]
    Training loss: 0.3703 [30/118]
    Training loss: 0.3349 [40/118]
    Training loss: 0.4097 [50/118]
    Training loss: 0.4256 [60/118]
    Training loss: 0.3691 [70/118]
    Training loss: 0.3390 [80/118]
    Training loss: 0.3891 [90/118]
    Training loss: 0.3203 [100/118]
    Training loss: 0.3685 [110/118]
    Epoch 16 end
    Validation loss at epoch 16: 0.3844
    Epoch 17 start
    Training loss: 0.3162 [0/118]
    Training loss: 0.3540 [10/118]
    Training loss: 0.3618 [20/118]
    Training loss: 0.3056 [30/118]
    Training loss: 0.4054 [40/118]
    Training loss: 0.3790 [50/118]
    Training loss: 0.3294 [60/118]
    Training loss: 0.3737 [70/118]
    Training loss: 0.3456 [80/118]
    Training loss: 0.3492 [90/118]
    Training loss: 0.3211 [100/118]
    Training loss: 0.3062 [110/118]
    Epoch 17 end
    Validation loss at epoch 17: 0.3798
    Epoch 18 start
    Training loss: 0.3132 [0/118]
    Training loss: 0.3743 [10/118]
    Training loss: 0.3461 [20/118]
    Training loss: 0.3777 [30/118]
    Training loss: 0.3114 [40/118]
    Training loss: 0.3312 [50/118]
    Training loss: 0.2937 [60/118]
    Training loss: 0.3612 [70/118]
    Training loss: 0.4152 [80/118]
    Training loss: 0.3434 [90/118]
    Training loss: 0.3293 [100/118]
    Training loss: 0.3090 [110/118]
    Epoch 18 end
    Validation loss at epoch 18: 0.3754
    Epoch 19 start
    Training loss: 0.3349 [0/118]
    Training loss: 0.3302 [10/118]
    Training loss: 0.2812 [20/118]
    Training loss: 0.3731 [30/118]
    Training loss: 0.3133 [40/118]
    Training loss: 0.3012 [50/118]
    Training loss: 0.4048 [60/118]
    Training loss: 0.3289 [70/118]
    Training loss: 0.3826 [80/118]
    Training loss: 0.3694 [90/118]
    Training loss: 0.2930 [100/118]
    Training loss: 0.3059 [110/118]
    Epoch 19 end
    Validation loss at epoch 19: 0.3818
    (2360, 20)

    Plot the training and validation losses with Matplotlib.

    import numpy as np
    batches_per_epoch = 118
    batches_x = np.arange(batches_per_epoch * epochs)
    training_losses_y = np.array(training_losses)
    epochs_x = batches_per_epoch * np.arange(epochs) + batches_per_epoch
    validation_losses_y = np.array(validation_losses)
    plt.figure(figsize=(8, 5))
    plt.plot(batches_x, training_losses_y, label='Training loss', linestyle='-')
    plt.plot(epochs_x, validation_losses_y, label='Validation loss', linestyle='--')
    plt.title('Training vs. validation loss')
    plt.xlabel('Batch #')
    plt.ylabel('Loss')
    plt.yscale('log')
    plt.grid(True, linestyle='--', alpha=0.6)
    plt.legend()
    plt.show()
    Training vs. validation loss

    Validating the accuracy of our model

    Let’s compute the validation loss and accuracy of our trained model.

    X_test = None
    y_test = None
    model.eval()
    with torch.no_grad():
    X_test, y_test = next(iter(test_loader))
    y_hat = model(X_test.to(gpu_0))
    y_test = y_test.to(gpu_0)
    loss = criterion(y_hat, y_test).item()
    y_hat = torch.argmax(y_hat, dim=1)
    total = 10000
    correct = (y_hat == y_test).sum().item()
    accuracy = correct / total
    print(f'Loss: {loss:.4f}, Accuracy: {accuracy:.4f}')
    .Loss: 0.3818, Accuracy: 0.8632

    Our accuracy is around $85 \text{-} 90\%$, a noticeable improvement from our simple linear model. Not bad!

    Let’s see it in action – predict labels for 10 images from our validation set and compare the predictions to the actual labels.

    X_test_10, y_test_10 = X_test[:10], y_test[:10]
    y_hat = model(X_test_10.to(gpu_0))
    y_hat = torch.argmax(y_hat, dim=1)
    X_test_10 = X_test_10.numpy()
    y_hat = y_hat.cpu().numpy()
    y_test_10 = y_test_10.cpu().numpy()
    fig, axes = plt.subplots(2, 5)
    for axis_idx, axis in enumerate(axes.flatten()):
    predicted = y_hat[axis_idx]
    actual = y_test_10[axis_idx]
    correct = (predicted == actual).item()
    color = 'blue' if correct else 'red'
    axis.set_title(f'Is: {LABELS[actual]}\nGot: {LABELS[predicted]}', color=color)
    axis.imshow(X_test_10[axis_idx].transpose(1, 2, 0))
    axis.axis('off')
    fig.tight_layout()
    fig.show()
    Fashion MNIST images, labels and predictions

    Exporting our model to ONNX format

    With our model trained on the Fashion MNIST dataset with satisfactory accuracy, let’s export it to ONNX format so others can download our model for inference. This is provided in PyTorch as torch.onnx.export.

    import os
    onnx_program = torch.onnx.export(model.cpu(), torch.from_numpy(X_test_10[:1]), dynamo=True)
    onnx_program.save('fashion-mnist-mlp.onnx')
    os.path.isfile('fashion-mnist-mlp.onnx')
    W0501 10:54:44.200000 25893 torch/onnx/_internal/exporter/_schemas.py:455] Missing annotation for parameter 'input' from (input, rois, spatial_scale: 'float', pooled_height: 'int', pooled_width: 'int', sampling_ratio: 'int' = -1, aligned: 'bool' = False). Treating as an Input.
    W0501 10:54:44.203000 25893 torch/onnx/_internal/exporter/_schemas.py:455] Missing annotation for parameter 'rois' from (input, rois, spatial_scale: 'float', pooled_height: 'int', pooled_width: 'int', sampling_ratio: 'int' = -1, aligned: 'bool' = False). Treating as an Input.
    W0501 10:54:44.207000 25893 torch/onnx/_internal/exporter/_schemas.py:455] Missing annotation for parameter 'input' from (input, boxes, output_size: 'Sequence[int]', spatial_scale: 'float' = 1.0). Treating as an Input.
    W0501 10:54:44.213000 25893 torch/onnx/_internal/exporter/_schemas.py:455] Missing annotation for parameter 'boxes' from (input, boxes, output_size: 'Sequence[int]', spatial_scale: 'float' = 1.0). Treating as an Input.
    [torch.onnx] Obtain model graph for `Sequential([...]` with `torch.export.export(..., strict=False)`...
    [torch.onnx] Obtain model graph for `Sequential([...]` with `torch.export.export(..., strict=False)`... ✅
    [torch.onnx] Run decomposition...
    [torch.onnx] Run decomposition... ✅
    [torch.onnx] Translate the graph into ONNX...
    [torch.onnx] Translate the graph into ONNX... ✅
    True

    Concluding remarks and going further

    We saw how the PyTorch Ascend plugin torch-npu allows us to migrate existing deep learning workloads originally optimized for NVIDIA GPUs to Huawei Ascend NPUs by simply adding an import statement to the existing code. While this approach may not work $100\%$ of the time especially if the code involves low-level performance optimizations tied to NVIDIA GPU hardware, it nonetheless greatly simplifies the migration path from NVIDIA to Ascend, allowing practitioners to focus on the interesting parts of the migration instead of being bogged down by repetitive grunt work.

    Porting existing PyTorch deep learning workloads directly to Ascend is just the first step of the migration from NVIDIA’s proprietary CUDA ecosystem to Huawei’s open Ascend CANN ecosystem. To maximize the benefits of accelerating deep learning workloads on Ascend NPUs, a logical next step would be to port the entire codebase from PyTorch to the MindSpore framework lead by Huawei and governed by the MindSpore community. Fortunately, MindSpore provides the mindspore.mint API compatibility layer whose design and structure closely follows PyTorch’s conventions. This enables practitioners already familiar with PyTorch to migrate their codebase to MindSpore without re-architecting their pipelines and workflows.

    I hope you enjoyed following through this notebook experiment as much as I did authoring it and stay tuned for updates 😉

    + , , , , , ,
  • This Kaggle Notebook is a GPU-enabled variation of my original notebook experiment.

    Open Neural Network Exchange (ONNX) is an open format built to represent machine learning models. It is used by popular deep learning frameworks such as MindSporePyTorch and TensorFlow to export machine learning models trained by these frameworks into the portable, unified and vendor-neutral ONNX format. This allows exported models to be loaded by any compatible framework or runtime for inference instead of being locked in to a single framework or provider.

    In this notebook experiment, we will load an ONNX model trained on the CIFAR-10 dataset mounted at /kaggle/input/models/donaldsebleung/cifar10-linear-simple/onnx/default/1/cifar10-linear-simple.onnx and serve it with ONNX Runtime for inference. ONNX Runtime is a cross-platform inference accelerator for ONNX models developed by Microsoft under the permissive MIT license.

    Installing dependent packages

    We’ll need the ONNX Runtime 1.24.4 with the GPU execution provider (EP) for this notebook experiment.

    Let’s install the required packages with pip.

    %pip install onnxruntime-gpu==1.24.4
    Collecting onnxruntime-gpu==1.24.4
    Downloading onnxruntime_gpu-1.24.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (5.6 kB)
    Requirement already satisfied: flatbuffers in /usr/local/lib/python3.12/dist-packages (from onnxruntime-gpu==1.24.4) (25.12.19)
    Requirement already satisfied: numpy>=1.21.6 in /usr/local/lib/python3.12/dist-packages (from onnxruntime-gpu==1.24.4) (2.0.2)
    Requirement already satisfied: packaging in /usr/local/lib/python3.12/dist-packages (from onnxruntime-gpu==1.24.4) (26.0)
    Requirement already satisfied: protobuf in /usr/local/lib/python3.12/dist-packages (from onnxruntime-gpu==1.24.4) (5.29.5)
    Requirement already satisfied: sympy in /usr/local/lib/python3.12/dist-packages (from onnxruntime-gpu==1.24.4) (1.14.0)
    Requirement already satisfied: mpmath<1.4,>=1.1.0 in /usr/local/lib/python3.12/dist-packages (from sympy->onnxruntime-gpu==1.24.4) (1.3.0)
    Downloading onnxruntime_gpu-1.24.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (252.8 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 252.8/252.8 MB 7.4 MB/s eta 0:00:00
    [?25hInstalling collected packages: onnxruntime-gpu
    Successfully installed onnxruntime-gpu-1.24.4
    Note: you may need to restart the kernel to use updated packages.

    Loading our ONNX model

    Our trained ONNX model is available locally and mounted under the path /kaggle/input/models/donaldsebleung/cifar10-linear-simple/onnx/default/1/cifar10-linear-simple.onnx.

    import os
    model_path = '/kaggle/input/models/donaldsebleung/cifar10-linear-simple/onnx/default/1/cifar10-linear-simple.onnx'
    os.path.isfile(model_path)
    True

    Serving our model with ONNX Runtime

    The onnxruntime-gpu Python package allows us to serve ONNX models for inference with GPU acceleration. Let’s list the available execution providers (EP) with onnxruntime.get_available_providers to confirm this.

    import onnxruntime as ort
    available_providers = ort.get_available_providers()
    available_providers, 'CUDAExecutionProvider' in available_providers
    (['TensorrtExecutionProvider',
    'CUDAExecutionProvider',
    'CPUExecutionProvider'],
    True)

    The output includes CUDAExecutionProvider which is what we will be using in this notebook experiment. Alternatively, we could use TensorrtExecutionProvider instead which is out of scope for this notebook experiment.

    Load our ONNX model and create an InferenceSession with the CUDA EP.

    session = ort.InferenceSession(model_path, providers=['CUDAExecutionProvider'])
    providers = session.get_providers()
    providers
    ['CUDAExecutionProvider', 'CPUExecutionProvider']

    Loading the CIFAR-10 dataset with Pickle

    Now that our ONNX model is loaded and ready for inference, let’s load our data with Pickle, the default object serialization library included within Python itself.

    import tarfile
    import urllib.request
    cifar10_url = 'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz'
    dataset_dir = 'data/'
    with urllib.request.urlopen(cifar10_url) as response:
    with tarfile.open(fileobj=response, mode='r|gz') as tar:
    tar.extractall(path=dataset_dir, filter='data')
    dataset_dir = os.path.join(dataset_dir, 'cifar-10-batches-py/')
    dataset_dir
    'data/cifar-10-batches-py/'
    import pickle
    test_batch_file_path = os.path.join(dataset_dir, 'test_batch')
    test_batch = None
    with open(test_batch_file_path, 'rb') as file:
    test_batch = pickle.load(file, encoding='bytes')
    test_batch.keys()
    dict_keys([b'batch_label', b'labels', b'data', b'filenames'])
    images = test_batch.get(b'data')
    labels = test_batch.get(b'labels')
    samples_count = len(labels)
    images.shape, samples_count
    ((10000, 3072), 10000)

    The images are given as a Numpy array of $10,000$ samples of $3 \times 32 \times 32 = 3072$ input features, while the labels are given as a Python list of $10,000$ integers in the range $[0, 10)$ corresponding to the 10 categories.

    Let’s reshape the 10k images to their original dimensions (32, 32, 3) and wrap our labels in a Numpy array for convenience.

    import numpy as np
    images, labels = images.reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1), np.array(labels)
    images.shape, labels.shape
    ((10000, 32, 32, 3), (10000,))

    Let’s shuffle our test set, then take the first 10 images and visualize them with Matplotlib.

    rng = np.random.default_rng()
    indices = rng.permutation(samples_count)
    images, labels = images[indices], labels[indices]
    X_samples, y_samples = images[:10], labels[:10]
    X_samples.shape, y_samples.shape
    ((10, 32, 32, 3), (10,))
    import matplotlib.pyplot as plt
    LABELS = [
    'airplane',
    'automobile',
    'bird',
    'cat',
    'deer',
    'dog',
    'frog',
    'horse',
    'ship',
    'truck'
    ]
    fig, axes = plt.subplots(2, 5)
    for axis_idx, axis in enumerate(axes.flatten()):
    axis.set_title(LABELS[y_samples[axis_idx]])
    axis.imshow(X_samples[axis_idx])
    axis.axis('off')
    fig.tight_layout()
    fig.show()
    Images and labels

    Transforming our data and performing model inference

    Our model accepts as input pre-processed images transformed via the standard procedure described below.

    1. Resize each image to $32 \times 32$ pixels. This should already be the case but better safe than sorry 😉
    2. Rescale each channel from integer in range $[0, 255]$ to float in range $[0, 1]$
    3. Reshape each image from dimensions (height, width, channel) to (channel, height, width)

    We’ll use Pillow for the image resizing operation in (1) and standard Numpy operations for the rest. Pillow is the de-facto standard for image processing in Python.

    import PIL
    X_samples_transformed = []
    for i in range(len(X_samples)):
    img = PIL.Image.fromarray(X_samples[i])
    img = img.resize((32, 32), PIL.Image.BILINEAR)
    img = np.array(img) / 255
    img = img.transpose(2, 0, 1)
    X_samples_transformed.append(img)
    X_samples_transformed = np.stack(X_samples_transformed, axis=0)
    X_samples_transformed.shape
    (10, 3, 32, 32)

    Now that our images are in the correct shape expected by our model, let’s pass them to our model for inference.

    # Only 1 input in our ONNX model named 'image' defined at model export time
    input_name = session.get_inputs()[0].name
    input_name
    'image'
    X_samples_transformed = X_samples_transformed.astype(dtype=np.float16)
    y_hat = []
    for i in range(len(X_samples_transformed)):
    y_hat.append(session.run(None, {input_name: X_samples_transformed[i:i+1]}))
    y_hat = np.squeeze(np.stack(y_hat, axis=0))
    y_hat.shape
    (10, 10)

    Our model outputs raw logits. Transform them to concrete category predictions via the 2-step process below.

    1. Apply softmax activation to the logits. This transforms the returned values to probabilities that sum up to 1
    2. Use argmax to select the most probable category based on the predicted outcomes

    Fortunately, since softmax is monotonic and preserves ordering, we can safely skip (1) entirely and apply argmax directly to the raw logits.

    y_hat = np.argmax(y_hat, axis=1)
    y_hat, y_samples
    (array([1, 8, 1, 5, 5, 5, 2, 6, 9, 6]), array([1, 1, 8, 5, 7, 2, 4, 6, 1, 6]))

    Visualize the predictions against the expected labels. Our model performs slightly better than random guessing but you get the idea (-:

    fig, axes = plt.subplots(2, 5)
    for axis_idx, axis in enumerate(axes.flatten()):
    color = 'blue' if y_samples[axis_idx] == y_hat[axis_idx] else 'red'
    axis.set_title(f'Is: {LABELS[y_samples[axis_idx]]}\nGot: {LABELS[y_hat[axis_idx]]}', color=color)
    axis.imshow(X_samples[axis_idx])
    axis.axis('off')
    fig.tight_layout()
    fig.show()
    Predictions vs. labels

    Concluding remarks and going further

    We saw in this notebook experiment how to:

    1. Load and serve existing ONNX models with ONNX Runtime
    2. Accelerate model inference on NVIDIA GPUs with the CUDA EP
    3. Deserialize test data with Pickle
    4. Visualize our data with Matplotlib
    5. Transform our images with Pillow and Numpy for model inference
    6. Interpret our model predictions against expected outcomes

    I hope you enjoyed following this notebook experiment as much as I did authoring it and stay tuned for updates 😉

    + , ,
  • The notebook source code for this experiment is available on GitHub.

    Open Neural Network Exchange (ONNX) is an open format built to represent machine learning models. It is used by popular deep learning frameworks such as MindSporePyTorch and TensorFlow to export machine learning models trained by these frameworks into the portable, unified and vendor-neutral ONNX format. This allows exported models to be loaded by any compatible framework or runtime for inference instead of being locked in to a single framework or provider.

    In this notebook experiment, we will download an ONNX model trained on the CIFAR-10 dataset from Hugging Face and serve it with ONNX Runtime for inference. ONNX Runtime is a cross-platform inference accelerator for ONNX models developed by Microsoft under the permissive MIT license.

    Installing dependent packages

    We’ll need the following software versions for this notebook experiment.

    1. Python 3.12
    2. huggingface-hub 1.11.0
    3. ONNX Runtime 1.24.4
    4. Matplotlib 3.10.8
    5. Pillow 12.2.0

    Let’s install the required packages with pip.

    !cat requirements.txt
    absl-py==2.4.0
    attrs==25.4.0
    cloudpickle==3.1.2
    decorator==5.2.1
    huggingface-hub==1.11.0
    jupyterlab==4.5.6
    jupyterlab-git==0.52.0
    jupyter-resource-usage==1.2.0
    matplotlib==3.10.8
    ml-dtypes==0.5.4
    onnxruntime==1.24.4
    pillow==12.2.0
    scipy==1.17.1
    sympy==1.14.0
    tornado==6.5.5
    %pip install -r requirements.txt
    Requirement already satisfied: absl-py==2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 1)) (2.4.0)
    Requirement already satisfied: attrs==25.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 2)) (25.4.0)
    Requirement already satisfied: cloudpickle==3.1.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 3)) (3.1.2)
    Requirement already satisfied: decorator==5.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 4)) (5.2.1)
    Requirement already satisfied: huggingface-hub==1.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 5)) (1.11.0)
    Requirement already satisfied: jupyterlab==4.5.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 6)) (4.5.6)
    Requirement already satisfied: jupyterlab-git==0.52.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 7)) (0.52.0)
    Requirement already satisfied: jupyter-resource-usage==1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 8)) (1.2.0)
    Requirement already satisfied: matplotlib==3.10.8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 9)) (3.10.8)
    Requirement already satisfied: ml-dtypes==0.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 10)) (0.5.4)
    Requirement already satisfied: onnxruntime==1.24.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 11)) (1.24.4)
    Requirement already satisfied: pillow==12.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 12)) (12.2.0)
    Requirement already satisfied: scipy==1.17.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 13)) (1.17.1)
    Requirement already satisfied: sympy==1.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 14)) (1.14.0)
    Requirement already satisfied: tornado==6.5.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 15)) (6.5.5)
    Requirement already satisfied: filelock>=3.10.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (3.28.0)
    Requirement already satisfied: fsspec>=2023.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (2026.3.0)
    Requirement already satisfied: hf-xet<2.0.0,>=1.4.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (1.4.3)
    Requirement already satisfied: httpx<1,>=0.23.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (0.28.1)
    Requirement already satisfied: packaging>=20.9 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (26.1)
    Requirement already satisfied: pyyaml>=5.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (6.0.3)
    Requirement already satisfied: tqdm>=4.42.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (4.67.3)
    Requirement already satisfied: typer in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (0.24.1)
    Requirement already satisfied: typing-extensions>=4.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from huggingface-hub==1.11.0->-r requirements.txt (line 5)) (4.15.0)
    Requirement already satisfied: async-lru>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.3.0)
    Requirement already satisfied: ipykernel!=6.30.0,>=6.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (7.2.0)
    Requirement already satisfied: jinja2>=3.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.1.6)
    Requirement already satisfied: jupyter-core in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (5.9.1)
    Requirement already satisfied: jupyter-lsp>=2.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.3.1)
    Requirement already satisfied: jupyter-server<3,>=2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.17.0)
    Requirement already satisfied: jupyterlab-server<3,>=2.28.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.28.0)
    Requirement already satisfied: notebook-shim>=0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.2.4)
    Requirement already satisfied: setuptools>=41.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (82.0.1)
    Requirement already satisfied: traitlets in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 6)) (5.14.3)
    Requirement already satisfied: nbdime~=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (4.0.4)
    Requirement already satisfied: nbformat in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (5.10.4)
    Requirement already satisfied: pexpect in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (4.9.0)
    Requirement already satisfied: prometheus-client in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 8)) (0.25.0)
    Requirement already satisfied: psutil>=5.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 8)) (7.2.2)
    Requirement already satisfied: pyzmq>=19 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 8)) (27.1.0)
    Requirement already satisfied: contourpy>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 9)) (1.3.3)
    Requirement already satisfied: cycler>=0.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 9)) (0.12.1)
    Requirement already satisfied: fonttools>=4.22.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 9)) (4.62.1)
    Requirement already satisfied: kiwisolver>=1.3.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 9)) (1.5.0)
    Requirement already satisfied: numpy>=1.23 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 9)) (2.4.4)
    Requirement already satisfied: pyparsing>=3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 9)) (3.3.2)
    Requirement already satisfied: python-dateutil>=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 9)) (2.9.0.post0)
    Requirement already satisfied: flatbuffers in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from onnxruntime==1.24.4->-r requirements.txt (line 11)) (25.12.19)
    Requirement already satisfied: protobuf in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from onnxruntime==1.24.4->-r requirements.txt (line 11)) (7.34.1)
    Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from sympy==1.14.0->-r requirements.txt (line 14)) (1.3.0)
    Requirement already satisfied: anyio in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (4.13.0)
    Requirement already satisfied: certifi in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (2026.2.25)
    Requirement already satisfied: httpcore==1.* in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (1.0.9)
    Requirement already satisfied: idna in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (3.11)
    Requirement already satisfied: h11>=0.16 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (0.16.0)
    Requirement already satisfied: comm>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.2.3)
    Requirement already satisfied: debugpy>=1.6.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.8.20)
    Requirement already satisfied: ipython>=7.23.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (9.12.0)
    Requirement already satisfied: jupyter-client>=8.8.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (8.8.0)
    Requirement already satisfied: matplotlib-inline>=0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.2.1)
    Requirement already satisfied: nest-asyncio>=1.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.6.0)
    Requirement already satisfied: MarkupSafe>=2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jinja2>=3.0.3->jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.0.3)
    Requirement already satisfied: platformdirs>=2.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-core->jupyterlab==4.5.6->-r requirements.txt (line 6)) (4.9.6)
    Requirement already satisfied: argon2-cffi>=21.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (25.1.0)
    Requirement already satisfied: jupyter-events>=0.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.12.0)
    Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.5.4)
    Requirement already satisfied: nbconvert>=6.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (7.17.1)
    Requirement already satisfied: send2trash>=1.8.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.1.0)
    Requirement already satisfied: terminado>=0.8.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.18.1)
    Requirement already satisfied: websocket-client>=1.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.9.0)
    Requirement already satisfied: babel>=2.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.18.0)
    Requirement already satisfied: json5>=0.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.14.0)
    Requirement already satisfied: jsonschema>=4.18.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (4.26.0)
    Requirement already satisfied: requests>=2.31 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.33.1)
    Requirement already satisfied: colorama in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (0.4.6)
    Requirement already satisfied: gitpython!=2.1.4,!=2.1.5,!=2.1.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (3.1.46)
    Requirement already satisfied: pygments in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (2.20.0)
    Requirement already satisfied: fastjsonschema>=2.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbformat->jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (2.21.2)
    Requirement already satisfied: six>=1.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib==3.10.8->-r requirements.txt (line 9)) (1.17.0)
    Requirement already satisfied: ptyprocess>=0.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pexpect->jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (0.7.0)
    Requirement already satisfied: click>=8.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from typer->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (8.3.2)
    Requirement already satisfied: shellingham>=1.3.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from typer->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (1.5.4)
    Requirement already satisfied: rich>=12.3.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from typer->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (15.0.0)
    Requirement already satisfied: annotated-doc>=0.0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from typer->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (0.0.4)
    Requirement already satisfied: argon2-cffi-bindings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (25.1.0)
    Requirement already satisfied: gitdb<5,>=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (4.0.12)
    Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.1.1)
    Requirement already satisfied: jedi>=0.18.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.19.2)
    Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.0.52)
    Requirement already satisfied: stack_data>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.6.3)
    Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2025.9.1)
    Requirement already satisfied: referencing>=0.28.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.37.0)
    Requirement already satisfied: rpds-py>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.30.0)
    Requirement already satisfied: python-json-logger>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (4.1.0)
    Requirement already satisfied: rfc3339-validator in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.1.4)
    Requirement already satisfied: rfc3986-validator>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.1.1)
    Requirement already satisfied: beautifulsoup4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (4.14.3)
    Requirement already satisfied: bleach!=5.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (6.3.0)
    Requirement already satisfied: defusedxml in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.7.1)
    Requirement already satisfied: jupyterlab-pygments in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.3.0)
    Requirement already satisfied: mistune<4,>=2.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.2.0)
    Requirement already satisfied: nbclient>=0.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.10.4)
    Requirement already satisfied: pandocfilters>=1.4.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.5.1)
    Requirement already satisfied: charset_normalizer<4,>=2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.4.7)
    Requirement already satisfied: urllib3<3,>=1.26 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.6.3)
    Requirement already satisfied: markdown-it-py>=2.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from rich>=12.3.0->typer->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (4.0.0)
    Requirement already satisfied: webencodings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.5.1)
    Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.4.0)
    Requirement already satisfied: smmap<6,>=3.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitdb<5,>=4.0.1->gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 7)) (5.0.3)
    Requirement already satisfied: parso<0.9.0,>=0.8.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jedi>=0.18.2->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.8.6)
    Requirement already satisfied: fqdn in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.5.1)
    Requirement already satisfied: isoduration in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (20.11.0)
    Requirement already satisfied: jsonpointer>1.13 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.1.1)
    Requirement already satisfied: rfc3987-syntax>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.1.0)
    Requirement already satisfied: uri-template in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.3.0)
    Requirement already satisfied: webcolors>=24.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (25.10.0)
    Requirement already satisfied: mdurl~=0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from markdown-it-py>=2.2.0->rich>=12.3.0->typer->huggingface-hub==1.11.0->-r requirements.txt (line 5)) (0.1.2)
    Requirement already satisfied: wcwidth in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.6.0)
    Requirement already satisfied: executing>=1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.2.1)
    Requirement already satisfied: asttokens>=2.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.0.1)
    Requirement already satisfied: pure-eval in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (0.2.3)
    Requirement already satisfied: cffi>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.0.0)
    Requirement already satisfied: soupsieve>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2.8.3)
    Requirement already satisfied: pycparser in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (3.0)
    Requirement already satisfied: lark>=1.2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.3.1)
    Requirement already satisfied: arrow>=0.15.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (1.4.0)
    Requirement already satisfied: tzdata in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 6)) (2026.1)
    [notice] A new release of pip is available: 25.0.1 -> 26.0.1
    [notice] To update, run: python -m pip install --upgrade pip
    Note: you may need to restart the kernel to use updated packages.

    Downloading our ONNX model from Hugging Face

    Our trained ONNX model is available on Hugging Face under the repository donaldsebleung/cifar10-linear-simple and the model file is named cifar10-linear-simple.onnx. Let’s use hf_hub_download from huggingface_hub to download it.

    import os
    from huggingface_hub import hf_hub_download
    models_dir = 'models/'
    os.makedirs(models_dir, exist_ok=True)
    repo = 'donaldsebleung/cifar10-linear-simple'
    filename = 'cifar10-linear-simple.onnx'
    hf_hub_download(repo_id=repo, filename=filename, local_dir=models_dir)
    model_path = os.path.join(models_dir, filename)
    os.path.isfile(model_path)
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
    from .autonotebook import tqdm as notebook_tqdm
    True

    Serving our model with ONNX Runtime

    The onnxruntime Python package allows us to serve ONNX models for inference via CPU without GPU/NPU/TPU acceleration. Let’s list the available execution providers (EP) with onnxruntime.get_available_providers to confirm this.

    import onnxruntime as ort
    available_providers = ort.get_available_providers()
    available_providers
    onnxruntime cpuid_info warning: Unknown CPU vendor. cpuinfo_vendor value: 0
    2026-04-19 13:51:07.204949886 [W:onnxruntime:Default, device_discovery.cc:325 DiscoverDevicesForPlatform] GPU device discovery failed: device_discovery.cc:92 ReadFileContents Failed to open file: "/sys/class/drm/card1/device/vendor"
    ['AzureExecutionProvider', 'CPUExecutionProvider']

    The output includes CPUExecutionProvider which is what we will be using in this notebook experiment. Inference acceleration with heterogeneous hardware such as GPU/NPU/TPU is beyond the scope of this experiment.

    Load our ONNX model and create an InferenceSession with the available providers.

    session = ort.InferenceSession(model_path, providers=available_providers)
    providers = session.get_providers()
    providers
    ['AzureExecutionProvider', 'CPUExecutionProvider']

    Loading the CIFAR-10 dataset with Pickle

    Now that our ONNX model is loaded and ready for inference, let’s load our data with Pickle, the default object serialization library included within Python itself.

    import tarfile
    import urllib.request
    cifar10_url = 'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz'
    dataset_dir = 'data/'
    with urllib.request.urlopen(cifar10_url) as response:
    with tarfile.open(fileobj=response, mode='r|gz') as tar:
    tar.extractall(path=dataset_dir, filter='data')
    dataset_dir = os.path.join(dataset_dir, 'cifar-10-batches-py/')
    dataset_dir
    'data/cifar-10-batches-py/'
    import pickle
    test_batch_file_path = os.path.join(dataset_dir, 'test_batch')
    test_batch = None
    with open(test_batch_file_path, 'rb') as file:
    test_batch = pickle.load(file, encoding='bytes')
    test_batch.keys()
    /tmp/ipykernel_19135/3196477776.py:6: VisibleDeprecationWarning: dtype(): align should be passed as Python or NumPy boolean but got `align=0`. Did you mean to pass a tuple to create a subarray type? (Deprecated NumPy 2.4)
    test_batch = pickle.load(file, encoding='bytes')
    dict_keys([b'batch_label', b'labels', b'data', b'filenames'])
    images = test_batch.get(b'data')
    labels = test_batch.get(b'labels')
    samples_count = len(labels)
    images.shape, samples_count
    ((10000, 3072), 10000)

    The images are given as a Numpy array of $10,000$ samples of $3 \times 32 \times 32 = 3072$ input features, while the labels are given as a Python list of $10,000$ integers in the range $[0, 10)$ corresponding to the 10 categories.

    Let’s reshape the 10k images to their original dimensions (32, 32, 3) and wrap our labels in a Numpy array for convenience.

    import numpy as np
    images, labels = images.reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1), np.array(labels)
    images.shape, labels.shape
    ((10000, 32, 32, 3), (10000,))

    Let’s shuffle our test set, then take the first 10 images and visualize them with Matplotlib.

    rng = np.random.default_rng()
    indices = rng.permutation(samples_count)
    images, labels = images[indices], labels[indices]
    X_samples, y_samples = images[:10], labels[:10]
    X_samples.shape, y_samples.shape
    ((10, 32, 32, 3), (10,))
    import matplotlib.pyplot as plt
    LABELS = [
    'airplane',
    'automobile',
    'bird',
    'cat',
    'deer',
    'dog',
    'frog',
    'horse',
    'ship',
    'truck'
    ]
    fig, axes = plt.subplots(2, 5)
    for axis_idx, axis in enumerate(axes.flatten()):
    axis.set_title(LABELS[y_samples[axis_idx]])
    axis.imshow(X_samples[axis_idx])
    axis.axis('off')
    fig.tight_layout()
    fig.show()
    Images and labels

    Transforming our data and performing model inference

    Our model accepts as input pre-processed images transformed via the standard procedure described below.

    1. Resize each image to $32 \times 32$ pixels. This should already be the case but better safe than sorry 😉
    2. Rescale each channel from integer in range $[0, 255]$ to float in range $[0, 1]$
    3. Reshape each image from dimensions (height, width, channel) to (channel, height, width)

    We’ll use Pillow for the image resizing operation in (1) and standard Numpy operations for the rest. Pillow is the de-facto standard for image processing in Python.

    import PIL
    X_samples_transformed = []
    for i in range(len(X_samples)):
    img = PIL.Image.fromarray(X_samples[i])
    img = img.resize((32, 32), PIL.Image.BILINEAR)
    img = np.array(img) / 255
    img = img.transpose(2, 0, 1)
    X_samples_transformed.append(img)
    X_samples_transformed = np.stack(X_samples_transformed, axis=0)
    X_samples_transformed.shape
    (10, 3, 32, 32)

    Now that our images are in the correct shape expected by our model, let’s pass them to our model for inference.

    # Only 1 input in our ONNX model named 'image' defined at model export time
    input_name = session.get_inputs()[0].name
    input_name
    'image'
    X_samples_transformed = X_samples_transformed.astype(dtype=np.float16)
    y_hat = []
    for i in range(len(X_samples_transformed)):
    y_hat.append(session.run(None, {input_name: X_samples_transformed[i:i+1]}))
    y_hat = np.squeeze(np.stack(y_hat, axis=0))
    y_hat.shape
    (10, 10)

    Our model outputs raw logits. Transform them to concrete category predictions via the 2-step process below.

    1. Apply softmax activation to the logits. This transforms the returned values to probabilities that sum up to 1
    2. Use argmax to select the most probable category based on the predicted outcomes

    Fortunately, since softmax is monotonic and preserves ordering, we can safely skip (1) entirely and apply argmax directly to the raw logits.

    y_hat = np.argmax(y_hat, axis=1)
    y_hat, y_samples
    (array([4, 0, 8, 8, 6, 6, 1, 5, 0, 6]), array([4, 0, 0, 0, 6, 2, 1, 5, 0, 5]))

    Visualize the predictions against the expected labels. Our model performs slightly better than random guessing but you get the idea (-:

    fig, axes = plt.subplots(2, 5)
    for axis_idx, axis in enumerate(axes.flatten()):
    color = 'blue' if y_samples[axis_idx] == y_hat[axis_idx] else 'red'
    axis.set_title(f'Is: {LABELS[y_samples[axis_idx]]}\nGot: {LABELS[y_hat[axis_idx]]}', color=color)
    axis.imshow(X_samples[axis_idx])
    axis.axis('off')
    fig.tight_layout()
    fig.show()
    Predictions vs. labels

    Concluding remarks and going further

    We saw in this notebook experiment how to:

    1. Download pre-trained machine learning models from Hugging Face
    2. Load and serve ONNX models with ONNX Runtime
    3. Deserialize test data with Pickle
    4. Visualize our data with Matplotlib
    5. Transform our images with Pillow and Numpy for model inference
    6. Interpret our model predictions against expected outcomes

    Note that we performed the model serving and inference using the default CPU executor in this notebook experiment without leveraging GPU/NPU/TPU acceleration. This is left as an exercise to the reader and we may revisit it in future articles.

    I hope you enjoyed following this notebook experiment as much as I did authoring it and stay tuned for updates 😉

    + , ,
  • The notebook source code for this article is available on: GitCodeGitHub

    MindSpore is an open source deep learning framework lead by Huawei and the MindSpore community. It is optimized for performing model training and inference tasks on Huawei’s Ascend series processors (NPUs), though it supports NVIDIA GPUs and CPU-only environments as well. It provides a compelling alternative to PyTorch, the leading open source deep learning framework under the Linux Foundation. Furthermore, it provides utility classes and functions compatible with a subset of PyTorch to ease the migration of training and inference pipelines from PyTorch to MindSpore, which is out of scope for this article.

    In this lab, we will use MindSpore for training a simple linear regression model consisting of a single fully connected layer to predict house prices in California. The dataset we will be using is the California housing dataset which we’ll fetch using scikit-learn’s sklearn.datasets.fetch_california_housing function.

    Prerequisites and suggested reading

    The first 3 chapters of Dive into Deep Learning, also known as D2L. It covers the background knowledge on introductory probability, statistics and linear algebra, as well as data pre-processing, transformation methods and linear regression techniques required to understand the steps performed in this lab.

    Software environment and dependencies

    The instructions in this lab were tested on the OrangePi AIpro (20T) development board. It should work in a CPU-only environment as well with minimal configuration – simply specify the NOTEBOOK_USE_CPU=1 environment variable. While it may work in NVIDIA GPU environments with few modifications by specifying the NOTEBOOK_USE_GPU=1 environment variable, this has not been explicitly tested.

    The software versions listed below which can be found in the provided requirements.txt as well.

    1. Python 3.12
    2. MindSpore 2.8.0
    3. CANN 8.5.0 – only on Ascend platform
    4. Matplotlib 3.10.8
    5. scikit-learn 1.8.0
    %pip install -r requirements.txt
    Requirement already satisfied: absl-py==2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 1)) (2.4.0)
    Requirement already satisfied: attrs==25.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 2)) (25.4.0)
    Requirement already satisfied: cloudpickle==3.1.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 3)) (3.1.2)
    Requirement already satisfied: decorator==5.2.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 4)) (5.2.1)
    Requirement already satisfied: jupyterlab==4.5.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 5)) (4.5.6)
    Requirement already satisfied: jupyterlab-git==0.52.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 6)) (0.52.0)
    Requirement already satisfied: jupyter-resource-usage==1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 7)) (1.2.0)
    Requirement already satisfied: matplotlib==3.10.8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 8)) (3.10.8)
    Requirement already satisfied: mindspore==2.8.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 9)) (2.8.0)
    Requirement already satisfied: ml-dtypes==0.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 10)) (0.5.4)
    Requirement already satisfied: nbmake==1.5.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 11)) (1.5.5)
    Requirement already satisfied: nbstripout==0.9.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 12)) (0.9.1)
    Requirement already satisfied: pytest==9.0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 13)) (9.0.2)
    Requirement already satisfied: scikit-learn==1.8.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 14)) (1.8.0)
    Requirement already satisfied: sympy==1.14.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 15)) (1.14.0)
    Requirement already satisfied: tornado==6.5.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from -r requirements.txt (line 16)) (6.5.5)
    Requirement already satisfied: async-lru>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.3.0)
    Requirement already satisfied: httpx<1,>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.28.1)
    Requirement already satisfied: ipykernel!=6.30.0,>=6.5.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (7.2.0)
    Requirement already satisfied: jinja2>=3.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.1.6)
    Requirement already satisfied: jupyter-core in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (5.9.1)
    Requirement already satisfied: jupyter-lsp>=2.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.3.1)
    Requirement already satisfied: jupyter-server<3,>=2.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.17.0)
    Requirement already satisfied: jupyterlab-server<3,>=2.28.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.28.0)
    Requirement already satisfied: notebook-shim>=0.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.4)
    Requirement already satisfied: packaging in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (26.0)
    Requirement already satisfied: setuptools>=41.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (82.0.1)
    Requirement already satisfied: traitlets in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab==4.5.6->-r requirements.txt (line 5)) (5.14.3)
    Requirement already satisfied: nbdime~=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (4.0.4)
    Requirement already satisfied: nbformat in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (5.10.4)
    Requirement already satisfied: pexpect in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (4.9.0)
    Requirement already satisfied: prometheus-client in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 7)) (0.24.1)
    Requirement already satisfied: psutil>=5.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 7)) (7.2.2)
    Requirement already satisfied: pyzmq>=19 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-resource-usage==1.2.0->-r requirements.txt (line 7)) (27.1.0)
    Requirement already satisfied: contourpy>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (1.3.3)
    Requirement already satisfied: cycler>=0.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (0.12.1)
    Requirement already satisfied: fonttools>=4.22.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (4.62.1)
    Requirement already satisfied: kiwisolver>=1.3.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (1.5.0)
    Requirement already satisfied: numpy>=1.23 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (1.26.4)
    Requirement already satisfied: pillow>=8 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (12.2.0)
    Requirement already satisfied: pyparsing>=3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (3.3.2)
    Requirement already satisfied: python-dateutil>=2.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from matplotlib==3.10.8->-r requirements.txt (line 8)) (2.9.0.post0)
    Requirement already satisfied: protobuf>=3.13.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.8.0->-r requirements.txt (line 9)) (7.34.1)
    Requirement already satisfied: asttokens>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.8.0->-r requirements.txt (line 9)) (3.0.1)
    Requirement already satisfied: scipy>=1.5.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.8.0->-r requirements.txt (line 9)) (1.17.1)
    Requirement already satisfied: astunparse>=1.6.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.8.0->-r requirements.txt (line 9)) (1.6.3)
    Requirement already satisfied: safetensors>=0.4.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.8.0->-r requirements.txt (line 9)) (0.7.0)
    Requirement already satisfied: dill>=0.3.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from mindspore==2.8.0->-r requirements.txt (line 9)) (0.4.1)
    Requirement already satisfied: nbclient>=0.6.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbmake==1.5.5->-r requirements.txt (line 11)) (0.10.4)
    Requirement already satisfied: pygments>=2.7.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbmake==1.5.5->-r requirements.txt (line 11)) (2.20.0)
    Requirement already satisfied: iniconfig>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pytest==9.0.2->-r requirements.txt (line 13)) (2.3.0)
    Requirement already satisfied: pluggy<2,>=1.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pytest==9.0.2->-r requirements.txt (line 13)) (1.6.0)
    Requirement already satisfied: joblib>=1.3.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from scikit-learn==1.8.0->-r requirements.txt (line 14)) (1.5.3)
    Requirement already satisfied: threadpoolctl>=3.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from scikit-learn==1.8.0->-r requirements.txt (line 14)) (3.6.0)
    Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from sympy==1.14.0->-r requirements.txt (line 15)) (1.3.0)
    Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.8.0->-r requirements.txt (line 9)) (0.46.3)
    Requirement already satisfied: six<2.0,>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from astunparse>=1.6.3->mindspore==2.8.0->-r requirements.txt (line 9)) (1.17.0)
    Requirement already satisfied: anyio in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.13.0)
    Requirement already satisfied: certifi in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2026.2.25)
    Requirement already satisfied: httpcore==1.* in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.0.9)
    Requirement already satisfied: idna in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.11)
    Requirement already satisfied: h11>=0.16 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.16.0)
    Requirement already satisfied: comm>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: debugpy>=1.6.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.8.20)
    Requirement already satisfied: ipython>=7.23.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (9.12.0)
    Requirement already satisfied: jupyter-client>=8.8.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (8.8.0)
    Requirement already satisfied: matplotlib-inline>=0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.1)
    Requirement already satisfied: nest-asyncio>=1.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.6.0)
    Requirement already satisfied: MarkupSafe>=2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jinja2>=3.0.3->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.0.3)
    Requirement already satisfied: platformdirs>=2.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-core->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.9.4)
    Requirement already satisfied: argon2-cffi>=21.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: jupyter-events>=0.11.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.12.0)
    Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.5.4)
    Requirement already satisfied: nbconvert>=6.4.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (7.17.0)
    Requirement already satisfied: send2trash>=1.8.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.1.0)
    Requirement already satisfied: terminado>=0.8.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.18.1)
    Requirement already satisfied: websocket-client>=1.7 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.9.0)
    Requirement already satisfied: babel>=2.10 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.18.0)
    Requirement already satisfied: json5>=0.9.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.14.0)
    Requirement already satisfied: jsonschema>=4.18.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.26.0)
    Requirement already satisfied: requests>=2.31 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.33.1)
    Requirement already satisfied: colorama in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (0.4.6)
    Requirement already satisfied: gitpython!=2.1.4,!=2.1.5,!=2.1.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (3.1.46)
    Requirement already satisfied: fastjsonschema>=2.15 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbformat->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (2.21.2)
    Requirement already satisfied: ptyprocess>=0.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from pexpect->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (0.7.0)
    Requirement already satisfied: typing_extensions>=4.5 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from anyio->httpx<1,>=0.25.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.15.0)
    Requirement already satisfied: argon2-cffi-bindings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (25.1.0)
    Requirement already satisfied: gitdb<5,>=4.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (4.0.12)
    Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.1.1)
    Requirement already satisfied: jedi>=0.18.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.19.2)
    Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.0.52)
    Requirement already satisfied: stack_data>=0.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.6.3)
    Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2025.9.1)
    Requirement already satisfied: referencing>=0.28.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.37.0)
    Requirement already satisfied: rpds-py>=0.25.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.30.0)
    Requirement already satisfied: python-json-logger>=2.0.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.1.0)
    Requirement already satisfied: pyyaml>=5.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (6.0.3)
    Requirement already satisfied: rfc3339-validator in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.1.4)
    Requirement already satisfied: rfc3986-validator>=0.1.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.1.1)
    Requirement already satisfied: beautifulsoup4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (4.14.3)
    Requirement already satisfied: bleach!=5.0.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (6.3.0)
    Requirement already satisfied: defusedxml in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.7.1)
    Requirement already satisfied: jupyterlab-pygments in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.3.0)
    Requirement already satisfied: mistune<4,>=2.0.3 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.2.0)
    Requirement already satisfied: pandocfilters>=1.4.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: charset_normalizer<4,>=2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.4.7)
    Requirement already satisfied: urllib3<3,>=1.26 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from requests>=2.31->jupyterlab-server<3,>=2.28.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.6.3)
    Requirement already satisfied: webencodings in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.5.1)
    Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from bleach[css]!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.4.0)
    Requirement already satisfied: smmap<6,>=3.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from gitdb<5,>=4.0.1->gitpython!=2.1.4,!=2.1.5,!=2.1.6->nbdime~=4.0.1->jupyterlab-git==0.52.0->-r requirements.txt (line 6)) (5.0.3)
    Requirement already satisfied: parso<0.9.0,>=0.8.4 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jedi>=0.18.2->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.8.6)
    Requirement already satisfied: fqdn in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.5.1)
    Requirement already satisfied: isoduration in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (20.11.0)
    Requirement already satisfied: jsonpointer>1.13 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.1.1)
    Requirement already satisfied: rfc3987-syntax>=1.1.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.1.0)
    Requirement already satisfied: uri-template in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.3.0)
    Requirement already satisfied: webcolors>=24.6.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (25.10.0)
    Requirement already satisfied: wcwidth in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.6.0)
    Requirement already satisfied: executing>=1.2.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.2.1)
    Requirement already satisfied: pure-eval in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from stack_data>=0.6.0->ipython>=7.23.1->ipykernel!=6.30.0,>=6.5.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (0.2.3)
    Requirement already satisfied: cffi>=1.0.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.0.0)
    Requirement already satisfied: soupsieve>=1.6.1 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2.8.3)
    Requirement already satisfied: pycparser in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (3.0)
    Requirement already satisfied: lark>=1.2.2 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.3.1)
    Requirement already satisfied: arrow>=0.15.0 in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (1.4.0)
    Requirement already satisfied: tzdata in /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.4.0->jupyterlab==4.5.6->-r requirements.txt (line 5)) (2026.1)
    [1m[[0m[34;49mnotice[0m[1;39;49m][0m[39;49m A new release of pip is available: [0m[31;49m25.0.1[0m[39;49m -> [0m[32;49m26.0.1[0m
    [1m[[0m[34;49mnotice[0m[1;39;49m][0m[39;49m To update, run: [0m[32;49mpython -m pip install --upgrade pip[0m
    Note: you may need to restart the kernel to use updated packages.

    Initializing and checking MindSpore

    Let’s initialize MindSpore based on our hardware platform and verify that it is correctly installed.

    import os
    NOTEBOOK_USE_ASCEND = os.getenv('NOTEBOOK_USE_ASCEND', '0')
    NOTEBOOK_USE_GPU = os.getenv('NOTEBOOK_USE_GPU', '0')
    NOTEBOOK_USE_CPU = os.getenv('NOTEBOOK_USE_CPU', '0')
    NOTEBOOK_CI_MODE = os.getenv('NOTEBOOK_CI_MODE', '0')
    import mindspore
    platform = 'Ascend'
    if NOTEBOOK_USE_ASCEND == '1':
    platform = 'Ascend'
    elif NOTEBOOK_USE_GPU == '1':
    platform = 'GPU'
    elif NOTEBOOK_USE_CPU == '1' or NOTEBOOK_CI_MODE == '1':
    platform = 'CPU'
    else:
    platform = 'Ascend'
    mindspore.set_device(device_target=platform)
    mindspore.run_check()
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    setattr(self, word, getattr(machar, word).flat[0])
    /home/HwHiAiUser/.pyenv/versions/3.12.13/envs/orangepiaipro-20t/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
    return self._float_to_str(self.smallest_subnormal)
    MindSpore version: 2.8.0
    The result of multiplication calculation is correct, MindSpore has been installed on platform [Ascend] successfully!

    Warnings can be safely ignored as long as no [CRITICAL] or [ERROR] messages appear, in which case check out the Ascend forum. If you see the below output, it means MindSpore 2.8.0 is correctly installed.

    MindSpore version: 2.8.0
    The result of multiplication calculation is correct, MindSpore has been installed on platform [Ascend] successfully!

    Loading and transforming the data

    Let’s fetch the California housing dataset with scikit-learn’s fetch_california_housing. We’ll convert the target to have shape (20640, 1), to avoid issues with our linear regression algorithm due to broadcasting.

    from sklearn.datasets import fetch_california_housing
    housing = fetch_california_housing()
    X = housing.data
    y = housing.target.reshape(-1, 1)
    X.shape, y.shape
    ((20640, 8), (20640, 1))

    Split the dataset into training and validation sets. We’ll use an $80:20$ ratio which is common in many machine learning applications.

    from sklearn.model_selection import train_test_split
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
    X_train.shape, X_test.shape, y_train.shape, y_test.shape
    ((16512, 8), (4128, 8), (16512, 1), (4128, 1))

    Let’s inspect the first sample in our training set. Notice that all features and labels are purely numeric, floating point values – a perfect example of using linear regression.

    X_train[0], y_train[0]
    (array([ 8.3252 , 41. , 6.98412698, 1.02380952,
    322. , 2.55555556, 37.88 , -122.23 ]),
    array([4.526]))

    Verify that our data is clean with no NaN values.

    import numpy as np
    np.any(np.isnan(X).ravel()), np.any(np.isnan(y).ravel())
    (False, False)

    Great – none of our samples contain NaNs! Let’s compute the mean and standard deviation of the labels in our training set.

    y_train.mean(), y_train.std()
    (2.02067031310562, 1.1352013072688294)

    The scikit-learn documentation on real-world datasets states that the house prices are given as multiples of USD\$100,000 so the label values range from $0.15$ through $5.0$. Nevertheless, it’s a good idea to transform the labels through the 2-step process described below to make the data more Gaussian and centered, which should help our linear regression model produce more accurate results.

    1. Compute $\log(1 + y_i)$ for each label $y_i$. The additional unit translation within the logarithm avoids issues with zero values since $\log 0$ is undefined, even though we don’t expect any of our housing prices to be $0$
    2. Apply the StandardScaler to the results in (1) to normalize the distribution to have zero mean $\mu = 0$ and unit variance $\sigma^2 = 1$

    We’ll achieve this through a custom scaler class HousingPriceScaler which inherits the following base classes in scikit-learn.

    1. sklearn.base.BaseEstimator: base class for all estimators in scikit-learn
    2. sklearn.base.TransformerMixin: base class for data transformation in scikit-learn
    from sklearn.base import BaseEstimator, TransformerMixin
    from sklearn.preprocessing import StandardScaler
    class HousingPriceScaler(BaseEstimator, TransformerMixin):
    def __init__(self):
    self.scaler = StandardScaler()
    def fit(self, y):
    y_log1p = np.log1p(y)
    print(f'After log1p, before scaling: mean = {y_log1p.mean():.4f}, stddev = {y_log1p.std():.4f}')
    self.scaler.fit(y_log1p)
    return self
    def transform(self, y):
    y_log1p = np.log1p(y)
    y_scaled = self.scaler.transform(y_log1p)
    return y_scaled
    def inverse_transform(self, y_scaled):
    y_log1p = self.scaler.inverse_transform(y_scaled)
    y = np.expm1(y_log1p)
    return y
    scaler = HousingPriceScaler()
    scaler

    HousingPriceScaler

    iParameters

    Before scaling the labels, let’s scale the features as well. Unlike the labels which should be transformed via the 2-step process described above for optimal linear regression behavior, it suffices to normalize our features directly with sklearn.preprocessing.StandardScaler. This makes our scaled features have mean $\mu = 0$ and standard deviation $\sigma = 1$.

    features_scaler = StandardScaler()
    X_train_scaled = features_scaler.fit_transform(X_train)
    print(f'Before scaling: mean = {X_train.mean():.4f}, stddev = {X_train.std():.4f}')
    print(f'After scaling: mean = {X_train_scaled.mean():.4f}, stddev = {X_train_scaled.std():.4f}')
    X_test_scaled = features_scaler.transform(X_test)
    Before scaling: mean = 174.5399, stddev = 631.1331
    After scaling: mean = -0.0000, stddev = 1.0000

    Now transform the labels in our training set with our custom scaler and observe the transformed labels are also centered with mean $\mu = 0$ and standard deviation $\sigma = 1$.

    y_train_scaled = scaler.fit_transform(y_train)
    print(f'Before scaling: mean = {y_train.mean():.4f}, stddev = {y_train.std():.4f}')
    print(f'After scaling: mean = {y_train_scaled.mean():.4f}, stddev = {y_train_scaled.std():.4f}')
    y_test_scaled = scaler.transform(y_test)
    After log1p, before scaling: mean = 1.0418, stddev = 0.3506
    Before scaling: mean = 2.0207, stddev = 1.1352
    After scaling: mean = 0.0000, stddev = 1.0000

    With our training labels appropriately scaled, it’s time to define and train our neural network!

    Defining and training our linear regression model

    Let’s define a simple neural network with exactly 1 fully connected layer. The fully connected layer has 8 input channels and 1 output channel which corresponds to the number of features and labels in our dataset respectively.

    With MindSpore, we do this by defining our own class inheriting from mindspore.nn.Cell and implement the construct method. Our fully connected layer is given by mindspore.nn.Dense.

    Let’s also define our class to accept the following optional parameters.

    1. lr: the learning rate of our model. Defaults to 0.01 if not specified
    2. wd: the weight decay factor $\lambda$. Defaults to 0.0 if not specified

    Note that we must use 16-bit floating point values defined as float16 in mindspore.dtype. This is because matrix-vector and matrix-matrix multiplication is defined only for 16-bit floats with the CANN kernels library for the Ascend 310B1 NPU chip included with the OrangePi AIpro (20T) development board. This will reduce the precision of our model which is necessary and sufficient for our use case.

    import mindspore.nn as nn
    from mindspore import dtype as mstype
    class MyModel(nn.Cell):
    def __init__(self, lr=0.01, wd=0.0):
    super().__init__()
    self.lr = lr
    self.wd = wd
    self.dense1 = nn.Dense(8, 1, dtype=mstype.float16)
    def construct(self, X):
    y_hat = self.dense1(X)
    return y_hat
    model = MyModel(lr=0.03, wd=0.0)
    model
    MyModel(
    (dense1): Dense(input_channels=8, output_channels=1, has_bias=True)
    )

    Use the mean squared error (MSE) for our loss function, predefined in MindSpore with mindspore.nn.MSELoss.

    loss_fn = nn.MSELoss()
    loss_fn
    MSELoss()

    Use minibatch stochaistic gradient descent (SGD) for our optimizer, predefined in MindSpore with mindspore.nn.SGD. Pass in the learning rate and weight decay factor from our model via the learning_rate and weight_decay arguments, respectively.

    optimizer = nn.SGD(params=model.trainable_params(),
    learning_rate=model.lr,
    weight_decay=model.wd)
    optimizer
    SGD()

    Now define our forward and gradient functions. mindspore.value_and_grad accepts the following parameters.

    1. fn: our forward function. It takes the features X and labels y as arguments and returns a tuple of (loss, prediction)
    2. grad_position: set it to None and differentiate based on the model weights instead
    3. weights: pass in the model weights available through our optimizer as optimizer.parameters
    4. has_aux: set to True so it returns the gradient based on just the first argument loss
    def forward_fn(X, y):
    y_hat = model(X)
    loss = loss_fn(y_hat, y)
    return loss, y_hat
    grad_fn = mindspore.value_and_grad(fn=forward_fn,
    grad_position=None,
    weights=optimizer.parameters,
    has_aux=True)

    Define our training step and training epoch. Each step we take a batch of a certain fixed size, usually a power of 2, e.g. $2^9=512$. 1 full pass on our training data is known as an epoch.

    def train_step(X, y):
    (loss, _), grads = grad_fn(X, y)
    optimizer(grads)
    return loss
    def train_epoch(dataset, epoch=0):
    model.set_train()
    print(f'Epoch {epoch} start')
    batch_total = dataset.get_dataset_size()
    training_losses = []
    for batch_idx, (X_batch, y_batch) in enumerate(dataset.create_tuple_iterator()):
    loss = train_step(X_batch, y_batch)
    print(f'Training loss (scaled): {loss.asnumpy():.4f} [{batch_idx}/{batch_total}]')
    training_losses.append(loss)
    print(f'Epoch {epoch} end')
    return training_losses

    At the end of each epoch, let’s also validate our model against the validation set. Recall that our model was trained on features normalized by StandardScaler, plus labels that have undergone the 2-step transformation described in an earlier section. It will return predictions which are similarly transformed. We can undo these transformations with the inverse_transform method of our scaler class, which gives us the predicted house prices in multiples of USD\$100,000.

    def validate_epoch(epoch=0):
    model.set_train(False)
    y_hat_scaled = model(mindspore.Tensor(X_test_scaled.astype(np.float16))).asnumpy()
    y_hat = scaler.inverse_transform(y_hat_scaled)
    validation_loss_scaled = loss_fn(mindspore.Tensor(y_hat_scaled), mindspore.Tensor(y_test_scaled))
    validation_loss = loss_fn(mindspore.Tensor(y_hat), mindspore.Tensor(y_test))
    print(f'Validation loss at epoch {epoch} (scaled): {validation_loss_scaled.asnumpy():.4f}')
    print(f'Validation loss at epoch {epoch}: {validation_loss.asnumpy():.4f}')
    return validation_loss_scaled

    Convert our dataset to mindspore.dataset.NumpySlicesDataset and feed it to our model in batches of $2^9=512$ samples per batch. We saw some of its included methods in the train_epoch function.

    1. get_dataset_size: get the total number of batches in the dataset
    2. create_tuple_iterator: convert the dataset into an iterator of tuples in the form (batch_idx, (X_batch, y_batch))
    import mindspore.dataset as ds
    import mindspore.ops as ops
    train_ds = ds.NumpySlicesDataset(data=(X_train_scaled.astype(np.float16), y_train_scaled.astype(np.float16)),
    column_names=['features', 'labels'])
    train_ds = train_ds.batch(batch_size=512)
    epochs = 15
    training_losses_scaled = []
    validation_losses_scaled = []
    for epoch_idx in range(epochs):
    training_losses_scaled.extend(train_epoch(train_ds, epoch=epoch_idx))
    validation_losses_scaled.append(validate_epoch(epoch=epoch_idx))
    training_losses_scaled = ops.cast(ops.stack(training_losses_scaled, axis=0), dtype=mstype.float64)
    validation_losses_scaled = ops.stack(validation_losses_scaled, axis=0)
    training_losses_scaled.shape, validation_losses_scaled.shape
    Epoch 0 start
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/classifier/transdata/transdata_classifier.py:223: SyntaxWarning: invalid escape sequence '\B'
    Return BN\BH SCH Result
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:146: SyntaxWarning: invalid escape sequence '\c'
    2. In forward, tiling would not split c1 and c0, find c1\c0 based on t2.
    /usr/local/Ascend/cann-8.5.0/python/site-packages/tbe/dsl/unify_schedule/vector/transdata/common/graph/transdata_graph_info.py:172: SyntaxWarning: invalid escape sequence '\c'
    1. Forward: tiling would not split c1\c0\h0, find c1\c0\h1\h0 based on t2
    /usr/local/Ascend/cann-8.5.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:97: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-8.5.0/opp/built-in/op_impl/ai_core/tbe/impl/ops_legacy/dynamic/gelu_grad_v2.py:157: SyntaxWarning: invalid escape sequence '\h'
    gelu_grad_erf = erfc(-\hat{x}) / 2 + (1 /sqrt(Pi)) * (\hat{x}) * exp(-\hat{x}^2)
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    /usr/local/Ascend/cann-8.5.0/python/site-packages/asc_op_compile_base/asc_op_compiler/ascendc_compile_gen_code.py:161: SyntaxWarning: invalid escape sequence '\w'
    match = re.search(f'{option}=(\w+)', ' '.join(compile_options))
    .Training loss (scaled): 1.3799 [0/33]
    Training loss (scaled): 1.2891 [1/33]
    Training loss (scaled): 1.1133 [2/33]
    Training loss (scaled): 1.0420 [3/33]
    Training loss (scaled): 0.9453 [4/33]
    Training loss (scaled): 1.2617 [5/33]
    Training loss (scaled): 0.8091 [6/33]
    Training loss (scaled): 0.7905 [7/33]
    Training loss (scaled): 0.7300 [8/33]
    Training loss (scaled): 0.6133 [9/33]
    Training loss (scaled): 0.6831 [10/33]
    Training loss (scaled): 0.6797 [11/33]
    Training loss (scaled): 0.7168 [12/33]
    Training loss (scaled): 0.6226 [13/33]
    Training loss (scaled): 0.7051 [14/33]
    Training loss (scaled): 0.5557 [15/33]
    Training loss (scaled): 0.5259 [16/33]
    Training loss (scaled): 0.5215 [17/33]
    Training loss (scaled): 0.4946 [18/33]
    Training loss (scaled): 0.4644 [19/33]
    Training loss (scaled): 0.4788 [20/33]
    Training loss (scaled): 0.4482 [21/33]
    Training loss (scaled): 0.4346 [22/33]
    Training loss (scaled): 0.4951 [23/33]
    Training loss (scaled): 0.5820 [24/33]
    Training loss (scaled): 0.4407 [25/33]
    Training loss (scaled): 0.6157 [26/33]
    Training loss (scaled): 0.4985 [27/33]
    Training loss (scaled): 1.1260 [28/33]
    Training loss (scaled): 0.5576 [29/33]
    Training loss (scaled): 0.5366 [30/33]
    Training loss (scaled): 0.5557 [31/33]
    Training loss (scaled): 0.4836 [32/33]
    Epoch 0 end
    Validation loss at epoch 0 (scaled): 0.5919
    Validation loss at epoch 0: 284.3527
    Epoch 1 start
    Training loss (scaled): 0.4980 [0/33]
    Training loss (scaled): 0.5049 [1/33]
    Training loss (scaled): 0.4485 [2/33]
    Training loss (scaled): 0.4717 [3/33]
    Training loss (scaled): 0.4900 [4/33]
    Training loss (scaled): 0.4839 [5/33]
    Training loss (scaled): 0.5483 [6/33]
    Training loss (scaled): 0.4541 [7/33]
    Training loss (scaled): 0.5259 [8/33]
    Training loss (scaled): 0.4878 [9/33]
    Training loss (scaled): 0.4846 [10/33]
    Training loss (scaled): 0.5684 [11/33]
    Training loss (scaled): 0.4893 [12/33]
    Training loss (scaled): 0.4773 [13/33]
    Training loss (scaled): 0.4653 [14/33]
    Training loss (scaled): 0.4905 [15/33]
    Training loss (scaled): 0.4165 [16/33]
    Training loss (scaled): 0.4250 [17/33]
    Training loss (scaled): 0.4495 [18/33]
    Training loss (scaled): 0.4648 [19/33]
    Training loss (scaled): 0.5757 [20/33]
    Training loss (scaled): 0.4775 [21/33]
    Training loss (scaled): 0.4695 [22/33]
    Training loss (scaled): 0.5386 [23/33]
    Training loss (scaled): 0.4153 [24/33]
    Training loss (scaled): 0.5107 [25/33]
    Training loss (scaled): 0.5142 [26/33]
    Training loss (scaled): 0.4727 [27/33]
    Training loss (scaled): 0.4907 [28/33]
    Training loss (scaled): 0.4236 [29/33]
    Training loss (scaled): 0.4270 [30/33]
    Training loss (scaled): 0.4553 [31/33]
    Training loss (scaled): 0.3872 [32/33]
    Epoch 1 end
    Validation loss at epoch 1 (scaled): 0.4860
    Validation loss at epoch 1: 0.7928
    Epoch 2 start
    Training loss (scaled): 0.4849 [0/33]
    Training loss (scaled): 0.4739 [1/33]
    Training loss (scaled): 0.4854 [2/33]
    Training loss (scaled): 0.4985 [3/33]
    Training loss (scaled): 0.4985 [4/33]
    Training loss (scaled): 0.4639 [5/33]
    Training loss (scaled): 0.4258 [6/33]
    Training loss (scaled): 0.5562 [7/33]
    Training loss (scaled): 0.4263 [8/33]
    Training loss (scaled): 0.3901 [9/33]
    Training loss (scaled): 0.4709 [10/33]
    Training loss (scaled): 0.4087 [11/33]
    Training loss (scaled): 0.5078 [12/33]
    Training loss (scaled): 0.4644 [13/33]
    Training loss (scaled): 0.4473 [14/33]
    Training loss (scaled): 0.4390 [15/33]
    Training loss (scaled): 0.4197 [16/33]
    Training loss (scaled): 0.4197 [17/33]
    Training loss (scaled): 0.5298 [18/33]
    Training loss (scaled): 0.4229 [19/33]
    Training loss (scaled): 0.4641 [20/33]
    Training loss (scaled): 0.4233 [21/33]
    Training loss (scaled): 0.4404 [22/33]
    Training loss (scaled): 0.5151 [23/33]
    Training loss (scaled): 0.5049 [24/33]
    Training loss (scaled): 0.4377 [25/33]
    Training loss (scaled): 0.5542 [26/33]
    Training loss (scaled): 0.4241 [27/33]
    Training loss (scaled): 0.4631 [28/33]
    Training loss (scaled): 0.4189 [29/33]
    Training loss (scaled): 0.3826 [30/33]
    Training loss (scaled): 0.4807 [31/33]
    Training loss (scaled): 0.4712 [32/33]
    Epoch 2 end
    Validation loss at epoch 2 (scaled): 0.4533
    Validation loss at epoch 2: 0.8286
    Epoch 3 start
    Training loss (scaled): 0.5015 [0/33]
    Training loss (scaled): 0.5015 [1/33]
    Training loss (scaled): 0.4878 [2/33]
    Training loss (scaled): 0.4609 [3/33]
    Training loss (scaled): 0.4365 [4/33]
    Training loss (scaled): 0.4392 [5/33]
    Training loss (scaled): 0.4238 [6/33]
    Training loss (scaled): 0.4951 [7/33]
    Training loss (scaled): 0.4319 [8/33]
    Training loss (scaled): 0.4109 [9/33]
    Training loss (scaled): 0.5068 [10/33]
    Training loss (scaled): 0.4204 [11/33]
    Training loss (scaled): 0.4448 [12/33]
    Training loss (scaled): 0.4456 [13/33]
    Training loss (scaled): 0.4688 [14/33]
    Training loss (scaled): 0.4763 [15/33]
    Training loss (scaled): 0.4114 [16/33]
    Training loss (scaled): 0.4299 [17/33]
    Training loss (scaled): 0.4363 [18/33]
    Training loss (scaled): 0.3933 [19/33]
    Training loss (scaled): 0.4175 [20/33]
    Training loss (scaled): 0.4856 [21/33]
    Training loss (scaled): 0.5078 [22/33]
    Training loss (scaled): 0.4187 [23/33]
    Training loss (scaled): 0.4204 [24/33]
    Training loss (scaled): 0.5415 [25/33]
    Training loss (scaled): 0.3647 [26/33]
    Training loss (scaled): 0.4138 [27/33]
    Training loss (scaled): 0.4194 [28/33]
    Training loss (scaled): 0.4302 [29/33]
    Training loss (scaled): 0.4780 [30/33]
    Training loss (scaled): 0.3928 [31/33]
    Training loss (scaled): 0.4355 [32/33]
    Epoch 3 end
    Validation loss at epoch 3 (scaled): 0.4293
    Validation loss at epoch 3: 0.7472
    Epoch 4 start
    Training loss (scaled): 0.4875 [0/33]
    Training loss (scaled): 0.4434 [1/33]
    Training loss (scaled): 0.3662 [2/33]
    Training loss (scaled): 0.4177 [3/33]
    Training loss (scaled): 0.4675 [4/33]
    Training loss (scaled): 0.4407 [5/33]
    Training loss (scaled): 0.4023 [6/33]
    Training loss (scaled): 0.4033 [7/33]
    Training loss (scaled): 0.5107 [8/33]
    Training loss (scaled): 0.4307 [9/33]
    Training loss (scaled): 0.4255 [10/33]
    Training loss (scaled): 0.4106 [11/33]
    Training loss (scaled): 0.4382 [12/33]
    Training loss (scaled): 0.4121 [13/33]
    Training loss (scaled): 0.4995 [14/33]
    Training loss (scaled): 0.4846 [15/33]
    Training loss (scaled): 0.4290 [16/33]
    Training loss (scaled): 0.4783 [17/33]
    Training loss (scaled): 0.4761 [18/33]
    Training loss (scaled): 0.4272 [19/33]
    Training loss (scaled): 0.4092 [20/33]
    Training loss (scaled): 0.4395 [21/33]
    Training loss (scaled): 0.3760 [22/33]
    Training loss (scaled): 0.4736 [23/33]
    Training loss (scaled): 0.4136 [24/33]
    Training loss (scaled): 0.4019 [25/33]
    Training loss (scaled): 0.5293 [26/33]
    Training loss (scaled): 0.4460 [27/33]
    Training loss (scaled): 0.4272 [28/33]
    Training loss (scaled): 0.4282 [29/33]
    Training loss (scaled): 0.4248 [30/33]
    Training loss (scaled): 0.4141 [31/33]
    Training loss (scaled): 0.4194 [32/33]
    Epoch 4 end
    Validation loss at epoch 4 (scaled): 0.4155
    Validation loss at epoch 4: 0.7660
    Epoch 5 start
    Training loss (scaled): 0.4307 [0/33]
    Training loss (scaled): 0.4094 [1/33]
    Training loss (scaled): 0.4468 [2/33]
    Training loss (scaled): 0.4265 [3/33]
    Training loss (scaled): 0.4500 [4/33]
    Training loss (scaled): 0.4451 [5/33]
    Training loss (scaled): 0.4629 [6/33]
    Training loss (scaled): 0.4011 [7/33]
    Training loss (scaled): 0.3989 [8/33]
    Training loss (scaled): 0.4148 [9/33]
    Training loss (scaled): 0.4294 [10/33]
    Training loss (scaled): 0.3813 [11/33]
    Training loss (scaled): 0.4500 [12/33]
    Training loss (scaled): 0.4382 [13/33]
    Training loss (scaled): 0.4919 [14/33]
    Training loss (scaled): 0.4407 [15/33]
    Training loss (scaled): 0.4353 [16/33]
    Training loss (scaled): 0.3940 [17/33]
    Training loss (scaled): 0.4619 [18/33]
    Training loss (scaled): 0.3779 [19/33]
    Training loss (scaled): 0.4795 [20/33]
    Training loss (scaled): 0.4648 [21/33]
    Training loss (scaled): 0.3726 [22/33]
    Training loss (scaled): 0.4307 [23/33]
    Training loss (scaled): 0.4753 [24/33]
    Training loss (scaled): 0.4597 [25/33]
    Training loss (scaled): 0.3872 [26/33]
    Training loss (scaled): 0.4868 [27/33]
    Training loss (scaled): 0.3879 [28/33]
    Training loss (scaled): 0.3955 [29/33]
    Training loss (scaled): 0.4275 [30/33]
    Training loss (scaled): 0.4331 [31/33]
    Training loss (scaled): 0.3843 [32/33]
    Epoch 5 end
    Validation loss at epoch 5 (scaled): 0.3980
    Validation loss at epoch 5: 0.7297
    Epoch 6 start
    Training loss (scaled): 0.3804 [0/33]
    Training loss (scaled): 0.4395 [1/33]
    Training loss (scaled): 0.3594 [2/33]
    Training loss (scaled): 0.4094 [3/33]
    Training loss (scaled): 0.4695 [4/33]
    Training loss (scaled): 0.4031 [5/33]
    Training loss (scaled): 0.4036 [6/33]
    Training loss (scaled): 0.4141 [7/33]
    Training loss (scaled): 0.4409 [8/33]
    Training loss (scaled): 0.4438 [9/33]
    Training loss (scaled): 0.4038 [10/33]
    Training loss (scaled): 0.4348 [11/33]
    Training loss (scaled): 0.4473 [12/33]
    Training loss (scaled): 0.4678 [13/33]
    Training loss (scaled): 0.4485 [14/33]
    Training loss (scaled): 0.4634 [15/33]
    Training loss (scaled): 0.4153 [16/33]
    Training loss (scaled): 0.3677 [17/33]
    Training loss (scaled): 0.4082 [18/33]
    Training loss (scaled): 0.4609 [19/33]
    Training loss (scaled): 0.4353 [20/33]
    Training loss (scaled): 0.4473 [21/33]
    Training loss (scaled): 0.3916 [22/33]
    Training loss (scaled): 0.3882 [23/33]
    Training loss (scaled): 0.4001 [24/33]
    Training loss (scaled): 0.4312 [25/33]
    Training loss (scaled): 0.4265 [26/33]
    Training loss (scaled): 0.4602 [27/33]
    Training loss (scaled): 0.4067 [28/33]
    Training loss (scaled): 0.5522 [29/33]
    Training loss (scaled): 0.3811 [30/33]
    Training loss (scaled): 0.4260 [31/33]
    Training loss (scaled): 0.3186 [32/33]
    Epoch 6 end
    Validation loss at epoch 6 (scaled): 0.3879
    Validation loss at epoch 6: 0.7155
    Epoch 7 start
    Training loss (scaled): 0.3860 [0/33]
    Training loss (scaled): 0.3933 [1/33]
    Training loss (scaled): 0.3569 [2/33]
    Training loss (scaled): 0.4600 [3/33]
    Training loss (scaled): 0.4119 [4/33]
    Training loss (scaled): 0.5010 [5/33]
    Training loss (scaled): 0.3506 [6/33]
    Training loss (scaled): 0.3987 [7/33]
    Training loss (scaled): 0.4194 [8/33]
    Training loss (scaled): 0.4277 [9/33]
    Training loss (scaled): 0.4182 [10/33]
    Training loss (scaled): 0.3855 [11/33]
    Training loss (scaled): 0.4700 [12/33]
    Training loss (scaled): 0.3882 [13/33]
    Training loss (scaled): 0.4424 [14/33]
    Training loss (scaled): 0.4597 [15/33]
    Training loss (scaled): 0.3625 [16/33]
    Training loss (scaled): 0.4492 [17/33]
    Training loss (scaled): 0.3894 [18/33]
    Training loss (scaled): 0.4302 [19/33]
    Training loss (scaled): 0.6040 [20/33]
    Training loss (scaled): 0.4192 [21/33]
    Training loss (scaled): 0.4119 [22/33]
    Training loss (scaled): 0.3787 [23/33]
    Training loss (scaled): 0.4592 [24/33]
    Training loss (scaled): 0.3889 [25/33]
    Training loss (scaled): 0.4431 [26/33]
    Training loss (scaled): 0.4304 [27/33]
    Training loss (scaled): 0.4224 [28/33]
    Training loss (scaled): 0.4387 [29/33]
    Training loss (scaled): 0.3936 [30/33]
    Training loss (scaled): 0.4045 [31/33]
    Training loss (scaled): 0.4368 [32/33]
    Epoch 7 end
    Validation loss at epoch 7 (scaled): 0.3768
    Validation loss at epoch 7: 0.7110
    Epoch 8 start
    Training loss (scaled): 0.4438 [0/33]
    Training loss (scaled): 0.3782 [1/33]
    Training loss (scaled): 0.4084 [2/33]
    Training loss (scaled): 0.3774 [3/33]
    Training loss (scaled): 0.4077 [4/33]
    Training loss (scaled): 0.4534 [5/33]
    Training loss (scaled): 0.3889 [6/33]
    Training loss (scaled): 0.4089 [7/33]
    Training loss (scaled): 0.3799 [8/33]
    Training loss (scaled): 0.4436 [9/33]
    Training loss (scaled): 0.4214 [10/33]
    Training loss (scaled): 0.4421 [11/33]
    Training loss (scaled): 0.4214 [12/33]
    Training loss (scaled): 0.3994 [13/33]
    Training loss (scaled): 0.4077 [14/33]
    Training loss (scaled): 0.4004 [15/33]
    Training loss (scaled): 0.4548 [16/33]
    Training loss (scaled): 0.4453 [17/33]
    Training loss (scaled): 0.4199 [18/33]
    Training loss (scaled): 0.4426 [19/33]
    Training loss (scaled): 0.3887 [20/33]
    Training loss (scaled): 0.4299 [21/33]
    Training loss (scaled): 0.4333 [22/33]
    Training loss (scaled): 0.4502 [23/33]
    Training loss (scaled): 0.4641 [24/33]
    Training loss (scaled): 0.3931 [25/33]
    Training loss (scaled): 0.4053 [26/33]
    Training loss (scaled): 0.4231 [27/33]
    Training loss (scaled): 0.4282 [28/33]
    Training loss (scaled): 0.4646 [29/33]
    Training loss (scaled): 0.3545 [30/33]
    Training loss (scaled): 0.3992 [31/33]
    Training loss (scaled): 0.4082 [32/33]
    Epoch 8 end
    Validation loss at epoch 8 (scaled): 0.3708
    Validation loss at epoch 8: 0.6989
    Epoch 9 start
    Training loss (scaled): 0.3257 [0/33]
    Training loss (scaled): 0.3926 [1/33]
    Training loss (scaled): 0.4119 [2/33]
    Training loss (scaled): 0.5244 [3/33]
    Training loss (scaled): 0.4785 [4/33]
    Training loss (scaled): 0.4290 [5/33]
    Training loss (scaled): 0.4595 [6/33]
    Training loss (scaled): 0.4036 [7/33]
    Training loss (scaled): 0.4187 [8/33]
    Training loss (scaled): 0.4075 [9/33]
    Training loss (scaled): 0.3384 [10/33]
    Training loss (scaled): 0.4338 [11/33]
    Training loss (scaled): 0.4077 [12/33]
    Training loss (scaled): 0.4485 [13/33]
    Training loss (scaled): 0.4392 [14/33]
    Training loss (scaled): 0.3640 [15/33]
    Training loss (scaled): 0.3997 [16/33]
    Training loss (scaled): 0.4136 [17/33]
    Training loss (scaled): 0.3755 [18/33]
    Training loss (scaled): 0.4504 [19/33]
    Training loss (scaled): 0.4307 [20/33]
    Training loss (scaled): 0.4619 [21/33]
    Training loss (scaled): 0.3486 [22/33]
    Training loss (scaled): 0.4304 [23/33]
    Training loss (scaled): 0.3750 [24/33]
    Training loss (scaled): 0.4080 [25/33]
    Training loss (scaled): 0.4058 [26/33]
    Training loss (scaled): 0.4558 [27/33]
    Training loss (scaled): 0.4185 [28/33]
    Training loss (scaled): 0.4119 [29/33]
    Training loss (scaled): 0.4121 [30/33]
    Training loss (scaled): 0.3945 [31/33]
    Training loss (scaled): 0.4443 [32/33]
    Epoch 9 end
    Validation loss at epoch 9 (scaled): 0.3671
    Validation loss at epoch 9: 0.7032
    Epoch 10 start
    Training loss (scaled): 0.4160 [0/33]
    Training loss (scaled): 0.3657 [1/33]
    Training loss (scaled): 0.4250 [2/33]
    Training loss (scaled): 0.3606 [3/33]
    Training loss (scaled): 0.4211 [4/33]
    Training loss (scaled): 0.4133 [5/33]
    Training loss (scaled): 0.4048 [6/33]
    Training loss (scaled): 0.5000 [7/33]
    Training loss (scaled): 0.3999 [8/33]
    Training loss (scaled): 0.4199 [9/33]
    Training loss (scaled): 0.4463 [10/33]
    Training loss (scaled): 0.3999 [11/33]
    Training loss (scaled): 0.3787 [12/33]
    Training loss (scaled): 0.3945 [13/33]
    Training loss (scaled): 0.4580 [14/33]
    Training loss (scaled): 0.4402 [15/33]
    Training loss (scaled): 0.4546 [16/33]
    Training loss (scaled): 0.3735 [17/33]
    Training loss (scaled): 0.4141 [18/33]
    Training loss (scaled): 0.4097 [19/33]
    Training loss (scaled): 0.3789 [20/33]
    Training loss (scaled): 0.3848 [21/33]
    Training loss (scaled): 0.3628 [22/33]
    Training loss (scaled): 0.3931 [23/33]
    Training loss (scaled): 0.4067 [24/33]
    Training loss (scaled): 0.4187 [25/33]
    Training loss (scaled): 0.4050 [26/33]
    Training loss (scaled): 0.3977 [27/33]
    Training loss (scaled): 0.3567 [28/33]
    Training loss (scaled): 0.4460 [29/33]
    Training loss (scaled): 0.4719 [30/33]
    Training loss (scaled): 0.4302 [31/33]
    Training loss (scaled): 0.4878 [32/33]
    Epoch 10 end
    Validation loss at epoch 10 (scaled): 0.3616
    Validation loss at epoch 10: 0.7103
    Epoch 11 start
    Training loss (scaled): 0.4387 [0/33]
    Training loss (scaled): 0.4246 [1/33]
    Training loss (scaled): 0.4741 [2/33]
    Training loss (scaled): 0.4214 [3/33]
    Training loss (scaled): 0.3855 [4/33]
    Training loss (scaled): 0.4331 [5/33]
    Training loss (scaled): 0.3752 [6/33]
    Training loss (scaled): 0.3652 [7/33]
    Training loss (scaled): 0.4309 [8/33]
    Training loss (scaled): 0.3799 [9/33]
    Training loss (scaled): 0.4414 [10/33]
    Training loss (scaled): 0.4143 [11/33]
    Training loss (scaled): 0.3821 [12/33]
    Training loss (scaled): 0.3503 [13/33]
    Training loss (scaled): 0.4426 [14/33]
    Training loss (scaled): 0.3931 [15/33]
    Training loss (scaled): 0.4011 [16/33]
    Training loss (scaled): 0.4319 [17/33]
    Training loss (scaled): 0.4209 [18/33]
    Training loss (scaled): 0.4080 [19/33]
    Training loss (scaled): 0.5190 [20/33]
    Training loss (scaled): 0.4082 [21/33]
    Training loss (scaled): 0.4209 [22/33]
    Training loss (scaled): 0.3794 [23/33]
    Training loss (scaled): 0.3772 [24/33]
    Training loss (scaled): 0.3721 [25/33]
    Training loss (scaled): 0.4241 [26/33]
    Training loss (scaled): 0.4021 [27/33]
    Training loss (scaled): 0.3865 [28/33]
    Training loss (scaled): 0.4167 [29/33]
    Training loss (scaled): 0.4834 [30/33]
    Training loss (scaled): 0.3765 [31/33]
    Training loss (scaled): 0.3296 [32/33]
    Epoch 11 end
    Validation loss at epoch 11 (scaled): 0.3568
    Validation loss at epoch 11: 0.7126
    Epoch 12 start
    Training loss (scaled): 0.3965 [0/33]
    Training loss (scaled): 0.3430 [1/33]
    Training loss (scaled): 0.4348 [2/33]
    Training loss (scaled): 0.3718 [3/33]
    Training loss (scaled): 0.4041 [4/33]
    Training loss (scaled): 0.4045 [5/33]
    Training loss (scaled): 0.4658 [6/33]
    Training loss (scaled): 0.4331 [7/33]
    Training loss (scaled): 0.3931 [8/33]
    Training loss (scaled): 0.4214 [9/33]
    Training loss (scaled): 0.4358 [10/33]
    Training loss (scaled): 0.4421 [11/33]
    Training loss (scaled): 0.4126 [12/33]
    Training loss (scaled): 0.4233 [13/33]
    Training loss (scaled): 0.3572 [14/33]
    Training loss (scaled): 0.3760 [15/33]
    Training loss (scaled): 0.3989 [16/33]
    Training loss (scaled): 0.3936 [17/33]
    Training loss (scaled): 0.4368 [18/33]
    Training loss (scaled): 0.4128 [19/33]
    Training loss (scaled): 0.4697 [20/33]
    Training loss (scaled): 0.4104 [21/33]
    Training loss (scaled): 0.4207 [22/33]
    Training loss (scaled): 0.3813 [23/33]
    Training loss (scaled): 0.3743 [24/33]
    Training loss (scaled): 0.4106 [25/33]
    Training loss (scaled): 0.4231 [26/33]
    Training loss (scaled): 0.4358 [27/33]
    Training loss (scaled): 0.4773 [28/33]
    Training loss (scaled): 0.4075 [29/33]
    Training loss (scaled): 0.3992 [30/33]
    Training loss (scaled): 0.3733 [31/33]
    Training loss (scaled): 0.3323 [32/33]
    Epoch 12 end
    Validation loss at epoch 12 (scaled): 0.3552
    Validation loss at epoch 12: 0.7013
    Epoch 13 start
    Training loss (scaled): 0.4077 [0/33]
    Training loss (scaled): 0.3345 [1/33]
    Training loss (scaled): 0.4136 [2/33]
    Training loss (scaled): 0.3936 [3/33]
    Training loss (scaled): 0.4302 [4/33]
    Training loss (scaled): 0.3457 [5/33]
    Training loss (scaled): 0.4199 [6/33]
    Training loss (scaled): 0.4307 [7/33]
    Training loss (scaled): 0.4023 [8/33]
    Training loss (scaled): 0.3308 [9/33]
    Training loss (scaled): 0.3813 [10/33]
    Training loss (scaled): 0.3892 [11/33]
    Training loss (scaled): 0.3499 [12/33]
    Training loss (scaled): 0.4666 [13/33]
    Training loss (scaled): 0.4937 [14/33]
    Training loss (scaled): 0.4275 [15/33]
    Training loss (scaled): 0.4087 [16/33]
    Training loss (scaled): 0.4822 [17/33]
    Training loss (scaled): 0.4170 [18/33]
    Training loss (scaled): 0.3948 [19/33]
    Training loss (scaled): 0.4583 [20/33]
    Training loss (scaled): 0.4229 [21/33]
    Training loss (scaled): 0.3940 [22/33]
    Training loss (scaled): 0.3770 [23/33]
    Training loss (scaled): 0.4866 [24/33]
    Training loss (scaled): 0.3835 [25/33]
    Training loss (scaled): 0.4238 [26/33]
    Training loss (scaled): 0.3699 [27/33]
    Training loss (scaled): 0.3833 [28/33]
    Training loss (scaled): 0.4583 [29/33]
    Training loss (scaled): 0.4092 [30/33]
    Training loss (scaled): 0.3901 [31/33]
    Training loss (scaled): 0.3960 [32/33]
    Epoch 13 end
    Validation loss at epoch 13 (scaled): 0.3552
    Validation loss at epoch 13: 0.7009
    Epoch 14 start
    Training loss (scaled): 0.3989 [0/33]
    Training loss (scaled): 0.4541 [1/33]
    Training loss (scaled): 0.4031 [2/33]
    Training loss (scaled): 0.3794 [3/33]
    Training loss (scaled): 0.4490 [4/33]
    Training loss (scaled): 0.4451 [5/33]
    Training loss (scaled): 0.4978 [6/33]
    Training loss (scaled): 0.3982 [7/33]
    Training loss (scaled): 0.4253 [8/33]
    Training loss (scaled): 0.3896 [9/33]
    Training loss (scaled): 0.4092 [10/33]
    Training loss (scaled): 0.3547 [11/33]
    Training loss (scaled): 0.4739 [12/33]
    Training loss (scaled): 0.4065 [13/33]
    Training loss (scaled): 0.4004 [14/33]
    Training loss (scaled): 0.3972 [15/33]
    Training loss (scaled): 0.3875 [16/33]
    Training loss (scaled): 0.3767 [17/33]
    Training loss (scaled): 0.4216 [18/33]
    Training loss (scaled): 0.3386 [19/33]
    Training loss (scaled): 0.3823 [20/33]
    Training loss (scaled): 0.4116 [21/33]
    Training loss (scaled): 0.3882 [22/33]
    Training loss (scaled): 0.3708 [23/33]
    Training loss (scaled): 0.4268 [24/33]
    Training loss (scaled): 0.3677 [25/33]
    Training loss (scaled): 0.4009 [26/33]
    Training loss (scaled): 0.4165 [27/33]
    Training loss (scaled): 0.4329 [28/33]
    Training loss (scaled): 0.3398 [29/33]
    Training loss (scaled): 0.4089 [30/33]
    Training loss (scaled): 0.4509 [31/33]
    Training loss (scaled): 0.4446 [32/33]
    Epoch 14 end
    Validation loss at epoch 14 (scaled): 0.3620
    Validation loss at epoch 14: 0.6809
    ((495,), (15,))

    Plot the scaled training vs. validation loss. Our model performs remarkably well on both seen and unseen inputs!

    import matplotlib.pyplot as plt
    batch_total = training_losses_scaled.size
    epoch_total = validation_losses_scaled.size
    batches_per_epoch = batch_total // epoch_total
    batch_x = np.arange(batch_total)
    epoch_x = np.arange(epoch_total) * batches_per_epoch + batches_per_epoch
    training_losses_y = training_losses_scaled.asnumpy()
    validation_losses_y = validation_losses_scaled.asnumpy()
    plt.figure(figsize=(8, 5))
    plt.plot(batch_x, training_losses_y, label='Training loss (scaled)', linestyle='-')
    plt.plot(epoch_x, validation_losses_y, label='Validation loss (scaled)', linestyle='--')
    plt.title('Training vs. validation loss (scaled)')
    plt.xlabel('Batch number')
    plt.ylabel('Loss (scaled)')
    plt.yscale('log')
    plt.grid(True, linestyle='--', alpha=0.6)
    plt.legend()
    plt.show()
    .
    Training vs. validation loss (scaled)

    Predicting the house price on a validation sample

    Let’s take a sample from the validation set and use our model to predict the house price. We’ll see how it compares to the actual price and how much it differs.

    Recall that:

    1. The features are normalized to have mean $\mu = 0$ and $\sigma = 1$ with scikit-learn’s StandardScaler
    2. The labels are transformed by the 2-step process below.
      1. Compute $\log (1 + y_i)$ for each label $y_i$
      2. Normalize the result in (a) with StandardScaler
    3. The original labels are expressed as multiples of USD\$100,000
    X_test_scaled_sample = X_test_scaled[0]
    y_test_scaled_sample = y_test_scaled[0].reshape(-1, 1)
    model.set_train(False)
    y_hat_scaled_sample = model(mindspore.Tensor(X_test_scaled_sample.astype(np.float16))).asnumpy().reshape(-1, 1)
    y_hat_sample = scaler.inverse_transform(y_hat_scaled_sample).item()
    y_hat_sample_usd = y_hat_sample * 100_000
    y_test_sample = scaler.inverse_transform(y_test_scaled_sample).item()
    y_test_sample_usd = y_test_sample * 100_000
    print(f'Predicted house price (USD$): {y_hat_sample_usd:>10.2f}')
    print(f'Actual house price (USD$): {y_test_sample_usd:>13.2f}')
    print(f'Percentage error: {(y_hat_sample_usd - y_test_sample_usd) / y_test_sample_usd * 100:>22.2f}%')
    Predicted house price (USD$): 129003.91
    Actual house price (USD$): 165600.00
    Percentage error: -22.10%

    Saving and exporting the model

    Now that our linear regression model is trained to predict house prices in California, let’s save and export it so others can download and import our model for inference. The most common exported model formats supported by MindSpore include but not limited to the below.

    1. MindIR: the intermediate representation (IR) format natively supported by MindSpore. Use the mindspore.export function with file_format='MINDIR' to export models in this format
    2. ONNX: the leading portable, vendor-neutral format for representing predictive machine learning models, a graduated project under LF AI & Data. Use the mindspore.export function with file_format='ONNX' to export models in this format

    Let’s export our model in MindIR format and specify the following arguments.

    1. net: our trained model
    2. *inputs: sample inputs that our model takes. Since each sample in our dataset has 8 features, our sample tensor has shape (1, 8)
    3. file_name: the name of our exported model, minus the file extension
    4. file_format: the format of our exported model. The appropriate file extension is automatically appended, e.g. .mindir
    # Export our model in MindIR format to `california-housing-linear-simple.mindir`
    mindspore.export(model,
    mindspore.Tensor(X_test_scaled_sample.astype(np.float16).reshape(-1, 8)),
    file_name='california-housing-linear-simple',
    file_format='MINDIR')
    # Verify the file exists
    os.path.isfile('california-housing-linear-simple.mindir')
    True

    To export our model in ONNX format, the file_format='ONNX' option is deprecated so we will use mindspore.onnx.export instead with the following parameters.

    1. net: our trained model
    2. *inputs: sample inputs to our model, similar with mindspore.export
    3. file_name: filename of our exported ONNX model. The .onnx file extension must be specified explicitly
    4. input_names: list of names for our model inputs, e.g. ['features']
    5. output_names: list of names for our model outputs, e.g. ['labels']
    # Export our model in ONNX format to `california-housing-linear-simple.onnx`
    mindspore.onnx.export(model,
    mindspore.Tensor(X_test_scaled_sample.astype(np.float16).reshape(-1, 8)),
    file_name='california-housing-linear-simple.onnx',
    input_names=['features'],
    output_names=['labels'])
    # Verify the file exists
    os.path.isfile('california-housing-linear-simple.onnx')
    True

    With our model exported in both formats, we can upload them to object storage or a dedicated hub for sharing machine learning models such as Hugging Face. This is outside the scope of this article.

    Concluding remarks and going further

    We saw in this interactive notebook article how to train a simple linear regression model in MindSpore to predict house prices in California. The key points are summarized below.

    1. Loading the California housing dataset with scikit-learn
    2. Checking and preprocessing our data to ensure it is clean and well-structured
    3. Applying transformations to our data to ensure model accuracy and performance
    4. Defining the neural network, loss and optimizer functions for training our model
    5. Organizing our training set in batches of $2^n$ to manage the training workload and memory consumption
    6. Making predictions on our validation set and unwinding the data transformations to obtain meaningful figures

    This experiment has only scratched the surface of what’s possible with MindSpore and the Ascend ecosystem. I hope you enjoyed this article and stay tuned for updates! 😉

    + , , , , , ,