MindSpore模型驗證


技術背景

在前面一篇博客中,我們介紹了MindSpore在機器學習過程中保存和加載模型的方法。這種將模型存儲為靜態文件的做法,使得我們可以更靈活的使用訓練出來的模型,比如用於各種數據集的驗證,或者是遷移學習等場景。

前言

這里使用的數據集和加載的模型,都來自於這篇博客。關於MindSpore的環境部署,可以參考這兩篇博客:CPU版本安裝GPU版本安裝,當然,這兩個方案都使用了Docker容器化部署的策略,這跟個人編程習慣有關。需要說明的是,在GPU版本中可以使用CPU版本的context,但是CPU版本中不能使用GPU版本的context。但是CPU版本的部署相比於GPU版本要容易很多,GPU版本的部署方案對本地Docker環境之外還有一些依賴,可以看個人需求來進行選取。關於性能問題,其實不好說GPU版本的一定就比CPU版本的更快,比如本文中所使用到的案例在CPU上運行的速度就比GPU上運行的速度要快。GPU由於其硬件架構的特殊性,需要在數據量達到一定程度之后,才能夠發揮出並行的優勢,小規模數據集使用CPU就足夠了。有個坑點需要說明的是,MindSpore在CPU和GPU兩者之間的算子和操作等兼容性做的不是很好,很多可以在GPU上面跑的代碼,僅僅切換到CPU版本去運行的話就會報錯。

同范圍數據集驗證

在這個案例中我們假定已經按照這篇博客中的步驟訓練好了模型,並保存成了ckpt文件。前面使用的訓練集是一個如下形式的方程:

\[f(x)=ax^2+b+noise,x\in[-1,1] \]

那么我們首先測試一個相同自變量范圍的函數,作為測試集:

\[f(x)=ax^2+b,x\in[-1,1] \]

因為是測試集,所以這里我們暫時先去掉了\(noise\)這一項,對應的代碼如下:

# load_model.py

from mindspore import context
context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
import mindspore.dataset as ds
from mindspore import load_checkpoint, load_param_into_net
from mindspore import nn, Tensor, Model
from mindspore.train.callback import Callback, LossMonitor
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):
        x = self.fc(x)
        return x

net = LinearNet()
net.set_train(False)
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={"loss"})

def get_data(num, a=2.0, b=3.0): # 與訓練模型相同格式
    for _ in range(num):
        x = np.random.uniform(-1.0, 1.0)
        z = a * x ** 2 + b
        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 = 160 # 測試集規模一般小於訓練集
batch_number = 1
repeat_number = 1

ds_valid = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number) # 生成測試集

acc = model.eval(ds_valid, dataset_sink_mode=False) # 模型驗證
print (acc)

需要注意的一點是,這里我們為了驗證模型的准確性,model的metrics選用了loss這一方法,還有很多其他方法比如accuracy等可以應用於其他場景。相對應的docker容器啟動指令如下:

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"
[WARNING] DEBUG(1,python):2021-05-18-03:25:53.600.802 [mindspore/ccsrc/debug/debugger/debugger.cc:80] Debugger] Not enabling debugger. Debugger does not support CPU.
{'loss': 0.0029351555945297037}

打印出來的是一個字典格式的loss值,這個值的計算方法為:

\[loss=\frac{\sum_n\left(f(x_i)-net(x_i)\right)^2}{n} \]

計算的結果是誤差平方的平均值,這里在相同范圍內的測試集的損失值為0.0029,還是一個相對比較好的結果。

擴大范圍數據集驗證

如果我們想推廣這個范圍,因為我們知道一個原始的模型一般都是具有比較好的普適性的,但是訓練出來的神經網絡很大程度上會收到訓練集的影響。讓我們直接看這樣的一個例子:

\[f(x)=ax^2+b,x\in[-10,10] \]

在這個新的測試集生成模型中,我們只是把原本的\([-1,1]\)的范圍改成了\([-10,10]\)的范圍。對應的代碼如下所示:

# load_model.py

from mindspore import context
context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
import mindspore.dataset as ds
from mindspore import load_checkpoint, load_param_into_net
from mindspore import nn, Tensor, Model
from mindspore.train.callback import Callback, LossMonitor
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):
        x = self.fc(x)
        return x

net = LinearNet()
net.set_train(False)
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={"loss"})

def get_data(num, a=2.0, b=3.0):
    for _ in range(num):
        x = np.random.uniform(-10.0, 10.0)
        z = a * x ** 2 + b
        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 = 160
batch_number = 1
repeat_number = 1

ds_valid = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)

acc = model.eval(ds_valid, dataset_sink_mode=False)
print (acc)

同樣的,用docker的方式拉起運行:

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"
[WARNING] DEBUG(1,python):2021-05-18-03:26:29.528.892 [mindspore/ccsrc/debug/debugger/debugger.cc:80] Debugger] Not enabling debugger. Debugger does not support CPU.
{'loss': 52.90038294600496}

此時我們看到平均的誤差變成了52.9,這個值就比較大了。

總結概要

在這篇文章中,我們接着前面的博客繼續講MindSpore在訓練好機器學習的模型並且保存成文件之后,如何加載並使用測試集加以驗證。從測試結果中我們得到的啟發是,機器學習的模型的有效性會很大程度上收到訓練集的影響,因此最好是能夠保障訓練集的廣泛性。如果測試集的范圍大大超出了訓練集所能夠表示的范圍,那么訓練的模型誤差就會很大。

版權聲明

本文首發鏈接為:https://www.cnblogs.com/dechinphy/p/valid.html
作者ID:DechinPhy
更多原著文章請參考:https://www.cnblogs.com/dechinphy/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM