贝叶斯神经网络:变分推理与MC Dropout方法解析
1. 变分推理与TensorFlow Probability
在深度学习研究中,仅进行一次评估的期望在强化学习或变分自编码器等不同场合都有应用。TensorFlow Probability(TFP)提供了多种构建变分推理贝叶斯神经网络(VI BNNs)的方法。
可以使用 tfp.layers.DenseReparameterization 类来构建一个全连接的贝叶斯网络,就像使用标准的Keras层一样,将各层堆叠起来。以下是一个构建三层VI网络的代码示例:
model = tf.keras.Sequential([
tfp.layers.DenseReparameterization(1, input_shape=(None,1)),
tfp.layers.DenseReparameterization(2),
tfp.layers.DenseReparameterization(3)
])
在默认设置下, DenseReparameterization 将偏置作为固定参数,而非分布。因此,该网络的参数计算如下:
| 层 | 偏置数量 | 边数量 | 参数数量 |
| — | — | — | — |
| 第一层 | 1 | 1 | 3 |
| 第二层 | 2 | 2 | 6 |
| 第三层 | 3 | 6 | 15 |
总计该网络有24个参数,相比标准神经网络,采用贝叶斯方法大约需要两倍的参数数量。
TFP还具有很高的灵活性,下面我们重建线性回归问题,将斜率和截距替换为分布,并假设σ已知。为了与TFP兼容,需要将模型转换为变分贝叶斯网络。以下是相应的代码:
def NLL(y, distr):
return -distr.log_prob(y)
def my_dist(mu):
return tfd.Normal(loc=mu[:,0:1], scale=sigma)
kl = tfp.distributions.kl_divergence
divergence_fn=lambda q, p, _: kl(q, p) / (num * 1.0)
model = tf.keras.Sequential([
tfp.layers.DenseReparameterization(1,
kernel_divergence_fn=divergence_fn,
bias_divergence_fn=divergence_fn,
bias_prior_fn= \
tfp.layers.util.default_multivariate_normal_fn,
bias_posterior_fn= \
tfp.layers.util.default_mean_field_normal_fn()
),
tfp.layers.DistributionLambda(my_dist)
])
sgd = tf.keras.optimizers.SGD(lr=.005)
model.compile(loss=NLL, optimizer=sgd)
此外,TFP还提供了用于构建卷积贝叶斯神经网络的层,如 Convolution2DReparameterization 及其1D和3D变体。同时,还有一些特殊类和高级的VI方法,例如 DenseFlipout 可以作为 DenseReparameterization 的替代,它使用了一种加速学习的技巧。
2. MC Dropout:近似贝叶斯方法
在前面我们了解了通过变分推理近似的贝叶斯神经网络,VI允许我们通过学习每个权重的近似后验分布来拟合贝叶斯深度学习模型。然而,从非贝叶斯神经网络转换到其贝叶斯变体时,参数数量会翻倍。幸运的是,MC Dropout方法可以解决这个问题。
2.1 训练时使用的经典Dropout
训练时使用的Dropout是一种防止神经网络过拟合的简单方法。在训练过程中,随机将神经网络中的一些神经元置为零,每次更新都会进行这样的操作。在Keras中,可以通过在权重层之后添加Dropout层并指定丢弃概率来实现。以下是一个定义和训练带有Dropout层的分类卷积神经网络(CNN)的代码示例:
model = Sequential()
model.add(Convolution2D(16,kernel_size,padding='same',\
input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(16,kernel_size,padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Convolution2D(32,kernel_size,padding='same'))
model.add(Activation('relu'))
model.add(Convolution2D(32,kernel_size,padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Flatten())
model.add(Dense(100))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(100))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',optimizer='adam',\
metrics=['accuracy'])
可以通过打开 这个笔记本 来验证Dropout是否能有效防止过拟合。Dropout有助于防止过拟合的原因主要有两个:一是训练了许多参数较少的精简神经网络版本,每次只更新未被丢弃的权重;二是使用Dropout时学习到的复杂特征较少,使得神经网络能够处理缺失信息,从而产生更鲁棒和独立的特征。
在测试时,使用经过Dropout训练的神经网络很简单,只需回到具有固定权重的完整神经网络,不过需要将学习到的权重值进行下调,以考虑训练时每个神经元平均输入较少的情况。幸运的是,Keras会自动处理这个问题。
2.2 训练和测试时都使用的MC Dropout
在测试时开启Dropout,就可以将其作为贝叶斯神经网络使用。在贝叶斯神经网络中,每个权重被权重分布所取代。使用Dropout时,权重分布更简单,本质上只有两个值:0或w。丢弃概率p*是一个固定的调优参数,权重分布的唯一参数是值w。
学习参数w的过程与通常一样,在训练时开启Dropout并使用通常的负对数似然(NLL)损失函数,通过随机梯度下降(SGD)来调整权重以最小化损失。
要将经过Dropout训练的神经网络作为贝叶斯神经网络使用,需要在测试时也开启Dropout。对于相同的输入进行多次预测,每次预测结果来自不同的Dropout变体的神经网络,这些预测结果可以近似贝叶斯预测分布。
在Keras中使用MC Dropout有两种选择。一种是在模型定义中设置训练阶段为真来创建网络;另一种更优雅的方式是可以选择在测试时是否使用Dropout。以下是实现代码:
import tensorflow.keras.backend as K
model_mc_pred = K.function([model_mc.input, K.learning_phase()],
[model_mc.output])
T= 5
for i in range(0,T):
print(model_mc_pred([x_train[0:1],0])[0])
for i in range(0,T):
print(model_mc_pred([x_train[0:1],1])[0])
3. 案例研究
我们通过一个回归任务的案例研究来比较变分推理网络、蒙特卡罗近似和非贝叶斯方法。可以使用合成正弦数据来拟合具有灵活方差的非线性回归模型。打开 这个笔记本 ,可以进行以下操作:
- 拟合一个非贝叶斯神经网络。
- 分别通过VI和Dropout拟合两个贝叶斯神经网络。
- 研究神经网络所表达的不确定性。
使用400个x值在 -10 到 30 之间、步长为 0.1 的验证数据,该范围不仅覆盖了训练数据范围,还包括了训练数据之外的范围,我们期望模型在超出训练数据范围时能表达出更高的认知不确定性。
为了比较这三种方法,我们来看结果的预测分布。通过对网络所有可能的权重配置w进行平均来计算贝叶斯模型的预测分布。对于给定输入xi,确定其结果分布p(y|xi, D)的过程在三种不同的概率神经网络模型中有所不同:
- 非贝叶斯神经网络 :每个连接具有固定权重θc,将其表示为概率分布时,给固定权重θc分配概率1。每次采样得到的神经网络都是相同的,因此对于相同输入x,每次运行得到的高斯参数都相同,结果分布是固定的。
- 贝叶斯VI神经网络 :将固定权重θc替换为具有均值μc和标准差σc的高斯分布。测试时,从这些权重分布中采样T次,每次得到的连接值略有不同,因此每次运行得到的高斯参数也略有不同,结果分布通过从这些确定的高斯分布中采样得到。
- 贝叶斯MC Dropout神经网络 :将每个固定权重θc替换为二元分布。测试时,从这些权重分布中采样T次,每次连接值要么为零,要么为wc,结果分布同样通过从确定的高斯分布中采样得到。
通过T次预测的结果,可以探索三种模型的结果不确定性。以下是三种模型的预测分布可视化结果:
通过这个案例研究,我们可以清楚地看到不同方法在处理不确定性方面的差异,贝叶斯方法在表达不确定性方面具有明显优势,能够更好地应对训练数据之外的情况。
综上所述,TFP提供的变分推理方法和MC Dropout方法为构建贝叶斯神经网络提供了强大的工具,不同的方法适用于不同的场景,我们可以根据具体需求选择合适的方法来处理实际问题。
贝叶斯神经网络:变分推理与MC Dropout方法解析
4. 不同模型的详细对比分析
为了更清晰地展示三种模型(非贝叶斯神经网络、贝叶斯VI神经网络、贝叶斯MC Dropout神经网络)在预测分布和不确定性表达上的差异,我们进一步分析相关数据和图表。
| 模型类型 | 权重表示 | 测试时采样情况 | 结果分布特点 |
|---|---|---|---|
| 非贝叶斯神经网络 | 固定权重θc,概率分布为给θc分配概率1 | 每次采样得到相同的神经网络 | 对于相同输入,每次运行得到相同的高斯参数,结果分布固定 |
| 贝叶斯VI神经网络 | 高斯分布,均值μc和标准差σc | 从权重分布中采样T次,每次连接值略有不同 | 每次运行得到略有不同的高斯参数,结果分布通过采样确定的高斯分布得到 |
| 贝叶斯MC Dropout神经网络 | 二元分布 | 从权重分布中采样T次,连接值为0或wc | 结果分布通过采样确定的高斯分布得到 |
从图8.14的预测分布可视化结果来看:
- 非贝叶斯神经网络 :在图中表现为所有采样结果基本重合,因为每次运行得到的参数相同,所以预测结果缺乏对不确定性的表达。在训练数据范围之外,它无法体现出认知不确定性的增加,仍然给出固定的预测,这在实际应用中可能会导致对未知情况的误判。
- 贝叶斯VI神经网络 :采样结果有一定的分散性,反映出权重的不确定性。在训练数据范围之外,预测区间明显变宽,表明模型能够意识到数据的不确定性增加,这是贝叶斯方法的优势之一。
- 贝叶斯MC Dropout神经网络 :同样能够体现出一定的不确定性,其采样结果的分散程度也反映了权重的随机性。与贝叶斯VI神经网络类似,在训练数据范围之外也能表现出不确定性的增加。
5. 操作步骤总结
在实际应用中,使用上述方法构建和训练神经网络可以按照以下步骤进行:
5.1 使用TFP构建变分推理贝叶斯神经网络
graph LR
A[定义模型结构] --> B[设置参数和损失函数]
B --> C[编译模型]
C --> D[训练模型]
- 定义模型结构 :使用
tfp.layers.DenseReparameterization或卷积层构建网络,例如:
model = tf.keras.Sequential([
tfp.layers.DenseReparameterization(1, input_shape=(None,1)),
tfp.layers.DenseReparameterization(2),
tfp.layers.DenseReparameterization(3)
])
- 设置参数和损失函数 :根据需求设置权重和偏置的先验、后验分布,以及KL散度的缩放因子,例如:
def NLL(y, distr):
return -distr.log_prob(y)
def my_dist(mu):
return tfd.Normal(loc=mu[:,0:1], scale=sigma)
kl = tfp.distributions.kl_divergence
divergence_fn=lambda q, p, _: kl(q, p) / (num * 1.0)
model = tf.keras.Sequential([
tfp.layers.DenseReparameterization(1,
kernel_divergence_fn=divergence_fn,
bias_divergence_fn=divergence_fn,
bias_prior_fn= \
tfp.layers.util.default_multivariate_normal_fn,
bias_posterior_fn= \
tfp.layers.util.default_mean_field_normal_fn()
),
tfp.layers.DistributionLambda(my_dist)
])
- 编译模型 :选择合适的优化器和损失函数,例如:
sgd = tf.keras.optimizers.SGD(lr=.005)
model.compile(loss=NLL, optimizer=sgd)
- 训练模型 :使用训练数据对模型进行训练。
5.2 使用MC Dropout构建贝叶斯神经网络
graph LR
A[定义网络结构并添加Dropout层] --> B[训练模型时开启Dropout]
B --> C[测试时选择是否使用Dropout]
- 定义网络结构并添加Dropout层 :在Keras中,在权重层之后添加Dropout层,例如:
model = Sequential()
model.add(Convolution2D(16,kernel_size,padding='same',\
input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(16,kernel_size,padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Convolution2D(32,kernel_size,padding='same'))
model.add(Activation('relu'))
model.add(Convolution2D(32,kernel_size,padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Flatten())
model.add(Dense(100))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(100))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',optimizer='adam',\
metrics=['accuracy'])
- 训练模型时开启Dropout :在训练过程中,Dropout会随机将一些神经元置为零,防止过拟合。
- 测试时选择是否使用Dropout :可以通过设置
K.learning_phase()来控制,例如:
import tensorflow.keras.backend as K
model_mc_pred = K.function([model_mc.input, K.learning_phase()],
[model_mc.output])
T= 5
for i in range(0,T):
print(model_mc_pred([x_train[0:1],0])[0])
for i in range(0,T):
print(model_mc_pred([x_train[0:1],1])[0])
6. 总结与建议
通过对变分推理和MC Dropout两种构建贝叶斯神经网络方法的介绍和案例研究,我们可以总结出以下要点:
- 变分推理方法 :能够更精确地学习权重的后验分布,但参数数量相对较多,计算复杂度较高。适用于对不确定性表达要求较高,且数据量和计算资源充足的场景。
- MC Dropout方法 :实现简单,参数数量不会翻倍,在处理过拟合问题的同时,也能较好地表达不确定性。适用于对计算资源有限,且希望在不增加过多参数的情况下引入贝叶斯特性的场景。
在实际应用中,可以根据具体问题的特点和需求,选择合适的方法。如果对模型的不确定性表达要求极高,且有足够的资源支持,变分推理方法是一个不错的选择;如果更注重模型的简单性和计算效率,MC Dropout方法可能更适合。同时,通过不断的实验和调优,可以进一步提高模型的性能和对不确定性的处理能力。
贝叶斯神经网络方法解析
超级会员免费看
3179

被折叠的 条评论
为什么被折叠?



