2019 年 2 月

# 使用 Infer.NET 來為競爭者評分

Infer.NET 是開放原始碼庫，可用來建立隨機性程式設計系統。我傾向於將做為主要以變數指定的類型，例如 char 變數，其值為"Q"。 值為基礎的其中一個或-dinary 電腦 program 機率程式設計主要根據機率分佈，例如高斯分佈，其中有平均 0.0 和 1.0 的標準差。

## 示範程式結構

[圖 2 的完整原始碼

``````using System;
using Microsoft.ML.Probabilistic.Models;
using Microsoft.ML.Probabilistic.Algorithms;
using Microsoft.ML.Probabilistic.Distributions;
// VS2017 (Framework 4.7) Infer.NET 0.3.1810.501

namespace InferStrengths
{
class InferStrengthsProgram
{
static void Main(string[] args)
{
Console.WriteLine("Begin Infer.NET demo ");

// ===== Set up teams and win-loss data =====================

string[] teamNames = new string[] { "Angels", "Bruins",
"Comets", "Demons", "Eagles", "Flyers" };
int N = teamNames.Length;

int[] winTeamIDs =  new int[] { 0, 2, 1, 0, 1, 3, 0, 2, 4 };
int[] loseTeamIDs = new int[] { 1, 3, 2, 4, 3, 5, 5, 4, 5 };

Console.WriteLine("Data: \n");
for (int i = 0; i < winTeamIDs.Length; ++i) {
Console.WriteLine("game: " + i + "   winning team: " +
teamNames[winTeamIDs[i]] + "   losing team: " +
teamNames[loseTeamIDs[i]]);
}

// ===== Define a probabilistic model =======================

Range teamIDsRange = new Range(N).Named("teamsIDRange");
Range gameIDsRange =
new Range(winTeamIDs.Length).Named("gameIDsRange");

double mean = 2000.0;
double sd = 200.0;
double vrnc = sd * sd;

Console.WriteLine("\nDefining Gaussian model mean = " +
mean.ToString("F1") + " and sd = " + sd.ToString("F1"));
VariableArray<double> strengths =
Variable.Array<double>(teamIDsRange).Named("strengths");

strengths[teamIDsRange] =
Variable.GaussianFromMeanAndVariance(mean,
vrnc).ForEach(teamIDsRange);

VariableArray<int> winners =
Variable.Array<int>(gameIDsRange).Named("winners");
VariableArray<int> losers =
Variable.Array<int>(gameIDsRange).Named("losers");

winners.ObservedValue = winTeamIDs;
losers.ObservedValue = loseTeamIDs;

using (Variable.ForEach(gameIDsRange))
{
var ws = strengths[winners[gameIDsRange]];
var ls = strengths[losers[gameIDsRange]];
Variable<double> winnerPerf =
Variable.GaussianFromMeanAndVariance(ws, 400).Named("winPerf");
Variable<double> loserPerf =
Variable.GaussianFromMeanAndVariance(ls, 400).
Named("losePerf");

Variable.ConstrainTrue(winnerPerf > loserPerf);
}

// ===== Infer team strengths using win-loss data ===========

Console.WriteLine("\nInferring strengths from win-loss data");
var iengine = new InferenceEngine();
iengine.Algorithm = new ExpectationPropagation();
iengine.NumberOfIterations = 40;
// iengine.ShowFactorGraph = true;  // needs Graphviz install

Gaussian[] inferredStrengths =
iengine.Infer<Gaussian[]>(strengths);
Console.WriteLine("Inference complete. Inferred strengths: ");

// ===== Show results =======================================

for (int i = 0; i < N; ++i) {
double strength = inferredStrengths[i].GetMean();
Console.WriteLine(teamNames[i] + ": " +
strength.ToString("F1"));
}

Console.WriteLine("\nEnd demo ");
} // Main
}
} // ns
``````

## 設定資料

``````string[] teamNames = new string[] { "Angels", "Bruins",
"Comets", "Demons", "Eagles", "Flyers" };
int N = teamNames.Length;
``````

Infer.NET 主要適用於隨機變數，因為在許多程式中所有資料都都會完全是數字。在這裡，小組名稱指定為字串，而不是整數索引只以提高可讀性。輸贏資料是：

``````int[] winTeamIDs =
new int[]  { 0, 2, 1, 0, 1, 3, 0, 2, 4 };
int[] loseTeamIDs =
new int[]  { 1, 3, 2, 4, 3, 5, 5, 4, 5 };
``````

``````for (int i = 0; i < winTeamIDs.Length; ++i) {
Console.WriteLine("game: " + i + " winning team: " +
teamNames[winTeamIDs[i]] + " losing team: " +
teamNames[loseTeamIDs[i]]);
}
``````

## 定義在機率模型

``````Range teamIDsRange = new Range(N).Named("teamsIDRange");
Range gameIDsRange =
new Range(winTeamIDs.Length).Named("gameIDsRange");
double mean = 2000.0;
double sd = 200.0;
double vrnc = sd * sd;
``````

``````VariableArray<double> strengths =
Variable.Array<double>(teamIDsRange).Named("strengths");
strengths[teamIDsRange] =
Variable.GaussianFromMeanAndVariance(mean,
vrnc).ForEach(teamIDsRange);
``````

``````Variable<double>[] arr = new Variable<double>[6];
for (int i = 0; i < 6; ++i)
arr[i] = Variable.GaussianFromMeanAndVariance(2000, 4000);
``````

``````VariableArray<int> winners =
Variable.Array<int>(gameIDsRange).Named("winners");
VariableArray<int> losers =
Variable.Array<int>(gameIDsRange).Named("losers");
winners.ObservedValue = winTeamIDs;
losers.ObservedValue = loseTeamIDs;
``````

``````using (Variable.ForEach(gameIDsRange)) {
var ws = strengths[winners[gameIDsRange]];
var ls = strengths[losers[gameIDsRange]];
Variable<double> winnerPerf =
Variable.GaussianFromMeanAndVariance(ws,
400.0).Named("winPerf");
Variable<double> loserPerf =
Variable.GaussianFromMeanAndVariance(ls,
400.0).Named("losePerf");

Variable.ConstrainTrue(winnerPerf > loserPerf);
}
``````

ConstrainTrue 陳述式會是關鍵，並加入可讓推斷引擎，來計算每個小組的強度的邏輯。是推斷引擎會使用複雜的演算法，來檢查不同的值，表示和變異數的六個的每個小組，並接著會判斷有多少觀察到的輸贏結果指定假設的方式和變異數。推斷演算法找到最佳比對觀察到的資料的變異數的六個方法。聰明 ！

## 推斷小組優點

``````var iengine = new InferenceEngine();
iengine.Algorithm = new ExpectationPropagation();
iengine.NumberOfIterations = 40;
// iengine.ShowFactorGraph = true;
``````

Infer.NET 支援三種不同的演算法： 期望傳播、 variational 訊息傳遞和 Gibbs 取樣。不同的演算法適用於不同類型的不確定性的模型。示範模型只期望傳播是有效的。期望傳播特有 Infer.NET 和 Kullback Liebler 分歧度量，來模擬機率分佈的一組觀察到的資料降到最低。來試驗和錯誤，就必須判斷 NumberOfIterations 屬性的值。

Infer.NET 的有趣功能是您可以自動產生的模型計算圖形中，例如中的視覺表示法**[圖 3** ，其對應於示範程式。這項功能會對開放原始碼 Graphviz 程式中的相依性。如果您將 ShowFactorGraph 為 true，而且安裝 Graphviz，圖形將會儲存在目前的工作目錄中的 SVG 格式，並不會顯示在瀏覽器中。

[圖 3 的計算圖形的視覺表示法

``````Gaussian[] inferredStrengths =
iengine.Infer<Gaussian[]>(strengths);
for (int i = 0; i < N; ++i) {
double strength = inferredStrengths[i].GetMean();
Console.WriteLine(teamNames[i] + ": " + strength);
}
``````

## 總結

Dr。James McCaffrey適用於在美國華盛頓州雷德蒙的 Microsoft Research他曾經有幾份 Microsoft，包括 Internet Explorer 和 Bing。Dr。McCaffrey 要聯絡jamccaff@microsoft.com

MSDN Magazine 論壇中的這篇文章的討論