スポンサーリンク

C#でMath.NET Numericsを使用する(統計計算編)

Math.NET Numericsは.NET Framework向けのオープンソースな数値計算用のライブラリです。基本的にはSystem.MathクラスなどのCLRが標準で用意している計算用ライブラリにない物やその拡張で、特殊関数、線形代数、確率モデル、乱数、補間、積分変換(FFT)を対象にしています。

Math.NET Numericsは.NET Framework 4.0, Mono 2.0, Silverlightで使用することが出来ます。

Math.NET NumericsのソースコードはGitHubでホストされ、MITライセンスの元公開されています。
git://github.com/mathnet/mathnet-numerics.git
(https://github.com/mathnet/mathnet-numerics)

詳しくは、Math.NET Numericsのサイトでご確認ください。
http://numerics.mathdotnet.com/

Math.NET Numericsの入手

一番手軽な入手方法はNuGetを使用する方法です。

GUIのNuGetパッケージの管理からMath.NETを検索する方法とパッケージマネージャーコンソールを使用する方法があります。

NuGetパッケージの管理を使用する方法

ソリューションエクスプローラーで参照設定を右クリックし、NuGetパッケージの管理を選択します。

①オンラインを選択

②検索ボックスに「Math.NET」と入力

③検索結果からMath.NET Numericsを選択し、表示されるInstallボタンをクリック。

※上図はインストール後の表示

パッケージマネージャーコンソールからのインストール

以下のように入力して、インストールします。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
PM> Install-<span class="hljs-keyword">Package</span> <span class="hljs-title">MathNet.Numerics</span>
PM> Install-<span class="hljs-keyword">Package</span> <span class="hljs-title">MathNet.Numerics</span>
PM> Install-Package MathNet.Numerics

統計計算

C#でMath.NETを使用した統計計算関数の使用方法です。

使用方法としてはこれといって難しいところは無いので、以下のサンプルと、ヘルプを見ていただければ、だいたいわかると思います。

標準偏差計算といった統計計算のライブラリはMathNet.Numerics.StatisticsネームスペースのStatisticsクラスにまとめられています。(オンラインのヘルプ)

以下はそのサンプルコードです。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.Statistics;
using System.Diagnostics;
namespace MathNetStatisticsSample
{
<span class="hljs-keyword">class</span> Program
{
static void <span class="hljs-constructor">Main(<span class="hljs-params">string</span>[] <span class="hljs-params">args</span>)</span> {
var sw = <span class="hljs-keyword">new</span> <span class="hljs-constructor">Stopwatch()</span>;
var rnd = <span class="hljs-keyword">new</span> System.<span class="hljs-constructor">Random()</span>;
double<span class="hljs-literal">[]</span> data = <span class="hljs-keyword">new</span> double<span class="hljs-literal">[<span class="hljs-number">10000000</span>]</span>;
<span class="hljs-built_in">int</span> i;
for (i = <span class="hljs-number">0</span>; i < <span class="hljs-number">10000000</span>; i++) {
data<span class="hljs-literal">[<span class="hljs-identifier">i</span>]</span> = rnd.<span class="hljs-constructor">NextDouble()</span>;
<span class="hljs-comment">//Console.Write(data[i] + ",");</span>
}
<span class="hljs-comment">//標本標準偏差</span>
sw.<span class="hljs-constructor">Start()</span>;
var stddiv = Statistics.<span class="hljs-constructor">StandardDeviation(<span class="hljs-params">data</span>)</span>;
sw.<span class="hljs-constructor">Stop()</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Standard Deviation = {0}"</span>, <span class="hljs-params">stddiv</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"{1}件入力で標本標準偏差の計算時間: {0}"</span>, <span class="hljs-params">sw</span>.Elapsed, <span class="hljs-params">i</span>)</span>;
<span class="hljs-comment">//母標準偏差</span>
sw.<span class="hljs-constructor">Reset()</span>;
sw.<span class="hljs-constructor">Start()</span>;
var pstddiv = Statistics.<span class="hljs-constructor">PopulationStandardDeviation(<span class="hljs-params">data</span>)</span>;
sw.<span class="hljs-constructor">Stop()</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Population Standard Deviation = {0}"</span>, <span class="hljs-params">pstddiv</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"{1}件入力で母標準偏差の計算時間: {0}"</span>, <span class="hljs-params">sw</span>.Elapsed, <span class="hljs-params">i</span>)</span>;
<span class="hljs-comment">//標本分散</span>
var variance = Statistics.<span class="hljs-constructor">Variance(<span class="hljs-params">data</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Variance = {0}"</span>, <span class="hljs-params">variance</span>)</span>;
<span class="hljs-comment">//母分散</span>
var pVariance = Statistics.<span class="hljs-constructor">PopulationVariance(<span class="hljs-params">data</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Population Variance = {0}"</span>, <span class="hljs-params">pVariance</span>)</span>;
<span class="hljs-comment">//最大値・最小値</span>
var max = Statistics.<span class="hljs-constructor">Maximum(<span class="hljs-params">data</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Maximum = {0}"</span>, <span class="hljs-params">max</span>)</span>;
var min = Statistics.<span class="hljs-constructor">Minimum(<span class="hljs-params">data</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Minimum = {0}"</span>, <span class="hljs-params">min</span>)</span>;
<span class="hljs-comment">//平均</span>
var mean = Statistics.<span class="hljs-constructor">Mean(<span class="hljs-params">data</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Mean = {0}"</span>, <span class="hljs-params">mean</span>)</span>;
<span class="hljs-comment">//メジアン(中央値)</span>
var median = Statistics.<span class="hljs-constructor">Median(<span class="hljs-params">data</span>)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Median = {0}"</span>, <span class="hljs-params">median</span>)</span>;
<span class="hljs-comment">//順序統計量</span>
var orderStatistic = Statistics.<span class="hljs-constructor">OrderStatistic(<span class="hljs-params">data</span>, 123)</span>;
Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Order Statisitc(i-Order = 123) = {0}"</span>, <span class="hljs-params">orderStatistic</span>)</span>;
Console.<span class="hljs-constructor">ReadLine()</span>;
}
}
}
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MathNet.Numerics.Statistics; using System.Diagnostics; namespace MathNetStatisticsSample { <span class="hljs-keyword">class</span> Program { static void <span class="hljs-constructor">Main(<span class="hljs-params">string</span>[] <span class="hljs-params">args</span>)</span> { var sw = <span class="hljs-keyword">new</span> <span class="hljs-constructor">Stopwatch()</span>; var rnd = <span class="hljs-keyword">new</span> System.<span class="hljs-constructor">Random()</span>; double<span class="hljs-literal">[]</span> data = <span class="hljs-keyword">new</span> double<span class="hljs-literal">[<span class="hljs-number">10000000</span>]</span>; <span class="hljs-built_in">int</span> i; for (i = <span class="hljs-number">0</span>; i < <span class="hljs-number">10000000</span>; i++) { data<span class="hljs-literal">[<span class="hljs-identifier">i</span>]</span> = rnd.<span class="hljs-constructor">NextDouble()</span>; <span class="hljs-comment">//Console.Write(data[i] + ",");</span> } <span class="hljs-comment">//標本標準偏差</span> sw.<span class="hljs-constructor">Start()</span>; var stddiv = Statistics.<span class="hljs-constructor">StandardDeviation(<span class="hljs-params">data</span>)</span>; sw.<span class="hljs-constructor">Stop()</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Standard Deviation = {0}"</span>, <span class="hljs-params">stddiv</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"{1}件入力で標本標準偏差の計算時間: {0}"</span>, <span class="hljs-params">sw</span>.Elapsed, <span class="hljs-params">i</span>)</span>; <span class="hljs-comment">//母標準偏差</span> sw.<span class="hljs-constructor">Reset()</span>; sw.<span class="hljs-constructor">Start()</span>; var pstddiv = Statistics.<span class="hljs-constructor">PopulationStandardDeviation(<span class="hljs-params">data</span>)</span>; sw.<span class="hljs-constructor">Stop()</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Population Standard Deviation = {0}"</span>, <span class="hljs-params">pstddiv</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"{1}件入力で母標準偏差の計算時間: {0}"</span>, <span class="hljs-params">sw</span>.Elapsed, <span class="hljs-params">i</span>)</span>; <span class="hljs-comment">//標本分散</span> var variance = Statistics.<span class="hljs-constructor">Variance(<span class="hljs-params">data</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Variance = {0}"</span>, <span class="hljs-params">variance</span>)</span>; <span class="hljs-comment">//母分散</span> var pVariance = Statistics.<span class="hljs-constructor">PopulationVariance(<span class="hljs-params">data</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Population Variance = {0}"</span>, <span class="hljs-params">pVariance</span>)</span>; <span class="hljs-comment">//最大値・最小値</span> var max = Statistics.<span class="hljs-constructor">Maximum(<span class="hljs-params">data</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Maximum = {0}"</span>, <span class="hljs-params">max</span>)</span>; var min = Statistics.<span class="hljs-constructor">Minimum(<span class="hljs-params">data</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Minimum = {0}"</span>, <span class="hljs-params">min</span>)</span>; <span class="hljs-comment">//平均</span> var mean = Statistics.<span class="hljs-constructor">Mean(<span class="hljs-params">data</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Mean = {0}"</span>, <span class="hljs-params">mean</span>)</span>; <span class="hljs-comment">//メジアン(中央値)</span> var median = Statistics.<span class="hljs-constructor">Median(<span class="hljs-params">data</span>)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Median = {0}"</span>, <span class="hljs-params">median</span>)</span>; <span class="hljs-comment">//順序統計量</span> var orderStatistic = Statistics.<span class="hljs-constructor">OrderStatistic(<span class="hljs-params">data</span>, 123)</span>; Console.<span class="hljs-constructor">WriteLine(<span class="hljs-string">"Order Statisitc(i-Order = 123) = {0}"</span>, <span class="hljs-params">orderStatistic</span>)</span>; Console.<span class="hljs-constructor">ReadLine()</span>; } } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.Statistics;
using System.Diagnostics;

namespace MathNetStatisticsSample
{
    class Program
    {
        static void Main(string[] args) {
            var sw = new Stopwatch();
            var rnd = new System.Random();
            double[] data = new double[10000000];

            int i;
            for (i = 0; i < 10000000; i++) {
                data[i] = rnd.NextDouble();
                //Console.Write(data[i] + ",");
            }
            //標本標準偏差
            sw.Start();
            var stddiv = Statistics.StandardDeviation(data);
            sw.Stop();
            Console.WriteLine("Standard Deviation = {0}", stddiv);
            Console.WriteLine("{1}件入力で標本標準偏差の計算時間: {0}", sw.Elapsed, i);
            //母標準偏差
            sw.Reset();
            sw.Start();
            var pstddiv = Statistics.PopulationStandardDeviation(data);
            sw.Stop();
            Console.WriteLine("Population Standard Deviation = {0}", pstddiv);
            Console.WriteLine("{1}件入力で母標準偏差の計算時間: {0}", sw.Elapsed, i);
            //標本分散
            var variance = Statistics.Variance(data);
            Console.WriteLine("Variance = {0}", variance);
            //母分散
            var pVariance = Statistics.PopulationVariance(data);
            Console.WriteLine("Population Variance = {0}", pVariance);
            //最大値・最小値
            var max = Statistics.Maximum(data);
            Console.WriteLine("Maximum = {0}", max);
            var min = Statistics.Minimum(data);
            Console.WriteLine("Minimum = {0}", min);
            //平均
            var mean = Statistics.Mean(data);
            Console.WriteLine("Mean = {0}", mean);
            //メジアン(中央値)
            var median = Statistics.Median(data);
            Console.WriteLine("Median = {0}", median);
            //順序統計量
            var orderStatistic = Statistics.OrderStatistic(data, 123);
            Console.WriteLine("Order Statisitc(i-Order = 123) = {0}", orderStatistic);

            Console.ReadLine();

        }
    }
}

※通常本サイトで公開されるソースコードライセンスはApache License v2.0ですが、上コードについてはMITライセンスとします。

コンパイルして実行してみていただきたいのですが、1000万件ぐらいだと標本標準偏差と、母標準偏差とではあまり計算時間に違いが無いというか、完全の誤差の範囲ですね。速いです。(さすがにメディアンの計算はちょっとかかります。)

ということで、Math.NETはF#との組み合わせで紹介される事が多いのですが、C#でもそれなりに使いやすく、高速な数値計算ライブラリです。

上のサンプルコードはGitHubにて公開しています。
https://github.com/ishisaka/MathNetSample

コメント

  1. […] C#でMath.NET Numericsを使用する(統計計算編2)前回の続き。 […]

タイトルとURLをコピーしました