欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

【mindspore】mindspore實現(xiàn)手寫數字識別-創(chuàng)新互聯(lián)

mindspore實現(xiàn)手寫數字識別

具體流程參考教程:MindSpore快速入門 MindSpore 接口文檔
注:本文章記錄的是我在開發(fā)過程中的學習筆記,僅供參考學習,歡迎討論,但不作為開發(fā)教程使用。

我們擁有10余年網頁設計和網站建設經驗,從網站策劃到網站制作,我們的網頁設計師為您提供的解決方案。為企業(yè)提供成都網站建設、網站建設、微信開發(fā)、重慶小程序開發(fā)成都手機網站制作H5開發(fā)、等業(yè)務。無論您有什么樣的網站設計或者設計方案要求,我們都將富于創(chuàng)造性的提供專業(yè)設計服務并滿足您的需求。數據的流水線處理
def datapipe(dataset, batch_size):
    '''
    數據處理流水線
    '''
    image_transform = [
        vision.Rescale(1.0 / 255.0, 0), # 縮放 output = image * rescale + shift.
        vision.Normalize(mean=(0.1307,), std=(0.3081,)),    # 根據平均值和標準偏差對輸入圖像進行歸一化
        vision.HWC2CHW()    # 轉換為NCHW格式
    ]
    label_transform = transforms.TypeCast(mindspore.int32)  # 轉為mindspore的int32格式

    dataset = dataset.map(image_transform, 'image')     # 對各個圖像按照流水線處理
    dataset = dataset.map(label_transform, 'label')     # 對各個標簽轉換為int32
    dataset = dataset.batch(batch_size)
    return dataset

這段代碼中對輸入圖片進行了縮放、歸一化和格式轉換三個操作,按照流水線運行。

流水線操作

數據流水線處理的介紹:【AI設計模式】03-數據處理-流水線(Pipeline)模式
總結而言,海量數據下,流水線模式可以實現(xiàn)高效的數據處理,當然也會占用更多的CPU和內存資源。

map操作

mindspore下dataset的map操作:第一個參數是處理函數列表,第二個參數是需要處理的列。
map函數會將數據集中第二個參數的指定的列作為輸入,調用第一個參數的處理函數執(zhí)行處理,如果有多個處理函數,上一個函數的輸出作為下一個函數的輸入。

NCHW和NHWC格式的優(yōu)缺點

NCHW
缺點:必須等所有通道輸入準備好才能得到最終輸出結果,需要占用較大的臨時空間。
優(yōu)點:是 Nvidia cuDNN 默認格式,使用 GPU 加速時用 NCHW 格式速度會更快。(這個是什么原因呢?沒找到資料_(:з」∠)_)
NHWC
缺點:GPU 加速較NCHW更慢
優(yōu)點:訪存局部性更好(每三個輸入像素即可得到一個輸出像素)
參考文章:【深度學習框架輸入格式】NCHW還是NHWC?
為什么pytorch中transforms.ToTorch要把(H,W,C)的矩陣轉為(C,H,W)?

模型
class Network(nn.Cell):
    '''
    Network model
    '''
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.dense_relu_sequential = nn.SequentialCell(
            nn.Dense(28*28, 512),
            nn.ReLU(),
            nn.Dense(512, 512),
            nn.ReLU(),
            nn.Dense(512, 10)
        )

    def construct(self, x):
        x = self.flatten(x)
        logits = self.dense_relu_sequential(x)
        return logits
基類

mindspore的模型基類是mindspore.nn.Cell
pytorch的模型基類是torch.nn.Module

全連接層

mindspore的全連接層是mindspore.nn.Dense
pytorch的全連接層是torch.nn.Linear

模型連接

mindspore的順序容器是mindspore.nn.SequentialCell
pytorch的順序容器是torch.nn.Sequential

前向傳播

mindspore的前向傳播函數(要執(zhí)行的計算邏輯)基類函數為construct(self, xxx)
pytorch的前向傳播函數基類函數為forward(self, xxx)

損失函數和優(yōu)化策略
my_loss_fn = nn.CrossEntropyLoss()
my_optimizer = nn.SGD(model.trainable_params(), 1e-2)

交叉熵:把來自一個分布q的消息使用另一個分布p的最佳代碼傳達方式計算得到的平均消息長度,即為交叉熵。針對交叉熵,這個文章講的較好:損失函數:交叉熵詳解

