Blitzは、Pytorchにベイジアンニューラルネットワーク層(ニューラルネットワークの重量の不確実性で提案されているものに基づく)を作成するためのシンプルで拡張可能なライブラリです。電撃層とUTILを使用することにより、標準のPytorchを使用しているかのように、層間の相互作用に影響を与えない簡単な方法でモデルの複雑さを簡単に収集できます。
コアウェイトサンプラークラスを使用することにより、このライブラリを拡張および改善して、Pytorch Wayによく統合されたように、より大きなレイヤーに不透明性を追加できます。また、プルリクエストは大歓迎です。
Blitzをインストールするには、PIPコマンドを使用できます。
pip install blitz-bayesian-pytorch
または、コンドラを介して:
conda install -c conda-forge blitz-bayesian-pytorch
また、それをgit-cloneして、ローカルにピップインストールすることもできます。
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 .
レイヤーのドキュメント、重量(および事前配布)サンプラーとutils:
(マシンでこの例を実行することで、自分のためにそれを見ることができます)。
これで、聖なる連続値予測ではなく、データポイント上に信頼区間を収集するために、ベイジアンディープラーニングを回帰に使用する方法を確認します。予測のために信頼区間を収集することは、低誤差の推定よりも有用な情報でさえあります。
私は、自信の間隔であるため、良い/高い問題で、いくつかのコンテキストで非常に近位の推定よりも信頼できる決定を下すことができるという事実についての私の議論を維持します。たとえば、良い信頼区間を持つことで、少なくとも、Wil Proceがより低くなるよりも(または高くなるよりも高い)価値があるかどうかを知ることができる場合。
確かに値が確実に(または確率が高い)かどうかを知ることは、賢明な決定をしている人々が、何らかの制限値よりも低いまたはそれ以上の場合、トランザクションに損失を引き起こす可能性があるという非常に近位の推定よりも多くの人を助けることができます。ポイントは、利益があるかどうかを知ることは、それを測定するよりも有用かもしれないということです。
それを実証するために、Boston-House-Data Toy Dataset用のベイジアンニューラルネットワークリグレッサーを作成し、予測しようとしている価格の信頼区間(CI)を作成しようとします。スケーリングを実行し、CIは約75%になります。予測されるCIの約90%が、高制限よりも低いまたは(包括的)低いものよりも高いことを見るのは興味深いでしょう。
既知のモジュールからのものにもかかわらず、Blitz Athe variational_estimatorデコレーターから持ち込みます。これは、モジュールのBayesianLinearリネア層を、残りのトーチと完全に統合したままにしておくのに役立ちます。
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 ここでは太陽の下で新しいものは何もありません。私たちは、トレーニングを支援するためにデータをインポートし、標準スケーリングしています。
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 ()トーチネットワークで行うように、Nn.moduleからの初期でクラスを作成できます。私たちのデコレーターは、ベイジアン層の複雑さのコストを計算し、損失をサンプリングするために多くのフィードフォワード(それぞれに異なる重みをサンプリング)を行うために、ベイジアンの特徴を処理する方法を紹介します。
@ 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_ )この関数は、ラベル値をサンプリングしようとしているバッチ上の各予測に対して信頼区間を作成します。次に、Predicton Distributionが実際にデータポイントの正しいラベルをどの程度含めたかを求めることにより、予測の精度を測定できます。
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 ()ここでは、他のニューラルネットワークと同じようにBayesianRegressorを作成することに注意してください。
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 )Sample_elboメソッドによって損失をサンプリングすることにより、一般的なトーチトレーニングとのみ異なるトレーニングループを行います。 Blitzでの私たちの目的は、さまざまなベイジアンNNSで問題を問題なく繰り返すことであなたの人生を緩和することであるため、他のすべてのことは正常に行うことができます。
これが私たちの非常にシンプルなトレーニングループです:
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 ))ベイジアンニューラルネットワークで不確実性がどのように導入されているか、およびその予測に対する信頼を客観的に改善し、ドロップアウトなしで分散を減らすために、その損失をモデル化する方法についての非常に高速な説明。
私たちが知っているように、決定論的な(非ベイズ)ニューラルネットワーク層では、トレーニング可能なパラメーターは、前のもの(またはそうである場合は、入力)の線形変換で使用される重みに直接対応します。次の方程式に対応します。
(zレイヤーiのアクティブ出力に対応)
ベイジアン層は、各フィードフォワード操作でトレーニング可能な変数によってパラメーター化された分布からそれらをサンプリングすることにより、重みに不確実性を導入しようとします。
これにより、モデルのパフォーマンスメトリックを最適化するだけでなく、特定のデータポイント上のネットワーク予測の不確実性を収集し(多くの場合サンプリングして分散を測定することにより)、予測上のネットワークの分散を可能な限り減らし、特定のデータパイントをモデル化しようとしている場合にまだレーベルがあるかどうかを知ることができます。
そうするために、各フィードフォワード操作で、線形変換のパラメーターを次の方程式でサンプリングします( ρパラメータ化標準偏差をパラメータ化し、 μはサンプル線形変換パラメーターの平均をパラメータ化します):
ウェイトの場合:
ここで、サンプリングされたwは、n番目のサンプル上のith層の線形変換で使用される重みに対応します。
バイアスのために:
サンプリングされたbが、n番目のサンプル上のith層の線形変換で使用されるバイアスに対応します。
タフでさえ、重みとバイアスにランダムな乗数を持っています。サンプリングされたパラメーターとトレーニング可能なパラメーターの差別化可能な関数(私たちの場合、損失)を考慮して、それらの両方に対する関数の導関数を合計して、それらを最適化することが可能です。
したがって:
そして
交差点損失(およびMSE)が微分可能であることが知られています。したがって、微分可能な複雑さコスト関数があることを証明する場合、フレームワークに導き誘導体を取り、最適化ステップで勾配を計算することができます。
複雑さのコストは、ベイジアン層のそれぞれによって、フィードフォワード操作で計算されます(層が事前に定義されたsimpler Apriori分布とその経験的分布を使用)。各層の複雑さの合計は、損失に合計されます。
ニューラルネットワークペーパーの重量の不確実性で提案されているように、カルバック繰り返しの発散をより単純な分布に導くことにより、分布の複雑さコストを収集できます。
手作業で設定された低エントロピー分布PDFにしましょう。これは、重みの「先験的」分布として想定されます
パラメーターを考慮して、サンプリングされた重みの事後経験的分布PDFにしましょう。
したがって、Wサンプリングマトリックスの各スカラーについて:
非常に大きなnを仮定することにより、概算することができます。
したがって、
Q分布の予想(平均)が値をスケーリングするだけで終わると、方程式からそれを取り除くことができます(フレームワーク追跡がないため)。次のようなn番目のサンプルの複雑さのコストを持っています
これは、そのすべてのパラメーターに対して微分可能です。
したがって、重みのn番目のサンプルのコスト関数全体は次のとおりです。
Monte Carloをサンプリングすることにより、真のフルコスト関数を推定し(Netwok X Timesをフィードフォードし、完全な損失を超えて平均を取る)、推定値を使用してBackPropagateを使用できます。バックプロップあたりの実験数が少ない場合も、単一の実験でも機能します。
一言で言えば、ベイジアンディープラーニングの終わりに来ました。ここで何が行われているかを知ることで、希望どおりにBNNモデルを実装できます。
サンプルごとに1つの最適化ステップを実行するか、このモンテカルロイッシュメソッドを使用して時々損失を収集し、その平均を取得してから最適化することにより、最適化することができます。あなたの動き。
FYI:ベイジアン層とUTILは、各フィードフォワード操作のレイヤーに沿った複雑さのコストを計算するのに役立ちますので、あまり気にしないでください。
調査でBLiTZ使用する場合、次のように引用できます。
@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/} } ,
}