《昇思25天学习打卡营第07天|qingyun201003》

news2024/9/20 0:51:41

日期

image.png

心得

越往后,越看不懂,只能说是有了解到如何去训练模型代码,对于模型代码该如何去保存,如何通过网络模型去训练。只能一步步来,目前来说是推进度,等后面全部有了认知,再回来重新学习

昇思MindSpore 基础入门学习 模型训练 (AI 代码解析)

模型训练

模型训练一般分为四个步骤:

  1. 构建数据集。
  2. 定义神经网络模型。
  3. 定义超参、损失函数及优化器。
  4. 输入数据集进行训练与评估。

现在我们有了数据集和模型后,可以进行模型的训练与评估。

构建数据集

首先从数据集 Dataset加载代码,构建数据集。

import mindspore
from mindspore import nn
from mindspore.dataset import vision, transforms
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)


def datapipe(path, batch_size):
    image_transforms = [
        vision.Rescale(1.0 / 255.0, 0),  # Rescale the image to [0, 1]
        vision.Normalize(mean=(0.1307,), std=(0.3081,)),  # Normalize the image
        vision.HWC2CHW()  # Convert image from HWC format to CHW format
    ]
    label_transform = transforms.TypeCast(mindspore.int32)  # Cast label to int32

    dataset = MnistDataset(path)  # Load MNIST dataset
    dataset = dataset.map(image_transforms, 'image')  # Apply image transformations
    dataset = dataset.map(label_transform, 'label')  # Apply label transformation
    dataset = dataset.batch(batch_size)  # Batch the dataset
    return dataset

train_dataset = datapipe('MNIST_Data/train', batch_size=64)  # Create training dataset
test_dataset = datapipe('MNIST_Data/test', batch_size=64)  # Create test dataset
  1. 导入模块:
    • mindspore: MindSpore的主模块,用于深度学习模型的构建和训练。
    • mindspore.nn: 包含神经网络层和损失函数等。
    • mindspore.dataset.vision: 包含图像处理相关的数据增强和变换函数。
    • mindspore.dataset.transforms: 包含数据变换函数。
    • mindspore.dataset.MnistDataset: 用于加载MNIST数据集。
    • download: 用于从指定URL下载数据。
  2. 下载数据:
    • url: 存储MNIST数据集的URL。
    • path = download(url, "./", kind="zip", replace=True): 下载并解压数据集到当前目录。
  3. **数据处理函数 **datapipe:
    • image_transforms: 一系列图像变换操作,包括重缩放、标准化和格式转换。
      • vision.Rescale(1.0 / 255.0, 0): 将图像像素值从[0, 255]缩放到[0, 1]。
      • vision.Normalize(mean=(0.1307,), std=(0.3081,)): 对图像进行标准化处理。
      • vision.HWC2CHW(): 将图像从高度-宽度-通道(HWC)格式转换为通道-高度-宽度(CHW)格式。
    • label_transform: 将标签数据转换为int32类型。
    • dataset = MnistDataset(path): 加载MNIST数据集。
    • dataset = dataset.map(image_transforms, 'image'): 对图像应用上述变换。
    • dataset = dataset.map(label_transform, 'label'): 对标签应用类型转换。
    • dataset = dataset.batch(batch_size): 将数据集分批处理。
  4. 创建训练和测试数据集:
    • train_dataset = datapipe('MNIST_Data/train', batch_size=64): 创建训练数据集。
    • test_dataset = datapipe('MNIST_Data/test', batch_size=64): 创建测试数据集。
  • mindspore.dataset.vision.Rescale: 用于图像像素值的缩放。
  • mindspore.dataset.vision.Normalize: 用于图像的标准化处理。
  • mindspore.dataset.vision.HWC2CHW: 用于图像格式的转换。
  • mindspore.dataset.transforms.TypeCast: 用于数据类型的转换。
  • mindspore.dataset.MnistDataset: 用于加载MNIST数据集。
  • dataset.map: 用于对数据集中的数据应用指定的变换。
  • dataset.batch: 用于将数据集分批处理。

定义神经网络模型
从网络构建中加载代码,构建一个神经网络模型。

