网络参数
MindSpore提供了关于变量、网络相关参数的初始化模块,用户可以通过封装算子来调用字符串、Initializer子类或自定义Tensor等方式完成对网络参数进行初始化。
下面图中蓝色表示具体的执行算子,绿色的表示张量Tensor,张量作为神经网络模型中的数据在网络中不断流动,主要包括网络模型的数据输入,算子的输入输出数据等;红色的为变量Parameter,作为网络模型或者模型中算子的属性,及其反向图中产生的中间变量和临时变量。
本章主要介绍数据类型dtype
、变量Parameter
、变量元组ParameterTuple
、网络的初始化方法和网络参数更新。
数据类型 dtype
MindSpore张量支持不同的数据类型dtype
,包含int8、int16、int32、int64、uint8、uint16、uint32、uint64、float16、float32、float64、bool_,与NumPy的数据类型一一对应。详见 mindspore.dtype。
在MindSpore的运算处理流程中,Python中的int数会被转换为定义的int64类型,float数会被转换为定义的float32类型。
以下代码,打印MindSpore的数据类型int32。
[1]:
import mindspore as ms
data_type = ms.int32
print(data_type)
Int32
数据类型转换接口
MindSpore提供了以下几个接口,实现与NumPy数据类型和Python内置的数据类型间的转换。
dtype_to_nptype
:将MindSpore的数据类型转换为NumPy对应的数据类型。dtype_to_pytype
:将MindSpore的数据类型转换为Python对应的内置数据类型。pytype_to_dtype
:将Python内置的数据类型转换为MindSpore对应的数据类型。
以下代码实现了不同数据类型间的转换,并打印转换后的类型。
[2]:
import mindspore as ms
np_type = ms.dtype_to_nptype(ms.int32)
ms_type = ms.pytype_to_dtype(int)
py_type = ms.dtype_to_pytype(ms.float64)
print(np_type)
print(ms_type)
print(py_type)
<class 'numpy.int32'>
Int64
<class 'float'>
变量 Parameter
MindSpore的变量(Parameter)表示在网络训练时,需要被更新的参数。例如,在前行计算的时候最常见的nn.conv
算子的变量有权重weight
和偏置bias
;在构建反向图和反向传播计算的时候,会产生很多中间变量,用于暂存一阶梯度信息、中间输出值等。
变量初始化
变量Parameter
的初始化方法有很多种,可以接收Tensor
、Initializer
等不同的数据类型。
default_input
:为输入数据,支持传入Tensor
、Initializer
、int
和float
四种数据类型;name
:可设置变量的名称,用于在网络中区别于其他变量;requires_grad
:表示在网络训练过程,是否需要计算参数梯度,如果不需要计算参数梯度,将requires_grad
设置为False
。
下面的示例代码中,使用int
或float
数据类型直接创建Parameter:
[1]:
import mindspore as ms
x = ms.Parameter(default_input=2.0, name='x')
y = ms.Parameter(default_input=5.0, name='y')
z = ms.Parameter(default_input=5, name='z', requires_grad=False)
print(type(x))
print(x, "value:", x.asnumpy())
print(y, "value:", y.asnumpy())
print(z, "value:", z.asnumpy())
<class 'mindspore.common.parameter.ParameterTensor'>
Parameter (name=x, shape=(), dtype=Float32, requires_grad=True) value: 2.0
Parameter (name=y, shape=(), dtype=Float32, requires_grad=True) value: 5.0
Parameter (name=z, shape=(), dtype=Int32, requires_grad=False) value: 5
下面示例代码中,使用MindSpore的张量Tensor
创建Parameter:
[2]:
import numpy as np
import mindspore as ms
my_tensor = ms.Tensor(np.arange(2 * 3).reshape((2, 3)))
x = ms.Parameter(default_input=my_tensor, name="tensor")
print(x)
Parameter (name=tensor, shape=(2, 3), dtype=Int64, requires_grad=True)
下面示例代码中,使用Initializer
创建Parameter:
[6]:
from mindspore.common.initializer import initializer as init
import mindspore as ms
x = ms.Parameter(default_input=init('ones', [1, 2, 3], ms.float32), name='x')
print(x)
Parameter (name=x, shape=(1, 2, 3), dtype=Float32, requires_grad=True)
属性
变量Parameter
的默认属性有变量名称name
、形状shape
、数据类型dtype
和是否需要进行求导requires_grad
。
下例通过Tensor
初始化一个变量Parameter
,并获取变量Parameter
的相关属性。示例代码如下:
[4]:
my_tensor = ms.Tensor(np.arange(2 * 3).reshape((2, 3)))
x = ms.Parameter(default_input=my_tensor, name="x")
print("x: ", x)
print("x.data: ", x.data)
x: Parameter (name=x, shape=(2, 3), dtype=Int64, requires_grad=True)
x.data: Parameter (name=x, shape=(2, 3), dtype=Int64, requires_grad=True)
变量操作
clone
:克隆变量张量Parameter
,克隆完成后可以给新的变量Parameter
指定新的名称。
[9]:
x = ms.Parameter(default_input=init('ones', [1, 2, 3], ms.float32))
x_clone = x.clone()
x_clone.name = "x_clone"
print(x)
print(x_clone)
Parameter (name=Parameter, shape=(1, 2, 3), dtype=Float32, requires_grad=True)
Parameter (name=x_clone, shape=(1, 2, 3), dtype=Float32, requires_grad=True)
set_data
:修改变量Parameter
的数据或形状shape
。
其中,set_data
方法有data
和slice_shape
两种入参。data
表示变量Parameter
新传入的数据;slice_shape
表示是否修改变量Parameter
的形状shape
,默认为False。
[11]:
x = ms.Parameter(ms.Tensor(np.ones((1, 2)), ms.float32), name="x", requires_grad=True)
print(x, x.asnumpy())
y = x.set_data(ms.Tensor(np.zeros((1, 2)), ms.float32))
print(y, y.asnumpy())
z = x.set_data(ms.Tensor(np.ones((1, 4)), ms.float32), slice_shape=True)
print(z, z.asnumpy())
Parameter (name=x, shape=(1, 2), dtype=Float32, requires_grad=True) [[1. 1.]]
Parameter (name=x, shape=(1, 2), dtype=Float32, requires_grad=True) [[0. 0.]]
Parameter (name=x, shape=(1, 4), dtype=Float32, requires_grad=True) [[1. 1. 1. 1.]]
init_data
:并行场景下存在参数的形状发生变化的情况,用户可以调用Parameter
的init_data
方法得到原始数据。
[9]:
x = ms.Parameter(ms.Tensor(np.ones((1, 2)), ms.float32), name="x", requires_grad=True)
print(x.init_data(), x.init_data().asnumpy())
Parameter (name=x, shape=(1, 2), dtype=Float32, requires_grad=True) [[1. 1.]]
变量参数更新
MindSpore提供了网络参数更新功能,使用nn.ParameterUpdate
可对网络参数进行更新,其输入的参数类型必须为张量,且张量shape
需要与原网络参数shape
保持一致。
更新网络的权重参数示例如下:
[14]:
import numpy as np
import mindspore as ms
from mindspore import nn
# 构建网络
network = nn.Dense(3, 4)
# 获取网络的权重参数
param = network.parameters_dict()['weight']
print("Parameter:\n", param.asnumpy())
# 更新权重参数
update = nn.ParameterUpdate(param)
weight = ms.Tensor(np.arange(12).reshape((4, 3)), ms.float32)
output = update(weight)
print("Parameter update:\n", output)
Parameter:
[[-0.0164615 -0.01204428 -0.00813806]
[-0.00270927 -0.0113328 -0.01384139]
[ 0.00849093 0.00351116 0.00989969]
[ 0.00233028 0.00649209 -0.0021333 ]]
Parameter update:
[[ 0. 1. 2.]
[ 3. 4. 5.]
[ 6. 7. 8.]
[ 9. 10. 11.]]
变量元组 Parameter Tuple
变量元组ParameterTuple,用于保存多个Parameter
,继承于元组tuple
,提供克隆功能。
如下示例提供ParameterTuple
创建方法:
[10]:
import numpy as np
import mindspore as ms
from mindspore.common.initializer import initializer
# 创建
x = ms.Parameter(default_input=ms.Tensor(np.arange(2 * 3).reshape((2, 3))), name="x")
y = ms.Parameter(default_input=initializer('ones', [1, 2, 3], ms.float32), name='y')
z = ms.Parameter(default_input=2.0, name='z')
params = ms.ParameterTuple((x, y, z))
# 从params克隆并修改名称为"params_copy"
params_copy = params.clone("params_copy")
print(params)
print(params_copy)
(Parameter (name=x, shape=(2, 3), dtype=Int64, requires_grad=True), Parameter (name=y, shape=(1, 2, 3), dtype=Float32, requires_grad=True), Parameter (name=z, shape=(), dtype=Float32, requires_grad=True))
(Parameter (name=params_copy.x, shape=(2, 3), dtype=Int64, requires_grad=True), Parameter (name=params_copy.y, shape=(1, 2, 3), dtype=Float32, requires_grad=True), Parameter (name=params_copy.z, shape=(), dtype=Float32, requires_grad=True))
网络参数初始化
MindSpore提供了多种网络参数初始化的方式,并在部分算子中封装了参数初始化的功能。本节以Conv2d
算子为例,分别介绍使用Initializer
子类,字符串和自定义Tensor
等方式对网络中的参数进行初始化。
Initializer初始化
使用Initializer
对网络参数进行初始化,示例代码如下:
[11]:
import numpy as np
import mindspore.nn as nn
import mindspore as ms
from mindspore.common import initializer as init
ms.set_seed(1)
input_data = ms.Tensor(np.ones([1, 3, 16, 50], dtype=np.float32))
# 卷积层,输入通道为3,输出通道为64,卷积核大小为3*3,权重参数使用正态分布生成的随机数
net = nn.Conv2d(3, 64, 3, weight_init=init.Normal(0.2))
# 网络输出
output = net(input_data)
字符串初始化
使用字符串对网络参数进行初始化,字符串的内容需要与Initializer
的名称保持一致(字母不区分大小写),使用字符串方式进行初始化将使用Initializer
类中的默认参数。
例如使用字符串Normal
等同于使用Initializer
的Normal()
,示例如下:
[12]:
import numpy as np
import mindspore.nn as nn
import mindspore as ms
ms.set_seed(1)
input_data = ms.Tensor(np.ones([1, 3, 16, 50], dtype=np.float32))
net = nn.Conv2d(3, 64, 3, weight_init='Normal')
output = net(input_data)
张量初始化
用户也可以通过自定义Tensor
的方式,来对网络模型中算子的参数进行初始化,示例代码如下:
[13]:
import numpy as np
import mindspore.nn as nn
import mindspore as ms
init_data = ms.Tensor(np.ones([64, 3, 3, 3]), dtype=ms.float32)
input_data = ms.Tensor(np.ones([1, 3, 16, 50], dtype=np.float32))
net = nn.Conv2d(3, 64, 3, weight_init=init_data)
output = net(input_data)