2015-01-07 60 views
0

我正在使用Javascript實現特定的貝葉斯網絡庫。 因爲我找不到任何其他在線可用的庫,我不得不從頭開始,包括乘法和邊緣化概率表(或潛在性)。乘法和邊緣化概率表的算法

在邊緣化中,被邊緣化的變量列被取出。 然後總結常見的行。 例如,c將被從表phi(a,b,c)邊緣化。 的,相對於ç列被取出並共同行一個b被相加,即,(0,0)(1,1)總和分別爲0.3和0.1, 。 enter image description here

在乘法中,我們查看相同值的公共變量(列)。 然後我們乘以匹配的行。例如,表phi(a,b)phi(b,c)將被相乘。 公共欄爲b。 其中b在兩個表中都有0(所有可能的組合),我們將這些值相乘。 Multiplication of two potentials

我第一次嘗試是實現在地圖的方式,其中每行是一個關鍵和概率值的表是。 但它似乎並不是一個好主意,因爲要實現乘法,我們需要知道變量的標籤。因此,爲了從函數參數中獲取標籤,我修改了一些代碼,但它不起作用,因爲行與標籤沒有直接關係。 所以,我把這段代碼放在一邊,現在我正在尋找新的想法。

請問,有人對如何實現這些例子有任何想法?

+0

這會不會是困難的,如果你能解釋一下計算的工作究竟如何,他們不是在直觀快速看。 – Nit

+1

「*因此,我修改了代碼... *」。什麼代碼?這純粹是一種映射練習,還是有計算邊緣化的算法? – RobG

+0

我剛剛修改了描述@Nit,以增加有關乘法和邊緣化操作的更多細節。謝謝。 – jhonatanoliveira

回答

1

以下似乎是做到邊緣化的工作。它創建一個具有成員和值的行的表。表格中的每一行必須具有相同數量的成員。

它還沒有實現乘法(真正的工作必須在某個時候完成......)。請注意,在ECMAScript中,0.1 + 0.2 = 0.30000000000000004因此您需要實施某種舍入來修復並保持準確性。

/** 
* A table has rows, all rows within a table have the same number of members 
* Each row as 1 to n members plus a value 
* e.g. a = 0, b = 0, c = 0, value = 0.1 
*  a = 0, b = 0, c = 1, value = 0.2 
*  a = 1, b = 0, c = 0, value = 0.1 
*  a = 1, b = 1, c = 0, value = 0.1 
*  a = 1, b = 1, c = 1, value = 0.1 
* 
* Marginalisation addition takes the values of matching values and sums them, 
* 
* e.g. 
*  marginalisation of {a, b} where a=0 and b=0: 
*  matching rows are 0 and 1, so add 0.1 + 0.2 => 0.3 
* 
*  marginalisation of {a, b} where a=1 and b=1: 
*  matching rows are 3 and 4, so add 0.1 + 0.1 => 0.2 
* 
* @param {number} numberOfValues - number of values in each row. So for 3 members 
*         plus value then numberOfValues is 4 
*/ 
function BayTable (numberOfValues) { 

    // Array containing rows of values 
    this.rows = []; 

    // Number of values in a row, so for [a, b, c, value] memberCount is 4 
    this.memberCount = numberOfValues; 
} 

/** 
* @param {number} memberValue[, memberValue, ...], rowValue 
* 
* e.g. addRow(0, 0, 0, 0.1) 
*/ 
BayTable.prototype.addRow = function() { 

    if (arguments.length != this.memberCount) return; // or throw error 

    var row = []; 

    for (var i=0, iLen=arguments.length; i<iLen; i++) { 
    row.push(arguments[i]); 
    } 
    this.rows.push(row); 
} 

/** 
* marginalise finds matching rows and adds their values, 
* so marginalise(0,0) finds rows where a=0 and b=0 ignoring 
* any other member in the row and 
* sums the value for the rows 
*/ 
BayTable.prototype.marginalise = function() { 

    // Guard agains too many arguments 
    if (arguments.length > this.memberCount - 2) return; // or throw error 

    var total = 0; 
    var row, match; 

    // For each row 
    for (var i=0, iLen=this.rows.length; i<iLen; i++) { 
    row = this.rows[i]; 
    match = true 

    // Check values against arguments until a missmatch 
    for (var j=0, jLen=arguments.length; j<jLen && match; j++) { 
     match = row[j] === arguments[j]; 
    } 

    // If no missmatch, add row value 
    if (match) total += row[row.length - 1]; 
    } 
    return total; 
} 