class Network(nn.Cell):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()  # Flatten the input tensor into a 2D matrix
        self.dense_relu_sequential = nn.SequentialCell(
            nn.Dense(28*28, 512),  # Fully connected layer with input size 28*28 and output size 512
            nn.ReLU(),  # Apply ReLU activation function
            nn.Dense(512, 512),  # Another fully connected layer with output size 512
            nn.ReLU(),  # Apply ReLU activation function
            nn.Dense(512, 10)  # Fully connected layer with output size 10 for classification
        )

    def construct(self, x):
        x = self.flatten(x)  # Flatten the input
        logits = self.dense_relu_sequential(x)  # Pass the input through the sequential dense layers with ReLU
        return logits  # Return the output logits

model = Network()  # Instantiate the neural network model
  1. **定义网络结构 **Network:
    • 继承自 mindspore.nn.Cell,这是MindSpore中神经网络模块的基类。
    • __init__ 方法定义了网络的层次结构:
      • self.flatten: 一个 Flatten 层,将输入的多维张量展平为二维张量。
      • self.dense_relu_sequential: 一个 SequentialCell 容器,按顺序包含多个层:
        • nn.Dense(28*28, 512): 一个全连接层,将输入张量从28x28(MNIST图像尺寸)展平后变成512维向量。
        • nn.ReLU(): 一个ReLU激活函数,用于引入非线性。
        • nn.Dense(512, 512): 另一个全连接层,输入输出尺寸都是512维。
        • nn.ReLU(): 再次使用ReLU激活函数。
        • nn.Dense(512, 10): 最后的全连接层,输出10个类别的得分(用于分类任务)。
  2. construct** 方法**:
    • 定义了前向传播的过程:
      • x = self.flatten(x): 将输入张量展平。
      • logits = self.dense_relu_sequential(x): 将展平后的张量通过定义好的全连接层序列。
  3. 实例化模型:
    • model = Network(): 创建 Network 类的实例,也就是我们定义的神经网络模型。
  • nn.Cell: MindSpore中所有神经网络模块的基类。
  • nn.Flatten: 将输入张量展平成二维张量。
  • nn.Dense: 全连接层,参数包括输入和输出的维度。
  • nn.ReLU: ReLU激活函数,应用非线性变换。
  • nn.SequentialCell: 用于按顺序容纳和执行多个子层。

定义超参、损失函数和优化器

超参

超参(Hyperparameters)是可以调整的参数,可以控制模型训练优化的过程,不同的超参数值可能会影响模型训练和收敛速度。目前深度学习模型多采用批量随机梯度下降算法进行优化,随机梯度下降算法的原理如下:
image.png
公式中,n𝑛是批量大小(batch size),ηη是学习率(learning rate)。另外,wt𝑤𝑡为训练轮次t𝑡中的权重参数,∇l∇𝑙为损失函数的导数。除了梯度本身,这两个因子直接决定了模型的权重更新,从优化本身来看,它们是影响模型性能收敛最重要的参数。一般会定义以下超参用于训练:

  • 训练轮次(epoch):训练时遍历数据集的次数。
  • 批次大小(batch size):数据集进行分批读取训练,设定每个批次数据的大小。batch size过小,花费时间多,同时梯度震荡严重,不利于收敛;batch size过大,不同batch的梯度方向没有任何变化,容易陷入局部极小值,因此需要选择合适的batch size,可以有效提高模型精度、全局收敛。
  • 学习率(learning rate):如果学习率偏小,会导致收敛的速度变慢,如果学习率偏大,则可能会导致训练不收敛等不可预测的结果。梯度下降法被广泛应用在最小化模型误差的参数优化算法上。梯度下降法通过多次迭代,并在每一步中最小化损失函数来预估模型的参数。学习率就是在迭代过程中,会控制模型的学习进度。
epochs = 3  # Number of complete passes through the training dataset
batch_size = 64  # Number of samples per gradient update
learning_rate = 1e-2  # Step size at each iteration while moving toward a minimum of a loss function
  1. epochs:
    • 定义了训练过程中数据集被完整遍历的次数。在每个epoch中,模型会看到整个训练数据集一次。增加epoch的数量可能会提高模型的性能,但同时也增加了过拟合的风险。
  2. batch_size:
    • 定义了每次梯度更新时使用的样本数量。较大的batch size可以提供更稳定的梯度估计,但可能会增加内存需求。较小的batch size可能导致训练过程更加不稳定,但有时可以提供更好的泛化性能。
  3. learning_rate:
    • 定义了优化算法(如梯度下降)在每次更新模型参数时的步长。学习率太大可能导致模型无法收敛,而学习率太小可能导致训练过程非常缓慢。选择合适的学习率是训练过程中的一个重要步骤。

这些参数通常需要根据具体问题和数据集进行调整,以达到最佳的训练效果。

