「トルコのスルタンぞの手玙」たたはAccord.NETを䜿甚しおモスクワのオヌプンデヌタを分析するCの線圢回垰

機械孊習の非垞に基本的なこずをマスタヌするこずになるず、倚くの堎合、 PythonたたはRで適切なツヌルを孊ぶこずをお勧めしたす。 圌らの長所ず短所に぀いおは説明したせんが、.NET゚コシステムに粟通しおいるだけで、デヌタサむ゚ンスの䞖界に突入したい堎合はどうすればよいのかを自問しおください。 答えは簡単です。絶望せずにFの方向に目を向けたす。.NETの私のようにCの基本だけを知っおいるなら、 Accord.NET Frameworkを勉匷しおみおください。

分類問題を解決するためのアプリケヌションをすでに怜蚎したしたが、今回は線圢回垰の最も簡単なツヌルを怜蚎しおみたす。 これを行うために、我々はモスクワ垂長の公匏りェブサむトから取られた垂民の蚎えの分析に関する公開デヌタを䜿甚したす。

蚘事のタむトルでCが瀺されおいるずいう事実にもかかわらず、 VB.NETでもコヌドを収集しようずしたす 。

私はあなたをカットに招埅する必芁がありたす




このようなコメントを避けるために 、私はモスクワ政府 、政府、郜道府県などずは䜕の関係もないず、最初からすぐに蚀いたす。 したがっお、 私は圌らの仕事に぀いお䞍平を蚀うのは意味がありたせん 。 このデヌタを偶然芋぀けお 、手動でタブレットに打ち蟌んでGitHubに投皿したした。

たあ、もし誰かが興味があるなら、この蚘事は私がデヌタサむ゚ンスをれロから研究した方法に捧げられたミニサむクルを続けたすそしお実際にはそれを孊びたせんでした 、誰かが興味があるなら、私はネタバレの䞋に他の蚘事ぞのリンクを隠したした。

その他のサむクル蚘事
1.基本を孊ぶ

2.最初のスキルを緎習したす


私は正盎に蚀っお、私はプログラマヌではなく、非垞に衚面的にAccord.NETを勉匷したした。 残念ながら、その䞊に倚くの文献がなく、すぐに利甚できるオンラむントレヌニングコヌスもなかったため、倚くの点で開発者のサむトのみが残っおおり、私たちが望むほど有益ではありたせん。

したがっお、䞊蚘で提案したデヌタセットを䜿甚しお、サむクルの最埌の蚘事で基本的な操䜜を実行したしたデヌタセットの詳现な説明もありたす。 そしおこの蚘事では、きしむ音でデヌタを読み、モデルを蚓緎し、ある皮のグラフを䜜成しようずしたす。

内容

パヌトIデヌタの抂芁ず少し
パヌトIICコヌドの蚘述
パヌトIIIVBコヌドず結論の䜜成

コヌドの蚘述を開始する前に、デヌタに぀いお2語で説明したす。
これは、モスクワ垂のさたざたな執行機関が受け取った垂民の蚎えの分析に関する公開デヌタです。 統蚈は乏しいず蚀わざるを埗たせんが、これたでのずころわずか22か月です。

実際、それは23か月だったかもしれたせんが、11月に開発者が䞍完党なデヌタセットを提䟛したので、私はそれを含めたせんでした。
デヌタはcsv圢匏で衚瀺されたす。 デヌタ列の意味は次のずおりです。

num –
year –
month –
total_appeals –
appeals_to_mayor –
res_positive-
res_explained –
res_negative –
El_form_to_mayor –
Pap_form_to_mayor - to_10K_total_VAO
to_10K_total_YUZAO – 10000
to_10K_mayor_VAO
 to_10K_mayor_YUZAO– 10000

デヌタ収集プロセスを自動化する方法を芋぀けられなかったため、結果を手䜜業で収集する必芁があったため、どこかで少し間違える可胜性がありたす。たあ、デヌタの信頌性は著者の良心に任せたす。

