<jupyter_start><jupyter_text>模型加密保护  概述MindSpore框架提供通过加密对模型文件进行保护的功能，使用对称加密算法对参数文件或推理模型进行加密，使用时直接加载密文模型完成推理或增量训练。目前加密方案支持在Linux平台下对CheckPoint参数文件的保护。以下通过图片分类应用示例来介绍保存CheckPoint格式文件和导出MindIR、AIR和ONNX格式文件的方法。> 本文档适用于Linux平台下CPU、GPU和Ascend AI处理器环境。 说明：在保存和转换模型前，我们需要完整进行图片分类训练，包含数据准备、定义网络、定义损失函数及优化器和训练网络，详细信息可以参考：https://gitee.com/mindspore/docs/blob/r1.2/tutorials/training/source_zh_cn/quick_start/quick_start.ipynb 整体流程如下：1. 数据准备2. 构造神经网络3. 搭建训练网络、定义损失函数及优化器4. 加密导出CheckPoint格式文件5. 加载密文CheckPoint格式文件  数据准备  下载MNIST数据集在Jupyter Notebook中运行以下命令来获取数据集：<jupyter_code>!mkdir -p ./datasets/MNIST_Data/train ./datasets/MNIST_Data/test
!wget -NP ./datasets/MNIST_Data/train https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/train-labels-idx1-ubyte --no-check-certificate
!wget -NP ./datasets/MNIST_Data/train https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/train-images-idx3-ubyte --no-check-certificate
!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-labels-idx1-ubyte --no-check-certificate
!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-images-idx3-ubyte --no-check-certificate
!tree ./datasets/MNIST_Data<jupyter_output>[01;34m./datasets/MNIST_Data[00m
├── [01;34mtest[00m
│   ├── t10k-images-idx3-ubyte
│   └── t10k-labels-idx1-ubyte
└── [01;34mtrain[00m
    ├── train-images-idx3-ubyte
    └── train-labels-idx1-ubyte

2 directories, 4 files<jupyter_text>数据处理：数据集对于训练非常重要，好的数据集可以有效提高训练精度和效率，在加载数据集前，我们通常会对数据集进行一些处理。  定义数据集及数据操作我们定义一个函数`create_dataset`来创建数据集。在这个函数中，我们定义好需要进行的数据增强和处理操作：1. 定义数据集。2. 定义进行数据增强和处理所需要的一些参数。3. 根据参数，生成对应的数据增强操作。4. 使用`map`映射函数，将数据操作应用到数据集。5. 对生成的数据集进行处理。<jupyter_code>import mindspore.dataset.vision.c_transforms as CV
import mindspore.dataset.transforms.c_transforms as C
from mindspore.dataset.vision import Inter
from mindspore import dtype as mstype
import mindspore.dataset as ds


def create_dataset(data_path, batch_size=32, repeat_size=1,
                   num_parallel_workers=1):
    """ 
    create dataset for train or test
    
    Args:
        data_path (str): Data path
        batch_size (int): The number of data records in each group
        repeat_size (int): The number of replicated data records
        num_parallel_workers (int): The number of parallel workers
    """
    # define dataset
    mnist_ds = ds.MnistDataset(data_path)

    # define some parameters needed for data enhancement and rough justification
    resize_height, resize_width = 32, 32
    rescale = 1.0 / 255.0
    shift = 0.0
    rescale_nml = 1 / 0.3081
    shift_nml = -1 * 0.1307 / 0.3081

    # according to the parameters, generate the corresponding data enhancement method
    resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR)
    rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
    rescale_op = CV.Rescale(rescale, shift)
    hwc2chw_op = CV.HWC2CHW()
    type_cast_op = C.TypeCast(mstype.int32)

    # using map to apply operations to a dataset
    mnist_ds = mnist_ds.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers)
    mnist_ds = mnist_ds.map(operations=resize_op, input_columns="image", num_parallel_workers=num_parallel_workers)
    mnist_ds = mnist_ds.map(operations=rescale_op, input_columns="image", num_parallel_workers=num_parallel_workers)
    mnist_ds = mnist_ds.map(operations=rescale_nml_op, input_columns="image", num_parallel_workers=num_parallel_workers)
    mnist_ds = mnist_ds.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=num_parallel_workers)
    
    # process the generated dataset
    buffer_size = 10000
    mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size)
    mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)
    mnist_ds = mnist_ds.repeat(repeat_size)

    return mnist_ds<jupyter_output><empty_output><jupyter_text>构造神经网络在对手写字体识别上，通常采用卷积神经网络架构（CNN）进行学习预测，最经典的属1998年由Yann LeCun创建的LeNet5架构，在构建LeNet5前，我们需要对全连接层以及卷积层进行初始化。<jupyter_code>import mindspore.nn as nn
from mindspore.common.initializer import Normal

class LeNet5(nn.Cell):
    """Lenet network structure."""
    # define the operator required
    def __init__(self, num_class=10, num_channel=1):
        super(LeNet5, self).__init__()
        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')
        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')
        self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))
        self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))
        self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))
        self.relu = nn.ReLU()
        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
        self.flatten = nn.Flatten()

    # use the preceding operators to construct networks
    def construct(self, x):
        x = self.max_pool2d(self.relu(self.conv1(x)))
        x = self.max_pool2d(self.relu(self.conv2(x)))
        x = self.flatten(x)
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x) 
        return x<jupyter_output><empty_output><jupyter_text>搭建训练网络构建完成神经网络后，就可以着手进行训练网络的构建，包括定义损失函数及优化器。<jupyter_code>import os