损失函数
损失函数(loss function)用于评估模型的预测值(logits)和目标值(targets)之间的误差。训练模型时,随机初始化的神经网络模型开始时会预测出错误的结果。损失函数会评估预测结果与目标值的相异程度,模型训练的目标即为降低损失函数求得的误差。
常见的损失函数包括用于回归任务的nn.MSELoss(均方误差)和用于分类的nn.NLLLoss(负对数似然)等。 nn.CrossEntropyLoss 结合了nn.LogSoftmaxnn.NLLLoss,可以对logits 进行归一化并计算预测误差。

loss_fn = nn.CrossEntropyLoss()  # Define the loss function as cross-entropy loss
  • loss_fn:
    • 定义了损失函数,用于衡量模型输出(预测值)与实际标签之间的差距。在神经网络的训练过程中,损失函数的输出值用于指导模型参数的更新,以使预测结果更加准确。
  • nn.CrossEntropyLoss():
    • Cross-Entropy Loss(交叉熵损失)是一种常用于分类任务的损失函数,尤其适用于多分类问题。它结合了 softmaxnegative log likelihood,即先将模型的输出通过 softmax 函数转化为概率分布,然后计算实际标签与预测概率分布之间的交叉熵。
    • 在多分类任务中,交叉熵损失能够有效地衡量预测的概率分布与真实分布的差异,从而帮助模型在训练过程中调整参数,提升分类准确率。

  • nn.CrossEntropyLoss:
    • 这是MindSpore中用于多分类任务的损失函数,适用于模型的输出是未归一化的得分(logits)形式。通过将logits输入到 CrossEntropyLoss 中,函数内部会首先计算 softmax,然后计算交叉熵损失。

优化器

模型优化(Optimization)是在每个训练步骤中调整模型参数以减少模型误差的过程。MindSpore提供多种优化算法的实现,称之为优化器(Optimizer)。优化器内部定义了模型的参数优化过程(即梯度如何更新至模型参数),所有优化逻辑都封装在优化器对象中。在这里,我们使用SGD(Stochastic Gradient Descent)优化器。
我们通过model.trainable_params()方法获得模型的可训练参数,并传入学习率超参来初始化优化器。

optimizer = nn.SGD(model.trainable_params(), learning_rate=learning_rate)  # Create an optimizer for training the model
  • optimizer:

    • 这个变量是一个优化器对象,它将被用来更新模型的参数以最小化损失函数。优化器根据计算得到的损失通过梯度下降法调整模型权重,以改善模型在训练数据上的表现。
  • nn.SGD:

    • nn.SGD 是 “Stochastic Gradient Descent”(随机梯度下降)的缩写。这是最常用的优化算法之一,对于许多机器学习问题而言,它是一个有效的优化方法。
    • 这个函数接受两个主要参数:一是我们想要优化的参数集合,在这里是通过 model.trainable_params() 获得的模型可训练参数;二是学习率 learning_rate
  • model.trainable_params():

    • 这是一个函数,返回模型中所有需要训练(即可以在训练过程中更新的)的参数。在神经网络中,这些通常是权重和偏置参数。
  • learning_rate=learning_rate:

    • 这是设置优化器学习率的参数。这里的 learning_rate 是之前定义的变量,它将作为优化器的学习率使用。学习率决定了在每次迭代中参数更新的步长大小。

随机梯度下降通常用于大规模数据集,因为每次迭代时只需要计算小批量数据的梯度,使得训练过程更高效。
在训练过程中,通过微分函数可计算获得参数对应的梯度,将其传入优化器中即可实现参数优化,具体形态如下:
grads = grad_fn(inputs)
optimizer(grads)

训练与评估

设置了超参、损失函数和优化器后,我们就可以循环输入数据来训练模型。一次数据集的完整迭代循环称为一轮(epoch)。每轮执行训练时包括两个步骤:

  1. 训练:迭代训练数据集,并尝试收敛到最佳参数。
  2. 验证/测试:迭代测试数据集,以检查模型性能是否提升。

接下来我们定义用于训练的train_loop函数和用于测试的test_loop函数。
使用函数式自动微分,需先定义正向函数forward_fn,使用value_and_grad获得微分函数grad_fn。然后,我们将微分函数和优化器的执行封装为train_step函数,接下来循环迭代数据集进行训练即可。

# Define forward function
def forward_fn(data, label):
    logits = model(data)  # Forward pass: compute predicted logits by passing data to the model
    loss = loss_fn(logits, label)  # Compute the loss using the predicted logits and true labels
    return loss, logits  # Return the computed loss and logits

