1. 程式人生 > >概率軟邏輯(PSL,Probabilistic soft logic)示例演練和模塊解釋

概率軟邏輯(PSL,Probabilistic soft logic)示例演練和模塊解釋

keyword sant 一個 bre att database specific ecif 改變

這裏將引導您完成Simple Acquaintances示例的Groovy版本。

一、建立示例項目

??首先,確保您的系統滿足先決條件。然後克隆psl-examples存儲庫:

git clone https://github.com/linqs/psl-examples.git

二、運行

??進入簡單groovy示例的根目錄:

cd psl-examples/simple-acquaintances/groovy

??在根目錄下運行(這裏特別容易失敗):

mvn compile
mvn eclipse:eclipse     //把項目編譯成eclipse版本

??通過eclipse裏的maven導入項目後,無報錯即可運行,結果如下:

0    [main] INFO  org.linqs.psl.examples.simpleacquaintances.Run  - Defining model rules
139  [main] INFO  org.linqs.psl.examples.simpleacquaintances.Run  - Loading data into database
171  [main] INFO  org.linqs.psl.examples.simpleacquaintances.Run  - Starting inference
389  [main] INFO  org.linqs.psl.application.inference.LazyMPEInference  - Beginning inference round 1.
488  [main] INFO  org.linqs.psl.reasoner.admm.ADMMReasoner  - Optimization completed in 411 iterations. Primal res.: 0.028260373, Dual res.: 9.052008E-4
488  [main] INFO  org.linqs.psl.application.inference.LazyMPEInference  - Inference round 1 complete.
566  [main] INFO  org.linqs.psl.application.inference.LazyMPEInference  - Beginning inference round 2.
566  [main] INFO  org.linqs.psl.reasoner.admm.ADMMReasoner  - Optimization completed in 1 iterations. Primal res.: NaN, Dual res.: NaN
566  [main] INFO  org.linqs.psl.application.inference.LazyMPEInference  - Inference round 2 complete.
584  [main] INFO  org.linqs.psl.examples.simpleacquaintances.Run  - Inference complete
631  [main] INFO  org.linqs.psl.examples.simpleacquaintances.Run  - Accuracy: 0.400000, F1: 0.280000, Positive Class Precision: 0.466667, Positive Class Recall: 0.200000, Negative Class Precision: 0.377778, Negative Class Recall: 0.680000

??要查看示例的輸出,請檢查groovy下的inferred-predicates/KNOWS.txt文件:

inferred-predicates/KNOWS.txt

??應該看到一些輸出,如:

‘Arti‘ ‘Ben‘  0.48425865173339844
‘Arti‘ ‘Steve‘       0.5642937421798706
< ... 48 rows omitted for brevity ...>
‘Jay‘  ‘Dhanya‘      0.4534565508365631
‘Alex‘ ‘Dhanya‘      0.48786869645118713

??輸出的確切順序可能會改變,為簡潔起見,省略了一些行。
??現在我們已經運行了示例,讓我們看看示例中唯一的源文件:

src/main/java/org/linqs/psl/examples/simpleacquaintances/Run.groovy。

三、Groovy源碼文件解析

1. 配置(Configuration)

??在構造函數中,您可以看到創建的ConfigBundle:

config = ConfigManager.getManager().getBundle("simpleacquaintances");

??請註意,傳入的字符串getBundle()是此配置集的前綴。這意味著特定於此程序的所有配置鍵都應該以前綴simpleacquaintances為前綴。

2. 謂詞定義(Defining Predicates)

??該definePredicates()方法為我們的示例定義了三個謂詞:

model.add predicate: "Lived", types: [ConstantType.UniqueStringID, ConstantType.UniqueStringID]; 
model.add predicate: "Likes", types: [ConstantType.UniqueStringID, ConstantType.UniqueStringID]; 
model.add predicate: "Knows", types: [ConstantType.UniqueStringID, ConstantType.UniqueStringID];

??這裏的每個謂詞都有兩個唯一的屬性為字符串標識符的作為參數,請註意,對於唯一標識符(Unique),ConstantType.UniqueStringID和ConstantType.UniqueIntID都是可用的。值得一提的是,擁有整數標識符通常需要在用戶方面進行更多預處理,但能獲得更好的性能。

謂詞釋義:
??? Lived 表示一個人住在特定的位置。例如:Lived(Sammy,SantaCruz)表示Sammy住在Santa Cruz。
??? Likes 表示一個人喜歡某事的程度。例如:Likes(Sammy,Hiking)會表明Sammy喜歡徒步旅行的程度。
??? Knows 表明一個人認識其他人。例如:Knows(Sammy,Jay)會表示Sammy和Jay相互認識。

3. 規則定義(Defining Rules)

??該defineRules()方法為該示例定義了六個規則。有些頁面涵蓋了PSL 規則規範和Groovy中的規則規範。我們將討論以下兩條規則:

model.add( rule: "20: Lived(P1, L) & Lived(P2, L) & (P1 != P2) -> Knows(P1, P2) ^2" ); 
model.add( rule: "5: !Knows(P1, P2) ^2" );

??第一條規則可以理解為 “ 如果P1和P2是不同的兩個人,並且兩者都住在同一個地方L,那麽他們彼此認識 ” 。此規則需要註意的一些要點是:

