使用 Infer.NET 進行機率編程

本文介紹瞭如何使用 Infer.NET 進行機率性編程。 機率性編程是一種將自定義模型表示爲計算機程序的機器學習方法。 藉助它能夠在模型中包含專業知識,使機器學習系統更易理解。 它還支持在線推斷,即在新數據到達時進行學習的過程。 Azure、Xbox 及必應中的多種 Microsoft 產品均使用了 Infer.NET。編程

什麼是機率性編程?

基於機率性編程,建立對真實世界過程的統計模型。app

系統必備

  • 本地.NET開發環境設置機器學習

建立應用程序

  1. 打開一個新的命令提示符,並運行下面的命令:
dotnet new console -o myApp
cd myApp

dotnet 命令將建立 console 類型的 new 應用程序。 -o 參數將建立名稱爲 myApp 的目錄,會在其中存儲應用並填充所需的文件。 cd myApp 命令會將你轉到新建立的應用目錄。編輯器

安裝 Infer.NET 包

需安裝 Microsoft.ML.Probabilistic.Compiler 包才能使用 Infer.NET。 在命令提示符中運行下面的命令:學習

dotnet add package Microsoft.ML.Probabilistic.Compiler

設計模型

示例使用在室內中進行的乒乓球或桌上足球比賽。 咱們具備參賽者的信息和每場比賽的結果。 咱們想要經過此數據推斷玩家的實力。 假設每位玩家的潛在實力呈正態分佈,且他們在給定比賽中的表現是此實力受干擾後的狀態。數據被設定的約束條件是贏家的表現大於輸家的表現。 這是熱門的 TrueSkill 模型的簡化版,此模型也支持團隊、平局及其餘擴展項。 熱銷的 Halo 和 Gears of War 遊戲中的比賽安排使用了此模型的高級版ui

咱們須要列出所推斷玩家的實力以及他們的差別(衡量實力的不肯定性)。this

遊戲結果示例數據編碼

遊戲 勝者 敗者
1 玩家 0 玩家 1
2 玩家 0 玩家 3
3 玩家 0 玩家 4
4 玩家 1 玩家 2
5 玩家 3 玩家 1
6 玩家 4 玩家 2

仔細觀察樣本數據,你會發現玩家3和4都有1次勝利和1次失敗。 讓咱們看看使用機率編程的排名是什麼樣的。另請注意基於咱們開發的編碼習慣,玩家編號是從零開始的,即便是室內遊戲匹配列表也是從零開始的。spa

編寫代碼

設計模型後,就可使用 Infer.NET 建模 API 將其表示爲機率性程序。 在經常使用的文本編輯器中,打開 Program.cs,並將其全部內容替換爲如下代碼:設計

namespace myApp

{
    using System;
    using System.Linq;
    using Microsoft.ML.Probabilistic;
    using Microsoft.ML.Probabilistic.Distributions;
    using Microsoft.ML.Probabilistic.Models;

    class Program
    {

        static void Main(string[] args)
        {
            // The winner and loser in each of 6 samples games
            var winnerData = new[] { 0, 0, 0, 1, 3, 4 };
            var loserData = new[] { 1, 3, 4, 2, 1, 2 };

            // Define the statistical model as a probabilistic program 
            var game = new Range(winnerData.Length);
            var player = new Range(winnerData.Concat(loserData).Max() + 1);
            var playerSkills = Variable.Array<double>(player);
            playerSkills[player] = Variable.GaussianFromMeanAndVariance(6, 9).ForEach(player);

            var winners = Variable.Array<int>(game);
            var losers = Variable.Array<int>(game);

            using (Variable.ForEach(game))
            {
                // The player performance is a noisy version of their skill
                var winnerPerformance = Variable.GaussianFromMeanAndVariance(playerSkills[winners[game]], 1.0);
                var loserPerformance = Variable.GaussianFromMeanAndVariance(playerSkills[losers[game]], 1.0);

                // The winner performed better in this game
                Variable.ConstrainTrue(winnerPerformance > loserPerformance);
            }

            // Attach the data to the model
            winners.ObservedValue = winnerData;
            losers.ObservedValue = loserData;

            // Run inference
            var inferenceEngine = new InferenceEngine();
            var inferredSkills = inferenceEngine.Infer<Gaussian[]>(playerSkills);

            // The inferred skills are uncertain, which is captured in their variance
            var orderedPlayerSkills = inferredSkills
               .Select((s, i) => new { Player = i, Skill = s })
               .OrderByDescending(ps => ps.Skill.GetMean());

            foreach (var playerSkill in orderedPlayerSkills)
            {
                Console.WriteLine($"Player {playerSkill.Player} skill: {playerSkill.Skill}");
            }
        }
    }
}

運行你的應用

在命令提示符中運行下面的命令:

dotnet run

結果

結果應以下所示:

Compiling model...done.
Iterating:
.........|.........|.........|.........|.........| 50
Player 0 skill: Gaussian(9.517, 3.926)
Player 3 skill: Gaussian(6.834, 3.892)
Player 4 skill: Gaussian(6.054, 4.731)
Player 1 skill: Gaussian(4.955, 3.503)
Player 2 skill: Gaussian(2.639, 4.288)

在結果中,請注意,根據咱們的模型,玩家3的排名略高於玩家4。 這是由於玩家3打敗了玩家1的意義大於玩家4打敗玩家2的意義 - 注意玩家1擊敗過玩家2,玩家0是總冠軍!

相關文章
相關標籤/搜索