# Get gradient function
grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)
# mindspore.value_and_grad computes both the value of the function and its gradient.
# Arguments:
#   - forward_fn: the function for which we want to compute the gradient
#   - None: no additional arguments for gradient computation
#   - optimizer.parameters: parameters with respect to which gradients are computed
#   - has_aux: indicates that forward_fn returns auxiliary data (logits) along with the loss

# Define function of one-step training
def train_step(data, label):
    (loss, _), grads = grad_fn(data, label)  # Compute loss and gradients for the given data and labels
    optimizer(grads)  # Update model parameters using computed gradients
    return loss  # Return the computed loss

def train_loop(model, dataset):
    size = dataset.get_dataset_size()  # Get the total number of batches in the dataset
    model.set_train()  # Set the model to training mode
    for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):
        loss = train_step(data, label)  # Perform one training step

        if batch % 100 == 0:  # Print loss every 100 batches
            loss, current = loss.asnumpy(), batch  # Convert loss from tensor to numpy for printing
            print(f"loss: {loss:>7f}  [{current:>3d}/{size:>3d}]")  # Print the current loss and batch number
  1. forward_fn(data, label):
    • 这是一个前向传播函数,用于计算给定数据 data 和标签 label 的损失值和预测的logits。
    • logits = model(data): 使用模型对输入数据进行前向传播,得到预测的logits。
    • loss = loss_fn(logits, label): 使用交叉熵损失函数计算预测的logits和实际标签之间的损失。
    • 返回损失和logits。
  2. grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True):
    • 这个函数返回一个新的函数 grad_fn,该函数计算前向函数 forward_fn 的输出值和梯度。
    • grad_fn(data, label): 计算前向函数的损失值和梯度。
    • None: 无需额外的参数。
    • optimizer.parameters: 需要计算梯度的模型参数。
    • has_aux=True: 表示前向函数返回辅助数据(logits)。
  3. train_step(data, label):
    • 这是一个训练步骤函数,用于执行一次前向传播、计算梯度并更新模型参数。
    • (loss, _), grads = grad_fn(data, label): 计算损失值和梯度。
    • optimizer(grads): 使用计算得到的梯度更新模型参数。
    • 返回计算得到的损失值。
  4. train_loop(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: 每100个批次打印一次损失值。
      • loss.asnumpy(): 将损失值从张量转换为numpy数组,以便打印。
      • print(f"loss: {loss:>7f} [{current:>3d}/{size:>3d}]"): 打印当前批次的损失值和批次编号。

test_loop函数同样需循环遍历数据集,调用模型计算loss和Accuray并返回最终结果。

def test_loop(model, dataset, loss_fn):
    num_batches = dataset.get_dataset_size()  # Get the total number of batches in the dataset
    model.set_train(False)  # Set the model to evaluation mode
    total, test_loss, correct = 0, 0, 0  # Initialize counters for total samples, test loss, and correct predictions
    
    for data, label in dataset.create_tuple_iterator():
        pred = model(data)  # Forward pass: compute predictions by passing data to the model
        total += len(data)  # Update the total number of samples
        test_loss += loss_fn(pred, label).asnumpy()  # Accumulate the test loss, converting it from tensor to numpy
        correct += (pred.argmax(1) == label).asnumpy().sum()  # Count correct predictions, comparing argmax of predictions to labels
    
    test_loss /= num_batches  # Compute the average test loss
    correct /= total  # Compute the accuracy by dividing correct predictions by the total number of samples
    
    print(f"Test: \n Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")  # Print the test accuracy and average loss
  1. test_loop(model, dataset, loss_fn):
    • 这个函数定义了测试循环,用于在给定数据集上评估模型的性能,包括计算准确率和平均损失。
  2. num_batches = dataset.get_dataset_size():
    • 获取数据集的总批次数。
  3. model.set_train(False):
    • 设置模型为评估模式。在评估模式下,某些操作(例如 dropout 和 batch normalization)会有不同的行为。
  4. total, test_loss, correct = 0, 0, 0:
    • 初始化总样本数、测试损失和正确预测数的计数器。
  5. for data, label in dataset.create_tuple_iterator()::
    • 遍历数据集中的每个批次。
  6. pred = model(data):
    • 使用模型对输入数据进行前向传播,得到预测结果。
  7. total += len(data):
    • 累加当前批次的样本数到总样本数。
  8. test_loss += loss_fn(pred, label).asnumpy():
    • 计算当前批次的损失,并累加到总测试损失。将损失从张量转换为 numpy 数组,以便进行数值计算。
  9. correct += (pred.argmax(1) == label).asnumpy().sum():
    • 计算当前批次中正确预测的样本数,并累加到总正确预测数。pred.argmax(1) 返回预测结果中每行最大值的索引,这相当于预测的类别。
  10. test_loss /= num_batches:
  • 计算测试集的平均损失。
  1. correct /= total:
  • 计算测试集的准确率,即正确预测的样本数除以总样本数。
  1. print(f"Test: \n Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f} \n"):
  • 打印测试集的准确率和平均损失,准确率以百分比形式显示,损失保留多位小数。

该代码段用于验证模型在测试集上的性能,计算并输出准确率和平均损失。通过逐批处理数据,累积损失和正确预测的计数,最终计算整体性能指标。

我们将实例化的损失函数和优化器传入train_looptest_loop中。训练3轮并输出loss和Accuracy,查看性能变化。

loss_fn = nn.CrossEntropyLoss()  # Define the loss function, in this case, Cross Entropy Loss
optimizer = nn.SGD(model.trainable_params(), learning_rate=learning_rate)  # Create an optimizer for training the model using Stochastic Gradient Descent

for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")  # Print the current epoch number
    train_loop(model, train_dataset)  # Call the training loop to train the model for one epoch on the training dataset
    test_loop(model, test_dataset, loss_fn)  # Call the testing loop to evaluate the model on the test dataset
print("Done!")  # Indicate that the training process is complete
  1. loss_fn = nn.CrossEntropyLoss():
    • 定义损失函数,这里使用的是交叉熵损失函数。交叉熵损失函数常用于分类任务,它度量了预测的概率分布与真实标签分布之间的距离。
  2. optimizer = nn.SGD(model.trainable_params(), learning_rate=learning_rate):
    • 创建一个优化器对象,这里使用的是随机梯度下降(SGD)优化器。它将用于在训练过程中更新模型的可训练参数。
    • model.trainable_params(): 获得模型中所有可以训练的参数。
    • learning_rate=learning_rate: 设置优化器的学习率。学习率决定了每次更新参数时步长的大小。
  3. for t in range(epochs)::
    • 用于控制训练的循环次数,即训练的轮数(epochs)。
  4. print(f"Epoch {t+1}\n-------------------------------"):
    • 打印当前的训练轮数,帮助跟踪训练进度。
  5. train_loop(model, train_dataset):
    • 调用训练循环函数 train_loop,在给定的训练数据集上训练模型一个轮次。
  6. test_loop(model, test_dataset, loss_fn):
    • 调用测试循环函数 test_loop,在给定的测试数据集上评估模型的性能,包括计算损失和准确率。
  7. print("Done!"):
    • 打印“Done!” 表示训练过程完成。

通过这个代码段,模型将会在指定的训练数据集上进行多轮训练(根据 epochs 的值),并且在每轮训练后对模型在测试数据集上的性能进行评估。这种方式可以帮助追踪模型的训练进展和验证模型的泛化能力。

整体代码

#!/usr/bin/env python
# coding: utf-8

# Import necessary libraries from MindSpore
import mindspore
from mindspore import nn
from mindspore.dataset import vision, transforms
from mindspore.dataset import MnistDataset

# Download data from open datasets
from download import download

# Specify the URL to download the MNIST dataset and the path to save it
url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/" \
      "notebook/datasets/MNIST_Data.zip"
path = download(url, "./", kind="zip", replace=True)

# Function to create and preprocess the dataset
def datapipe(path, batch_size):
    # Define transformations for images
    image_transforms = [
        vision.Rescale(1.0 / 255.0, 0),  # Rescale pixel values to [0, 1]
        vision.normalize(mean=(0.1307,), std=(0.3081,)),  # Normalize with mean and std
        vision.HWC2CHW()  # Change image format from HWC to CHW
    ]
    # Define transformation for labels
    label_transform = transforms.TypeCast(mindspore.int32)

    # Create the dataset
    dataset = MnistDataset(path)
    dataset = dataset.map(image_transforms, 'image')  # Apply image transformations
    dataset = dataset.map(label_transform, 'label')  # Apply label transformation
    dataset = dataset.batch(batch_size)  # Batch the dataset
    return dataset

# Create training and test datasets
train_dataset = datapipe('MNIST_Data/train', batch_size=64)
test_dataset = datapipe('MNIST_Data/test', batch_size=64)

# Define a neural network model
class Network(nn.Cell):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()  # Flatten the input
        self.dense_relu_sequential = nn.SequentialCell(
            nn.Dense(28*28, 512),  # Fully connected layer with 512 units
            nn.ReLU(),  # ReLU activation
            nn.Dense(512, 512),  # Fully connected layer with 512 units
            nn.ReLU(),  # ReLU activation
            nn.Dense(512, 10)  # Fully connected layer with 10 units for classification
        )

    def construct(self, x):
        x = self.flatten(x)  # Flatten the input
        logits = self.dense_relu_sequential(x)  # Forward pass through the sequential layers
        return logits

# Instantiate the model
model = Network()

# Define hyperparameters
epochs = 3
batch_size = 64
learning_rate = 1e-2

# Define the loss function
loss_fn = nn.CrossEntropyLoss()  # Cross Entropy Loss for classification

# Define the optimizer
optimizer = nn.SGD(model.trainable_params(), learning_rate=learning_rate)  # Stochastic Gradient Descent

# Define forward function
def forward_fn(data, label):
    logits = model(data)  # Forward pass: compute logits
    loss = loss_fn(logits, label)  # Compute loss
    return loss, logits

# Get gradient function
grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)
# mindspore.value_and_grad computes both the value of the function and its gradient.
# Arguments:
#   - forward_fn: the function for which we want to compute the gradient
#   - None: no additional arguments for gradient computation
#   - optimizer.parameters: parameters with respect to which gradients are computed
#   - has_aux: indicates that forward_fn returns auxiliary data (logits) along with the loss