var x = new BayTable(4); 
x.addRow(0, 0, 0, 0.1); 
x.addRow(0, 0, 1, 0.2); 
x.addRow(1, 0, 0, 0.1); 
x.addRow(1, 1, 0, 0.1); 
x.addRow(1, 1, 1, 0.1); 

console.log(x.marginalise(0, 0)); // 0.30000000000000004 
console.log(x.marginalise(1, 0)); // 0.1 
console.log(x.marginalise(1, 1)); // 0.2 

這裏的對象版本,它使用一對夫婦的ES5方法:

/** 
* A table has rows, all rows within a table have the same number of members 
* Each row as 1 to n members plus a value 
* e.g. a = 0, b = 0, c = 0, value = 0.1 
*  a = 0, b = 0, c = 1, value = 0.2 
*  a = 1, b = 0, c = 0, value = 0.1 
*  a = 1, b = 1, c = 0, value = 0.1 
*  a = 1, b = 1, c = 1, value = 0.1 
* 
* Marginalisation addition takes the values of matching values and sums them, 
* 
* e.g. 
*  marginalisation of {a, b} where a=0 and b=0: 
*  matching rows are 0 and 1, so add 0.1 + 0.2 => 0.3 
* 
*  marginalisation of {a, b} where a=1 and b=1: 
*  matching rows are 3 and 4, so add 0.1 + 0.1 => 0.2 
* 
* @param {number} numberOfValues - number of values in each row. So for 3 members plus value 
*         then numberOfValues is 4 
*/ 
function BayTable (numberOfValues) { 

    // Array containing rows of values 
    this.rows = []; 

    // Number of values in a row, so for [a, b, c, value] memberCount is 4 
    this.memberCount = numberOfValues; 
} 

/** 
* @param {Object} row - {label:value[, label:value, ...], 'value':value} 
* 
* e.g. addRow({a:0, b:0, c:0, value:0.1}) 
*/ 
BayTable.prototype.addRow = function(row) { 
    this.rows.push(row); 
} 

/** 
* marginalise finds matching rows and adds their values, 
* so marginalise({a:0, b:0}) finds rows where a=0 and b=0 ignoring 
* any other member in the row and sums the values of matched rows 
*/ 
BayTable.prototype.marginalise = function(obj) { 

    var keys = Object.keys(obj); 

    // For each row 
    return this.rows.reduce(function(total, row) { 

    // If all key/values match, accumlate value 
    if (keys.every(function(key){return obj[key] === row[key]})) 
     total += row.value; 
    return total; 
    }, 0); 

/* 
    // Less obscure version, same number of lines of code 
    var total = 0; 
    var keys = Object.keys(obj); 

    // For each row 
    this.rows.forEach(function(row) { 

    // If key/values match, add row value to total 
    if (keys.every(function(key){return obj[key] === row[key]})) 
     total += row.value; 
    }); 
    return total; 
*/ 
} 


var x = new BayTable(4); 

x.addRow({a:0, b:0, c:0, value:0.1}); 
x.addRow({a:0, b:0, c:1, value:0.2}); 
x.addRow({a:1, b:0, c:0, value:0.1}); 
x.addRow({a:1, b:1, c:0, value:0.1}); 
x.addRow({a:1, b:1, c:1, value:0.1}); 

console.log(x.marginalise({a:0, b:0})); // 0.30000000000000004 
console.log(x.marginalise({a:1, b:0})); // 0.1 
console.log(x.marginalise({a:1, b:1})); // 0.2 
console.log(x.marginalise({a:1, c:1})); // 0.1 
console.log(x.marginalise({b:0, c:0})); // 0.2 
+0

這爲邊緣化做了工作,@RobG!我認爲你最大的觀點是你如何表示表格(作爲一個簡單的數組,包含變量的域*和值)。我正在使用一個Map,從變量的域到值。我認爲你的想法更好,因爲它更簡單。我會在我的代碼中試用它。非常感謝! – jhonatanoliveira

+0

我現在意識到,使用對象而不是數組可能會更好,在上面不可能邊緣化* {a,c} *,因爲成員是由位置而不是名稱表示的。這不是一個大變化。 – RobG

+0

好點。但是,你現在就如何處理這張桌子給了我深刻的見解。不管怎樣,謝謝你。 – jhonatanoliveira