技术背景

近几年在机器学习和传统搜索算法的结合中,逐渐发展出了一种Search To Optimization的思维,旨在通过构造一个特定的机器学习模型,来替代传统算法中的搜索过程,进而加速经典图论等问题的求解。那么这里面就涉及到一个非常关键的工程步骤:把机器学习中训练出来的模型保存成一个文件或者数据库,使得其他人可以重复的使用这个已经训练出来的模型。甚至是可以发布在云端,通过API接口进行调用。那么本文的内容就是介绍给予MindSpore的模型保存与加载,官方文档可以参考这个链接

保存模型

这里我们使用的模型来自于这篇博客,是一个非常基础的线性神经网络模型,用于拟合一个给定的函数。因为这里我们是基于线性的模型,因此当我们需要去拟合一个更加高阶的函数的话,需要手动的处理,比如这里我们使用的平方函数。总结起来该模型可以抽象为:

\[f(x)=ax^2+b
\]

而这里产生训练集时,我们是加了一个随机的噪声,也就是:

\[D(x)=ax^2+b+noise
\]

完整的代码如下所示:

# save_model.py

from mindspore import context
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")
import numpy as np
from mindspore import dataset as ds
from mindspore import nn, Tensor, Model
import time
from mindspore.train.callback import Callback, LossMonitor, ModelCheckpoint def get_data(num, a=2.0, b=3.0):
for _ in range(num):
x = np.random.uniform(-1.0, 1.0)
noise = np.random.normal(0, 0.03)
z = a * x ** 2 + b + noise
# 返回数据的时候就返回数据的平方
yield np.array([x**2]).astype(np.float32), np.array([z]).astype(np.float32) def create_dataset(num_data, batch_size=16, repeat_size=1):
input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['x','z'])
input_data = input_data.batch(batch_size)
input_data = input_data.repeat(repeat_size)
return input_data data_number = 1600 # 一共产生1600组数据
batch_number = 16 # 分为16组分别进行优化
repeat_number = 2 # 重复2次,可以取到更低的损失函数值 ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number) class LinearNet(nn.Cell):
def __init__(self):
super(LinearNet, self).__init__()
self.fc = nn.Dense(1, 1, 0.02, 0.02) def construct(self, x):
x = self.fc(x)
return x net = LinearNet()
model_params = net.trainable_params()
print ('Param Shape is: {}'.format(len(model_params)))
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
net_loss = nn.loss.MSELoss() # 设定优化算法,常用的是Momentum和ADAM
optim = nn.Momentum(net.trainable_params(), learning_rate=0.005, momentum=0.9)
model = Model(net, net_loss, optim)
ckpt_cb = ModelCheckpoint() epoch = 1
# 设定每8个batch训练完成后就播报一次,这里一共播报25次
model.train(epoch, ds_train, callbacks=[LossMonitor(16), ckpt_cb], dataset_sink_mode=False) for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())

最后是通过ModelCheckpoint这一方法将训练出来的模型保存成.ckpt的checkpoint文件格式。上述代码执行的结果如下:

dechin@ubuntu2004:~/projects/gitlab/dechin/src/mindspore$ sudo docker run --rm -v /dev/shm:/dev/shm -v /home/dechin/projects/gitlab/dechin/src/mindspore/:/home/ --runtime=nvidia --privileged=true swr.cn-south-1.myhuaweicloud.com/mindspore/mindspore-gpu:1.2.0 /bin/bash -c "cd /home && python save_model.py"
Param Shape is: 2
Parameter (name=fc.weight, shape=(1, 1), dtype=Float32, requires_grad=True) [[0.02]]
Parameter (name=fc.bias, shape=(1,), dtype=Float32, requires_grad=True) [0.02]
epoch: 1 step: 16, loss is 0.9980968
epoch: 1 step: 32, loss is 0.3894167
epoch: 1 step: 48, loss is 0.090543285
epoch: 1 step: 64, loss is 0.060300454
epoch: 1 step: 80, loss is 0.014248277
epoch: 1 step: 96, loss is 0.015697923
epoch: 1 step: 112, loss is 0.014582128
epoch: 1 step: 128, loss is 0.008066677
epoch: 1 step: 144, loss is 0.007225203
epoch: 1 step: 160, loss is 0.0046849623
epoch: 1 step: 176, loss is 0.006007362
epoch: 1 step: 192, loss is 0.004276552
Parameter (name=fc.weight, shape=(1, 1), dtype=Float32, requires_grad=True) [[1.8259585]]
Parameter (name=fc.bias, shape=(1,), dtype=Float32, requires_grad=True) [3.0577476]

可能是由于数据集的问题,可能是由于噪声的问题,使得我们训练出来的参数跟我们最开始所定义的参数有些许的区别,但是具体的误差范围还得通过测试集来验证。运行结束后会在当前目录下生成一系列的.ckpt文件和一个.meta的计算图文件:

dechin@ubuntu2004:~/projects/gitlab/dechin/src/mindspore$ ll
total 148
drwxr-xr-x 2 1000 1000 4096 May 16 13:25 ./
drwxr-xr-x 1 root root 4096 May 15 01:55 ../
-r-------- 1 root root 211 May 16 13:25 CKP-1_196.ckpt
-r-------- 1 root root 211 May 16 13:25 CKP-1_197.ckpt
-r-------- 1 root root 211 May 16 13:25 CKP-1_198.ckpt
-r-------- 1 root root 211 May 16 13:25 CKP-1_199.ckpt
-r-------- 1 root root 211 May 16 13:25 CKP-1_200.ckpt
-r-------- 1 root root 3705 May 16 13:25 CKP-graph.meta
-rw-r--r-- 1 1000 1000 2087 May 16 13:25 save_model.py

接下来就可以开始加载这些文件中所给出的模型,用于测试集的验证。

加载模型

在模型的加载中,我们依然还是需要原始的神经网络对象LinearNet

# load_model.py

from mindspore import context
context.set_context(mode=context.GRAPH_MODE, device_target="GPU")
import mindspore.dataset as ds
from mindspore import load_checkpoint, load_param_into_net
from mindspore import nn, Tensor, Model
import numpy as np class LinearNet(nn.Cell):
def __init__(self):
super(LinearNet, self).__init__()
self.fc = nn.Dense(1,1,0.02,0.02) def construct(self, x):
print ('x:', x)
x = self.fc(x)
print ('z:', x)
return x net = LinearNet()
param_dict = load_checkpoint("CKP-1_200.ckpt")
load_param_into_net(net, param_dict) net_loss = nn.loss.MSELoss()
model = Model(net, net_loss, metrics={"accuracy"}) data = {'x':np.array([[0.01],[0.25],[1],[4],[9]]).astype(np.float32),
'z':np.array([3.02,3.5,5,11,21]).astype(np.float32)}
dataset = ds.NumpySlicesDataset(data=data)
dataset = dataset.batch(1) acc = model.eval(dataset, dataset_sink_mode=False)

这里我们只是定义了一个非常简单的测试集,在实际场景中往往测试集也是非常大量的数据。这里为了简化本地环境,使用的是Docker的编程环境,并且在Docker容器的拉起中使用了--rm选项,在运行结束后会删除这个容器,确保环境的整洁。关于在Docker容器环境下安装和部署MindSpore的方案,可以参考这篇CPU部署博客,以及这篇GPU部署博客。上述代码的执行结果如下:

dechin@ubuntu2004:~/projects/gitlab/dechin/src/mindspore$ sudo docker run --rm -v /dev/shm:/dev/shm -v /home/dechin/projects/gitlab/dechin/src/mindspore/:/home/ --runtime=nvidia --privileged=true swr.cn-south-1.myhuaweicloud.com/mindspore/mindspore-gpu:1.2.0 /bin/bash -c "cd /home && python load_model.py"
x:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 9.00000000e+00]])
z:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 1.94898682e+01]])
x:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 2.50000000e-01]])
z:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 3.52294850e+00]])
x:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 9.99999978e-03]])
z:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 3.08499861e+00]])
x:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 1.00000000e+00]])
z:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 4.89154148e+00]])
x:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 4.00000000e+00]])
z:
Tensor(shape=[1, 1], dtype=Float32, value=
[[ 1.03659143e+01]])

从这个结果中我们可以看到,由于在训练集中我们使用的数据集中在比较小的范围,因此在测试这个范围外的数据时,误差相较于这个区域内的数据点会更大一些,这也是属于正常的现象。

总结概要

本文主要从工程实现的角度测试了一下MindSpore的机器学习模型保存与加载的功能,通过这个功能,我们可以将自己训练好的机器学习模型发布出去供更多的人使用,我们也可以直接使用别人在更好的硬件体系上训练好的模型,或者应用于迁移学习。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/sl.html

作者ID:DechinPhy

更多原著文章请参考:https://www.cnblogs.com/dechinphy/