# Define function of one-step training
def train_step(data, label):
    (loss, _), grads = grad_fn(data, label)  # Compute loss and gradients for the given data and labels
    optimizer(grads)  # Update model parameters using computed gradients
    return loss  # Return the computed loss

def train_loop(model, dataset):
    size = dataset.get_dataset_size()  # Get the total number of batches in the dataset
    model.set_train()  # Set the model to training mode
    for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):
        loss = train_step(data, label)  # Perform one training step

        if batch % 100 == 0:  # Print loss every 100 batches
            loss, current = loss.asnumpy(), batch  # Convert loss from tensor to numpy for printing
            print(f"loss: {loss:>7f}  [{current:>3d}/{size:>3d}]")  # Print the current loss and batch number

def test_loop(model, dataset, loss_fn):
    num_batches = dataset.get_dataset_size()  # Get the total number of batches in the dataset
    model.set_train(False)  # Set the model to evaluation mode
    total, test_loss, correct = 0, 0, 0  # Initialize counters for total samples, test loss, and correct predictions
    
    for data, label in dataset.create_tuple_iterator():
        pred = model(data)  # Forward pass: compute predictions by passing data to the model
        total += len(data)  # Update the total number of samples
        test_loss += loss_fn(pred, label).asnumpy()  # Accumulate the test loss, converting it from tensor to numpy
        correct += (pred.argmax(1) == label).asnumpy().sum()  # Count correct predictions, comparing argmax of predictions to labels
    
    test_loss /= num_batches  # Compute the average test loss
    correct /= total  # Compute the accuracy by dividing correct predictions by the total number of samples
    
    print(f"Test: \n Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")  # Print the test accuracy and average loss

