*
贝叶斯神经网络简介      

     
 对于一个神经网络来说,最为核心的是如何根据训练集的数据,得到各层的模型参数,使得Loss最小,因其强大的非线性拟合能力而在各个领域有着重要应用。而其问题是在数据量较少的情况下存在严重的过拟合现象,对于获得数据代价昂贵的一些课题比如车辆控制等领域,应用存在局限性。

        贝叶斯神经网络的优点是可以根据较少的数据得到较为solid的模型,而且得到的是各层参数的分布(一般假设各层参数 
 服从高斯分布,根据训练集数据计算得出  的均值和方差),从而得到  ,
可以有效的解决过拟合的问题,不仅可以对结果进行预测,还可以对结果的误差进行有效预测。的核心思想是

     
 我们先来直观的看一下,贝叶斯神经网络的作用和效果,如下图所示,红色的点为训练集的数据,然后针对每一个x,对f(x)采样1000个点,之所以输出多个y值是为了体现出模型对于y的方差的预测能力。 
  


*
贝叶斯公式与KL散度

       我们从最基本的贝叶斯公式出发,来理解一下贝叶斯神经网络的迭代过程:

       贝叶斯公式:

其中,(X,Y)为训练集的数据,由于训练集是给定的所以  为常数,即我们的目标 ,为W的先验概率,为在给定参数W和X的情况下,网络输出Y的概率。

       由于  的概率分布复杂,难以求得均值方差等,因此贝叶斯神经网络通过建立一个 函数来逼近  函数,利用一个较为简单的分布,如高斯分布等(参数为,
),来逼近 ,参数 ,  即为神经网络需要更新调整的参数,这是整个算法的核心思想。

      那么如何判断 函数逼近 
 函数的效果呢?判断依据一般选取为两种分布的KL散度,KL散度又称为两种分布的相对熵,在一定程度上,熵可以度量两个随机变量的距离。KL散度是两个概率分布P和Q差别的非对称性的度量,用来度量使用基于 
 的编码来编码来自  的样本平均所需的额外的位元数。 典型情况下,P表示数据的真实分布,Q表示数据的模型分布,即P的近似分布。 其数学定义如下。

                                                          

       进一步分析,我们得到:                     

       这里面比较重要的一点是KL散度是    关于  的期望,这一点很特殊,
是一个函数,我们对这个函数进行优化使得KL散度最小,这样的对于函数的操作称之为“变分”,本文主要基于变分贝叶斯推理的方法来进行贝叶斯神经网路的实现。

*
贝叶斯神经网络的核心思想

     
对于普通的神经网络来讲,需要设计好损失函数,通过SDG、Adam等优化器进行优化求得最优参数,使得Loss最小,而对于贝叶斯神经网络,需要最小化的便是KL散度,我们需要将KL散度拆分成方便计算求解的项。

                                                          

                                                                            

                                                                            

其中  是常数,稍作整理可得:

                                           

由此,我们就得到了需要 minimize的目标函数:

       至此,我们还是最后一个环节,也就是 ,这三项的具体计算方法,  这一项很好计算  是先验概率,一般我们指定为均值为0方差为
的高斯分布即可;在上文中提到,  因此对 累加求和取平均值即可求出; 的计算十分关键,这一项是表示在给定参数和自变量的情况下,输出  为数据集中所对应的
的概率,采用如下公式来计算:     , 其中  为Y 的先验参数(的先验方差一般与的先验方差相同)。

核心代码
class VariationalDense: def __init__(self, n_in, n_out): self.W_mu =
tf.Variable(tf.truncated_normal([n_in, n_out], stddev=stddev_var))
self.W_logsigma = tf.Variable(tf.truncated_normal([n_in, n_out], mean = 0.,
stddev=stddev_var)) self.b_mu = tf.Variable(tf.zeros([n_out])) self.b_logsigma
= tf.Variable(tf.zeros([n_out])) self.epsilon_w =
self.get_random([n_in,n_out],mu=0., std_dev=epsilon_prior) self.epsilon_b =
self.get_random([n_out], mu=0., std_dev =epsilon_prior) self.W = self.W_mu +
tf.multiply(tf.log(1. + tf.exp(self.W_logsigma)), self.epsilon_w) self.b =
self.b_mu + tf.multiply(tf.log(1. + tf.exp(self.b_logsigma)), self.epsilon_b)
def __call__(self, x, activation=tf.identity): output =
activation(tf.matmul(x,self.W) + self.b) output = tf.squeeze(output) return
output def log_gaussian(self, x, mu, sigma): return
-0.5*tf.log(2*np.pi)-tf.log(sigma)-(x-mu)**2/(2*sigma**2) def get_random(self,
shape, mu, std_dev): return tf.random_normal(shape, mean=mu, stddev=std_dev)
def regularization(self): sample_log_pw, sample_log_qw= 0. , 0. sample_log_pw
+= tf.reduce_sum(self.log_gaussian(self.W, 0., sigma_prior)) sample_log_pw +=
tf.reduce_sum(self.log_gaussian(self.b, 0., sigma_prior)) sample_log_qw +=
tf.reduce_sum(self.log_gaussian(self.W, self.W_mu, tf.log(1. +
tf.exp(self.W_logsigma)))) sample_log_qw +=
tf.reduce_sum(self.log_gaussian(self.b, self.b_mu, tf.log(1. +
tf.exp(self.b_logsigma)))) regulizer =
tf.reduce_sum((sample_log_qw-sample_log_pw)) return regulizer # Create the
Model n_sample = 20 X = np.random.normal(size=(n_sample,1)) y =
np.random.normal(np.cos(5.*X) / (np.abs(X) + 1.), 0.1).ravel() X_pred =
np.atleast_2d(np.linspace(-3.,3.,num=100)).T feature_size = X.shape[1] n_hidden
= 100 # Place holder of Network inputs and outputs model_x =
tf.placeholder(tf.float32, shape=[None, feature_size]) model_y =
tf.placeholder(tf.float32, shape=[None]) #Define neural network net_Layer_input
= VariationalDense(feature_size, n_hidden) net_Layer_hidden =
VariationalDense(n_hidden, n_hidden) net_Layer_output =
VariationalDense(n_hidden, 1) Input_Layer_output = net_Layer_input(model_x,
tf.nn.relu) Hidden_Layer_output = net_Layer_hidden(Input_Layer_output,
tf.nn.relu) net_pred = net_Layer_output(Hidden_Layer_output) # Define ELBO
sample_log_Likelihood = tf.reduce_sum(net_Layer_output.log_gaussian(model_y,
net_pred, sigma_prior)) regularization_term = net_Layer_input.regularization()
+ net_Layer_hidden.regularization() + net_Layer_output.regularization() elbo =
-sample_log_Likelihood + regularization_term / n_hidden train_step =
tf.train.AdamOptimizer(lr).minimize(elbo) # Mean Square Error (Network
Performance) model_mse = tf.reduce_sum(tf.square(model_y - net_pred))/n_sample
*
实验结果分析

      我们依次取10个数据点、50个数据点、100个数据点,可以看到训练集大小的不同,对于整体拟合效果的影响结果如下:

10个数据点 50个数据点 100个数据点
                                           

   
 下面我们来可视化的看一下贝叶斯神经网络随着迭代次数的增加,拟合效果的变化,分别取eposide=2500,3000,3500,4000,观察训练效果的变化:

2500次 3000次
3500次 4000次
                

                 

 

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信