mindspore的交叉熵函數和pytorch類似:
前者是mindspore.nn.CrossEntropyLoss(),后者是torch.nn.CrossEntropyLoss()

訓練
def train(model_train, dataset, loss_fn, optimizer):
    '''
    訓練函數
    '''
    # Define forward function
    def forward_fn(data, label):
        logits = model_train(data)
        loss = loss_fn(logits, label)
        return loss, logits

    # Get gradient function
    grad_fn = ops.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)

    # Define function of one-step training
    def train_step(data, label):
        (loss, _), grads = grad_fn(data, label)
        loss = ops.depend(loss, optimizer(grads))
        return loss

    size = dataset.get_dataset_size()
    model_train.set_train()
    for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):
        loss = train_step(data, label)

        if batch % 100 == 0:
            loss, current = loss.asnumpy(), batch
            print(f"loss: {loss:>7f}  [{current:>3d}/{size:>3d}]")
value_and_grad

官網對value_and_grad函數的介紹如下:mindspore.ops.value_and_grad
按照官網的描述,這個函數的作用是:生成求導函數,用于計算給定函數的正向計算結果和梯度。
我們需要給這個函數傳入模型的正向傳輸函數和待求導的參數
其中模型的正向傳輸函數需要封裝一下,返回loss的計算, 用于后續(xù)優(yōu)化器的梯度計算;
待求導的參數可以寫為model.trainable_params(),也可以由優(yōu)化器提供(optimizer.parameters),因為優(yōu)化器初始化時已經傳入需要求導的參數。
總之,這個接口返回的是一個函數,函數的作用是把正向傳播、反向傳播的整個流程走一遍,最后的輸出為正向傳輸函數的返回值+待求導參數的梯度值

depend算子

在訓練時使用到了depend算子,官網對Depend函數的介紹如下:mindspore.ops.Depend

# Define function of one-step training
    def train_step(data, label):
        (loss, _), grads = grad_fn(data, label)
        loss = ops.depend(loss, optimizer(grads))
        return loss

經詢問分析,使用depend算子的原因是,在靜態(tài)圖模式下,函數執(zhí)行的先后順序可能會被優(yōu)化,這就可能存在loss在grad_fn(value_and_grad)之前就被返回使用的情況,導致返回的loss不正確。
因此通過使用depend算子,來保證loss的返回動作在optimizer之后執(zhí)行,而optimizer的輸入依賴grad_fn,因此optimizer一定在grad_fn之后執(zhí)行,這就保證了depend返回的loss確實是經過grad_fn計算的最新結果。
當然,mindspore也是支持動態(tài)圖模式的,只需加一行代碼:

# 設置為動態(tài)圖模式
mindspore.set_context(mode=mindspore.PYNATIVE_MODE)
# 設置為靜態(tài)圖模式
# mindspore.set_context(mode=mindspore.GRAPH_MODE)

model = Network()
print(model)

然后訓練函數就可以這么寫:

def train_step(data, label):
    (loss, _), grads = grad_fn(data, label)
    optimizer(grads)
    return loss

但是實測,動態(tài)圖模式下,訓練速度相比靜態(tài)圖慢了很多。
關于mindspore動態(tài)圖和靜態(tài)圖模式的介紹,可看這個官方文檔:動靜態(tài)圖

訓練尺寸

各個文章在介紹梯度下降法時,通常介紹的是批量梯度下降法,但是訓練模型時用的最多的是小批量梯度下降法。這里先講下批量梯度下降、隨機梯度下降和小批量梯度下降的區(qū)別。

批量梯度下降

批量梯度下降法的流程是:假設有1000個數據,經過正向計算,得到1000個計算結果,誤差函數的計算公式依賴這1000個計算結果;再對誤差函數進行反向傳播求導,得到模型里參數的梯度值;同樣地,對誤差函數求導得梯度,也依賴這1000個計算結果;最后基于學習率更新參數,然后進入下一輪訓練。
因此,標準的批量梯度下降,需要每次計算出1000個數據的正向傳播結果,才可以得到參數梯度值,然后下一輪訓練,重新計算1000個計算結果…這就存在大量的運算量,使得訓練容易變得非常耗時。
梯度下降

隨機梯度下降