# Train the model for the specified number of epochs and test it after each epoch
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")  # Print the current epoch number
    train_loop(model, train_dataset)  # Call the training loop to train the model for one epoch on the training dataset
    test_loop(model, test_dataset, loss_fn)  # Call the testing loop to evaluate the model on the test dataset
print("Done!")  # Indicate that the training process is complete

  1. 引入和下载数据集:
    • import mindspore: 导入MindSpore库。
    • from mindspore import nn: 导入神经网络模块。
    • from mindspore.dataset import vision, transformsfrom mindspore.dataset import MnistDataset: 导入数据集和数据预处理工具。
    • from download import download: 导入下载工具。
    • url** 和 **path: 定义数据集的下载URL和保存路径。
    • path = download(url, "./", kind="zip", replace=True): 下载MNIST数据集。
  2. **数据集预处理函数 **datapipe:
    • image_transforms: 定义图像预处理步骤,包括重缩放、归一化和格式转换。
    • label_transform: 定义标签转换步骤。
    • MnistDataset: 加载MNIST数据集。
    • dataset.map(image_transforms, 'image')dataset.map(label_transform, 'label'): 应用图像和标签的预处理。
    • dataset.batch(batch_size): 按批次大小分割数据集。
    • 返回预处理后的数据集。
  3. **定义神经网络模型 **Network:
    • nn.Cell: 继承自MindSpore的神经网络模块。
    • self.flatten: 定义flatten层。
    • self.dense_relu_sequential: 使用nn.SequentialCell定义全连接+激活的顺序层。
    • construct: 定义前向传播逻辑。
  4. 定义超参数:
    • epochs = 3: 训练轮次。
    • batch_size = 64: 批次大小。
    • learning_rate = 1e-2: 学习率。
  5. 定义损失函数和优化器:
    • loss_fn = nn.CrossEntropyLoss(): 定义交叉熵损失函数。
    • optimizer = nn.SGD(model.trainable_params(), learning_rate=learning_rate): 定义随机梯度下降优化器。
  6. **定义前向函数 **forward_fn:
    • logits = model(data): 计算logits。
    • loss = loss_fn(logits, label): 计算损失。
    • 返回损失和logits。
  7. **获取梯度函数 **grad_fn:
    • grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True): 获取前向函数的值和梯度。
  8. **定义训练步骤函数 **train_step:
    • (loss, _), grads = grad_fn(data, label): 计算损失和梯度。
    • optimizer(grads): 使用梯度更新模型参数。
    • 返回损失。
  9. **定义训练循环 **train_loop:
    • 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: 每100个批次打印一次损失。
    • print(f"loss: {loss:>7f} [{current:>3d}/{size:>3d}]"): 打印当前损失和批次编号。
  10. **定义测试循环 **test_loop:
  • 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. 训练和测试模型:
  • for t in range(epochs): 循环训练。
  • print(f"Epoch {t+1}\n-------------------------------"): 打印当前训练轮次。
  • train_loop(model, train_dataset): 训练模型。
  • test_loop(model, test_dataset, loss_fn): 测试模型。
  • print("Done!"): 打印训练完成。

