目录
一、mindspore简介
MindSpore是华为开源的全场景深度学习框架,旨在实现易开发、高效执行、全场景覆盖三大目标,其中易开发表现为API友好、调试难度低,高效执行包括计算效率、数据预处理效率和分布式训练效率,全场景则指框架同时支持云、边缘以及端侧场景。
MindSpore支持的Windows和linux系统,其中Windows版本仅支持CPU运行,linux版本则支持GPU和NPU(华为昇腾系列处理器)。
MindSpore官网地址:https://www.mindspore.cn/。官网包含了安装说明、教程、文档、官方开源模型等资源,方便初学者快速入门。
二、训练环境
硬件环境:cpu(i7-1165G7)、内存16G;
软件环境:windows10、python3.7、pycharm、mindspore1.5
三、数据集与数据加载
MindSpore提供API接口直接加载Cirfar10、ImageNet、coco等开源数据集,对图像分类自定义数据集加载也十分方便。这里准备训练一个识别哈士奇和拉布拉多犬的二分类模型,首先需要准备图像并存入对应文件夹。如下:
数据准备:数据集分为训练集和测试集,两种类别的图片数量尽量一致,训练集husky(399)、labrador(400),验证集:husky(51)、labrador(49)。数据集文件结构:
dataset: train: husky:1.jpg... labrador:1.jpg... val: husky:1.jpg... labrador:1.jpg... |
加载数据集:将不同类别图像放在不同文件夹下,mindspore.dataset .ImageFolderDataset()接口可以直接对数据集进行加载和标注。
train_data_path = 'dataset/train'
data_set = ds.ImageFolderDataset(data_path, num_parallel_workers=8, shuffle=True)
图像预处理:图像解码、调整大小、标准化、矩阵转置。
image_size = [224, 224]
mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]
std = [0.229 * 255, 0.224 * 255, 0.225 * 255]
trans = [
CV.Decode(),
CV.Resize(image_size),
CV.Normalize(mean=mean, std=std),
CV.HWC2CHW()
]
数据增强:如果数据集比较小,为了增强模型泛化能力,可以通过修改tran配置进行数据增强。
trans = [
CV.RandomCropDecodeResize(image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)),
CV.RandomHorizontalFlip(prob=0.5),
CV.Normalize(mean=mean, std=std),
CV.HWC2CHW()
]
数据的map映射、批量处理和数据重复的操作:
data_set = data_set.map(operations=trans, input_columns="image", num_parallel_workers=8)
data_set = data_set.map(operations=type_cast_op, input_columns="label", num_parallel_workers=8)
data_set = data_set.batch(batch_size, drop_remainder=True)
data_set = data_set.repeat(repeat_num)
四、模型训练和验证
使用MindSpore官方resnet.py脚本构建一个resnet50网络。
net = resnet50(2)
num_epochs=5
定义优化器和损失函数:
opt = nn.Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)
loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
实例化模型:
model = Model(net, loss, opt, metrics={"Accuracy": nn.Accuracy()})
模型训练:
eval_param_dict = {"model":model,"dataset":val_ds,"metrics_name":"Accuracy"}
eval_cb = EvalCallBack(apply_eval, eval_param_dict,)
model.train(num_epochs,train_ds, callbacks=[eval_cb, TimeMonitor()], dataset_sink_mode=False)
训练过程中,对每一个epoch进行验证,保留验证精度最好的模型参数。
训练结束后,使用训练过程保存的精度最好的参数对验证集进行验证,并对验证结果可视化。
五、迁移学习
MindSpore实现迁移学习流程:定义网络并加载预训练模型;删除预训练模型最后一层参数;给网络加载加载预训练参数;冻结除最后一层外所有参数。
# 加载预训练模型
param_dict = load_checkpoint('resnet50.ckpt')
# 获取最后一层参数的名字
filter_list = [x.name for x in net.end_point.get_parameters()]
# 删除预训练模型最后一层的参数
filter_checkpoint_parameter_by_list(param_dict, filter_list)
# 给网络加载参数
load_param_into_net(net, param_dict)
# 冻结除最后一层外的所有参数
for param in net.get_parameters():
if param.name not in ["end_point.weight","end_point.bias"]:
param.requires_grad = False
六、模型测试和导出
测试模型:模型训练完成后,通过推理代码和测试集对模型进行评估。
import os
import numpy as np
import cv2
import mindspore.nn as nn
from mindspore import dtype as mstype
import mindspore.dataset.vision.c_transforms as CV
from mindspore import Model, Tensor, context, load_checkpoint, load_param_into_net
from resnet import resnet50
#设置使用设备,CPU/GPU/Ascend
context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
def ms_normalize(image):
mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]
std = [0.229 * 255, 0.224 * 255, 0.225 * 255]
resize = CV.Resize([224, 224])
normalization = CV.Normalize(mean=mean, std=std)
hwc2chw = CV.HWC2CHW()
image = resize(image)
image = normalization(image)
image = hwc2chw(image)
return image
def normalize(image):
mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]
std = [0.229 * 255, 0.224 * 255, 0.225 * 255]
image = cv2.resize(image, [224, 224], cv2.INTER_LINEAR)
image = image / 1.0
image = (image[:, :] - mean) / std
image = image[:, :, ::-1].transpose((2, 0, 1)) # HWC-->CHW
return image
def pre_deal(data_path):
image = cv2.imread(data_path)
norm_img = normalize(image)
#norm_img = ms_normalize(image)
images = [norm_img]
images = Tensor(images, mstype.float32)
return images
def infer(ckpt_path, data_path, num_class):
image = pre_deal(data_path)
net = resnet50(num_class)
param_dict = load_checkpoint(ckpt_path)
load_param_into_net(net, param_dict)
loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
model = Model(net, loss, metrics={"Accuracy": nn.Accuracy()})
output = model.predict(image)
print(output)
pred = np.argmax(output.asnumpy(), axis=1)
return pred
if __name__ == '__main__':
ckpt_path = 'transfer_best.ckpt'
data_path = 'test'
class_name = {0: 'husky', 1: 'labrador'}
for path in os.listdir(os.path.join(data_path)):
path = os.path.join(data_path) + '/' + path
print(path)
result = infer(ckpt_path, path, 2)
print(class_name[result[0]])
为了方便推理部署,MindSpore支持导出MINDIR、AIR、ONNX三种格式。
from mindspore import export, load_checkpoint, load_param_into_net
from mindspore import Tensor
import numpy as np
from resnet import resnet50
net = resnet50(2)
# 将模型参数存入parameter的字典中
param_dict = load_checkpoint("best.ckpt")
# 将参数加载到网络中
load_param_into_net(net, param_dict)
input = np.random.uniform(0.0, 1.0, size=[1, 3, 224, 224]).astype(np.float32)
#导出模型,可导出ONNX、MINDIR、AIR格式
export(net, Tensor(input), file_name='resnet50_best', file_format='ONNX')
全部实现代码:
https://gitee.com/chen-jian51/mindspore_resnet50_husky_labrador/tree/master