09 综合实验

📅 2026/7/9 12:08:32
09 综合实验
综合实验本节通过MindSpore的API来快速实现一个简单的深度学习模型。若想要深入了解MindSpore的使用方法请参阅各节最后提供的参考链接。首先导入样例所需的公共包和接口。importmindsporefrommindsporeimportnnfrommindspore.datasetimportvision,transformsfrommindspore.datasetimportMnistDataset处理数据集MindSpore提供基于Pipeline的数据引擎通过数据集Dataset实现高效的数据预处理。在本教程中我们使用Mnist数据集自动下载完成后使用mindspore.dataset提供的数据变换进行预处理。本章节中的示例代码依赖download可使用命令pip install download安装。如本文档以Notebook运行时完成安装后需要重启kernel才能执行后续代码。# Download data from open datasetsfromdownloadimportdownload urlhttps://mindspore-website.obs.cn-north-4.myhuaweicloud.com/\notebook/datasets/MNIST_Data.zippathdownload(url,./,kindzip,replaceTrue)Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/MNIST_Data.zip (10.3 MB) file_sizes: 100%|██████████████████████████| 10.8M/10.8M [00:0000:00, 84.5MB/s] Extracting zip file... Successfully downloaded / unzipped to ./MNIST数据集目录结构如下MNIST_Data └── train ├── train-images-idx3-ubyte (60000个训练图片) ├── train-labels-idx1-ubyte (60000个训练标签) └── test ├── t10k-images-idx3-ubyte (10000个测试图片) ├── t10k-labels-idx1-ubyte (10000个测试标签)数据下载完成后获得数据集对象。train_datasetMnistDataset(MNIST_Data/train)test_datasetMnistDataset(MNIST_Data/test)打印数据集中包含的数据列名用于dataset的预处理。print(train_dataset.get_col_names())[image, label]MindSpore的dataset使用数据处理流水线Data Processing Pipeline需指定map、batch、shuffle等操作。这里我们使用map对图像数据及标签进行变换处理将输入的图像缩放为1/255根据均值0.1307和标准差值0.3081进行归一化处理然后将处理好的数据集打包为大小为64的batch。defdatapipe(dataset,batch_size):image_transforms[vision.Rescale(1.0/255.0,0),vision.Normalize(mean(0.1307,),std(0.3081,)),vision.HWC2CHW()]label_transformtransforms.TypeCast(mindspore.int32)datasetdataset.map(image_transforms,image)datasetdataset.map(label_transform,label)datasetdataset.batch(batch_size)returndataset# Map vision transforms and batch datasettrain_datasetdatapipe(train_dataset,64)test_datasetdatapipe(test_dataset,64)可使用create_tuple_iterator 或create_dict_iterator对数据集进行迭代访问查看数据和标签的shape和datatype。forimage,labelintest_dataset.create_tuple_iterator():print(fShape of image [N, C, H, W]:{image.shape}{image.dtype})print(fShape of label:{label.shape}{label.dtype})breakShape of image [N, C, H, W]: (64, 1, 28, 28) Float32 Shape of label: (64,) Int32fordataintest_dataset.create_dict_iterator():print(fShape of image [N, C, H, W]:{data[image].shape}{data[image].dtype})print(fShape of label:{data[label].shape}{data[label].dtype})breakShape of image [N, C, H, W]: (64, 1, 28, 28) Float32 Shape of label: (64,) Int32更多细节详见数据加载与处理。网络构建mindspore.nn类是构建所有网络的基类也是网络的基本单元。当用户需要自定义网络时可以继承nn.Cell类并重写__init__方法和construct方法。__init__包含所有网络层的定义construct包含数据Tensor的变换过程。# Define modelclassNetwork(nn.Cell):def__init__(self):super().__init__()self.flattennn.Flatten()self.dense_relu_sequentialnn.SequentialCell(nn.Dense(28*28,512),nn.ReLU(),nn.Dense(512,512),nn.ReLU(),nn.Dense(512,10))defconstruct(self,x):xself.flatten(x)logitsself.dense_relu_sequential(x)returnlogits modelNetwork()print(model)Network( (flatten): Flatten() (dense_relu_sequential): SequentialCell( (0): Dense(input_channels784, output_channels512, has_biasTrue) (1): ReLU() (2): Dense(input_channels512, output_channels512, has_biasTrue) (3): ReLU() (4): Dense(input_channels512, output_channels10, has_biasTrue) ) )更多细节详见网络构建。模型训练在模型训练中一个完整的训练过程step需要实现以下三步正向计算模型输出预测结果logits并与正确标签label计算预测损失loss。反向传播利用自动微分机制自动计算模型参数parameters对loss的梯度gradients。参数优化将梯度更新到参数上。MindSpore使用函数式自动微分机制因此针对上述步骤需要实现定义正向计算函数。使用value_and_grad通过函数变换获得梯度计算函数。定义训练函数使用set_train设置为训练模式执行正向计算、反向传播和参数优化。# Instantiate loss function and optimizerloss_fnnn.CrossEntropyLoss()optimizernn.SGD(model.trainable_params(),1e-2)# 1. Define forward functiondefforward_fn(data,label):logitsmodel(data)lossloss_fn(logits,label)returnloss,logits# 2. Get gradient functiongrad_fnmindspore.value_and_grad(forward_fn,None,optimizer.parameters,has_auxTrue)# 3. Define function of one-step trainingdeftrain_step(data,label):(loss,_),gradsgrad_fn(data,label)optimizer(grads)returnlossdeftrain(model,dataset):sizedataset.get_dataset_size()model.set_train()forbatch,(data,label)inenumerate(dataset.create_tuple_iterator()):losstrain_step(data,label)ifbatch%1000:loss,currentloss.asnumpy(),batchprint(floss:{loss:7f}[{current:3d}/{size:3d}])除训练外我们定义测试函数用来评估模型的性能。deftest(model,dataset,loss_fn):num_batchesdataset.get_dataset_size()model.set_train(False)total,test_loss,correct0,0,0fordata,labelindataset.create_tuple_iterator():predmodel(data)totallen(data)test_lossloss_fn(pred,label).asnumpy()correct(pred.argmax(1)label).asnumpy().sum()test_loss/num_batches correct/totalprint(fTest: \n Accuracy:{(100*correct):0.1f}%, Avg loss:{test_loss:8f}\n)训练过程需多次迭代数据集一次完整的迭代称为一轮epoch。在每一轮遍历训练集进行训练结束后使用测试集进行预测。打印每一轮的loss值和预测准确率Accuracy可以看到loss在不断下降Accuracy在不断提高。epochs3fortinrange(epochs):print(fEpoch{t1}\n-------------------------------)train(model,train_dataset)test(model,test_dataset,loss_fn)print(Done!)Epoch 1 ------------------------------- ..loss: 2.296963 [ 0/938] loss: 1.749713 [100/938] loss: 0.851979 [200/938] loss: 0.588595 [300/938] loss: 0.488721 [400/938] loss: 0.406701 [500/938] loss: 0.262928 [600/938] loss: 0.336964 [700/938] loss: 0.426515 [800/938] loss: 0.144623 [900/938] .Test: Accuracy: 90.8%, Avg loss: 0.315322 Epoch 2 ------------------------------- loss: 0.543347 [ 0/938] loss: 0.368381 [100/938] loss: 0.468306 [200/938] loss: 0.267778 [300/938] loss: 0.388619 [400/938] loss: 0.314621 [500/938] loss: 0.281045 [600/938] loss: 0.214138 [700/938] loss: 0.259455 [800/938] loss: 0.245736 [900/938] Test: Accuracy: 92.8%, Avg loss: 0.248434 Epoch 3 ------------------------------- loss: 0.115722 [ 0/938] loss: 0.424686 [100/938] loss: 0.099604 [200/938] loss: 0.128217 [300/938] loss: 0.348238 [400/938] loss: 0.215483 [500/938] loss: 0.345179 [600/938] loss: 0.215064 [700/938] loss: 0.197455 [800/938] loss: 0.142803 [900/938] Test: Accuracy: 93.7%, Avg loss: 0.212541 Done!更多细节详见模型训练。保存模型模型训练完成后需要保存其参数。# Save checkpointmindspore.save_checkpoint(model,model.ckpt)print(Saved Model to model.ckpt)Saved Model to model.ckpt加载模型加载保存的权重分为两步重新实例化模型对象构造模型。加载模型参数并将其加载至模型上。# Instantiate a random initialized modelmodelNetwork()# Load checkpoint and load parameter to modelparam_dictmindspore.load_checkpoint(model.ckpt)param_not_load,_mindspore.load_param_into_net(model,param_dict)print(param_not_load)[]param_not_load是未被加载的参数列表。为空时表示所有参数均加载成功。加载后的模型可以直接用于预测推理。model.set_train(False)fordata,labelintest_dataset:predmodel(data)predictedpred.argmax(1)print(fPredicted: {predicted[:10]}, Actual: {label[:10]})breakPredicted: [0 0 0 4 2 3 1 1 6 3], Actual: [0 0 0 4 2 3 1 1 6 3]更多细节详见保存与加载。