网络构建
神经网络模型由tensor操作和神经网络层构成。
MIndSporezhong,Cell是构建所有网络的基类,也是网络的基本单元。cell也由子cell构成。
定义模型类
# 继承nn.Cell类
class Network(nn.Cell):def __init__(self):super().__init__()self.flatten = nn.Flatten()self.dense_relu_sequential = nn.SequentialCell(nn.Dense(28*28, 512, weight_init="normal", bias_init="zeros"),nn.ReLU(),nn.Dense(512, 512, weight_init="normal", bias_init="zeros"),nn.ReLU(),nn.Dense(512, 10, weight_init="normal", bias_init="zeros"))# 构建神经网络def construct(self, x):x = self.flatten(x)logits = self.dense_relu_sequential(x)return logits# 实例化Network
model = Network()
这个网络的结构是
Flatten层:将输入的二维图像(28x28)展开成一维向量(784)。这一层是必要的,因为全连接层(Dense层)只能接受一维的输入。
Dense-ReLU 序列:
第一层 Dense(28*28, 512),将长度784的输入映射到512。正态分布初始化的权重和零初始化的偏置
一层 ReLU激活函数,添加非线性,使网络能够学习到复杂的模式。
第二层:Dense(512, 512),将长度512的输入映射到另一个512。
ReLU激活函数:再次添加非线性。
第三层:Dense(512, 10),将长度512的输入映射到10的输出。这里的10代表了分类任务中的10个类别(例如,数字0到9)。
由此可以得到这个网络的输入是28*28,输出是10。
使用模型预测
构建一个28*28的全一数据,输入模型得到模型的10维输出。
X = ops.ones((1, 28, 28), mindspore.float32)
logits = model(X)
logits 的输出结果
Tensor(shape=[1, 10], dtype=Float32, value= [[-3.85994534e-03,
1.12577295e-03, -5.73400781e-03 … 3.27425171e-03, -2.65434897e-03, 2.91853398e-03]])
再增加一个softmax层来获取预测概率。softmax可以将每个类别的输出值映射到0-1之间的概率值,所有类别加起来的总和为1.
pred_probab = nn.Softmax(axis=1)(logits)
y_pred = pred_probab.argmax(1)
argmax(1) 找到 pred_probab 中概率最大的索引,也就是网络最终预测的一个具体类别。
模型层具体分析
这里还是由构建数据开始,构建一个shape为(3, 28, 28)的随机数据(3个28x28的图像)
input_image = ops.ones((3, 28, 28), mindspore.float32)
nn.Flatten
flatten = nn.Flatten()
flat_image = flatten(input_image)
把输入的32828压扁(flatten)之后,flat_image的尺寸变成了3*784,也就是二维变一维。
nn.Dense
创建一个输入28*28,输出为20的全连接层。
layer1 = nn.Dense(in_channels=28*28, out_channels=20)
hidden1 = layer1(flat_image)
将上述flatten过后的数据输入该层后,得到的形状是(3,20)
nn.ReLU
给网络中加入非线性的激活函数,帮助神经网络学习各种复杂的特征。
hidden1 = nn.ReLU()(hidden1)
nn.SequentialCell
nn.SequentialCell是一个有序的Cell容器。有序指输入的Tensor会根据定义的顺序通过所有Cell
seq_modules = nn.SequentialCell(flatten,layer1,nn.ReLU(),nn.Dense(20, 10)
)logits = seq_modules(input_image)
这里定义了一个包含flatten,之前定义全连接层,激活函数,新的长度20转10的全连接层。将我们的数据输入,会得到(3,10)向量。
nn.Softmax
在最后加入一个softmax将输出缩放到0-1
softmax = nn.Softmax(axis=1)
pred_probab = softmax(logits)
axis指输出的各个类别的数据和为1
模型参数
在前文中看到dense定义中可以定义bias和weight。这些参数会在训练中不断得到优化。
for name, param in model.parameters_and_names():print(f"Layer: {name}\nSize: {param.shape}\nValues : {param[:2]} \n")
使用parameters_and_names()查看参数名和参数详情。可以看到每一层的情况。
Layer: dense_relu_sequential.0.weight
Size: (512, 784) Values : [[ 0.00794508 0.00425111 -0.01005943 …
0.00410124 -0.00289778 -0.00012033] [-0.00127386 -0.01262395 0.0012368 … 0.00155892 -0.01996486
0.00456555]]Layer: dense_relu_sequential.0.bias Size: (512,) Values : [0. 0.]
Layer: dense_relu_sequential.2.weight Size: (512, 512) Values :
[[-0.00016954 0.00101638 0.00625031 … -0.01277918 0.01667405
0.01246558] [ 0.00640481 -0.00602338 0.01730538 … 0.00377386 -0.01358849 -0.00035654]]Layer: dense_relu_sequential.2.bias Size: (512,) Values : [0. 0.]
Layer: dense_relu_sequential.4.weight Size: (10, 512) Values :
[[-0.01012482 0.0130543 0.0018377 … 0.01546062 0.00060095
0.01009192] [-0.0025501 0.01740856 -0.00141961 … -0.01067028 -0.00205624
0.01058894]]Layer: dense_relu_sequential.4.bias Size: (10,) Values : [0. 0.]
1,3层是relu函数。因此没有参数输出。
总结
本章介绍了搭建神经网络的整体流程,对每一层如何使用及实现进行了详细阐述。