MindSpore保存与加载模型的更多相关文章

  1. TensorFlow保存、加载模型参数 | 原理描述及踩坑经验总结

    写在前面 我之前使用的LSTM计算单元是根据其前向传播的计算公式手动实现的,这两天想要和TensorFlow自带的tf.nn.rnn_cell.BasicLSTMCell()比较一下,看看哪个训练速度 ...

  2. [深度学习] Pytorch(三)—— 多/单GPU、CPU,训练保存、加载模型参数问题

    [深度学习] Pytorch(三)-- 多/单GPU.CPU,训练保存.加载预测模型问题 上一篇实践学习中,遇到了在多/单个GPU.GPU与CPU的不同环境下训练保存.加载使用使用模型的问题,如果保存 ...

  3. tensorflow学习笔记(三十四):Saver(保存与加载模型)

    Savertensorflow 中的 Saver 对象是用于 参数保存和恢复的.如何使用呢? 这里介绍了一些基本的用法. 官网中给出了这么一个例子: v1 = tf.Variable(..., nam ...

  4. sklearn训练模型的保存与加载

    使用joblib模块保存于加载模型 在机器学习的过程中,我们会进行模型的训练,最常用的就是sklearn中的库,而对于训练好的模型,我们当然是要进行保存的,不然下次需要进行预测的时候就需要重新再进行训 ...

  5. tensorflow 模型保存与加载 和TensorFlow serving + grpc + docker项目部署

    TensorFlow 模型保存与加载 TensorFlow中总共有两种保存和加载模型的方法.第一种是利用 tf.train.Saver() 来保存,第二种就是利用 SavedModel 来保存模型,接 ...

  6. 深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 1.cv2.resize(图片压缩) 2..get_shape()[1:4].num_elements(获得最后三维度之和) 3.saver.save(训练参数的保存) 4.tf.train.import_meta_graph(加载模型结构) 5.saver.restore(训练参数载入)

    1.cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR) 参数说明:image表示输入图片,image_size表示变 ...

  7. PyTorch保存模型与加载模型+Finetune预训练模型使用

    Pytorch 保存模型与加载模型 PyTorch之保存加载模型 参数初始化参 数的初始化其实就是对参数赋值.而我们需要学习的参数其实都是Variable,它其实是对Tensor的封装,同时提供了da ...

  8. [Pytorch]Pytorch 保存模型与加载模型(转)

    转自:知乎 目录: 保存模型与加载模型 冻结一部分参数,训练另一部分参数 采用不同的学习率进行训练 1.保存模型与加载 简单的保存与加载方法: # 保存整个网络 torch.save(net, PAT ...

  9. tensorflow 之模型的保存与加载(三)

    前面的两篇博文 第一篇:简单的模型保存和加载,会包含所有的信息:神经网络的op,node,args等; 第二篇:选择性的进行模型参数的保存与加载. 本篇介绍,只保存和加载神经网络的计算图,即前向传播的 ...

随机推荐

  1. .NET初探源代码生成(Source Generators)

    前言 Source Generators顾名思义代码生成器,可进行创建编译时代码,也就是所谓的编译时元编程,这可让一些运行时映射的代码改为编译时,同样也加快了速度,我们可避免那种昂贵的开销,这是有价值 ...

  2. python-6-1

    1.定义一个时间戳转换成格式化时间的函数import time def timestamp_to_fomat(timestamp= None,format ='%Y-%m-%d %H:%M:%S' ) ...

  3. springMVC:校验框架:多规则校验,嵌套校验,分组校验;ssm整合技术

    知识点梳理 课堂讲义 学习目标 能够阐述表单验证的分类和区别 能够运用表单验证的常用注解 能够编写表单验证的示例 能够编写SSM整合的应用案例 能够总结SSM整合的步骤 1 校验框架 1.1 入门-视 ...

  4. Ubuntu20.04linux内核(5.4.0版本)编译准备与实现过程-编译前准备(1)

    最近项目也和linux kernel技术有关,调试内核和内核模块.修改内核源码,是学习内核的重要技术手段之一.应用这些技术时,都有一本基本的要求,那就是编译内核.因此,在分析内核调试技术之前,本随笔给 ...

  5. 第21 章 : Kubernetes 存储架构及插件使用

    Kubernetes 存储架构及插件使用 本文将主要分享以下三方面的内容: Kubernetes 存储体系架构: Flexvolume 介绍及使用: CSI 介绍及使用. Kubernetes 存储体 ...

  6. (文字版)Qt信号槽源码剖析(三)

    大家好,我是IT文艺男,来自一线大厂的一线程序员 上节视频给大家讲解了Qt信号槽的Qt宏展开推导:今天接着深入分析,进入Qt信号槽源码剖析系列的第三节视频. Qt信号槽宏推导归纳 #define si ...

  7. ATMS中去拉起新的进程,并在新进程启动后调用attachApplication时,resume待启动的Activity

    相关文章: ATMS中去pause Activity A. 目录 ATMS拉起新进程 堆栈 resumeTopActivityInnerLocked:1684, ActivityStack start ...

  8. 承接上一篇,whale系统开篇,聊聊用户认证

    写在前面 上次老猫和大家说过想要开发一个系统,从简单的权限开始做起,有的网友表示还是挺支持的,但是有的网友嗤之以鼻,认为太简单了,不过也没事,简单归简单,主要的还是个人技术的一个整合和实战. 没错,系 ...

  9. Spring Boot demo系列(五):Docker部署

    2021.2.24 更新 1 概述 本文讲述了如何使用Docker部署Spring Boot应用,首先介绍了Docker的安装过程,接着介绍了Docker的一些基础知识,最后讲述了Dockerfile ...

  10. Go-41-回调

    回调函数,函数有一个参数是函数类型,这个函数就是回调函数 回调函数,可以实现多态,即调用同一个接口,不同的表现,可以实现不同表现 package main import "fmt" ...