Blitz adalah perpustakaan yang sederhana dan dapat diperluas untuk membuat lapisan jaringan saraf Bayesian (berdasarkan apa yang diusulkan dalam ketidakpastian berat dalam kertas jaringan saraf) di pytorch. Dengan menggunakan lapisan blitz dan util, Anda dapat menambahkan ketidakpastian dan mengumpulkan biaya kompleksitas model Anda dengan cara sederhana yang tidak mempengaruhi interaksi antara lapisan Anda, seolah -olah Anda menggunakan pytorch standar.
Dengan menggunakan kelas sampler berat inti kami, Anda dapat memperpanjang dan meningkatkan perpustakaan ini untuk menambah ketidakpastian pada ruang lingkup lapisan yang lebih besar seperti yang Anda lakukan dengan cara Pytorch yang terintegrasi dengan baik. Permintaan tarik juga dipersilakan.
Untuk menginstal blitz, Anda dapat menggunakan perintah PIP:
pip install blitz-bayesian-pytorch
Atau, melalui conda:
conda install -c conda-forge blitz-bayesian-pytorch
Anda juga dapat git-mengkloningnya dan menginstalnya secara lokal:
conda create -n blitz python=3.9
conda activate blitz
git clone https://github.com/piEsposito/blitz-bayesian-deep-learning.git
cd blitz-bayesian-deep-learning
pip install .
Dokumentasi untuk sampler lapisan, berat (dan distribusi sebelumnya) kami dan util:
(Anda dapat melihatnya untuk diri Anda sendiri dengan menjalankan contoh ini di mesin Anda).
Kita sekarang akan melihat bagaimana pembelajaran mendalam Bayesian dapat digunakan untuk regresi untuk mengumpulkan interval kepercayaan diri atas datapoint kita daripada prediksi nilai kontinu pontual. Mengumpulkan interval kepercayaan untuk prediksi Anda mungkin bahkan lebih berguna daripada estimasi kesalahan rendah.
Saya mempertahankan argumentasi saya tentang fakta bahwa, dengan interval kepercayaan yang baik/tinggi, Anda dapat membuat keputusan yang lebih dapat diandalkan daripada dengan estimasi yang sangat proksimal pada beberapa konteks: jika Anda mencoba untuk mendapatkan keuntungan dari operasi perdagangan, misalnya, memiliki interval kepercayaan yang baik dapat membuat Anda tahu jika, setidaknya, nilai Operasi yang akan lebih rendah (atau lebih tinggi (atau lebih tinggi) daripada beberapa.
Mengetahui apakah suatu nilai akan, tentunya (atau dengan probabilitas yang baik) pada interval yang ditentukan dapat membantu orang pada keputusan yang masuk akal lebih dari estimasi yang sangat proksimal bahwa, jika lebih rendah atau lebih tinggi dari beberapa nilai batas, dapat menyebabkan kerugian pada transaksi. Intinya adalah bahwa, kadang -kadang, mengetahui apakah akan ada keuntungan mungkin lebih berguna daripada mengukurnya.
Untuk menunjukkan hal itu, kami akan membuat regresor jaringan saraf Bayesian untuk dataset mainan Data-House-House, mencoba menciptakan interval kepercayaan (CI) untuk rumah-rumah yang harga yang kami coba prediksi. Kami akan melakukan beberapa penskalaan dan CI akan sekitar 75%. Akan menarik untuk melihat bahwa sekitar 90% dari CI yang diprediksi lebih rendah dari batas tinggi atau (inklusif) lebih tinggi dari yang lebih rendah.
Terlepas dari modul yang diketahui, kami akan membawa dari blitz variational_estimator dekorator, yang membantu kami menangani lapisan Bayesianlinear pada modul yang membuatnya sepenuhnya terintegrasi dengan sisa obor, dan, tentu saja, BayesianLinear , yang merupakan lapisan kami yang menampilkan ketidakpastian berat.
import torch
import torch . nn as nn
import torch . nn . functional as F
import torch . optim as optim
import numpy as np
from blitz . modules import BayesianLinear
from blitz . utils import variational_estimator
from sklearn . datasets import load_boston
from sklearn . preprocessing import StandardScaler
from sklearn . model_selection import train_test_split Tidak ada yang baru di bawah matahari di sini, kami mengimpor dan skala standar data untuk membantu pelatihan.
X , y = load_boston ( return_X_y = True )
X = StandardScaler (). fit_transform ( X )
y = StandardScaler (). fit_transform ( np . expand_dims ( y , - 1 ))
X_train , X_test , y_train , y_test = train_test_split ( X ,
y ,
test_size = .25 ,
random_state = 42 )
X_train , y_train = torch . tensor ( X_train ). float (), torch . tensor ( y_train ). float ()
X_test , y_test = torch . tensor ( X_test ). float (), torch . tensor ( y_test ). float ()Kami dapat membuat kelas kami dengan mendi dari NN.Module, seperti yang akan kami lakukan dengan jaringan obor apa pun. Dekorator kami memperkenalkan metode untuk menangani fitur -fitur Bayesian, karena menghitung biaya kompleksitas lapisan Bayesian dan melakukan banyak feedforwards (mencicipi bobot yang berbeda pada masing -masing) untuk mencicipi kehilangan kami.
@ variational_estimator
class BayesianRegressor ( nn . Module ):
def __init__ ( self , input_dim , output_dim ):
super (). __init__ ()
#self.linear = nn.Linear(input_dim, output_dim)
self . blinear1 = BayesianLinear ( input_dim , 512 )
self . blinear2 = BayesianLinear ( 512 , output_dim )
def forward ( self , x ):
x_ = self . blinear1 ( x )
x_ = F . relu ( x_ )
return self . blinear2 ( x_ )Fungsi ini memang menciptakan interval kepercayaan untuk setiap prediksi pada batch yang kami coba sampel nilai label. Kami kemudian dapat mengukur keakuratan prediksi kami dengan mencari berapa banyak distribusi predison yang sebenarnya termasuk label yang benar untuk titik data.
def evaluate_regression ( regressor ,
X ,
y ,
samples = 100 ,
std_multiplier = 2 ):
preds = [ regressor ( X ) for i in range ( samples )]
preds = torch . stack ( preds )
means = preds . mean ( axis = 0 )
stds = preds . std ( axis = 0 )
ci_upper = means + ( std_multiplier * stds )
ci_lower = means - ( std_multiplier * stds )
ic_acc = ( ci_lower <= y ) * ( ci_upper >= y )
ic_acc = ic_acc . float (). mean ()
return ic_acc , ( ci_upper >= y ). float (). mean (), ( ci_lower <= y ). float (). mean () Perhatikan di sini bahwa kami membuat BayesianRegressor kami seperti yang akan kami lakukan dengan jaringan saraf lainnya.
regressor = BayesianRegressor ( 13 , 1 )
optimizer = optim . Adam ( regressor . parameters (), lr = 0.01 )
criterion = torch . nn . MSELoss ()
ds_train = torch . utils . data . TensorDataset ( X_train , y_train )
dataloader_train = torch . utils . data . DataLoader ( ds_train , batch_size = 16 , shuffle = True )
ds_test = torch . utils . data . TensorDataset ( X_test , y_test )
dataloader_test = torch . utils . data . DataLoader ( ds_test , batch_size = 16 , shuffle = True )Kami melakukan loop pelatihan yang hanya berbeda dari pelatihan obor umum dengan membuat kehilangan sampel dengan metode sampel_elbo -nya. Semua hal lain dapat dilakukan secara normal, karena tujuan kami dengan Blitz adalah untuk meringankan hidup Anda untuk mengulangi data Anda dengan NNS Bayesian yang berbeda tanpa masalah.
Inilah loop pelatihan kami yang sangat sederhana:
iteration = 0
for epoch in range ( 100 ):
for i , ( datapoints , labels ) in enumerate ( dataloader_train ):
optimizer . zero_grad ()
loss = regressor . sample_elbo ( inputs = datapoints ,
labels = labels ,
criterion = criterion ,
sample_nbr = 3 )
loss . backward ()
optimizer . step ()
iteration += 1
if iteration % 100 == 0 :
ic_acc , under_ci_upper , over_ci_lower = evaluate_regression ( regressor ,
X_test ,
y_test ,
samples = 25 ,
std_multiplier = 3 )
print ( "CI acc: {:.2f}, CI upper acc: {:.2f}, CI lower acc: {:.2f}" . format ( ic_acc , under_ci_upper , over_ci_lower ))
print ( "Loss: {:.4f}" . format ( loss ))Penjelasan yang sangat cepat tentang bagaimana ketidakpastian yang diperkenalkan dalam jaringan saraf Bayesian dan bagaimana kami memodelkan kehilangannya untuk secara objektif meningkatkan kepercayaan diri atas prediksi dan mengurangi varian tanpa putus sekolah.
Seperti yang kita ketahui, pada lapisan jaringan saraf deterministik (non Bayesian), parameter yang dapat dilatih sesuai langsung dengan bobot yang digunakan pada transformasi linier dari yang sebelumnya (atau input, jika itu masalahnya). Itu sesuai dengan persamaan berikut:
(Z sesuai dengan output teraktivasi dari lapisan I)
Lapisan Bayesian berusaha untuk memperkenalkan ketidakpastian pada bobotnya dengan mencicipi mereka dari distribusi yang diparametrized dengan variabel yang dapat dilatih pada setiap operasi feedforward.
Hal ini memungkinkan kita tidak hanya untuk mengoptimalkan metrik kinerja model, tetapi juga mengumpulkan ketidakpastian prediksi jaringan di atas titik data tertentu (dengan mencicipinya berkali -kali dan mengukur dispersi) dan dengan hormat mengurangi sebanyak mungkin varian jaringan yang kita coba untuk fungsi, memungkinkan untuk mengetahui seberapa banyak ketidakcocokan yang masih kita miliki tentang label jika kita mencoba untuk menampilkannya dalam fungsi kita dalam fungsi kita dalam fungsi kita.
Untuk melakukannya, pada setiap operasi feedforward kami mencicipi parameter transformasi linier dengan persamaan berikut (di mana ρ parametri standar deviasi dan μ parametrizisasi rata -rata untuk sampel parameter transformasi linier):
Untuk bobot:
Di mana sampled w sesuai dengan bobot yang digunakan pada transformasi linier untuk lapisan ke -i pada sampel ke -n.
Untuk bias:
Di mana sampled b sesuai dengan bias yang digunakan pada transformasi linier untuk lapisan ke -i pada sampel ke -n.
Bahkan sulit kita memiliki pengganda acak untuk bobot dan bias kita, dimungkinkan untuk mengoptimalkannya dengan, mengingat beberapa fungsi yang dapat dibedakan dari bobot sampel dan parameter yang dapat dilatih (dalam kasus kami, kerugian), menjumlahkan turunan dari fungsi relatif terhadap keduanya:
Karena itu:
Dan
Diketahui bahwa kehilangan crossentropy (dan MSE) dapat dibedakan. Oleh karena itu jika kita membuktikan bahwa ada fungsi kompleksitas-biaya yang dapat dibedakan, kita dapat menyerahkannya pada kerangka kerja kita mengambil turunan dan menghitung gradien pada langkah optimasi.
Biaya kompleksitas dihitung, pada operasi feedforward, oleh masing-masing lapisan Bayesian, (dengan lapisan distribusi apriori yang telah ditentukan sebelumnya dan distribusi empirisnya). Jumlah biaya kompleksitas setiap lapisan disimpulkan untuk kerugian.
Seperti yang diusulkan dalam ketidakpastian berat dalam kertas jaringan saraf, kita dapat mengumpulkan biaya kompleksitas distribusi dengan mengambil divergensi Kullback-Leibler dari itu ke distribusi yang jauh lebih sederhana, dan dengan membuat beberapa perkiraan, kita akan dapat membedakan fungsi ini relatif terhadap variabelnya (distribusi):
Biarkan menjadi distribusi entropi rendah PDF yang ditetapkan dengan tangan, yang akan dianggap sebagai distribusi "a priori" untuk bobot
Biarkan menjadi PDF distribusi empiris posteriori untuk bobot sampel kami, mengingat parameternya.
Oleh karena itu, untuk setiap skalar pada matriks sampel W:
Dengan mengasumsikan N yang sangat besar, kita bisa mendekati:
dan karena itu:
Karena yang diharapkan (rata-rata) dari distribusi Q berakhir dengan hanya menskalakan nilai-nilai, kita dapat mengeluarkannya dari persamaan (karena tidak akan ada pelacakan kerangka kerja). Memiliki biaya kompleksitas sampel ke -n sebagai:
Yang dapat dibedakan relatif terhadap semua parameternya.
Oleh karena itu seluruh fungsi biaya pada sampel bobot ke -n adalah:
Kami dapat memperkirakan fungsi biaya penuh yang sebenarnya dengan Monte Carlo mencicipinya (memberi makan Netwok x kali dan mengambil rata -rata kerugian penuh) dan kemudian kembali menggunakan nilai estimasi kami. Ini bekerja untuk rendahnya jumlah percobaan per backprop dan bahkan untuk percobaan kesatuan.
Kami tiba di akhir tutorial Bayesian Deep Learning dalam nutshell. Dengan mengetahui apa yang sedang dilakukan di sini, Anda dapat mengimplementasikan model BNN Anda sesuai keinginan.
Mungkin Anda dapat mengoptimalkan dengan melakukan satu langkah mengoptimalkan per sampel, atau dengan menggunakan metode Monte-Carlo-ish ini untuk mengumpulkan kerugian beberapa kali, mengambil rata-rata dan kemudian pengoptimal. Langkah Anda.
FYI: Lapisan dan util Bayesian kami membantu menghitung biaya kompleksitas di sepanjang lapisan pada setiap operasi feedforward, jadi jangan terlalu keberatan.
Jika Anda menggunakan BLiTZ dalam penelitian Anda, Anda dapat mengutipnya sebagai berikut:
@misc { esposito2020blitzbdl ,
author = { Piero Esposito } ,
title = { BLiTZ - Bayesian Layers in Torch Zoo (a Bayesian Deep Learing library for Torch) } ,
year = { 2020 } ,
publisher = { GitHub } ,
journal = { GitHub repository } ,
howpublished = { url{https://github.com/piEsposito/blitz-bayesian-deep-learning/} } ,
}