【MindSpore第六期兩日集訓(xùn)營】MindSpore控制流作業(yè)記錄
【MindSpore第六期兩日集訓(xùn)營】于2021年11月6日到11月7日在B站拉開了帷幕,錯過直播?https://live.bilibili.com/22127570?的老鐵們別忘了還有錄播,鏈接分別為:
第一天:
第六期兩日集訓(xùn)營 | MindSpore AI電磁仿真?https://www.bilibili.com/video/BV1Y34y1Z7E8?spm_id_from=333.999.0.0
第六期兩日集訓(xùn)營 | MindSpore并行使能大模型訓(xùn)練?https://www.bilibili.com/video/BV193411b7on?spm_id_from=333.999.0.0
第六期兩日集訓(xùn)營 | MindSpore Boost,讓你的訓(xùn)練變得飛快?https://www.bilibili.com/video/BV1c341187ML?spm_id_from=333.999.0.0
第二天:
第六期兩日集訓(xùn)營 | MindSpore 控制流概述?https://www.bilibili.com/video/BV1A34y1d7G7?spm_id_from=333.999.0.0
第六期兩日集訓(xùn)營 | MindSpore Lite1.5特性發(fā)布,帶來全新端側(cè)AI體驗?https://www.bilibili.com/video/BV1f34y1o7mR?spm_id_from=333.999.0.0
第六期兩日集訓(xùn)營 | 可視化集群調(diào)優(yōu)重磅發(fā)布,從LeNet到盤古大模型都能調(diào)優(yōu)?https://www.bilibili.com/video/BV1dg411K7Nb?spm_id_from=333.999.0.0
我們來看第二天第一講:MindSpore 控制流概述
作業(yè)如下:
作業(yè)思路:
1.先看看如果不用控制流,Python本身應(yīng)該怎么做這個題目。
2.看看如何能啟動MindSpore控制流。
3.將Python相關(guān)代碼放入MindSpore控制流的建立方式中,實現(xiàn)相關(guān)功能。
張小白的解題思路:
遞歸的話,看一下0~1000的累加求和,相當(dāng)于實現(xiàn)滿足兩種要求:
n>=1時:
f(n)=f(n-1)+n
n=0時:
f(n)=0
其實從0開始加和從1開始加都一樣。所以題目即可以從0開始算,也可以從1開始算。
先用Python實現(xiàn)一個簡單的遞歸:
vi python_recursion_01.py
def f(n): if n == 0: return 0 else: return f(n-1) + n sum = f(100) print(sum)
執(zhí)行一下:
python python_recursion_01.py
貌似沒啥問題。
改成1000試試:
不行了。
因為Python3缺省的遞歸最大數(shù)為998,所以執(zhí)行后直接報錯。
我們試一下:
確實如此,但是有一種方法提高堆棧的最大值:
在代碼中加入以下代碼:
import sys sys.setrecursionlimit(20000)
這個20000是張小白自己設(shè)置的。越大估計越占內(nèi)存吧。
不如再改為10000試試:
也不用再往上試了。按理說這樣子就可以遷移到控制流里面了。
聽了老師的控制流視頻后,
也可以再看看官網(wǎng)介紹的文檔?https://www.mindspore.cn/docs/programming_guide/zh-CN/r1.5/control_flow.html
因為MindSpore默認的模式為GRAPH_MODE模式,所以直接按照示例來寫代碼就可以直接用到MindSpore控制流了。
我們來依葫蘆畫瓢一下:
看示例,首先要在網(wǎng)絡(luò)中生成控制流算子。所以需要按下圖示例使用MindSpore特有的方式建立一個SingleIfNet的網(wǎng)絡(luò):
我們?nèi)绶ㄅ谥疲?/p>
vi python_recursion_02.py
import numpy as np from mindspore import context from mindspore import Tensor, nn from mindspore import dtype as ms import sys sys.setrecursionlimit(20000) zero = Tensor(np.array(0), dtype=ms.int32) one = Tensor(np.array(1), dtype=ms.int32) count = Tensor(np.array(100), dtype=ms.int32) class SingleIfNet(nn.Cell): def construct(self, n): if n == zero: return zero else: return self.construct( n - one ) + n forward_net = SingleIfNet() output = forward_net(count) print (output)
當(dāng)然在這種情況下,我們需要進入mindspore1.5-gpu的conda 環(huán)境,運行一下:
加到100沒問題,那加到10000呢?
看樣子是沒啥問題。
前面張小白的代碼要解釋一下,原來代碼中使用0,1這些整型數(shù)進行比較,但是由于現(xiàn)在是進行控制流計算,所以直接比較整型和tensor是不行的。需要把整型換成tensor(張量)來比較。
所以張小白才定義了
zero = Tensor(np.array(0), dtype=ms.int32) one = Tensor(np.array(1), dtype=ms.int32) count = Tensor(np.array(100), dtype=ms.int32)
這幾個值,然后 所謂的0,1,count比較也是變量跟這些tensor的比較。
其實如果這樣實現(xiàn)的話,那么while循環(huán)的實現(xiàn)反而簡單了。
先看一下純Python怎么做。
vi python_while.py
def f(n): x = 0 out = 0 while x < n: x = x + 1 out = out + x return out sum = f(100) print(sum)
改成10000,1000000試試:
都沒啥問題。
那么就繼續(xù)改造成MindSpore控制流的方式:
vi python_while_02.py
import numpy as np from mindspore import context from mindspore import Tensor, nn from mindspore import dtype as ms import sys sys.setrecursionlimit(20000) zero = Tensor(np.array(0), dtype=ms.int32) one = Tensor(np.array(1), dtype=ms.int32) count = Tensor(np.array(100), dtype=ms.int32) class SingleIfNet(nn.Cell): def construct(self, n): x = zero out = zero while x < n: x = x + 1 out = out + x return out forward_net = SingleIfNet() output = forward_net(count) print (output)
執(zhí)行一下:
python python_while_02.py
改成 普通python能計算的100萬,看來mindspore控制流計算得比較吃力。
不過它算出來了:
而且似乎算錯了,好像是溢出了——32位操作系統(tǒng)int類型的最大值是 2147483647,一共10位。
100萬的計算結(jié)果,是500000500000,一共12位。
顯然溢出了。
那只有改成int64:
cat python_while_03.py
python python_while_03.py
改成這樣就沒問題了。
張小白覺得前面maxdepth的顯示非常得讓人惱火。張小白也搜索到一些方式,比如尾遞歸的方法。
張小白找到了這篇:
https://blog.csdn.net/fall_song/article/details/106732276
先試試這篇好不好使:
vi python_recursion_03.py
import types def f_recursive(cur_i, cur_computer_result=1): if cur_i == 1: yield cur_computer_result yield f_recursive(cur_i - 1, cur_i + cur_computer_result) def f_recursive_wapper(generator, i): gen = generator(i) while isinstance(gen, types.GeneratorType): gen = gen.__next__() return gen print(f_recursive_wapper(f_recursive,10000))
執(zhí)行一下代碼,好像確實沒問題。
那么能不能將其改造到MindSpore里面去呢。。。
按照 @Chameleon?老師 的提示,“定義一個函數(shù)f。然后f進行遞歸,在construct里去調(diào)用這個f”,我們來試試:
import types import numpy as np from mindspore import context from mindspore import Tensor, nn from mindspore import dtype as ms zero = Tensor(np.array(0), dtype=ms.int32) one = Tensor(np.array(1), dtype=ms.int32) count = Tensor(np.array(10000), dtype=ms.int32) count0 = 10000 def f_recursive(cur_i, cur_computer_result=one): if cur_i == one: yield cur_computer_result yield f_recursive(cur_i - one, cur_i + cur_computer_result) def f_recursive_wapper(generator, i): gen = generator(i) while isinstance(gen, types.GeneratorType): gen = gen.__next__() return gen output0 = f_recursive_wapper(f_recursive,count0) print(output0) class SingleIfNet(nn.Cell): def construct(self,n): out = f_recursive_wapper(f_recursive,n) return out forward_net = SingleIfNet() output = forward_net( count ) print (output)
python python_recursion_04.py
原生的方法輸出的output0出來了。
但是mindspore控制流的方式報不支持yield.
也問了老師,說目前MindSpore控制流確實不支持yield語法。
張小白又找到一篇更高大上的做法:
https://zhuanlan.zhihu.com/p/37060182
不過這個改造成mindspore控制流方式估計難度更大。
好了,先不試驗了。綜上,MindSpore控制流的用法通過遞歸和非遞歸的例子,大家應(yīng)該都能了解了吧。如果大家還有興趣了解一下控制流是怎么做出來了,可以再聽聽視頻,或者看看MIndSpore的源代碼。MindSpore是開源的項目,你想看到的東西應(yīng)該都能看到,就看你有沒有心思去找了。
MindSpore代碼倉:https://gitee.com/mindspore/mindspore.git
MindSpore官網(wǎng):https://mindspore.cn
(全文完,謝謝閱讀)
MindSpore Python
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。