diff --git a/tutorials/source_zh_cn/advanced_use/deep_probability_program.md b/tutorials/source_zh_cn/advanced_use/deep_probability_program.md
index 13e92b1452da668a0c9f9632c0bcbf307681ff9c..9b7bcdb89ec197de2dda15716206c6faf7c98ad2 100644
--- a/tutorials/source_zh_cn/advanced_use/deep_probability_program.md
+++ b/tutorials/source_zh_cn/advanced_use/deep_probability_program.md
@@ -5,11 +5,11 @@
- [深度概率编程](#深度概率编程)
- [概述](#概述)
- - [贝叶斯神经网络](#贝叶斯神经网络)
+ - [使用贝叶斯神经网络](#使用贝叶斯神经网络)
- [处理数据集](#处理数据集)
- [定义损失函数和优化器](#定义损失函数和优化器)
- [训练网络](#训练网络)
- - [变分推断](#变分推断)
+ - [使用变分自编码器](#使用变分自编码器)
- [定义变分自编码器](#定义变分自编码器)
- [定义损失函数和优化器](#定义损失函数和优化器)
- [处理数据](#处理数据)
@@ -17,29 +17,37 @@
- [DNN一键转换成BNN](#DNN一键转换成BNN)
- [定义DNN模型](#定义DNN模型)
- [定义损失函数和优化器](#定义损失函数和优化器)
- - [功能一:转换整个模型](#功能一:转换整个模型)
- - [功能二:转换指定类型的层](#功能二:转换指定类型的层)
- - [不确定性估计](#不确定性估计)
+ - [实现功能一:转换整个模型](#实现功能一:转换整个模型)
+ - [实现功能二:转换指定类型的层](#实现功能二:转换指定类型的层)
+ - [使用不确定性估计工具箱](#使用不确定性估计工具箱)
-## 概述
-MindSpore深度概率编程(MindSpore Deep Probabilistic Programming, MDP)的目标是将深度学习和贝叶斯学习结合,并能面向不同的开发者。具体来说,对于专业的贝叶斯学习用户,提供概率采样、推理算法和模型构建库;另一方面,为不熟悉贝叶斯深度学习的用户提供了高级的API,从而不用更改深度学习编程逻辑,即可利用贝叶斯模型。
-
-本章将详细介绍深度概率编程在MindSpore上的应用。
+
-### 贝叶斯神经网络
-本例子利用贝叶斯神经网络实现一个简单的图片分类功能,整体流程如下:
-1. 处理MNIST数据集。
-2. 定义贝叶斯LeNet网络。
-3. 定义损失函数和优化器。
+## 概述
+深度学习模型具有强大的拟合能力,而贝叶斯理论具有很好的可解释能力。深度概率编程将深度学习和贝叶斯学习结合,通过设置网络权重为分布、引入隐空间分布等,可以对分布进行采样前向传播,由此引入了不确定性。因此,增强了模型的鲁棒性和可解释性。但是,业界主流的框架,比如基于TensorFlow的TFP和基于PyTorch的Pyro,都存在着对深度学习用户不友好的问题。其API的设计比较专业化,编程逻辑也与我们熟悉的深度学习编程逻辑差异比较大,更适用于专业的概率学习人员。MinsSpore深度概率编程(MinsSpore Deep Probabilistic Programming, MDP)不仅包含通用、专业的概率学习编程语言,适用于“专业”用户,而且支持使用开发深度学习模型的逻辑进行概率编程,让“小白”用户轻松上手;此外,还提供深度概率学习的工具箱,拓展贝叶斯应用功能。
+
+本章将详细介绍深度概率编程在MindSpore上的应用。在动手进行实践之前,确保,你已经正确安装了MindSporev0.7-beta及其以上版本。本章的具体内容如下:
+1. 介绍如何使用[bnn_layers模块](https://gitee.com/mindspore/mindspore/tree/master/mindspore/nn/probability/bnn_layers)实现贝叶斯神经网(Bayesian Neural Network, BNN);
+2. 介绍如何使用[variational模块](https://gitee.com/mindspore/mindspore/tree/master/mindspore/nn/probability/infer/variational)和[dpn模块](https://gitee.com/mindspore/mindspore/tree/master/mindspore/nn/probability/dpn)实现变分自编码器(Variational AutoEncoder, VAE);
+3. 介绍如何使用[transforms模块](https://gitee.com/mindspore/mindspore/tree/master/mindspore/nn/probability/transforms)实现DNN(Deep Neural Network, DNN)一键转BNN;
+4. 介绍如何使用[toolbox模块](https://gitee.com/mindspore/mindspore/tree/master/mindspore/nn/probability/toolbox/uncertainty_evaluation.py)实现不确定性估计。
+
+## 使用贝叶斯神经网络
+贝叶斯神经网络是由概率模型和神经网络组成的基本模型,它的权重不再是一个确定的值,而是一个分布。本例介绍了如何使用MDP中的bnn_layers模块实现贝叶斯神经网络,并利用贝叶斯神经网络实现一个简单的图片分类功能,整体流程如下:
+1. 处理MNIST数据集;
+2. 定义贝叶斯LeNet网络;
+3. 定义损失函数和优化器;
4. 加载数据集并进行训练。
-#### 处理数据集
+> 本例面向GPU或Ascend 910 AI处理器平台,你可以在这里下载完整的样例代码:
+
+### 处理数据集
本例子使用的是MNIST数据集,数据处理过程与教程中的[实现一个图片分类应用](https://www.mindspore.cn/tutorial/zh-CN/master/quick_start/quick_start.html)一致。
-#### 定义贝叶斯神经网络
-本例子使用的是贝叶斯LeNet。利用bnn_layers构建贝叶斯神经网络的方法与构建普通的神经网络相同。值得注意的是,bnn_layers和普通的神经网络层可以互相组合。
+### 定义贝叶斯神经网络
+本例使用的是Bayesian LeNet。利用bnn_layers模块构建贝叶斯神经网络的方法与构建普通的神经网络相同。值得注意的是,bnn_layers和普通的神经网络层可以互相组合。
```
import mindspore.nn as nn
@@ -87,21 +95,24 @@ class BNNLeNet5(nn.Cell):
x = self.fc3(x)
return x
```
-#### 定义损失函数和优化器
+### 定义损失函数和优化器
接下来需要定义损失函数(Loss)和优化器(Optimizer)。损失函数是深度学习的训练目标,也叫目标函数,可以理解为神经网络的输出(Logits)和标签(Labels)之间的距离,是一个标量数据。
+
常见的损失函数包括均方误差、L2损失、Hinge损失、交叉熵等等。图像分类应用通常采用交叉熵损失(CrossEntropy)。
+
优化器用于神经网络求解(训练)。由于神经网络参数规模庞大,无法直接求解,因而深度学习中采用随机梯度下降算法(SGD)及其改进算法进行求解。MindSpore封装了常见的优化器,如SGD、Adam、Momemtum等等。本例采用Adam优化器,通常需要设定两个参数,学习率(learnin _rate)和权重衰减项(weight decay)。
+
MindSpore中定义损失函数和优化器的代码样例如下:
```
# loss function definition
-criterion = SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")
+criterion = SoftmaxCrossEntropyWithLogits(is_grad=False, sparse=True, reduction="mean")
# optimization definition
optimizer = AdamWeightDecay(params=network.trainable_params(), learning_rate=0.0001)
```
-#### 训练网络
+### 训练网络
贝叶斯神经网络的训练过程与DNN基本相同,唯一不同的是将`WithLossCell`替换为适用于BNN的`WithBNNLossCell`。除了`backbone`和`loss_fn`两个参数之外,`WithBNNLossCell`增加了`dnn_factor`和`bnn_factor`两个参数。`dnn_factor`是由损失函数计算得到的网络整体损失的系数,`bnn_factor`是每个贝叶斯层的KL散度的系数,这两个参数是用来平衡网络整体损失和贝叶斯层的KL散度的,防止KL散度的值过大掩盖了网络整体损失。
```
@@ -157,9 +168,16 @@ def validate_model(net, dataset):
return acc_mean
```
-### 变分推断
-#### 定义变分自编码器
-我们只需要自定义编码器和解码器,编码器和解码器都是神经网络。
+## 使用变分自编码器
+接下来介绍如何使用MDP中的variational模块和dpn模块实现变分自编码器。变分自编码器是经典的应用了变分推断的深度概率模型,用来学习潜在变量的表示,通过该模型,不仅可以压缩输入数据,还可以生成该类型的新图像。本例的整体流程如下:
+1. 定义变分自编码器;
+2. 定义损失函数和优化器;
+3. 处理数据;
+4. 训练网络;
+5. 生成新样本或重构输入样本。
+> 本例面向GPU或Ascend 910 AI处理器平台,你可以在这里下载完整的样例代码:
+### 定义变分自编码器
+使用dpn模块来构造变分自编码器尤为简单,你只需要自定义编码器和解码器(DNN模型),调用VAE接口即可。
```
class Encoder(nn.Cell):
@@ -210,11 +228,11 @@ optimizer = nn.Adam(params=vae.trainable_params(), learning_rate=0.001)
net_with_loss = nn.WithLossCell(vae, net_loss)
```
-#### 处理数据
+### 处理数据
本例使用的是MNIST数据集,数据处理过程与教程中的[实现一个图片分类应用](https://www.mindspore.cn/tutorial/zh-CN/master/quick_start/quick_start.html)一致。
-#### 训练网络
-使用`SVI`接口对VAE网络进行训练。
+### 训练网络
+使用variational模块中的`SVI`接口对VAE网络进行训练。
```
from mindspore.nn.probability.infer import SVI
@@ -224,7 +242,7 @@ vae = vi.run(train_dataset=ds_train, epochs=10)
trained_loss = vi.get_train_loss()
```
通过`vi.run`可以得到训练好的网络,使用`vi.get_train_loss`可以得到训练之后的损失。
-#### 生成新样本或重构输入样本
+### 生成新样本或重构输入样本
利用训练好的VAE网络,我们可以生成新的样本或重构输入样本。
```
@@ -235,8 +253,13 @@ for sample in ds_train.create_dict_iterator():
reconstructed_sample = vae.reconstruct_sample(sample_x)
```
-### DNN一键转换成BNN
-对于不熟悉贝叶斯模型的DNN研究人员,MDP提供了高级API`TransformToBNN`,支持DNN模型一键转换成BNN模型。
+## DNN一键转换成BNN
+对于不熟悉贝叶斯模型的DNN研究人员,MDP提供了高级API`TransformToBNN`,支持DNN模型一键转换成BNN模型。本例将会介绍如何使用transforms模块中的`TransformToBNN`API实现DNN一键转换成BNN,整体流程如下:
+1. 定义DNN模型;
+2. 定义损失函数和优化器;
+3. 实现功能一:转换整个模型;
+4. 实现功能二:转换指定类型的层。
+> 本例面向GPU或Ascend 910 AI处理器平台,你可以在这里下载完整的样例代码:
#### 定义DNN模型
本例使用的DNN模型是LeNet。
@@ -306,14 +329,28 @@ class LeNet5(nn.Cell):
x = self.fc3(x)
return x
```
-#### 定义损失函数和优化器
+LeNet的网络结构如下:
+
+```
+LeNet5
+ (conv1) Conv2dinput_channels=1, output_channels=6, kernel_size=(5, 5),stride=(1, 1), pad_mode=valid, padding=0, dilation=(1, 1), group=1, has_bias=False
+ (conv2) Conv2dinput_channels=6, output_channels=16, kernel_size=(5, 5),stride=(1, 1), pad_mode=valid, padding=0, dilation=(1, 1), group=1, has_bias=False
+ (fc1) Densein_channels=400, out_channels=120, weight=Parameter (name=fc1.weight), has_bias=True, bias=Parameter (name=fc1.bias)
+ (fc2) Densein_channels=120, out_channels=84, weight=Parameter (name=fc2.weight), has_bias=True, bias=Parameter (name=fc2.bias)
+ (fc3) Densein_channels=84, out_channels=10, weight=Parameter (name=fc3.weight), has_bias=True, bias=Parameter (name=fc3.bias)
+ (relu) ReLU
+ (max_pool2d) MaxPool2dkernel_size=2, stride=2, pad_mode=VALID
+ (flatten) Flatten
+```
+
+### 定义损失函数和优化器
接下来需要定义损失函数(Loss)和优化器(Optimizer)。本例使用交叉熵损失作为损失函数,Adam作为优化器。
```
network = LeNet5()
# loss function definition
-criterion = SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")
+criterion = SoftmaxCrossEntropyWithLogits(is_grad=False, sparse=True, reduction="mean")
# optimization definition
optimizer = AdamWeightDecay(params=network.trainable_params(), learning_rate=0.0001)
@@ -321,7 +358,7 @@ optimizer = AdamWeightDecay(params=network.trainable_params(), learning_rate=0.0
net_with_loss = WithLossCell(network, criterion)
train_network = TrainOneStepCell(net_with_loss, optimizer)
```
-#### 实例化TransformToBNN
+### 实例化TransformToBNN
`TransformToBNN`的`__init__`函数定义如下:
```
@@ -343,7 +380,7 @@ from mindspore.nn.probability import transforms
bnn_transformer = transforms.TransformToBNN(train_network, 60000, 0.000001)
```
-#### 功能一:转换整个模型
+### 实现功能一:转换整个模型
`transform_to_bnn_model`方法可以将整个DNN模型转换为BNN模型。其定义如下:
```
@@ -374,12 +411,86 @@ bnn_transformer = transforms.TransformToBNN(train_network, 60000, 0.000001)
"""
```
参数`get_dense_args`指定从DNN模型的全连接层中获取哪些参数,`get_conv_args`指定从DNN模型的卷积层中获取哪些参数,参数`add_dense_args`和`add_conv_args`分别指定了要为BNN层指定哪些新的参数值。需要注意的是,`add_dense_args`中的参数不能与`get_dense_args`重复,`add_conv_args`和`get_conv_args`也是如此。
+
在MindSpore中将整个DNN模型转换成BNN模型的代码如下:
```
train_bnn_network = bnn_transformer.transform_to_bnn_model()
```
-#### 功能二:转换指定类型的层
+整个模型转换后的结构如下:
+
+```
+LeNet5
+ (conv1) ConvReparam
+ in_channels=1, out_channels=6, kernel_size=(5, 5), stride=(1, 1), pad_mode=valid, padding=0, dilation=(1, 1), group=1, weight_mean=Parameter (name=conv1.weight_posterior.mean), weight_std=Parameter (name=conv1.weight_posterior.untransformed_std), has_bias=False
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (conv2) ConvReparam
+ in_channels=6, out_channels=16, kernel_size=(5, 5), stride=(1, 1), pad_mode=valid, padding=0, dilation=(1, 1), group=1, weight_mean=Parameter (name=conv2.weight_posterior.mean), weight_std=Parameter (name=conv2.weight_posterior.untransformed_std), has_bias=False
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (fc1) DenseReparam
+ in_channels=400, out_channels=120, weight_mean=Parameter (name=fc1.weight_posterior.mean), weight_std=Parameter (name=fc1.weight_posterior.untransformed_std), has_bias=True, bias_mean=Parameter (name=fc1.bias_posterior.mean), bias_std=Parameter (name=fc1.bias_posterior.untransformed_std)
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+ (bias_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (bias_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (fc2) DenseReparam
+ in_channels=120, out_channels=84, weight_mean=Parameter (name=fc2.weight_posterior.mean), weight_std=Parameter (name=fc2.weight_posterior.untransformed_std), has_bias=True, bias_mean=Parameter (name=fc2.bias_posterior.mean), bias_std=Parameter (name=fc2.bias_posterior.untransformed_std)
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+ (bias_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (bias_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (fc3) DenseReparam
+ in_channels=84, out_channels=10, weight_mean=Parameter (name=fc3.weight_posterior.mean), weight_std=Parameter (name=fc3.weight_posterior.untransformed_std), has_bias=True, bias_mean=Parameter (name=fc3.bias_posterior.mean), bias_std=Parameter (name=fc3.bias_posterior.untransformed_std)
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+ (bias_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (bias_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (relu) ReLU
+ (max_pool2d) MaxPool2dkernel_size=2, stride=2, pad_mode=VALID
+ (flatten) Flatten
+```
+可以看到,整个LeNet网络中的卷积层和全连接层都转变成了相应的贝叶斯层。
+
+### 实现功能二:转换指定类型的层
`transform_to_bnn_layer`方法可以将DNN模型中指定类型的层(nn.Dense或者nn.Conv2d)转换为对应的贝叶斯层。其定义如下:
```
@@ -401,8 +512,76 @@ train_bnn_network = bnn_transformer.transform_to_bnn_model()
```
参数`dnn_layer`指定将哪个类型的DNN层转换成BNN层,`bnn_layer`指定DNN层将转换成哪个类型的BNN层,`get_args`和`add_args`分别指定从DNN层中获取哪些参数和要为BNN层的哪些参数重新赋值。
-### 不确定性估计
-不确定性估计工具箱基于MindSpore Deep probability Programming (MDP),适用于主流的深度学习模型,如回归、分类、目标检测等。在推理阶段,利用不确定性估计工具箱,开发人员只需通过训练模型和训练数据集,指定需要估计的任务和样本,即可得到任意不确定性(aleatoric uncertainty)和认知不确定性(epistemic uncertainty)。基于不确定性信息,开发人员可以更好地理解模型和数据集。
+在MindSpore中将DNN模型中的Dense层转换成相应贝叶斯层DenseReparam的代码如下:
+
+```
+train_bnn_network = bnn_transformer.transform_to_bnn_layer(nn.Dense, bnn_layers.DenseReparam)
+```
+转换后网络的结构如下:
+
+```
+LeNet5
+ (conv1) Conv2dinput_channels=1, output_channels=6, kernel_size=(5, 5),stride=(1, 1), pad_mode=valid, padding=0, dilation=(1, 1), group=1, has_bias=False
+ (conv2) Conv2dinput_channels=6, output_channels=16, kernel_size=(5, 5),stride=(1, 1), pad_mode=valid, padding=0, dilation=(1, 1), group=1, has_bias=False
+ (fc1) DenseReparam
+ in_channels=400, out_channels=120, weight_mean=Parameter (name=fc1.weight_posterior.mean), weight_std=Parameter (name=fc1.weight_posterior.untransformed_std), has_bias=True, bias_mean=Parameter (name=fc1.bias_posterior.mean), bias_std=Parameter (name=fc1.bias_posterior.untransformed_std)
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+ (bias_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (bias_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (fc2) DenseReparam
+ in_channels=120, out_channels=84, weight_mean=Parameter (name=fc2.weight_posterior.mean), weight_std=Parameter (name=fc2.weight_posterior.untransformed_std), has_bias=True, bias_mean=Parameter (name=fc2.bias_posterior.mean), bias_std=Parameter (name=fc2.bias_posterior.untransformed_std)
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+ (bias_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (bias_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (fc3) DenseReparam
+ in_channels=84, out_channels=10, weight_mean=Parameter (name=fc3.weight_posterior.mean), weight_std=Parameter (name=fc3.weight_posterior.untransformed_std), has_bias=True, bias_mean=Parameter (name=fc3.bias_posterior.mean), bias_std=Parameter (name=fc3.bias_posterior.untransformed_std)
+ (weight_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (weight_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+ (bias_prior) NormalPrior
+ (normal) Normalmean = 0.0, standard deviation = 0.1
+
+ (bias_posterior) NormalPosterior
+ (normal) Normalbatch_shape = None
+
+
+ (relu) ReLU
+ (max_pool2d) MaxPool2dkernel_size=2, stride=2, pad_mode=VALID
+ (flatten) Flatten
+```
+可以看到,LeNet网络中的卷积层保持不变,全连接层变成了对应的贝叶斯层DenseReparam。
+
+## 使用不确定性估计工具箱
+贝叶斯神经网络的优势之一就是可以获取不确定性,MDP在上层提供了不确定性估计的工具箱,用户可以很方便地使用该工具箱计算不确定性。不确定性意味着深度学习模型对预测结果的不确定程度。目前,大多数深度学习算法只能给出预测结果,而不能判断预测结果的可靠性。不确定性主要有两种类型:偶然不确定性和认知不确定性。
+- 偶然不确定性(Aleatoric Uncertainty):描述数据中的内在噪声,即无法避免的误差,这个现象不能通过增加采样数据来削弱。
+- 认知不确定性(Epistemic Uncertainty):模型自身对输入数据的估计可能因为训练不佳、训练数据不够等原因而不准确,可以通过增加训练数据等方式来缓解。
+
+不确定性估计工具箱,适用于主流的深度学习模型,如回归、分类等。在推理阶段,利用不确定性估计工具箱,开发人员只需通过训练模型和训练数据集,指定需要估计的任务和样本,即可得到任意不确定性和认知不确定性。基于不确定性信息,开发人员可以更好地理解模型和数据集。
+> 本例面向GPU或Ascend 910 AI处理器平台,你可以在这里下载完整的样例代码:
+
以分类任务为例,本例中使用的模型是LeNet,数据集为MNist,数据处理过程与教程中的[实现一个图片分类应用](https://www.mindspore.cn/tutorial/zh-CN/master/quick_start/quick_start.html)一致。为了评估测试示例的不确定性,使用工具箱的方法如下:
```
@@ -429,4 +608,3 @@ for eval_data in ds_eval.create_dict_iterator():
aleatoric_uncertainty = evaluation.eval_aleatoric_uncertainty(eval_data)
```
-