MindSpore第六期两日集训营】MindSpore控制流作业记录

网友投稿 454 2022-05-29

【MindSpore第六期两日集训营】于2021年11月6日到11月7日在B站拉开了帷幕,错过直播 https://live.bilibili.com/22127570 的老铁们别忘了还有录播,链接分别为:

第一天:

第六期两日集训营 | MindSpore AI电磁仿真 https://www.bilibili.com/video/BV1Y34y1Z7E8?spm_id_from=333.999.0.0

第六期两日集训营 | MindSpore并行使能大模型训练 https://www.bilibili.com/video/BV193411b7on?spm_id_from=333.999.0.0

第六期两日集训营 | MindSpore Boost,让你的训练变得飞快 https://www.bilibili.com/video/BV1c341187ML?spm_id_from=333.999.0.0

第二天:

第六期两日集训营 | MindSpore 控制流概述 https://www.bilibili.com/video/BV1A34y1d7G7?spm_id_from=333.999.0.0

第六期两日集训营 | MindSpore Lite1.5特性发布,带来全新端侧AI体验 https://www.bilibili.com/video/BV1f34y1o7mR?spm_id_from=333.999.0.0

第六期两日集训营 | 可视化集群调优重磅发布,从LeNet到盘古大模型都能调优 https://www.bilibili.com/video/BV1dg411K7Nb?spm_id_from=333.999.0.0

我们来看第二天第一讲:MindSpore 控制流概述

作业如下:

作业思路:

1.先看看如果不用控制流,Python本身应该怎么做这个题目。

2.看看如何能启动MindSpore控制流。

3.将Python相关代码放入MindSpore控制流的建立方式中,实现相关功能。

张小白的解题思路:

递归的话,看一下0~1000的累加求和,相当于实现满足两种要求:

n>=1时:

f(n)=f(n-1)+n

n=0时:

f(n)=0

其实从0开始加和从1开始加都一样。所以题目即可以从0开始算,也可以从1开始算。

先用Python实现一个简单的递归:

vi python_recursion_01.py

def f(n): if n == 0: return 0 else: return f(n-1) + n sum = f(100) print(sum)

执行一下:

python python_recursion_01.py

貌似没啥问题。

改成1000试试:

不行了。

因为Python3缺省的递归最大数为998,所以执行后直接报错。

我们试一下:

确实如此,但是有一种方法提高堆栈的最大值:

在代码中加入以下代码:

import sys sys.setrecursionlimit(20000)

这个20000是张小白自己设置的。越大估计越占内存吧。

不如再改为10000试试:

也不用再往上试了。按理说这样子就可以迁移到控制流里面了。

听了老师的控制流视频后,

也可以再看看官网介绍的文档 https://www.mindspore.cn/docs/programming_guide/zh-CN/r1.5/control_flow.html

因为MindSpore默认的模式为GRAPH_MODE模式,所以直接按照示例来写代码就可以直接用到MindSpore控制流了。

我们来依葫芦画瓢一下:

看示例,首先要在网络中生成控制流算子。所以需要按下图示例使用MindSpore特有的方式建立一个SingleIfNet的网络:

我们如法炮制:

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)

当然在这种情况下,我们需要进入mindspore1.5-gpu的conda 环境,运行一下:

加到100没问题,那加到10000呢?

看样子是没啥问题。

前面张小白的代码要解释一下,原来代码中使用0,1这些整型数进行比较,但是由于现在是进行控制流计算,所以直接比较整型和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的比较。

其实如果这样实现的话,那么while循环的实现反而简单了。

先看一下纯Python怎么做。

vi python_while.py

【MindSpore第六期两日集训营】MindSpore控制流作业记录

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试试:

都没啥问题。

那么就继续改造成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)

执行一下:

python python_while_02.py

改成 普通python能计算的100万,看来mindspore控制流计算得比较吃力。

不过它算出来了:

而且似乎算错了,好像是溢出了——32位操作系统int类型的最大值是 2147483647,一共10位。

100万的计算结果,是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))

执行一下代码,好像确实没问题。

那么能不能将其改造到MindSpore里面去呢。。。

按照 @Chameleon 老师 的提示,“定义一个函数f。然后f进行递归,在construct里去调用这个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控制流的用法通过递归和非递归的例子,大家应该都能了解了吧。如果大家还有兴趣了解一下控制流是怎么做出来了,可以再听听视频,或者看看MIndSpore的源代码。MindSpore是开源的项目,你想看到的东西应该都能看到,就看你有没有心思去找了。

MindSpore代码仓:https://gitee.com/mindspore/mindspore.git

MindSpore官网:https://mindspore.cn

(全文完,谢谢阅读)

MindSpore Python

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:TL8168-EVM开发板规格书
下一篇:2020 年最全 Python 面试题汇总 (四)
相关文章