《昇思25天学习打卡营第2天|快速入门》

基本介绍&快速入门&张量Tensor&数据集Dataset&数据变换Transforms&网络构建&函数式自动微分&模型训练&保存与加载&使用静态图加速


该板块主要介绍如何构建一个基于MNIST数据集的手写数字识别。

主要流程如下:

  1. 导入MindSpore相关库
  2. 处理数据集
  3. 划分数据集(该数据集已经划分好了训练集和测试集)
  4. 构建数据处理流水线(Data Processing Pipeline)
  5. 构建神经网络
  6. 模型训练
  7. 评估模型性能
  8. 保存模型
  9. 加载模型
  10. 用加载好的模型进行预测推理

1.导入MindSpore库

import mindspore
from mindspore import nn
from mindspore.dataset import vision, transforms
from mindspore.dataset import MnistDataset

2.处理数据集

# 将数据集下载到本地
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)

# 用MnistDataset处理下载好的数据
train_dataset = MnistDataset("MNIST_Data/train")
test_dataset = MnistDataset("MNIST_Data/test")

数据集的结构如下:


MNIST_Data
└── train
    ├── train-images-idx3-ubyte (60000个训练图片)
    ├── train-labels-idx1-ubyte (60000个训练标签)
└── test
    ├── t10k-images-idx3-ubyte (10000个测试图片)
    ├── t10k-labels-idx1-ubyte (10000个测试标签)
    

3.划分数据集

用MnistDataset来处理Mnist数据集

train_dataset = MnistDataset("MNIST_Data/train")
test_dataset = MnistDataset("MNIST_Data/test")

生成的数据集有两列: [image, label]。 image 列的数据类型为uint8。 label 列的数据类型为uint32。

参数:

  • dataset_dir (str) - 包含数据集文件的根目录路径。
  • usage (str, 可选) - 指定数据集的子集,可取值为 ‘train’ 、 ‘test’ 或 ‘all’ 。 取值为 ‘train’ 时将会读取60,000个训练样本,取值为 ‘test’ 时将会读取10,000个测试样本,取值为 ‘all’ 时将会读取全部70,000个样本。默认值: None ,读取全部样本图片。
  • num_samples (int, 可选) - 指定从数据集中读取的样本数,可以小于数据集总数。默认值: None ,读取全部样本图片。
  • num_parallel_workers (int, 可选) - 指定读取数据的工作线程数。默认值: None ,使用全局默认线程数(8),也可以通过 mindspore.dataset.config.set_num_parallel_workers() 配置全局线程数。

4.构建数据处理流水线(Data Processing Pipeline)

构建Pipeline

def datapipe(dataset, batch_size):
    image_transforms = [
        vision.Rescale(1.0 / 255.0, 0),
        vision.Normalize(mean=(0.1307,), std=(0.3081,)),
        vision.HWC2CHW(),
    ]
    label_transform = transforms.TypeCast(mindspore.int32)

    dataset = dataset.map(image_transforms, "image")
    dataset = dataset.map(label_transform, "label")
    dataset = dataset.batch(batch_size)
    return dataset
    
# 映射视觉转换和批处理数据集
train_dataset = datapipe(train_dataset, 64)
test_dataset = datapipe(test_dataset, 64)

构建image和label的transform。以下是相关方法及其参数解释。

image:

  • Rescale(rescale, shift):
    • 基于给定的缩放和平移因子调整图像的像素大小。输出图像的像素大小为:output = image * rescale + shift。
    • 参数:
      • rescale (float) - 缩放因子。
      • shift (float) - 平移因子。
  • Normalize(mean, std, is_hwc=True):
    • 根据均值和标准差对输入图像进行归一化。
    • 此处理将使用以下公式对输入图像进行归一化: o u t p u t c = i n p u t c − m e a n c s t d c output_{c} = \frac{input_{c} - mean_{c}}{std_{c}} outputc=stdcinputcmeanc,其中 c代表通道索引,c>= 1。
    • 参数:
      • mean (sequence)
        • 图像每个通道的均值组成的列表或元组。平均值必须在 [0.0, 255.0] 范围内。
      • std (sequence)
        • 图像每个通道的标准差组成的列表或元组。标准差值必须在 (0.0, 255.0] 范围内。
      • is_hwc (bool, 可选)
        • 表示输入图像是否为HWC格式, True 为HWC格式, False 为CHW格式。默认值: True 。
  • HWC2CHW:
    • 将输入图像的shape从 <H, W, C> 转换为 <C, H, W>。 如果输入图像的shape为 <H, W> ,图像将保持不变。