该代码段展示了一个完整的深度学习训练流程,包括数据预处理、模型定义、训练和测试。通过循环训练和评估,模型的性能可以逐步得到提升。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1929255.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Re:从零开始的C++世界——类和对象(中)

文章目录 前言1. 类的默认成员函数2. 构造函数🍎概念🍎特点🍌特点一🍌特点二🍌特点三🍌特点四🍌特点五🍌特点六🍌特性七 🍎总结 3.析构函数🍎概念…

Foxmail新版本迁移邮箱的数据文件教程

Foxmail作为轻量化办公中使用最多的邮件沟通应用,而当其邮件积累到一定数量后,会几乎占满所在的硬盘空间,小编接下来为大家介绍如何将邮件数据文件迁移到其他硬盘,且迁移后保持foxmail的旧邮件数据存在,方便搜索和转发…

职升网:一建和注安哪个难度大?哪个含金量高?选择哪个?

从考试难度来看,一级建造师(简称一建)的考试难度通常被认为要高于注册安全工程师(简称注安)。一建考试涵盖的内容比较广泛,需要考生对教材进行全面了解和深入复习,特别是在实务这一块内容&#…

第三季度加密市场动荡:市场缺乏炒作题材,波动加剧

摘要 根据 Arkham 的数据,德国政府联邦刑事调查局 (BKA) 可能已完成抛售,其持有量从 6 月中旬的约 50,000 BTC(35.5 亿美元)减少到 7 月 12 日的数据为 0 BTC。市场担忧美国经济在今年晚些时候或 2025 年初陷入衰退,导…

使用mitmproxy抓包详细记录(一)

1、安装mitmproxy pip install mitmproxy 安装失败解决方案,见上一篇 2、编辑代码,可以直接复制我的. 给文件起名,attacy.py import mitmproxyimport csv from mitmproxy import httpclass RequestRecorder:def __init__(self):self.records…

植物大战僵尸杂交版等超火的版本汇总(附说明和下载链接)

1.杂交版 (最火的一版) B站游戏作者潜艇伟伟迷(点击进进入作者空间) 夸克网盘链接:https://pan.quark.cn/s/095de551d1d1 UC网盘链接:https://drive.uc.cn/s/86debb3ce1294 新增7月5日更新的2.2版本链接…

条件匹配工具之ACL概述

基本概念 ACL,即Access Control List(访问控制列表),每个ACL但是是由单条或多条Rule(规则)组成的一个集合 技术背景: 1.用户需求: 用户对网络服务体验的要求越来越高&#xff0c…