??? 變量L在兩個Lived原子中重復使用,因此必須引用相同的位置L。
??? (P1 != P2)指的是P1和P2是不同的人(不同的獨特ID)。

??第二條規則是作為先驗的特殊規則。請註意這條規則與其他所有規則的含義並不相同。相反,此規則可以理解為“默認情況下,人們彼此不了解”。因此,該項目將首先相信沒有人相互了解,並且這個先驗的觀念將被其他定義的規則作為證據來克服。

4. 加載數據(Loading Data)

??該loadData()方法將數據從data目錄中的文件加載到PSL正在使用的虛擬數據存儲庫中。為了便於理解,我們來查看兩個文件:

Inserter inserter = dataStore.getInserter(Lived, obsPartition); 
inserter.loadDelimitedData(Paths.get(DATA_PATH, "lived_obs.txt").toString()); 
inserter = dataStore.getInserter(Likes, obsPartition); 
inserter.loadDelimitedDataTruth(Paths.get(DATA_PATH, "likes_obs.txt").toString());

??兩個部分都使用一個加載數據Inserter。兩個調用之間的主要區別在於第二個調用正在加載真值,而第一個調用默認真值是1。
??如果我們查看文件內容,我們會看到以下行:


../data/lives_obs.txt

Jay    Maryland
Jay    California

../data/likes_obs.txt

Jay    Machine Learning  1
Jay    Skeeball 0.8

??在lives_obs.txt,沒有必要使用真值,因為生活在某個地方是一個離散的行為。你要麽住在那裏,要麽沒有。然而,喜歡某些東西為連續的軟真值會更符合常理。如:Jay有 100%的可能會喜歡機器學習,但他只有80%的可能喜歡Skeeball。

5. 分區(Partitions)

??在PSL中,使用分區來組織數據。分區只不過是數據的容器,但我們使用它們將特定的數據塊保存在一起或分開。例如,如果我們正在運行結果評估模塊,我們必須確保在訓練中不使用我們的測試分區。
??PSL用戶通常在至少三個不同的分區中組織他們的數據(在本例中您可以看到所有這些分區):
???obsPartition 在這個例子中稱為觀察分區:在這個分區中我們放置了實際的觀察數據。在這個例子中,我們把關於誰住在哪裏,誰喜歡什麽,誰知道誰在觀察分區中的所有觀察。
???targetsPartition 在本例中稱為目標分區:在這個分區中,我們放置了我們想要推斷的值的原子。例如,如果我們想要推斷Jay和Sammy相互認識的概率,那麽我們會將原子Knows(Jay, Sammy)放入目標分區。
???truthPartition 在這個例子中稱為事實分區:在這個分區中,我們放置了實際值的數據,但不包括在我們的已知觀察數據,目的用於評估模型推理效果。例如,如果我們知道Jay和Sammy確實相互了解,我們會將Knows(Jay, Sammy)事實分區放入真值1。

6. 運行推理(Running Inference)

??該runInference()方法處理我們加載的所有數據的運行推理。
??在我們進行推理之前,我們必須建立一個用於推理的數據庫:

Database inferDB = dataStore.getDatabase(targetsPartition, [Lived, Likes] as Set, obsPartition);

??getDatabase()方法對於DataStore是獲得一個數據庫的正確方法。此方法至少需要兩個參數:

???允許此數據庫寫入的分區targetsPartition。在推理中,我們將原子的推斷真值寫入目標分區,因此我們需要將其打開以進行寫入。
???要在寫入分區中關閉的一組分區obsPartition。即使我們將值寫入寫分區,我們可能只有一些謂詞,我們實際上想要推斷它們的值。此參數允許您關閉那些沒有更改的謂詞(封閉謂詞)。最後,getDatabase()獲取要包含在此數據庫中的任意數量的只讀分區。在我們的示例中,我們希望在進行推理時包含我們的觀察結果。

??接下來我們準備推理部分:

InferenceApplication inference = new MPEInference(model, inferDB);
inference.inference();
inference.close();
inferDB.close();

??對於MPEInference構造函數,我們提供我們的模型和數據庫來推斷。要查看結果,我們需要查看目標分區。

7. 輸出(Output)

??該方法writeOutput()處理打印(輸出)出推斷的結果。此方法有兩個關鍵行:

Database resultsDB = ds.getDatabase(targetsPartition);
...
for (GroundAtom atom : resultsDB.getAllGrondAtoms(Knows)) {

??第一行得到一個新的數據庫,我們可以從中獲取原子。請註意,我們把targetsPartition作為寫分區傳入,但實際上我們只是從它讀取已經推理得到的結果數據。
??第二行使用Queries來叠代此數據庫中的所有為 Knows 的原子。

8. 評估(Evaluation)

??最後,用evalResults()方法評判我們的模型的效果。本DiscreteEvaluator類提供基本的工具來比較兩個分區。在這個例子中,我們將目標分區與真值分區進行比較。

private void evalResults(Partition targetsPartition, Partition truthPartition) {
        Database resultsDB = dataStore.getDatabase(targetsPartition);
        Database truthDB = dataStore.getDatabase(truthPartition, [Knows] as Set);

        Evaluator eval = new DiscreteEvaluator();
        eval.compute(resultsDB, truthDB, Knows);
        log.info(eval.getAllStats());

        resultsDB.close();
        truthDB.close();
}

概率軟邏輯(PSL,Probabilistic soft logic)示例演練和模塊解釋