隨機梯度下降法的流程是,假設有1000個數據,我們隨機取1個數據,經過正向計算,得到1個計算結果,誤差函數的計算公式就只依賴這1個計算結果;然后反向傳播求導,得到基于1個計算結果的梯度值,最后基于學習率更新參數,然后進入下一輪訓練。下一輪訓練時,隨機取另1個數據,重復上述操作…
這種方法下,極大地降低了計算量,而且理論上,只要數據量夠大,數據足夠隨機,最后也總會下降到所需極值點,畢竟計算數據量小了很多,算得更快了,下降速度也會快很多。但是每次只依賴1個數據,就使得梯度的下降方向在整體方向上不穩(wěn)定,容易到處飄,最后的結果可能不會是全局最優(yōu)。
隨機梯度下降

小批量梯度下降

小批量梯度下降法的流程是:假設有1000個數據,我們隨機取100個數據,經過正向計算,得到100個計算結果,誤差函數的計算公式依賴這100個計算結果;然后反向傳播求導,得到基于100個計算結果的梯度值,最后基于學習率更新參數,然后進入下一輪訓練。下一輪訓練時,隨機取另100個數據,重復上述操作…
可以看出,小批量梯度下降 結合了 批量梯度下降 和 隨機梯度下降 的優(yōu)缺點,使得計算即不那么耗時,又保證參數更新路徑和結果相對穩(wěn)定。

實例

mindspore的這個例子用的是小批量梯度下降,train_step每次輸入64個數據,然后前向傳播、計算梯度、更新參數,再進入下一個epoch,隨機取新的64個數據,重復訓練…

size = dataset.get_dataset_size()
model_train.set_train()
for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):
    loss = train_step(data, label)
    if batch % 100 == 0:
        loss, current = loss.asnumpy(), batch
        print(f"loss: {loss:>7f}  [{current:>3d}/{size:>3d}]")

在將數據集進行datapipe后,返回的train_dataset和test_dataset都是以batch_size=64個為一組進行輸出的,此處dataset.get_dataset_size()返回的size是有多少組數據。測試集返回的size為938,表示一共有938組,每組64個圖片數據。實際上MNIST只有60000個測試集圖片,因此最后一組只有32個圖片。

運行結果
Epoch 1
-------------------------------
loss: 2.303684  [  0/938]
loss: 2.291476  [100/938]
loss: 2.273411  [200/938]
loss: 2.212310  [300/938]
loss: 1.969760  [400/938]
loss: 1.600426  [500/938]
loss: 1.004380  [600/938]
loss: 0.735266  [700/938]
loss: 0.672223  [800/938]
loss: 0.578563  [900/938]
Test: 
 Accuracy: 85.3%, Avg loss: 0.528851

Epoch 2
-------------------------------
loss: 0.384008  [  0/938]
loss: 0.453575  [100/938]
loss: 0.277697  [200/938]
loss: 0.317674  [300/938]
loss: 0.294471  [400/938]
loss: 0.519272  [500/938]
loss: 0.253794  [600/938]
loss: 0.389252  [700/938]
loss: 0.383196  [800/938]
loss: 0.334877  [900/938]
Test: 
 Accuracy: 90.2%, Avg loss: 0.334850

此處跑了兩輪訓練,可以看出,第一輪的938組數據的訓練過程中,參數快速調整至合理范圍(loss從2.3降低到0.5),但是第二輪的938組數據的訓練過程中,loss出現(xiàn)了上下波動(0.3->0.4->0.2->0.3…),即模型參數向當前數據組的梯度下降的方向走了一小步后,新的數據組算出的loss反而比之前還提高了。
這主要是因為當前數據組的梯度下降方向 無法代表 替他數據組/所有數據的梯度下降方向,當然也可能是學習率(步長)太大導致跨過了最低點,這個就具體問題具體分析了。

總結

mindspore和pytorch在接口命名上存在區(qū)別,但是實際使用過程中,開發(fā)思路還是一致的。因此最關鍵的還是要熟悉深度學習的思路和流程,至于思路和代碼實現(xiàn)的映射,這就唯手熟爾。

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧

當前題目:【mindspore】mindspore實現(xiàn)手寫數字識別-創(chuàng)新互聯(lián)
網頁路徑:http://chinadenli.net/article40/gdsho.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供自適應網站商城網站ChatGPT微信小程序品牌網站設計面包屑導航

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

網站托管運營