技术背景

近几年在机器学习和传统搜索算法的结合中,逐渐发展出了一种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. C语言之漫谈指针(上)

    C语言之漫谈指针(上) 在C语言学习的途中,我们永远有一个绕不了的坑,那就是--指针. 在这篇文章中我们就谈一谈指针的一些基础知识. 纲要: 零.谈指针之前的小知识 一.指针与指针变量 二.指针变量的 ...

  2. python--requests模块详解

    GET请求 首先构造一个最简单的get请求,请求的链接为http://httpbin.org/get import requests 2 r = requests.get("http://h ...

  3. The 2018 ACM-ICPC CCPC NING XIA G-Factories

    题意:在一棵数的叶子上建k个工厂保证,求两两距离之和的最小值. 思路:如果一个一个叶子节点去考虑去与否太麻烦了,直接考虑该节点的子树上选取几个作为工厂,利用树形DP,dp[u][i]表示的是u节点为根 ...

  4. 抗DDOS应急预案实践-生产环境总结-建议必看

    一.首先摸清楚环境与资源 为DDoS应急预案提供支撑 所在的网络环境中,有多少条互联网出口?每一条带宽多少? 每一条互联网出口的运营商是否支持DDoS攻击清洗,我们是否购买,或可以紧急试用?当发生DD ...

  5. Go Protobuf(比xml小3-10倍, 快20-100倍)

    简介 Protocol Buffers是什么? protocol buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小.更快.更为简单.你可以定义数据 ...

  6. SparkStreaming使用mapWithState时,设置timeout()无法生效问题解决方案

    前言 当我在测试SparkStreaming的状态操作mapWithState算子时,当我们设置timeout(3s)的时候,3s过后数据还是不会过期,不对此key进行操作,等到30s左右才会清除过期 ...

  7. Vue 中的 mixin,component,render,hoc

    在项目中,一般我们经常会基于一套现有组件库进行快速开发,但是现实中往往需要对组件库进行定制化改造二次封装 混入(mixin) vue 官方介绍 混入 (mixin) 提供了一种非常灵活的方式,来分发 ...

  8. (十三)VMware Harbor 身份验证模式

    VMware Harbor 修改Harbor仓库admin用户 参考:https://blog.csdn.net/qq_40460909 https://blog.csdn.net/qq_404609 ...

  9. JAVAEE_Servlet_19_重定向可以解决页面刷新问题(sendRedirect)

    重定向可以解决页面刷新问题(sendRedirect) 在向数据库中添加数据的时候,如果使用转发(getRequestDispatcher),数据插入成功后,转发到提示插入成功页面,在数据插入成功页面 ...

  10. 超详细!!Spring5框架开发笔记

    Spring5开发教程 简介 spring特性 sping是轻量级的开源的JavaEE框架 Spring可以解决企业应用开发的复杂性 Sping两个核心的部分:IOC和AOC IOC:控制反转.把创建 ...