label:

  • TypeCast(data_type):
    • 将输入的Tensor转换为指定的数据类型。
    • 参数:
      • data_type (Union[mindspore.dtype, numpy.dtype])
        • 指定要转换的数据类型。

查看转换后数据的shape和datatype。

for image, label in test_dataset.create_tuple_iterator():
    print(f"Shape of image [N, C, H, W]: {image.shape} {image.dtype}")
    print(f"Shape of label: {label.shape} {label.dtype}")
    break

输出结果:

Shape of image [N, C, H, W]: (64, 1, 28, 28) Float32
Shape of label: (64,) Int32

5. 构建神经网络

# 定义模型
class Network(nn.Cell):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.dense_relu_sequential = nn.SequentialCell(
            nn.Dense(28 * 28, 512),
            nn.ReLU(),
            nn.Dense(512, 512),
            nn.ReLU(),
            nn.Dense(512, 10),
        )
    def construct(self, x):
        x = self.flatten(x)
        logits = self.dense_relu_sequential(x)
        return logits
model = Network()
print(model)

构建一共三层全连接层,中间激活函数用ReLu。
解释如下:

  • Dense:
    • Dense(in_channels, out_channels, weight_init=None, bias_init=None, has_bias=True, activation=None, dtype=mstype.float32)
    • 适用于输入的密集连接层。公式如下:
      o u t p u t s = a c t i v a t i o n ( X × k e r n e l + b i a s ) outputs=activation(X \times kernel+bias) outputs=activation(X×kernel+bias)
    • 其中 X X X是输入Tensor, a c t i v a t i o n activation activation是激活函数, k e r n e l kernel kernel是一个权重矩阵,其数据类型与 X X X相同, b i a s bias bias是一个偏置向量,其数据类型与 X X X相同(仅当has_bias为True时)。
    • 参数:
      • in_channels (int)
        • Dense层输入Tensor的空间维度。
      • out_channels (int)
        • Dense层输出Tensor的空间维度。
  • ReLU:
    • 逐元素计算ReLU(Rectified Linear Unit activation function)修正线性单元激活函数。
      R e L U ( i n p u t ) = ( i n p u t ) + = m a x ( 0 , i n p u t ) ReLU(input)=(input)^+=max(0, input) ReLU(input)=(input)+=max(0,input)
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RC0LJ3ox-1719535062525)(https://i-blog.csdnimg.cn/direct/935a7d1c7878445d9001cbf1b4a76f25.png)]

6.模型训练

# 实例化损失函数和优化器
loss_fn = nn.CrossEntropyLoss()
optimizer = nn.SGD(model.trainable_params(), 1e-2)

# 1. 定义前向计算函数
def forward_fn(data, label):
    logits = model(data)
    loss = loss_fn(logits, label)
    return loss, logits

# 2. 使用value_and_grad通过函数变换获得梯度计算函数。
grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)


# 3. 定义一步训练函数
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}]")

7.评估模型性能

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")

epochs = 3
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(model, train_dataset)
    test(model, test_dataset, loss_fn)
print("Done!")

8.保存模型

# 保存检查点
mindspore.save_checkpoint(model, "model.ckpt")
print("Saved Model to model.ckpt")

9.加载模型

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

  1. 重新实例化模型对象,构造模型。
  2. 加载模型参数,并将其加载至模型上。
# 实例化一个随机初始化模型
model = Network()

# 将检查点和参数加载到模型中
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为空时代表所有参数均加载成功。

10.用加载好的模型进行推理

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: "Tensor(shape=[10], dtype=Int32, value= [3, 9, 6, 1, 6, 7, 4, 5, 2, 2])", Actual: "Tensor(shape=[10], dtype=Int32, value= [3, 9, 6, 1, 6, 7, 4, 5, 2, 2])"

快速入门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会Python小白-xin

感谢打赏!我会持续更新的~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值