1. 保存與加載
在訓練網絡模型的過程中,實際上我們希望保存中間和最后的結果,用于微調(fine-tune)和后續的模型推理與部署,本章節我們將介紹如何保存與加載模型。
1.1 導入依賴
# 導入numpy庫,并將其重命名為np,以便在代碼中引用
import numpy as np# 導入MindSpore庫,這是華為推出的一個開源深度學習框架,用于構建和訓練神經網絡
import mindspore# 從MindSpore庫中導入nn模塊,這個模塊包含了構建神經網絡所需的各種層和函數
from mindspore import nn# 從MindSpore庫中導入Tensor模塊,Tensor是MindSpore中用于表示張量的類
from mindspore import Tensor
1.1定義神經網絡模型
# 定義一個函數,該函數創建一個簡單的全連接神經網絡模型
def network():# 使用nn.SequentialCell創建一個層序列,這是一個容器類,可以包含多個層model = nn.SequentialCell(# 第一個層是一個Flatten層,用于將輸入的二維圖像數據展平為一維向量nn.Flatten(),# 第二個層是一個全連接層,將28x28的輸入節點映射到512個節點nn.Dense(28*28, 512),# 第三個層是一個ReLU激活函數,用于非線性變換nn.ReLU(),# 第四個層是一個全連接層,將512個節點映射到512個節點nn.Dense(512, 512),# 第五個層是一個ReLU激活函數,用于非線性變換nn.ReLU(),# 第六個層是一個全連接層,將512個節點映射到10個節點,對應于10個類別的輸出nn.Dense(512, 10))# 返回創建好的模型return model
1.2 保存和加載模型權重
1.2.1 保存模型
保存模型使用save_checkpoint
接口,傳入網絡和指定的保存路徑:
# 創建一個神經網絡模型實例
model = network()# 使用MindSpore的save_checkpoint函數將模型的檢查點保存到文件
# 第一個參數是模型對象
# 第二個參數是文件名,這里保存為"model.ckpt"
mindspore.save_checkpoint(model, "model.ckpt")
# 打印模型結構
print(model)
輸出:
SequentialCell<(0): Flatten<>(1): Dense<input_channels=784, output_channels=512, has_bias=True>(2): ReLU<>(3): Dense<input_channels=512, output_channels=512, has_bias=True>(4): ReLU<>(5): Dense<input_channels=512, output_channels=10, has_bias=True>>
模型大小估算:
model_capacity ≈ 模型參數 * 數據精度(默認是int32類型)大小 = [(784512+512) + (512512+512) + (512*10 +10)] *32bit/8(bit/Byte)= 669704 *4 = 2678824 Byte
可以看到,模型參數量約為67W,占用空間大小應約為2678824字節
實際該模型文件大小為2679017。可以說非常接近了,剩下的字節應該就是文件類型描述符加模型結構描述符之類的內容了。
所以當我們已知一個模型的參數量和參數精度后,實際就可以估算出模型占用的磁盤空間大小了。
1.2.2 加載模型
要加載模型權重,需要先創建相同模型的實例,然后使用load_checkpoint
和load_param_into_net
方法加載參數。
# 創建一個神經網絡模型
model = network()# 使用MindSpore的load_checkpoint函數從文件中加載模型的參數和優化器狀態
# 參數是檢查點的文件名,這里加載的文件名為"model.ckpt"
param_dict = mindspore.load_checkpoint("model.ckpt")# 使用MindSpore的load_param_into_net函數將加載的參數字典加載到模型中
# 第一個參數是模型對象
# 第二個參數是參數字典
# 返回值是一個元組,第一個元素是未加載的參數列表,第二個元素是加載的參數列表
param_not_load, _ = mindspore.load_param_into_net(model, param_dict)# 打印未加載的參數列表,如果加載成功,這個列表應該是空的
print(param_not_load)
輸出:
[]
param_not_load
是未被加載的參數列表,為空時代表所有參數均加載成功。
1.3 保存和加載MindIR
除Checkpoint外,MindSpore提供了云側(訓練)和端側(推理)統一的中間表示(Intermediate Representation,IR)。可使用export
接口直接將模型保存為MindIR。
# 創建網絡模型
model = network()
# 創建一個Tensor對象,它包含一個大小為[1, 1, 28, 28]的矩陣,所有元素都是1,數據類型為float32
inputs = Tensor(np.ones([1, 1, 28, 28]).astype(np.float32))
# 使用mindspore.export函數將模型導出為MINDIR格式
# 第一個參數是模型對象
# 第二個參數是輸入數據,這里使用了一個Tensor對象作為示例
# 第三個參數是文件名,這里導出的文件名為"model"
# 第四個參數是文件格式,這里設置為"MINDIR",表示導出的模型格式
mindspore.export(model, inputs, file_name="model", file_format="MINDIR")
MindIR同時保存了Checkpoint和模型結構,因此需要定義輸入Tensor來獲取輸入shape。
已有的MindIR模型可以方便地通過load
接口加載,傳入nn.GraphCell
即可進行推理。
nn.GraphCell
僅支持圖模式。
# 設置MindSpore的執行模式為GRAPH_MODE
mindspore.set_context(mode=mindspore.GRAPH_MODE)
# 加載之前導出的MINDIR模型
graph = mindspore.load("model.mindir")
# 創建一個GraphCell對象,它將graph作為其成員
model = nn.GraphCell(graph)
# 使用模型對輸入數據進行前向計算,得到輸出
outputs = model(inputs)
# 打印輸出的形狀
print(outputs.shape)
輸出:
2. 小結
本文主要介紹了模型的保存和加載,都包括檢查點checkpoint
和統一中間表示MindIR
(Intermediate Representation)兩種方法,還介紹了模型大小的估算方法。