Bayesian Neural Net with Flipout

##Reference
[Flipout: Efficient Pseudo-Independent Weight Perturbations on Mini-Batches](https://arxiv.org/pdf/1803.04386.pdf)

##Data
```python
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

import tensorflow_probability as tfp
tfd = tfp.distributions

from tensorflow.keras.models import Sequential

cancer = load_breast_cancer()

print (len(cancer.data))
print (cancer.feature_names)
print (cancer.target_names)

malignant_count = len(np.where(cancer.target==0)[0])
benign_count = len(np.where(cancer.target==1)[0])
print('# of 0 (malignant): ', malignant_count)
print('# of 1 (benign): ', benign_count)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254604/1ef6954b-b65e-47e6-2483-4a35ef8a344e.png)

```python
data = np.array(cancer.data)
target = np.reshape(cancer.target, (-1, 1))

x_train, x_test, y_train, y_test = train_test_split(data, target, 
                                                  test_size=0.2, random_state=0)

print ('x_train shape: ', x_train.shape)
print ('y_train shape: ', y_train.shape)
print ('x_test shape: ', x_test.shape)
print ('y_test shape: ', y_test.shape)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254604/e11d3b8b-25e8-4bfa-bf81-acbdf2745f1d.png)


##Sample Code
```python
tf.reset_default_graph()

model = Sequential()
layer = tfp.layers.DenseFlipout(1, input_shape=(30, ))
model.add(layer)
               
model.summary()
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254604/60753805-ae9a-23bf-014b-041a21895bc7.png)

```python
n_iter = 500
show_step = 100
n_samples = 50

x = tf.placeholder(shape = [None, 30], dtype = tf.float32)
y = tf.placeholder(shape = [None, 1], dtype = tf.int32)

logits = model(x)
labels_distribution = tfd.Bernoulli(logits=logits)

neg_log_likelihood = -tf.reduce_mean(labels_distribution.log_prob(y))
kl = tf.reduce_mean(model.losses)
elbo_loss = neg_log_likelihood + kl

optimizer = tf.train.AdamOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(elbo_loss)

preds = tf.cast(logits > 0, dtype=tf.int32)
correct_preds = tf.equal(preds, y)
accuracy = tf.reduce_mean(tf.cast(correct_preds, tf.float32))

init = tf.global_variables_initializer()

with tf.Session() as sess:
  sess.run(init)
  
  history_loss_train = []
  history_loss_test = []
  history_acc_train = []
  history_acc_test = []

  print ('Training')  
  for step in range(n_iter):
    feed_dict = {x: x_train, y:y_train}
    
    sess.run(train_op, feed_dict=feed_dict)
    
    loss_train = sess.run(elbo_loss, feed_dict=feed_dict)
    acc_train = sess.run(accuracy, feed_dict=feed_dict)

    history_loss_train.append(loss_train)
    history_acc_train.append(acc_train)

    if (step+1) % show_step == 0:
      print ('-'*50)
      print ('Step: {:>3d} Loss: {:.3f} Accuracy: {:.3f}'.format(
          step+1, loss_train, acc_train))
      
    feed_dict = {x: x_test, y: y_test}
    loss_test = sess.run(elbo_loss, feed_dict=feed_dict)
    acc_test = sess.run(accuracy, feed_dict=feed_dict)

    history_loss_test.append(loss_test)
    history_acc_test.append(acc_test)
    
  w_draw = layer.kernel_posterior.sample()
  b_draw = layer.bias_posterior.sample()
  
  sample_w = []
  sample_b = []
  feed_dict = {x: x_train, y:y_train}
  for _ in range(n_samples):
      w, b = sess.run((w_draw, b_draw), feed_dict=feed_dict)
      sample_w.append(w)
      sample_b.append(b)        
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254604/f88cef24-030c-42d9-e6c9-5d33fc5f0558.png)

```python
fig = plt.figure(figsize = (10, 3))
ax1 = fig.add_subplot(1, 2, 1)
ax1.plot(range(n_iter), history_loss_train, 'b-', label = 'Training')
ax1.plot(range(n_iter), history_loss_test, 'r-', label = 'Test')
ax1.set_title('Loss')
ax1.legend(loc = 'upper right')

ax2 = fig.add_subplot(1, 2, 2)
ax2.plot(range(n_iter), history_acc_train, 'b-', label = 'Training')
ax2.plot(range(n_iter), history_acc_test, 'r-', label = 'Test')
ax2.set_ylim(0.0, 1.0)
ax2.set_title('Accuracy')
ax2.legend(loc = 'lower right')

plt.show()
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254604/5c6a495a-cd96-e934-c7ca-9feff151caee.png)

```python
fig = plt.figure(figsize = (10, 3))
ax1 = fig.add_subplot(1, 2, 1)
ax1.plot(range(n_samples), np.array(sample_w)[:,0, 0])
ax1.set_title('w')

ax2 = fig.add_subplot(1, 2, 2)
ax2.plot(range(n_samples), np.array(sample_b)[:, 0])
ax2.set_title('b')

plt.show()
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254604/668e4d1e-b6d0-6b60-386c-480d0ec5a686.png)