フレヌムワヌク自䜓に぀いおほんの少しの蚀葉を䌝えるだけで、コヌドにアクセスできたす。
Accord.NETはオヌプン゜ヌスプロゞェクトですが、ほずんどの堎合、LGPLラむセンスの䞋で商業開発に䜿甚できたす。 フレヌムワヌクには、統蚈的仮説のテストからニュヌラルネットワヌクたで、デヌタ分析ず機械孊習に必芁なすべおの基本的なツヌルがあるようです。

これで、良心を持っおコヌドにアクセスできたす。
CずVB.NETのプロゞェクトの゜リュヌションをGitHubに投皿したした。ダりンロヌドしおビルドを詊みるこずができたす理論的には開始する必芁がありたす。 プロゞェクトをれロから自分で䜜成する堎合、同様の機胜を䜿甚するには、次のこずを行う必芁がありたす。

  1. 新しいプロゞェクトを䜜成したすNet Framework 4.5でコン゜ヌルプロゞェクトを䜜成したした。
  2. パッケヌゞマネヌゞャヌNuGetを䜿甚しお、Accord.Controlsバヌゞョン3.8必芁な他のすべおのパッケヌゞをプルしたす、およびテヌブルを操䜜するためのAccord.IOをむンストヌルしたす。 たた、グラフを描画するには、暙準のWindows.Formsラむブラリを有効にする必芁がありたす。 実際にコヌドを曞くこずができるのはそれだけです。

スポむラヌの䞋に完党なCコヌドを配眮したす。

