ベイジアンネットワークの背後にある理論を理解し、実際に構築するのに何が必要か疑問に思っています。この例では、100個の離散確率変数のベイジアン(有向)ネットワークがあるとします。各変数は、最大10個の値のいずれかを取ることができます。
すべてのノードをDAGに保存し、各ノードについて条件付き確率テーブル(CPT)を保存しますか?一部のCPTが変更されたときに(DAGで使用されるものとは別に)値の効率的な計算を保証するために使用する必要がある他のデータ構造はありますか?
ベイジアンネットワークの背後にある理論を理解し、実際に構築するのに何が必要か疑問に思っています。この例では、100個の離散確率変数のベイジアン(有向)ネットワークがあるとします。各変数は、最大10個の値のいずれかを取ることができます。
すべてのノードをDAGに保存し、各ノードについて条件付き確率テーブル(CPT)を保存しますか?一部のCPTが変更されたときに(DAGで使用されるものとは別に)値の効率的な計算を保証するために使用する必要がある他のデータ構造はありますか?
回答:
「最適な」データ構造は、おそらく、解決しようとしている特定の問題に依存します。私が見た(そして自分で使った)アプローチの1つは、すべての情報を単に保存し、それをどうするかをアルゴリズムに任せるというものです。
まず、0〜n-1の一意の整数でノードにインデックスを付けます。次に、各ノードについて、その親のリストを整数の配列として単純に保存します。たとえば、C ++では、std::vector<std::vector<int> >
ノード上の最初のベクトル、それぞれの親の2番目のベクトルがあります)。これにより、DAG構造全体がキャプチャされます。
さらに、各ノードには1つの条件付き確率テーブルが関連付けられているため、同じ整数IDでインデックスを付けることができます。確率表ごとに、そのスコープ、つまり定義されたランダム変数のセットを保存する必要があります。次に、実際の条件付き確率を含む浮動小数点数の大きなリストが1つあります(インデックス付けが正しいことを確認する必要があります)。もう一度C ++の例を挙げると、次のようなことができます。
struct CondProbTable {
std::vector<int> scope; // list of random variables the CPT is defined over
std::vector<double> table; // appropriately sized and indexed table of
// conditional probabilities
};
これにより、a std::vector<CondProbTable>
を使用してすべてのCPTを保存できます。
繰り返しますが、これは基本的にBayesネットのみを保存するものであり、何をしたいかについては何も想定していません。CondProbTableにCPTスコープを含めることは、ポイント1で説明した親ノードのリストから推測できるため、いくぶん冗長です。
基本的に離散CPTはハイパーマトリックスであり、このように見る必要があります。
ハイパーマトリックスを表す非常に一般的な方法は、文字列インデックスを使用してハッシュテーブルを使用することです。たとえば、2次元ではt [1] [2]はt.get( "1_2")になります
よりメモリ効率の良いソリューションが可能です。ハイパーマトリックスがスパースの場合、特別なスパース表現(例:Fuchs 72)を使用できます。構造があれば、ADD(アルゴリズム決定図)または論理ベースのルールを使用できます。
最後の質問はあまり明確ではありませんが、CPTを頻繁に変更すると予想される場合は、テーブルまたはハッシュテーブルのいずれかでCPTをフラットに表現する方がよいでしょう。