from mindspore.nn import SoftmaxCrossEntropyWithLogits
from mindspore.nn import Accuracy
from mindspore import context, Model

context.set_context(mode=context.GRAPH_MODE, device_target="CPU")

lr = 0.01
momentum = 0.9 

# create the network
network = LeNet5()

# define the optimizer
net_opt = nn.Momentum(network.trainable_params(), lr, momentum)

# define the loss function
net_loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')

# define the model
model = Model(network, net_loss, net_opt, metrics={"Accuracy": Accuracy()} )

epoch_size = 1
mnist_path = "./datasets/MNIST_Data"

train_dataset = create_dataset("./datasets/MNIST_Data/train")
eval_dataset = create_dataset("./datasets/MNIST_Data/test")

repeat_size = 1
print("========== The Training Model is Defined. ==========")<jupyter_output>========== The Training Model is Defined. ==========<jupyter_text>安全导出CheckPoint文件目前MindSpore支持使用Callback机制传入回调函数`ModelCheckpoint`对象以保存模型参数，用户可以通过配置`CheckpointConfig`对象来启用参数文件的加密保护。下面示例展示了训练过程中每32个steps导出一次加密CheckPoint文件的过程：<jupyter_code>from mindspore.train.callback import CheckpointConfig, ModelCheckpoint, LossMonitor

config_ck = CheckpointConfig(save_checkpoint_steps=1875, keep_checkpoint_max=10, enc_key=b'<KEY>', enc_mode='AES-GCM')
ckpoint_cb = ModelCheckpoint(prefix='lenet_enc', directory=None, config=config_ck)
model.train(10, train_dataset, dataset_sink_mode=False, callbacks=[ckpoint_cb, LossMonitor(1875)])
model.eval(eval_dataset, dataset_sink_mode=False)<jupyter_output>epoch: 1 step: 1875, loss is 0.04268155
epoch: 2 step: 1875, loss is 0.33143944
epoch: 3 step: 1875, loss is 0.13743193
epoch: 4 step: 1875, loss is 0.062083688
epoch: 5 step: 1875, loss is 0.090901025
epoch: 6 step: 1875, loss is 0.02297108
epoch: 7 step: 1875, loss is 0.07450344
epoch: 8 step: 1875, loss is 0.00035639966
epoch: 9 step: 1875, loss is 0.015088511
epoch: 10 step: 1875, loss is 0.0009289649<jupyter_text>除了上面这种保存模型参数的方法，还可以调用`save_checkpoint`接口来随时导出模型参数，使用方法如下：<jupyter_code>from mindspore import save_checkpoint

save_checkpoint(network, 'lenet_enc.ckpt', enc_key=b'<KEY>', enc_mode='AES-GCM')<jupyter_output><empty_output><jupyter_text>加载密文CheckPoint文件MindSpore提供`load_checkpoint`和`load_distributed_checkpoint`分别用于单文件和分布式场景下加载CheckPoint参数文件。以单文件场景为例，可以用如下方式加载密文CheckPoint文件：<jupyter_code>from mindspore import load_checkpoint, load_param_into_net

param_dict = load_checkpoint('lenet_enc-10_1875.ckpt', dec_key=b'<KEY>', dec_mode='AES-GCM')
load_param_into_net(network, param_dict)
model.eval(eval_dataset, dataset_sink_mode=False)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1120601733809281, 'fraction_numerical': 0.041560428352881186, 'mean_word_length': 5.705128205128205, 'pattern_counts': {'":': 1, '<': 29, '<?xml version=': 0, '>': 30, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '160318', 'license': 'Apache-2.0', 'n_tokens_mistral': 3586, 'n_tokens_neox': 3510, 'n_words': 480, 'path': 'docs/notebook/model_encrypt_protection.ipynb', 'repo_name': 'bwcsswcx/docs', 'size': '7877'}