训练模型
Ascend
GPU
CPU
入门
模型开发
通过上面章节的学习,我们已经学会如何创建模型和构建数据集,现在开始学习如何设置超参和优化模型参数。
超参
超参是可以调整的参数,可以控制模型训练优化的过程,不同的超参数值可能会影响模型训练和收敛速度。
一般会定义以下用于训练的超参:
训练轮次(epoch):训练时遍历数据集的次数。
批次大小(batch size):数据集进行分批读取训练,设定每个批次数据的大小。
学习率(learning rate):如果学习率偏小,会导致收敛的速度变慢,如果学习率偏大则可能会导致训练不收敛等不可预测的结果。
[1]:
epochs = 5
batch_size = 64
learning_rate = 1e-3
损失函数
损失函数用来评价模型的预测值和真实值不一样的程度,在这里,使用绝对误差损失函数L1Loss
。mindspore.nn.loss
也提供了许多其他常用的损失函数,如SoftmaxCrossEntropyWithLogits
、MSELoss
、SmoothL1Loss
等。
我们给定输出值和目标值,计算损失值,使用方法如下所示:
[2]:
import numpy as np
import mindspore.nn as nn
from mindspore import Tensor
loss = nn.L1Loss()
output_data = Tensor(np.array([[1, 2, 3], [2, 3, 4]]).astype(np.float32))
target_data = Tensor(np.array([[0, 2, 5], [3, 1, 1]]).astype(np.float32))
print(loss(output_data, target_data))
1.5
优化器
优化器用于计算和更新梯度,模型优化算法的选择直接关系到最终模型的性能,如果有时候效果不好,未必是特征或者模型设计的问题,很有可能是优化算法的问题。MindSpore所有优化逻辑都封装在Optimizer
对象中,在这里,我们使用Momentum优化器。mindspore.nn
也提供了许多其他常用的优化器,如Adam
、Momentum
。
我们需要构建一个Optimizer
对象,这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。
为了构建一个Optimizer
,我们需要给它一个包含可优化的参数(必须是Variable对象)的迭代器,如网络中所有可以训练的parameter
,将params
设置为net.trainable_params()
即可。然后,你可以设置Optimizer的参数选项,比如学习率、权重衰减等等。
代码样例如下:
from mindspore import nn
optim = nn.Momentum(net.trainable_params(), 0.1, 0.9)
训练
在模型训练过程中,一般分为四个步骤。
定义神经网络。
构建数据集。
定义超参、损失函数及优化器。
输入训练轮次和数据集进行训练。
以下示例代码将数据集下载并解压到指定位置。
[ ]:
import os
import requests
import tarfile
import zipfile
requests.packages.urllib3.disable_warnings()
def download_dataset(url, target_path):
"""下载并解压数据集"""
if not os.path.exists(target_path):
os.makedirs(target_path)
download_file = url.split("/")[-1]
if not os.path.exists(download_file):
res = requests.get(url, stream=True, verify=False)
if download_file.split(".")[-1] not in ["tgz", "zip", "tar", "gz"]:
download_file = os.path.join(target_path, download_file)
with open(download_file, "wb") as f:
for chunk in res.iter_content(chunk_size=512):
if chunk:
f.write(chunk)
if download_file.endswith("zip"):
z = zipfile.ZipFile(download_file, "r")
z.extractall(path=target_path)
z.close()
if download_file.endswith(".tar.gz") or download_file.endswith(".tar") or download_file.endswith(".tgz"):
t = tarfile.open(download_file)
names = t.getnames()
for name in names:
t.extract(name, target_path)
t.close()
print("The {} file is downloaded and saved in the path {} after processing".format(os.path.basename(url), target_path))
download_dataset("https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz", "./datasets")
模型训练示例代码如下所示:
[4]:
import mindspore.dataset as ds
import mindspore.dataset.transforms.c_transforms as C
import mindspore.dataset.vision.c_transforms as CV
from mindspore import nn, Tensor, Model
from mindspore import dtype as mstype
from mindspore.train.callback import LossMonitor
DATA_DIR = "./datasets/cifar-10-batches-bin"
# 定义神经网络
class Net(nn.Cell):
def __init__(self, num_class=10, num_channel=3):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')
self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')
self.fc1 = nn.Dense(16 * 5 * 5, 120)
self.fc2 = nn.Dense(120, 84)
self.fc3 = nn.Dense(84, num_class)
self.relu = nn.ReLU()
self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
self.flatten = nn.Flatten()
def construct(self, x):
x = self.conv1(x)
x = self.relu(x)
x = self.max_pool2d(x)
x = self.conv2(x)
x = self.relu(x)
x = self.max_pool2d(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
return x
net = Net()
epochs = 5
batch_size = 64
learning_rate = 1e-3
# 构建数据集
sampler = ds.SequentialSampler(num_samples=128)
dataset = ds.Cifar10Dataset(DATA_DIR, sampler=sampler)
# 数据类型转换
type_cast_op_image = C.TypeCast(mstype.float32)
type_cast_op_label = C.TypeCast(mstype.int32)
HWC2CHW = CV.HWC2CHW()
dataset = dataset.map(operations=[type_cast_op_image, HWC2CHW], input_columns="image")
dataset = dataset.map(operations=type_cast_op_label, input_columns="label")
dataset = dataset.batch(batch_size)
# 定义超参、损失函数及优化器
optim = nn.Momentum(net.trainable_params(), learning_rate, 0.9)
loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
cb = LossMonitor()
# 输入训练轮次和数据集进行训练
model = Model(net, loss_fn=loss, optimizer=optim)
model.train(epoch=epochs, train_dataset=dataset, callbacks=cb)
epoch: 1 step: 1, loss is 2.3025818
epoch: 1 step: 2, loss is 2.3025775
epoch: 2 step: 1, loss is 2.3025408
epoch: 2 step: 2, loss is 2.3025331
epoch: 3 step: 1, loss is 2.3024616
epoch: 3 step: 2, loss is 2.302457
epoch: 4 step: 1, loss is 2.3023522
epoch: 4 step: 2, loss is 2.3023558
epoch: 5 step: 1, loss is 2.3022182
epoch: 5 step: 2, loss is 2.3022337