赞
踩
昇思MindSpore是一个全场景深度学习框架,详见基本介绍
那什么是深度学习呢?
深度学习是一种特殊的机器学习,主要是利用了多层神经网络模拟人脑,自动提取特征并进行预测。
什么是机器学习?
通过给“机器”喂养一些数据和答案,让其学习并训练处一套规则,新的数据可以通过这个规则,得出答案,这也是现在风靡全球的AI大模型的基本原理。
下图为现在已经发展成熟的完整流程
MindSpore提供基于Pipeline的数据引擎,通过数据集(Dataset)和数据变换(Transforms)实现高效的数据预处理。
预装mindspore(2.2.14)、numpy、pandas等依赖
%%capture captured_output
# 实验环境已经预装了mindspore==2.2.14,如需更换mindspore版本,可更改下面mindspore的版本号
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
import mindspore
from mindspore import nn
from mindspore.dataset import vision, transforms # 使用mindspore.dataset提供的数据变换进行预处理
from mindspore.dataset import MnistDataset
# Download data from open datasets
from download import download
url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/" \
"notebook/datasets/MNIST_Data.zip"
path = download(url, "./", kind="zip", replace=True)
可以看到下面两个对象,分别为MNIST数据集train分支和test分支下的数据对象,获取到数据对象后,我们来查看一下这些数据的value等信息
train_dataset = MnistDataset('MNIST_Data/train')
test_dataset = MnistDataset('MNIST_Data/test')
通过运行下面的代码,查看运行结果,结合上面的MNIST数据集train分支和test分支下的子分支,可以很直观的看出,数据集包含图片和标签
print(train_dataset.get_col_names())
print(test_dataset.get_col_names())
运行结果:
['image', 'label']
['image', 'label']
请看代码中的注释理解这段代码的作用
# 自定义一个函数 接受一个数据集(dataset)和批量大小(batch_size)作为输入,并返回经过一系列预处理和变换后的数据集 def datapipe(dataset, batch_size): # 定义一个包含了三个图像处理变换(transforms)的列表image_transforms 将这些变换组合在一起,可以对图像进行一系列预处理操作,以便将其输入到深度学习模型中 image_transforms = [ vision.Rescale(1.0 / 255.0, 0),# 用于将图像的像素值从 [0, 255] 缩放到 [0, 1] vision.Normalize(mean=(0.1307,), std=(0.3081,)), # 用于标准化图像数据 vision.HWC2CHW() # 用于改变图像的维度顺序 ] #将标签数据转换为 mindspore.int32 类型 label_transform = transforms.TypeCast(mindspore.int32) #transforms为mindspore.dataset提供的数据变换 # 使用上面定义的图像变换和标签变换,通过map方法作用到图像和标签数据集 dataset = dataset.map(image_transforms, 'image') dataset = dataset.map(label_transform, 'label') # 将经过变换的数据集按照 batch_size 参数指定的大小进行批处理 dataset = dataset.batch(batch_size) # 返回经过处理后的数据集 return dataset
调用上面的自定义函数datapipe(dataset, batch_size),并传入参数
此处我们设置一个对照组,只处理train_dataset分支下的数据,比较处理前后数据集的shape和datatype有何不同
# Map vision transforms and batch dataset
train_dataset = datapipe(train_dataset, 64)
# test_dataset = datapipe(test_dataset, 64)
使用create_tuple_iterator
或create_dict_iterator
对数据集进行迭代访问,查看数据和标签的shape和datatype
可以清晰的看到,经过变换处理后图片和标签数据的shape和datatype都发生了变化
mindspore.nn
类是构建所有网络的基类,也是网络的基本单元。当用户需要自定义网络时,可以继承nn.Cell
类,并重写__init__
方法和construct
方法。__init__
包含所有网络层的定义,construct
中包含数据(Tensor)的变换过程。
# Define model # 定义一个NetWork类继承nn.Cell类 MindSpore中nn.Cell是所有神经网络模块的基类 class Network(nn.Cell): # 重写__init__方法 def __init__(self): super().__init__() # 调用super().__init__()来调用父类nn.Cell的初始化方法 self.flatten = nn.Flatten() # 一个nn.Flatten层,用于将输入张量展平成一维向量。这通常用于将图像数据(通常是四维的,如[batch_size, channels, height, width])转换为一维向量,以便可以输入到全连接层(Dense层) self.dense_relu_sequential = nn.SequentialCell( # 一个顺序容器nn.SequentialCell,它包含三个全连接层(nn.Dense)和两个ReLU激活函数。每个nn.Dense层后面都跟着一个ReLU激活函数(除了最后一个,因为它通常用于输出层之前,并且可能后续会接softmax等函数) nn.Dense(28*28, 512), nn.ReLU(), nn.Dense(512, 512), nn.ReLU(), nn.Dense(512, 10) ) # 重写construct方法 def construct(self, x): # construct方法定义了网络的前向传播过程。它接受一个输入x,首先通过flatten层展平,然后传入到dense_relu_sequential中,最后返回logits(即网络的输出) x = self.flatten(x) logits = self.dense_relu_sequential(x) return logits # 创建了一个NetWork类的实例 并打印模型的结构 model = Network() print(model)
运行结果:
输出会包含网络的结构、每层的类型和参数数量等信息
Network<
(flatten): Flatten<>
(dense_relu_sequential): SequentialCell<
(0): Dense<input_channels=784, output_channels=512, has_bias=True>
(1): ReLU<>
(2): Dense<input_channels=512, output_channels=512, has_bias=True>
(3): ReLU<>
(4): Dense<input_channels=512, output_channels=10, has_bias=True>
>
>
在模型训练中,一个完整的训练过程(step)需要实现以下三步:
正向计算:模型预测结果(logits),并与正确标签(label)求预测损失(loss)。
反向传播:利用自动微分机制,自动求模型参数(parameters)对于loss的梯度(gradients)。
参数优化:将梯度更新到参数上。
MindSpore使用函数式自动微分机制,因此针对上述步骤需要实现:
定义正向计算函数。
使用value_and_grad通过函数变换获得梯度计算函数。
定义训练函数,使用set_train设置为训练模式,执行正向计算、反向传播和参数优化。
# Instantiate loss function and optimizer loss_fn = nn.CrossEntropyLoss() # 定义损失函数 optimizer = nn.SGD(model.trainable_params(), 1e-2) # 定义优化器 # 1. Define forward function def forward_fn(data, label): logits = model(data) loss = loss_fn(logits, label) return loss, logits # 2. Get gradient function grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True) # 3. Define function of one-step training def train_step(data, label): (loss, _), grads = grad_fn(data, label) optimizer(grads) return loss def train(model, dataset): size = dataset.get_dataset_size() model.set_train() for batch, (data, label) in enumerate(dataset.create_tuple_iterator()): loss = train_step(data, label) if batch % 100 == 0: loss, current = loss.asnumpy(), batch print(f"loss: {loss:>7f} [{current:>3d}/{size:>3d}]")
定义测试函数,用来评估模型的性能
def test(model, dataset, loss_fn):
num_batches = dataset.get_dataset_size()
model.set_train(False)
total, test_loss, correct = 0, 0, 0
for data, label in dataset.create_tuple_iterator():
pred = model(data)
total += len(data)
test_loss += loss_fn(pred, label).asnumpy()
correct += (pred.argmax(1) == label).asnumpy().sum()
test_loss /= num_batches
correct /= total
print(f"Test: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
训练过程需多次迭代数据集,一次完整的迭代称为一轮(epoch)。在每一轮,遍历训练集进行训练,结束后使用测试集进行预测。打印每一轮的loss值和预测准确率(Accuracy),可以看到loss在不断下降,Accuracy在不断提高
** 注意:此处的train_dataset
和test_dataset
都经过自定义的变换处理,上面的为两个数据集经过变换的对照演示
epochs = 3
for t in range(epochs):
print(f"Epoch {t+1}\n-------------------------------")
# 调用上面定义的训练函数 ,用train_dataset来训练
train(model, train_dataset)
# 调用测试函数,用test_dataset来测试
test(model, test_dataset, loss_fn)
print("Done!")
运行结果:
Epoch 1 ------------------------------- loss: 2.314158 [ 0/938] loss: 1.719715 [100/938] loss: 0.902341 [200/938] loss: 0.661312 [300/938] loss: 0.513485 [400/938] loss: 0.373087 [500/938] loss: 0.292349 [600/938] loss: 0.361322 [700/938] loss: 0.348529 [800/938] loss: 0.241514 [900/938] Test: Accuracy: 90.9%, Avg loss: 0.317471 Epoch 2 ------------------------------- loss: 0.272879 [ 0/938] loss: 0.197702 [100/938] loss: 0.462247 [200/938] loss: 0.277897 [300/938] loss: 0.355524 [400/938] loss: 0.302988 [500/938] loss: 0.346760 [600/938] loss: 0.160622 [700/938] loss: 0.147934 [800/938] loss: 0.376813 [900/938] Test: Accuracy: 92.7%, Avg loss: 0.247925 Epoch 3 ------------------------------- loss: 0.099119 [ 0/938] loss: 0.183959 [100/938] loss: 0.185701 [200/938] loss: 0.252462 [300/938] loss: 0.256019 [400/938] loss: 0.121666 [500/938] loss: 0.154538 [600/938] loss: 0.282256 [700/938] loss: 0.159089 [800/938] loss: 0.164129 [900/938] Test: Accuracy: 93.9%, Avg loss: 0.207038 Done!
模型训练完成后需要其参数进行保存,此处可以理解为保存了一个名为model.ckpt
的模型快照
# Save checkpoint
mindspore.save_checkpoint(model, "model.ckpt")
print("Saved Model to model.ckpt")
加载保存的权重分为两步:
1、 重新实例化模型对象,构造模型。
2、加载模型参数,并将其加载至模型上。
# Instantiate a random initialized model
model = Network()
# Load checkpoint and load parameter to model
param_dict = mindspore.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) # 用于将模型设置为评估模式或推断模式
for data, label in test_dataset:
pred = model(data)
predicted = pred.argmax(1)
print(f'Predicted: "{predicted[:10]}", Actual: "{label[:10]}"')
break
运行结果:
预测的标签值和实际的标签值是一样的
Predicted: "[4 7 6 2 1 4 4 4 3 3]", Actual: "[4 7 6 2 1 4 4 4 3 3]"
模型预测与训练的全流程:
1、数据准备:包括用于训练的数据和用于预测的数据。并对数据进行处理,使其满足我们模型的训练条件
2、网络构建:自定义神经网络,通过设置一些参数,使其符合我们的要求
3、模型训练:正向计算,反向传播,参数优化。将训练好的模型保存起来,用于直接载入我们在预测时自定义的model
4、加载模型:经过前四个步骤的准备,我们已经训练好了一个预测模型,将用于预测的数据传入这个模型即可进行预测。
0基础入门,有说的不对的地方,希望各位路过的大佬批评指正
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。