Openerstry + lua + redis根据请求参数实现动态路由转发

文章目录 一、需求分析二、准备1、软件安装2、redis-lua封装优化 三、实现1、nginx.conf2、dynamic.lua注意 3、准备两个应用4、访问nginx 四、参数直接传要代理的地址端口 一、需求分析 根据用户访问url的参数,将请求转发到对应指定IP的服务器上。 二、准备 1、…

java实现树形结构的设计

一、页面效果 二、数据库表设计 CREATE TABLE qc_question (id bigint(20) NOT NULL AUTO_INCREMENT,p_id bigint(11) NOT NULL,rank int(4) NOT NULL COMMENT 层级,name varchar(255) NOT NULL COMMENT 名称,code varchar(255) DEFAULT NULL COMMENT 编号,group_id bigint(20…

网络安全防御【防火墙双机热备带宽管理综合实验】

目录 一、实验拓扑图 二、实验要求 三、实验思路: 四、实验步骤: 1、FW3的网络相关配置: 2、FW1的新增配置: 3、交换机LSW6(总公司)的新增配置: 4、双机热备技术配置(双机热…

【人工智能】高级搜索技术(模拟退火搜索算法和遗传算法解决旅行商问题)

目录 一、旅行商问题 1. 需求分析 2. 数据结构、功能模块设计与说明 2.1 数据结构 (1)模拟退火搜索算法 (2)遗传算法 2.2 功能模块设计 (1)模拟退火搜索算法 (2)遗传算法 …

离散数学,传递闭包的运算 ,集合的划分和覆盖 ,等价关系 ,等价类,相容关系 ,偏序关系

目录 1.传递闭包的运算 2.集合的划分和覆盖 3.等价关系 4.等价类 等价关系的性质 商集 5.相容关系 相容类 写出以下相容关系的最大相容类 完全覆盖 6.偏序关系 覆盖 7.哈斯图例子 1.传递闭包的运算 2.集合的划分和覆盖 3.等价关系 4.等价类 等价关…

starrcoks内存溢出后重启失败

sr版本:version 2.1.12 RELEASE (build 04f2931) 部署方式: FE:10.6.xx.107~10.6.xx.109 BE:10.6.xx.107~10.6.xx.111 问题:某天10.6.xx.107机器上的BE提示内存溢出(日志如下),重启后,be却无法…

Gooxi受邀参加第三届中国数据中心服务器与设备峰会

7月2-3日,第三届中国数据中心服务器与设备峰会在上海召开,作为国内最聚焦在服务器领域的专业峰会,吸引了来自全国的行业专家、服务器与机房设备厂家,企业IT用户,数据中心业主共同探讨AIGC时代下智算中心设备的设计之道…

普通人用AI提升收入的四种途径分享(附教程)

全文干货视频很长,建议先收藏再看。 实操和AI绘画工具可以扫描下方,免费获取 01 提升赚钱效率:拆解主业,让AI为你的主业做乘法 首先我要告诉你的是,用 AI 来提升收入这件事并不难,只不过大多数人用错了方…

文心一言 VS 讯飞星火 VS chatgpt (304)-- 算法导论22.2 2题

二、请计算出在图22-3所示无向图上运行广度优先搜索算法后的 d 值和 π 值。这里假定结点 u 为算法所用的源结点。 文心一言: 为了计算在图22-3所示的无向图上运行广度优先搜索(BFS)算法后的d值和π值,我们首先需要明确图的结构…

【linux】服务器重装系统之系统盘写入准备

【linux】服务器重装系统之系统盘写入准备 【创作不易,求点赞关注收藏】😀 文章目录 【linux】服务器重装系统之系统盘写入准备一、前期准备1、准备一个U盘,并进行格式化2、下载UltralSO工具3、下载对应的Ubuntu版本 二、写入操作教程 一、…

手机和电脑通过TCP传输(一)

一.工具 手机端:网络调试精灵 电脑端:野火网络调试助手 在开始通信之前,千万要查看一下电脑的防火墙是否关闭,否则可能会无法通信 在开始通信之前,千万要查看一下电脑的防火墙是否关闭,否则可能会无法通信…

中仕公考:考公基层工作经历怎么计算?

在国家及省级公务员考试中,可能会有岗位要求“基层工作经历”,很多考生对于这一概念了解的不是很清楚,该经历定义为个人在县级或以下级别的机关、国有企事业单位、以及村(社区)组织或其他经济和社会组织中的工作历程。 须知:应届…