当前位置:   article > 正文

昇思25天学习打卡营第01天|基本介绍&快速入门

昇思25天学习打卡营第01天|基本介绍&快速入门

在这里插入图片描述

一、什么是昇思MindSpore?

昇思MindSpore是一个全场景深度学习框架,详见基本介绍

那什么是深度学习呢?

深度学习是一种特殊的机器学习,主要是利用了多层神经网络模拟人脑,自动提取特征并进行预测。

什么是机器学习?

通过给“机器”喂养一些数据和答案,让其学习并训练处一套规则,新的数据可以通过这个规则,得出答案,这也是现在风靡全球的AI大模型的基本原理。
在这里插入图片描述
下图为现在已经发展成熟的完整流程
在这里插入图片描述

二、快速入门

1.准备工作

1.1环境准备

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
  • 1
  • 2
  • 3
  • 4
  • 5

1.2数据变换Transforms导入

import mindspore
from mindspore import nn
from mindspore.dataset import vision, transforms  # 使用mindspore.dataset提供的数据变换进行预处理
from mindspore.dataset import MnistDataset
  • 1
  • 2
  • 3
  • 4

1.3导入Mnist数据集

# 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

1.4使用(查看)数据集

1.4.1获得数据集对象

可以看到下面两个对象,分别为MNIST数据集train分支和test分支下的数据对象,获取到数据对象后,我们来查看一下这些数据的value等信息

train_dataset = MnistDataset('MNIST_Data/train')
test_dataset = MnistDataset('MNIST_Data/test')
  • 1
  • 2
1.4.2打印数据集中包含的数据列名

通过运行下面的代码,查看运行结果,结合上面的MNIST数据集train分支和test分支下的子分支,可以很直观的看出,数据集包含图片标签

print(train_dataset.get_col_names())
print(test_dataset.get_col_names())
  • 1
  • 2

运行结果:

['image', 'label']
['image', 'label']
  • 1
  • 2
1.4.3对图像数据及标签进行变换处理

请看代码中的注释理解这段代码的作用

# 自定义一个函数 接受一个数据集(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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
1.4.4使用自定义的变换处理

调用上面的自定义函数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)
  • 1
  • 2
  • 3

使用create_tuple_iteratorcreate_dict_iterator对数据集进行迭代访问,查看数据和标签的shape和datatype

可以清晰的看到,经过变换处理后图片和标签数据的shape和datatype都发生了变化
在这里插入图片描述

2.网络构建

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行结果:
输出会包含网络的结构、每层的类型和参数数量等信息

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>
    >
  >
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.模型训练

在模型训练中,一个完整的训练过程(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}]")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

定义测试函数,用来评估模型的性能

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")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

训练过程需多次迭代数据集,一次完整的迭代称为一轮(epoch)。在每一轮,遍历训练集进行训练,结束后使用测试集进行预测。打印每一轮的loss值和预测准确率(Accuracy),可以看到loss在不断下降,Accuracy在不断提高
** 注意:此处的train_datasettest_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!")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

运行结果:

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!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

4.保存模型

模型训练完成后需要其参数进行保存,此处可以理解为保存了一个名为model.ckpt的模型快照

# Save checkpoint
mindspore.save_checkpoint(model, "model.ckpt")
print("Saved Model to model.ckpt")
  • 1
  • 2
  • 3

5.加载模型

加载保存的权重分为两步:

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行结果:
param_not_load是未被加载的参数列表,为空时代表所有参数均加载成功。

[]
  • 1

加载后的模型可以直接用于推理预测

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行结果:
预测的标签值和实际的标签值是一样的

Predicted: "[4 7 6 2 1 4 4 4 3 3]", Actual: "[4 7 6 2 1 4 4 4 3 3]"
  • 1

6.总结

模型预测与训练的全流程:
1、数据准备:包括用于训练的数据和用于预测的数据。并对数据进行处理,使其满足我们模型的训练条件
2、网络构建:自定义神经网络,通过设置一些参数,使其符合我们的要求
3、模型训练:正向计算,反向传播,参数优化。将训练好的模型保存起来,用于直接载入我们在预测时自定义的model
4、加载模型:经过前四个步骤的准备,我们已经训练好了一个预测模型,将用于预测的数据传入这个模型即可进行预测。

0基础入门,有说的不对的地方,希望各位路过的大佬批评指正

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/924253
推荐阅读
相关标签
  

闽ICP备14008679号