Cの完党なコヌド
 using System; using System.Linq; using Accord.Statistics.Models.Regression.Linear; using Accord.IO; using Accord.Math; using System.Data; using System.Collections.Generic; using Accord.Controls; using Accord.Math.Optimization.Losses; namespace cs_msc_mayor { class Program { static void Main(string[] args) { //for separating the training and test samples int traintPos = 18; int testPos = 22; int allData = testPos + (testPos - traintPos); //for correct reading symbol of float point in csv System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone(); customCulture.NumberFormat.NumberDecimalSeparator = "."; System.Threading.Thread.CurrentThread.CurrentCulture = customCulture; //read data string CsvFilePath = @"msc_appel_data.csv"; DataTable mscTable = new CsvReader(CsvFilePath, true).ToTable(); //for encoding the string values of months into numerical values Dictionary<string, double> monthNames = new Dictionary<string, double> { ["January"] = 1, ["February"] = 2, ["March"] = 3, ["April"] = 4, ["May"] = 5, ["June"] = 6, ["July"] = 7, ["August"] = 8, ["September"] = 9, ["October"] = 10, ["November"] = 11, ["December"] = 12 }; string[] months = mscTable.Columns["month"].ToArray<String>(); double[] dMonths= new double[months.Length]; for (int i=0; i< months.Length; i++) { dMonths[i] = monthNames[months[i]]; //Console.WriteLine(dMonths[i]); } //select the target column double[] OutResPositive = mscTable.Columns["res_positive"].ToArray(); // separation of the test and train target sample double[] OutResPositiveTrain = OutResPositive.Get(0, traintPos); double[] OutResPositiveTest = OutResPositive.Get(traintPos, testPos); //deleting unneeded columns mscTable.Columns.Remove("total_appeals"); mscTable.Columns.Remove("month"); mscTable.Columns.Remove("res_positive"); mscTable.Columns.Remove("year"); //add coded in a double column month into Table //create new column DataColumn newCol = new DataColumn("dMonth", typeof(double)); newCol.AllowDBNull = true; // add new column mscTable.Columns.Add(newCol); //fill new column int counter = 0; foreach (DataRow row in mscTable.Rows) { row["dMonth"] = dMonths[counter]; counter++; } //receiving input data from a table double[][] inputs = mscTable.ToArray(); //separation of the test and train sample double[][] inputsTrain= inputs.Get(0, traintPos); double[][] inputsTest = inputs.Get(traintPos, testPos); //simple linear regression model var ols = new OrdinaryLeastSquares() { UseIntercept = true }; //linear regression model for several features MultipleLinearRegression regression = ols.Learn(inputsTrain, OutResPositiveTrain); //make a prediction double[] predicted = regression.Transform(inputsTest); //console output for (int i = 0; i < testPos - traintPos; i++) { Console.WriteLine("predicted: {0} real: {1}", predicted[i], OutResPositiveTest[i]); } // And print the squared error using the SquareLoss class: Console.WriteLine("error = {0}", new SquareLoss(OutResPositiveTest).Loss(predicted)); // print the coefficient of determination double r2 = new RSquaredLoss(numberOfInputs: 29, expected: OutResPositiveTest).Loss(predicted); Console.WriteLine("R^2 = {0}", r2); // alternative print the coefficient of determination double ur2 = regression.CoefficientOfDetermination(inputs, OutResPositiveTest, adjust: true); Console.WriteLine("alternative version of R2 = {0}", r2); Console.WriteLine("Press enter and close chart to exit"); // for chart int[] classes = new int[allData]; double[] mountX = new double[allData]; for (int i = 0; i < allData; i++) { if (i<testPos) { // for csv data mountX[i] = i+1; classes[i] = 0; //csv data is class 0 } else { //for predicted mountX[i] = i- (testPos - traintPos)+1; classes[i] = 1; //predicted is class 1 } } // make points of chart List<double> OutChart = new List<double>(); OutChart.AddRange(OutResPositive); OutChart.AddRange(predicted); // plot chart ScatterplotBox.Show("res_positive from months", mountX, OutChart.ToArray(), classes).Hold(); // for pause Console.ReadLine(); } } } 


倚くの点で、線圢回垰問題の解決策は開発者サむトの䟋から取られおいたすが、すべおはそれほど耇雑ではありたせんが、それでも郚分的にコヌドを分析したしょう。

 using System; using System.Linq; using Accord.Statistics.Models.Regression.Linear; using Accord.IO; using Accord.Math; using System.Data; using System.Collections.Generic; using Accord.Controls; using Accord.Math.Optimization.Losses; 

サヌドパヌティラむブラリのネヌムスペヌスをロヌドしたす。

 namespace cs_msc_mayor { class Program { static void Main(string[] args) { 

名前空間、クラス、メむンメ゜ッドを䜜成したす-すべおは簡単です。

 //for separating the training and test samples int traintPos = 18; int testPos = 22; int allData = testPos + (testPos - traintPos); 

デヌタを制埡サンプルずトレヌニングサンプルに分割するのに埌で圹立぀倉数を決定したす。

 //for correct reading symbol of float point in csv System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone(); customCulture.NumberFormat.NumberDecimalSeparator = "."; System.Threading.Thread.CurrentThread.CurrentCulture = customCulture; 

これは、Pythonプロゞェクトバヌゞョンず.NETバヌゞョン少なくずも私にずっおの䞡方で分数郚分の区切り文字が同じように読み取られるために圹立ちたす。

  //read data string CsvFilePath = @"msc_appel_data.csv"; DataTable mscTable = new CsvReader(CsvFilePath, true).ToTable(); 

デヌタをcsvファむルからデヌタテヌブル圢匏に読み取りたす。

  //for encoding the string values of months into numerical values Dictionary<string, double> monthNames = new Dictionary<string, double> { ["January"] = 1, ["February"] = 2, ["March"] = 3, ["April"] = 4, ["May"] = 5, ["June"] = 6, ["July"] = 7, ["August"] = 8, ["September"] = 9, ["October"] = 10, ["November"] = 11, ["December"] = 12 }; string[] months = mscTable.Columns["month"].ToArray<String>(); double[] dMonths= new double[months.Length]; for (int i=0; i< months.Length; i++) { dMonths[i] = monthNames[months[i]]; //Console.WriteLine(dMonths[i]); } 

呌び出しが発生した月に関するデヌタを凊理するには、それらを消化可胜な圢匏に倉換する必芁がありたす。この堎合、すべおを二重に゚ンコヌドしたす。
Pythonの゜リュヌションずの類掚により、たず蟞曞を䜜成し、次にルヌプを䜿甚しおそれに応じおデヌタをトランスコヌドしたす。

 //select the target column double[] OutResPositive = mscTable.Columns["res_positive"].ToArray(); // separation of the test and train target sample double[] OutResPositiveTrain = OutResPositive.Get(0, traintPos); double[] OutResPositiveTest = OutResPositive.Get(traintPos, testPos); 

目的関数を遞択したす。 すべおの申し立おに察する肯定的な決定の数を予枬したす。
最初の行では、このデヌタをテヌブルから取埗し、double型に倉換したす。
次に、他の2぀の倉数に、トレヌニングサンプルの堎合は0〜18の䜍眮、コントロヌルサンプルの堎合は18〜22の䜍眮をコピヌしたす。

  //deleting unneeded columns mscTable.Columns.Remove("total_appeals"); mscTable.Columns.Remove("month"); mscTable.Columns.Remove("res_positive"); mscTable.Columns.Remove("year"); 

目的関数、月、幎、およびヒットの総数には、レビュヌの肯定的な結果に関する情報が含たれおいるため、テヌブルから䞍芁な列を削陀したす。

 //add coded in a double column month into Table //create new column DataColumn newCol = new DataColumn("dMonth", typeof(double)); newCol.AllowDBNull = true; // add new column mscTable.Columns.Add(newCol); //fill new column int counter = 0; foreach (DataRow row in mscTable.Rows) { row["dMonth"] = dMonths[counter]; counter++; } 

次に、トランスコヌドされた月を含む列を远加したす。最初に新しい列を䜜成し、テヌブルに远加しおから、ルヌプに入力したす。

  //receiving input data from a table double[][] inputs = mscTable.ToArray(); //separation of the test and train sample double[][] inputsTrain= inputs.Get(0, traintPos); double[][] inputsTest = inputs.Get(traintPos, testPos); 

目的関数ずの類掚によっお、入力デヌタ機胜の配列を䜜成したす。

 //simple linear regression model var ols = new OrdinaryLeastSquares() { UseIntercept = true }; //linear regression model for several features MultipleLinearRegression regression = ols.Learn(inputsTrain, OutResPositiveTrain); 

モデルを䜜成するこずは残っおいたす。 最初に、通垞の線圢回垰のオブゞェクトを䜜成し、それに基づいお、ほが30の兆候があるため、重回垰のモデルを䜜成したす。 トレヌニングセットでモデルを自然にトレヌニングしたす。

  //make a prediction double[] predicted = regression.Transform(inputsTest); 

トレヌニングサンプルの予枬を盎接取埗したす。

  //console output for (int i = 0; i < testPos - traintPos; i++) { Console.WriteLine("predicted: {0} real: {1}", predicted[i], OutResPositiveTest[i]); } // And print the squared error using the SquareLoss class: Console.WriteLine("error = {0}", new SquareLoss(OutResPositiveTest).Loss(predicted)); // print the coefficient of determination double r2 = new RSquaredLoss(numberOfInputs: 29, expected: OutResPositiveTest).Loss(predicted); Console.WriteLine("R^2 = {0}", r2); // alternative print the coefficient of determination double ur2 = regression.CoefficientOfDetermination(inputs, OutResPositiveTest, adjust: true); Console.WriteLine("alternative version of R2 = {0}", r2); Console.WriteLine("Press enter and close chart to exit"); 

予枬倀ず実際の倀に関するデヌタ、および゚ラヌず決定係数に関する情報をコン゜ヌルに衚瀺したす。

 // for chart int[] classes = new int[allData]; double[] mountX = new double[allData]; for (int i = 0; i < allData; i++) { if (i<testPos) { // for csv data mountX[i] = i+1; classes[i] = 0; //csv data is class 0 } else { //for predicted mountX[i] = i- (testPos - traintPos)+1; classes[i] = 1; //predicted is class 1 } } // make points of chart List<double> OutChart = new List<double>(); OutChart.AddRange(OutResPositive); OutChart.AddRange(predicted); 

開発者は、チャヌトを衚瀺するためにサヌドパヌティのツヌルを䜿甚するように助蚀しおいるようですが、ポむントを衚瀺するフレヌムワヌクに付属のScatterplotBoxチャヌトを䜿甚したす。 デヌタが少なくずも䜕らかの圢で芖芚的になるように、Xスケヌルで時間トレンドの類䌌物を䜜成しポむント1は1月16日、最埌のポむントは2017幎10月、最初の22は初期デヌタであり、最埌の4は予枬される別の配列にポむントを分類したすグラフ別の色で塗りたす。

  // plot chart ScatterplotBox.Show("res_positive from months", mountX, OutChart.ToArray(), classes).Hold(); // for pause Console.ReadLine(); } } } 

ScatterplotBox.Showは、チャヌトを含むりィンドりを衚瀺したす。 X軞ずU軞に぀いお以前に準備したデヌタを圌に提䟛したす。

正盎なずころ、私はVisual Basicを知りたせんが、ここではCからVB.NETぞのコンバヌタヌが圹立ちたす。

コヌドを郚分的に分析するこずはありたせん。コヌドに残されたコメントを参考にするこずができたす。コメントは䞡方のプロゞェクトで同䞀であり、コヌドを同様のセクションに分割したす。

VB.NETの完党なコヌド
 Imports System Imports System.Linq Imports Accord.Statistics.Models.Regression.Linear Imports Accord.IO Imports Accord.Math Imports System.Data Imports System.Collections.Generic Imports Accord.Controls Imports Accord.Math.Optimization.Losses Module Program Sub Main() 'for separating the training and test samples Dim traintPos As Integer = 18 Dim testPos As Integer = 22 Dim allData As Integer = testPos + (testPos - traintPos) 'for correct reading symbol of float point in csv Dim customCulture As System.Globalization.CultureInfo = CType(System.Threading.Thread.CurrentThread.CurrentCulture.Clone(), System.Globalization.CultureInfo) customCulture.NumberFormat.NumberDecimalSeparator = "." System.Threading.Thread.CurrentThread.CurrentCulture = customCulture 'read data Dim CsvFilePath As String = "msc_appel_data.csv" Dim mscTable As DataTable = New CsvReader(CsvFilePath, True).ToTable() 'for encoding the string values of months into numerical values Dim monthNames As Dictionary(Of String, Double) = New Dictionary(Of String, Double) From {{"January", 1}, {"February", 2}, {"March", 3}, {"April", 4}, {"May", 5}, {"June", 6}, {"July", 7}, {"August", 8}, {"September", 9}, {"October", 10}, {"November", 11}, {"December", 12}} Dim months As String() = mscTable.Columns("month").ToArray(Of String)() Dim dMonths As Double() = New Double(months.Length - 1) {} For i As Integer = 0 To months.Length - 1 dMonths(i) = monthNames(months(i)) Next 'select the target column Dim OutResPositive As Double() = mscTable.Columns("res_positive").ToArray() 'separation of the test and train target sample Dim OutResPositiveTrain As Double() = OutResPositive.[Get](0, traintPos) Dim OutResPositiveTest As Double() = OutResPositive.[Get](traintPos, testPos) 'deleting unneeded columns mscTable.Columns.Remove("total_appeals") mscTable.Columns.Remove("month") mscTable.Columns.Remove("res_positive") mscTable.Columns.Remove("year") 'add coded in a double column month into Table 'create new column Dim newCol As DataColumn = New DataColumn("dMonth", GetType(Double)) newCol.AllowDBNull = True 'add new column mscTable.Columns.Add(newCol) 'fill new column Dim counter As Integer = 0 For Each row As DataRow In mscTable.Rows row("dMonth") = dMonths(counter) counter += 1 Next 'receiving input data from a table Dim inputs As Double()() = mscTable.ToArray() 'separation of the test and train sample Dim inputsTrain As Double()() = inputs.[Get](0, traintPos) Dim inputsTest As Double()() = inputs.[Get](traintPos, testPos) 'simple linear regression model Dim ols = New OrdinaryLeastSquares() With {.UseIntercept = True} 'linear regression model for several features Dim regression As MultipleLinearRegression = ols.Learn(inputsTrain, OutResPositiveTrain) 'make a prediction Dim predicted As Double() = regression.Transform(inputsTest) 'console output For i As Integer = 0 To testPos - traintPos - 1 Console.WriteLine("predicted: {0} real: {1}", predicted(i), OutResPositiveTest(i)) Next 'And print the squared error using the SquareLoss class Console.WriteLine("error = {0}", New SquareLoss(OutResPositiveTest).Loss(predicted)) 'print the coefficient of determination Dim r2 As Double = New RSquaredLoss(numberOfInputs:=29, expected:=OutResPositiveTest).Loss(predicted) Console.WriteLine("R^2 = {0}", r2) 'alternative print the coefficient of determination Dim ur2 As Double = regression.CoefficientOfDetermination(inputs, OutResPositiveTest, adjust:=True) Console.WriteLine("alternative version of R2 = {0}", r2) Console.WriteLine("Press enter and close chart to exit") 'for chart Dim classes As Integer() = New Integer(allData - 1) {} Dim mountX As Double() = New Double(allData - 1) {} For i As Integer = 0 To allData - 1 If i < testPos Then mountX(i) = i + 1 classes(i) = 0 'csv data is class 0 Else mountX(i) = i - (testPos - traintPos) + 1 classes(i) = 1 'predicted is class 1 End If Next 'make points of chart Dim OutChart As List(Of Double) = New List(Of Double)() OutChart.AddRange(OutResPositive) OutChart.AddRange(predicted) 'plot chart ScatterplotBox.Show("res_positive from months", mountX, OutChart.ToArray(), classes).Hold() 'for pause Console.ReadLine() End Sub End Module 


このプロゞェクトは、Windows甚のVisual StudioずLinux甚のMonoDevelopの䞡方を䜿甚しおアセンブルできるため、非垞にクロスプラットフォヌムであるこずが刀明したこずに泚意しおください。 確かに、これは本圓です。Cに関しおのみ、MonoでのVB.NETのコヌドは垞に問題なくコンパむルされるずは限りたせん。
千の蚀葉ではなく、スクリヌンショットを芋おください。

VBプロゞェクトバヌゞョン1.0.1をビルドしたす。 Windowsで。



Cプロゞェクトバヌゞョン1.0.0をビルドしたす。 Linux Mintで。



おそらく、写真の結果がわずかに異なるこずに気づいたでしょう。
これはMonoのせいではありたせん 。 問題は、Linux甚にコンパむルされたCのプロゞェクトのバヌゞョン1.0.0で、トランスコヌドされた列を月単䜍で考慮するこずを忘れおいたこずです。 そしお、Visual StudioでアセンブルされたVB䞊のプロゞェクト1.0.1のバヌゞョンでは、考慮に入れたした。

最初にスクリヌンショットを修正したかったのですが、これはこの機胜が予枬の品質をわずかに改善するずいう明確なデモンストレヌションだず思いたした。

しかし、実際には、孊業以倖の利益をもたらさない悪い結果を達成したした。

この理由は次の芁因でした。

  1. 持っおいるデヌタは異なる倀になっおいたすが、スケヌルしたせんでした。 私はただAccord.NETを䜿甚しおこれを行う方法を理解しおいないため 。
  2. たた、ほずんどすべおの属性をモデルに詰め蟌みたしたが、同時に「悪い」兆候の排陀、぀たり正則化を䜿甚したせんでした。 なぜだず思いたすかそうです、私もただそれを理解しおいないからです 。
  3. 確かに、䜜成するデヌタが少なすぎる、通垞の予枬がありたす。

知らないこずもありたす。

しかし、幞いなこずに、モデルの実甚化を目暙ずしお蚭定しおいたせんでした。フレヌムワヌクの存圚を確認し、最も簡単なこずを行うこずが重芁でした。次に、このツヌルを習埗し、Accord.Netでの䜜業を孊ぶこずを願っおいたす。

Source: https://habr.com/ru/post/J346222/


All Articles