{"id":14213,"date":"2022-07-18T07:00:45","date_gmt":"2022-07-18T05:00:45","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=14213"},"modified":"2023-02-16T13:55:39","modified_gmt":"2023-02-16T12:55:39","slug":"ml-net-uczenie-maszynowe-w-wydaniu-microsoftu","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/ml-net-uczenie-maszynowe-w-wydaniu-microsoftu\/","title":{"rendered":"ML.NET \u2013 uczenie maszynowe w wydaniu Microsoftu"},"content":{"rendered":"\n<p>ML.NET jest darmow\u0105 bibliotek\u0105 rozwijan\u0105 w ramach modelu open-source przeznaczon\u0105 do uczenia maszynowego na platformie .NET z wykorzystaniem j\u0119zyk\u00f3w C# oraz F#.&nbsp;Mo\u017cna j\u0105 uruchamia\u0107 na systemach Windows, Linux oraz MacOS, wykorzystuj\u0105c .NET Core, oraz na Windowsie u\u017cywaj\u0105c .NET Framework.<\/p>\n\n\n\n<p>Wed\u0142ug za\u0142o\u017ce\u0144 ma by\u0107 prosta w obs\u0142udze dla developer\u00f3w platformy .NET oraz os\u00f3b niemaj\u0105cych du\u017cego do\u015bwiadczenia w uczeniu maszynowym, a tak\u017ce zapewnia\u0107 obs\u0142ug\u0119 gotowych modeli z innych bibliotek takich jak Infer.NET, TensorFlow czy ONNX.<\/p>\n\n\n\n<p>W niniejszym artykule postaram si\u0119 przedstawi\u0107 na konkretnym przyk\u0142adzie:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>w jaki spos\u00f3b korzysta\u0107 z ML.NET,<\/li><li>jak przetworzy\u0107 dane,<\/li><li>w jaki spos\u00f3b wytrenowa\u0107 model uczenia maszynowego,<\/li><li>oraz jak dokona\u0107 klasyfikacji binarnej.<\/li><\/ul>\n\n\n\n<p>Nast\u0119pnie om\u00f3wi\u0119:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>metody pozwalaj\u0105ce na ewaluacj\u0119 uzyskanych wynik\u00f3w,<\/li><li>jak zoptymalizowa\u0107 stworzony model,<\/li><li>a tak\u017ce przyjrz\u0119 si\u0119 aspektowi wydajno\u015bciowemu biblioteki.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Zbi\u00f3r danych i problem dziedzinowy<\/h2>\n\n\n\n<p><strong>Zbi\u00f3r danych<\/strong><\/p>\n\n\n\n<p>Aby w pe\u0142ni pozna\u0107 mo\u017cliwo\u015bci ML.NET, przyjrzymy si\u0119 konkretnemu zbiorowi danych dost\u0119pnemu<br>w Internecie i spr\u00f3bujemy rozwi\u0105za\u0107 zadany problem z wykorzystaniem narz\u0119dzia do uczenia maszynowego od firmy Microsoft.<\/p>\n\n\n\n<p>W tym celu u\u017cy\u0142em zbioru danych <a href=\"https:\/\/onlinelibrary.wiley.com\/doi\/10.1111\/ele.13898\" rel=\"nofollow\" >AVONET: morphological, ecological and geographical data for all birds<\/a> zawieraj\u0105cego dane zebrane w wyniku katalogowania osobnik\u00f3w <strong>ptak\u00f3w r\u00f3\u017cnych gatunk\u00f3w<\/strong>. Mo\u017cna go pobra\u0107 pod tym adresem: <a href=\"https:\/\/figshare.com\/articles\/dataset\/AVONET_morphological_ecological_and_geographical_data_for_all_birds_Tobias_et_al_2021_Ecology_Letters_\/16586228\" rel=\"nofollow\" >zbi\u00f3r do pobrania.<\/a><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Dataset-1024x237-1.png\"><img decoding=\"async\" width=\"1024\" height=\"237\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Dataset-1024x237-1.png\" alt=\"\" class=\"wp-image-18102\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Dataset-1024x237-1.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Dataset-1024x237-1-300x69.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Dataset-1024x237-1-768x178.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Ryc. 1 Przyk\u0142adowy wycinek zbioru danych<\/figcaption><\/figure><\/div>\n\n\n\n<p>Dane zawieraj\u0105 90 020 rekord\u00f3w dotycz\u0105cych 11 009 gatunk\u00f3w ptak\u00f3w zebranych w 181 krajach. Niekt\u00f3re z zawartych w nich p\u00f3l to:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>gatunek ptaka (nazwa systematyczna),<\/li><li>jego p\u0142e\u0107,<\/li><li>wiek,<\/li><li>kraj, w kt\u00f3rym zosta\u0142 od\u0142owiony,<\/li><li>a tak\u017ce szereg atrybut\u00f3w numerycznych, dotycz\u0105cych cho\u0107by d\u0142ugo\u015bci<\/li><li>i szeroko\u015bci dzioba czy te\u017c d\u0142ugo\u015bci skrzyde\u0142.<\/li><\/ul>\n\n\n\n<p><strong>Problem dziedzinowy<\/strong><\/p>\n\n\n\n<p>Problemem, nad kt\u00f3rym b\u0119dziemy pracowa\u0107 w ramach eksploracji ML.NET, jest klasyfikacja binarna, czyli przyporz\u0105dkowanie dla danego rekordu jednej z dw\u00f3ch warto\u015bci atrybutu etykiety. W naszym przypadku b\u0119dzie to p\u0142e\u0107 \u2013 naszym celem jest predykcja p\u0142ci ptaka na podstawie innych dost\u0119pnych atrybut\u00f3w.<\/p>\n\n\n\n<p>Okre\u015blenie p\u0142ci u ptak\u00f3w jest rzeczywistym problemem, z kt\u00f3rym mierz\u0105 si\u0119 naukowcy, ornitolodzy czy te\u017c posiadacze ptak\u00f3w w charakterze zwierz\u0105t domowych. Wynika to z faktu, i\u017c nie u ka\u017cdego<br>z gatunk\u00f3w wyst\u0119puje dymorfizm p\u0142ciowy, pozwalaj\u0105cy na jednoznaczne przyporz\u0105dkowane osobnika do p\u0142ci. Zagadnienie te jest zg\u0142\u0119biane w licznych pracach naukowych, opracowywane s\u0105 ro\u017cne metody na radzenie sobie z tym problemem. Naszym zadaniem jest pr\u00f3ba wykorzystania do tego celu uczenia maszynowego.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Instalacja i przygotowanie \u015brodowiska<\/h2>\n\n\n\n<p>Aby rozpocz\u0105\u0107 tworzenie kodu, musimy posiada\u0107 wspierany system operacyjny oraz architektur\u0119 procesora (<a href=\"https:\/\/github.com\/dotnet\/machinelearning#operating-systems-and-processor-architectures-supported-by-mlnet\" rel=\"nofollow\" >lista wspieranych \u015brodowisk<\/a>) wraz z zainstalowan\u0105 odpowiedni\u0105 wersj\u0105 platformy .NET.<\/p>\n\n\n\n<p>W moim przypadku b\u0119dzie to system Windows 10 z zainstalowanym .NET Framework SDK w wersji 6.0.301 (dost\u0119pny do pobrania na <a href=\"https:\/\/dotnet.microsoft.com\/en-us\/download\" rel=\"nofollow\" >oficjalnej stronie<\/a>). Naszym IDE b\u0119dzie Visual Studio 2022<br>w darmowej wersji <a href=\"https:\/\/visualstudio.microsoft.com\/pl\/vs\/community\/\" rel=\"nofollow\" >Community<\/a>.<\/p>\n\n\n\n<p>Po zainstalowaniu wszystkich niezb\u0119dnych komponent\u00f3w oraz uruchomieniu VS2022, nale\u017cy utworzy\u0107 nowy projekt (w naszym przypadku b\u0119dzie to aplikacja konsolowa) i post\u0119powa\u0107 wed\u0142ug wskaz\u00f3wek kreatora.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Project.png\"><img decoding=\"async\" width=\"1013\" height=\"676\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Project.png\" alt=\"\" class=\"wp-image-18104\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Project.png 1013w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Project-300x200.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Project-768x513.png 768w\" sizes=\"(max-width: 1013px) 100vw, 1013px\" \/><\/a><figcaption>Ryc. 2 Wyb\u00f3r projektu aplikacji konsolowej w Visual Studio 2022<\/figcaption><\/figure><\/div>\n\n\n\n<p>Aby m\u00f3c korzysta\u0107 z narz\u0119dzia ML.NET w nowym projekcie, musimy pobra\u0107 odpowiedni\u0105 paczk\u0119 z menad\u017cera paczek NuGet. W tym celu, w widoku drzewa projektu, wybieramy w\u0119ze\u0142 g\u0142\u00f3wny (Solution), klikamy PPM i wskazujemy \u201eManage NuGet Packages for Solution\u2026\u201d.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Packages.png\"><img decoding=\"async\" width=\"363\" height=\"281\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Packages.png\" alt=\"\" class=\"wp-image-18106\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Packages.png 363w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Packages-300x232.png 300w\" sizes=\"(max-width: 363px) 100vw, 363px\" \/><\/a><figcaption>Ryc. 3 Menu kontekstowe dla solucji<\/figcaption><\/figure><\/div>\n\n\n\n<p>Nast\u0119pnym krokiem jest pobrane odpowiedniego pakietu. Aby to zrobi\u0107, wpisujemy w polu wyszukiwania nazw\u0119 \u201eML.NET\u201d i gdy interesuj\u0105cy nas wpis pojawi si\u0119 na ekranie, klikamy przycisk Install.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Nuget-1024x306-1.png\"><img decoding=\"async\" width=\"1024\" height=\"306\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Nuget-1024x306-1.png\" alt=\"\" class=\"wp-image-18108\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Nuget-1024x306-1.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Nuget-1024x306-1-300x90.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Nuget-1024x306-1-768x230.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Ryc. 4 NuGet Package Manager<\/figcaption><\/figure><\/div>\n\n\n\n<p>Po poprawnie wykonanej instalacji mo\u017cemy przyst\u0105pi\u0107 do tworzenia rozwi\u0105zania uczenia maszynowego.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u0141adowanie danych<\/h2>\n\n\n\n<p>Pierwszym krokiem, kt\u00f3ry musimy wykona\u0107, jest za\u0142adowanie naszego zbioru danych do pami\u0119ci, aby m\u00f3c dalej przetwarza\u0107 zawarte w nim dane, a nast\u0119pnie wytrenowa\u0107 oraz wykorzysta\u0107 model klasyfikatora.<\/p>\n\n\n\n<p>Aby operowa\u0107 na rekordach naszego zbioru, musimy stworzy\u0107 klas\u0119, kt\u00f3ra odzwierciedla wszystkie jego atrybuty. W tym celu nale\u017cy utworzy\u0107 klas\u0119 Bird, zawieraj\u0105c\u0105 jako w\u0142a\u015bciwo\u015bci interesuj\u0105ce nas kolumny.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing Microsoft.ML.Data;\n\nnamespace ML.NET.Models\n{\n    public class Bird\n    {\n        &#x5B;LoadColumn(8), ColumnName(\"Label\")]\n        public string Sex { get; set; }\n\n        &#x5B;LoadColumn(1)]\n        public string Species { get; set; }\n        &#x5B;LoadColumn(11)]\n        public string Country { get; set; }\n        &#x5B;LoadColumn(13)]\n        public float BeakLengthCulmen { get; set; }\n        &#x5B;LoadColumn(14)]\n        public float BeakLengthNares { get; set; }\n        &#x5B;LoadColumn(15)]\n        public float BeakWidth { get; set; }\n        &#x5B;LoadColumn(16)]\n        public float BeakDepth { get; set; }\n        &#x5B;LoadColumn(17)]\n        public float TarsusLength { get; set; }\n        &#x5B;LoadColumn(18)]\n        public float WingLength { get; set; }\n        &#x5B;LoadColumn(19)]\n        public float KippsDistance { get; set; }\n        &#x5B;LoadColumn(20)]\n        public float SecondaryLength { get; set; }\n        &#x5B;LoadColumn(21)]\n        public float HandWingIndex { get; set; }\n        &#x5B;LoadColumn(22)]\n        public float TailLength { get; set; }\n    }\n}\n<\/pre><\/div>\n\n\n<p>Nast\u0119pnie tworzymy obiekt klasy MLContext, jako parametr podaj\u0105c ziarno, czyli dowoln\u0105 liczb\u0119, kt\u00f3ra zostanie wykorzystana przez generator liczb pseudolosowych. Zapewnia to powtarzalno\u015b\u0107 wynik\u00f3w naszych eksperyment\u00f3w na przestrzeni r\u00f3\u017cnych wywo\u0142a\u0144. Wywo\u0142ujemy nast\u0119pnie jedn\u0105 z dost\u0119pnych w obiekcie mlContext.Data metod na wczytanie danych \u2013 w tym przypadku b\u0119dzie to odczyt pliku .csv z dysku. Podajemy r\u00f3wnie\u017c parametry dotycz\u0105ce separatora warto\u015bci oraz flag\u0119 informuj\u0105c\u0105 o obecno\u015bci nag\u0142\u00f3wk\u00f3w kolumn w pliku.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\u0141adowanie danych\nvar mlContext = new MLContext(42);\nvar data = mlContext.Data.LoadFromTextFile&lt;Bird&gt;(filePath, separatorChar: &#039;,&#039;, hasHeader: true);\nvar splitDataView = mlContext.Data.TrainTestSplit(data, testFraction: 0.2);\n<\/pre><\/div>\n\n\n<p>Tak wczytany zbi\u00f3r mo\u017cemy od razu podzieli\u0107 na zbiory treningowe i testowe za pomoc\u0105 metody TrainTestSplit. Zbi\u00f3r treningowy b\u0119dziemy wykorzystywa\u0107 do trenowania naszego modelu uczenia maszynowego, natomiast testowy pos\u0142u\u017cy do ewaluacji jego wynik\u00f3w.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Transformacja danych<\/h2>\n\n\n\n<p>Kolejnym krokiem jest transformacja wczytanych danych tak, aby mog\u0142y by\u0107 one wykorzystane do trenowania modeli uczenia maszynowego. Podejmiemy si\u0119 w tym celu transformacji kilku z kolumn do odpowiedniego formatu.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/Transformacja danych\nvar map = new Dictionary&lt;string, bool&gt; { { &quot;M&quot;, true }, { &quot;F&quot;, false } };\nvar pipeline = mlContext.Transforms.Conversion.MapValue(&quot;Label&quot;, map)\n                                                      .Append(mlContext.Transforms.Text.FeaturizeText(inputColumnName: &quot;Species&quot;, outputColumnName: &quot;SpeciesFeaturized&quot;))\n                                                      .Append(mlContext.Transforms.Text.FeaturizeText(inputColumnName: &quot;Country&quot;, outputColumnName: &quot;CountryFeaturized&quot;))\n                                                      .Append(mlContext.Transforms.Concatenate(&quot;Features&quot;, &quot;SpeciesFeaturized&quot;, &quot;CountryFeaturized&quot;, &quot;BeakLengthCulmen&quot;,&quot;BeakLengthNares&quot;,&quot;BeakWidth&quot;, &quot;BeakDepth&quot;, &quot;TarsusLength&quot;, &quot;WingLength&quot;, &quot;KippsDistance&quot;, &quot;SecondaryLength&quot;, &quot;HandWingIndex&quot;, &quot;TailLength&quot;))\n                                                      .Append(mlContext.BinaryClassification.Trainers.LightGbm(labelColumnName: &quot;Label&quot;, featureColumnName: &quot;Features&quot;));\n<\/pre><\/div>\n\n\n<p>Pierwsz\u0105 z operacji jest mapowanie warto\u015bci okre\u015blaj\u0105cych p\u0142e\u0107 ptaka z \u0142a\u0144cuch\u00f3w znak\u00f3w na warto\u015bci logiczne. W tym celu tworzymy s\u0142ownik, kt\u00f3ry pos\u0142u\u017cy nam jako parametr metody MapValue z obiektu mlContext.Transforms.Conversion.<\/p>\n\n\n\n<p>Musimy dokona\u0107 tej transformacji, aby nasz klasyfikator m\u00f3g\u0142 poprawnie operowa\u0107 na danych. Po wykonaniu tego fragmentu kodu mo\u017cemy dalej operowa\u0107 na uzyskanym wyniku, dodaj\u0105c dalsze kroki transformacji i tworz\u0105c \u0142a\u0144cuch kolejnych wywo\u0142a\u0144.<\/p>\n\n\n\n<p>Kolejne dwie operacje dotycz\u0105 zamiany warto\u015bci tekstowych z kolumn odnosz\u0105cych si\u0119 do kraju oraz gatunku ptaka na warto\u015bci numeryczne. Jest to standardowa praktyka przy budowaniu modeli uczenia maszynowego, gdy\u017c wymagaj\u0105 one warto\u015bci liczbowych do poprawnego przetwarzania.<\/p>\n\n\n\n<p>W tym celu wykorzystujemy metod\u0119 FeaturizeText, jako argumenty podaj\u0105c nazw\u0119 kolumny, kt\u00f3r\u0105 chcemy transformowa\u0107 oraz jej now\u0105 nazw\u0119 po wykonaniu tej operacji.<\/p>\n\n\n\n<p>Nast\u0119pnym krokiem jest wywo\u0142anie metody Concatenate, w celu z\u0142\u0105czenia wszystkich kolumn dotycz\u0105cych cech naszego zbioru w jedn\u0105 o nazwie Features, kt\u00f3rej obecno\u015b\u0107 jest wymagana poprzez modele w ML.NET<\/p>\n\n\n\n<p>Ostatnim etapem przygotowania danych jest wskazanie klasyfikatora, kt\u00f3ry chcemy wykorzysta\u0107. Na potrzeby rozwi\u0105zania naszego problemu klasyfikacji wybierzmy klasyfikator <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/microsoft.ml.trainers.lightgbm.lightgbmbinarytrainer?view=ml-dotnet\" rel=\"nofollow\" >LightGbm<\/a>, korzystaj\u0105cy z metody <em>binary &nbsp;boosted decision tree. <\/em>Jako parametry dla metody wskazujemy nazw\u0119 kolumny danych zawieraj\u0105cej etykiety (warto\u015b\u0107, kt\u00f3r\u0105 chcemy szacowa\u0107) oraz cechy (warto\u015bci, na podstawie kt\u00f3rych algorytm b\u0119dzie dokonywa\u0107 predykcji).<\/p>\n\n\n\n<p>W tym momencie nasz przep\u0142yw transformacji danych jest gotowy. Warto wiedzie\u0107, i\u017c do tego momentu podczas uruchomienia kodu nie zostanie wykonany \u017caden z tych krok\u00f3w, przep\u0142yw danych zostanie uruchomiony dopiero przy wywo\u0142aniu operacji trenowania zbioru danych \u2013 realizowane jest tu op\u00f3\u017anione wykonanie.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Uczenie zbioru<\/h2>\n\n\n\n<p>Mo\u017cemy teraz przyst\u0105pi\u0107 do trenowania naszego klasyfikatora. Wykorzystamy w tym celu wydzielony wcze\u015bniej ze zbioru g\u0142\u00f3wnego zbi\u00f3r treningowy.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/Trenowanie modelu\nvar model = pipeline.Fit(splitDataView.TrainSet);\n<\/pre><\/div>\n\n\n<p>Po wykonaniu metody Fit na obiekcie reprezentuj\u0105cym stworzony przez nas przep\u0142yw transformacji danych, uzyskujemy wytrenowany model, kt\u00f3ry mo\u017cna wykorzysta\u0107 w dzia\u0142aniu. Warto w tym miejscu zwr\u00f3ci\u0107 uwag\u0119, i\u017c trenowanie mo\u017ce by\u0107 w niekt\u00f3rych przypadkach bardzo czasoch\u0142onne. Zale\u017cy to od wielu czynnik\u00f3w, takich jak:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>rozmiar zbioru,<\/li><li>liczba jego cech<\/li><li>czy te\u017c wykorzystanego algorytmu uczenia maszynowego.<\/li><\/ul>\n\n\n\n<p>Istnieje mo\u017cliwo\u015b\u0107 zapisu gotowego modelu do pliku i \u0142atwego wczytania go p\u00f3\u017aniej, tak, aby nie wykonywa\u0107 czynno\u015bci trenowania za ka\u017cdym razem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Klasyfikacja<\/h2>\n\n\n\n<p>Pierwszym krokiem w uzyskaniu wyniku klasyfikacji jest stworzenie prostej klasy, kt\u00f3ra przechowywa\u0107 b\u0119dzie wynik wraz z polami pomocniczymi, kt\u00f3re b\u0119d\u0105 przydatne przy ewaluacji efektywno\u015bci modelu. Do tego celu wykorzystamy klas\u0119 BirdPrediction.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing Microsoft.ML.Data;\n\nnamespace ML.NET.Models\n{\n    public class BirdPrediction\n    {\n        &#x5B;ColumnName(\"PredictedLabel\")]\n        public bool IsMale { get; set; }\n        public float Probability { get; set; }\n        public float Score { get; set; }\n    }\n}\n<\/pre><\/div>\n\n\n<p>Wynik klasyfikacji b\u0119dzie warto\u015bci\u0105 logiczn\u0105, kt\u00f3ra znajdzie si\u0119 we w\u0142a\u015bciwo\u015bci IsMale (musimy j\u0105 oznaczy\u0107 za pomoc\u0105 atrybutu [ColumnName(&#8222;PredictedLabel&#8221;)] w celu poprawnego dzia\u0142ania).<\/p>\n\n\n\n<p>Gdy odpowiednia klasa jest gotowa, mo\u017cemy przyst\u0105pi\u0107 do klasyfikacji. Stw\u00f3rzmy przyk\u0142adowy obiekt klasy Bird, zawieraj\u0105cy dane na temat konkretnego ptaka (w tym przypadku jest to puchacz plamisty ze zbioru danych).<\/p>\n\n\n\n<p>Pami\u0119tajmy, aby nie przypisywa\u0107 warto\u015bci atrybutowi etykiety \u2013 jest to zadanie klasyfikatora, aby oszacowa\u0107 t\u0119 warto\u015b\u0107. Nast\u0119pnie wywo\u0142ujemy metod\u0119 CreatePredictionEngine wraz ze wskazaniem parametr\u00f3w klas uog\u00f3lnionych, aby uzyska\u0107 obiekt, na kt\u00f3rym wywo\u0142ujemy metod\u0119 Predict, podaj\u0105c jako parametr stworzony wcze\u015bniej rekord do klasyfikacji.&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/Sprawdzenie klasyfikacji\nvar testBird = new Bird \n{ \n    Species = &quot;Bubo africanus&quot;, \n    Country = &quot;Kenya&quot;,\n    BeakLengthCulmen = 38.9f,\n    BeakLengthNares = 19.1f,\n    BeakWidth = 10.7f,\n    BeakDepth = 17.2f,\n    TarsusLength = 53.5f,\n    WingLength = 320f,\n    KippsDistance = 98.2f,\n    SecondaryLength = 221.8f,\n    HandWingIndex = 30.7f,\n    TailLength = 162f\n \n};\nvar predictedBirdSex = mlContext.Model.CreatePredictionEngine&lt;Bird, BirdPrediction&gt;(model).Predict(testBird).IsMale;\n<\/pre><\/div>\n\n\n<p>Po wykonaniu powy\u017cszego fragment kodu mo\u017cemy zauwa\u017cy\u0107, i\u017c pole IsMale ma warto\u015b\u0107 logiczn\u0105 \u201efa\u0142sz\u201d, oznacza to, i\u017c model zaklasyfikowa\u0142 okaz ptaka jako samic\u0119. W tym przypadku predykcja jest zgodna ze stanem faktycznym, jednak aby realnie oceni\u0107 przydatno\u015b\u0107 stworzonego przez nas modelu, musimy przeprowadzi\u0107 rzeteln\u0105 ewaluacj\u0119 wynik\u00f3w, wykorzystuj\u0105c w tym celu wszystkie dost\u0119pne dane wraz z szeregiem odpowiednich metryk.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ewaluacja wynik\u00f3w<\/h2>\n\n\n\n<p>Dokonamy teraz oceny przydatno\u015bci naszego wytrenowanego modelu, korzystaj\u0105c z powszechnie wykorzystywanych <a href=\"https:\/\/towardsdatascience.com\/performance-metrics-for-binary-classifier-in-simple-words-be958535db49\" rel=\"nofollow\" >metryk<\/a>:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Accuracy,<\/li><li>F1Score,<\/li><li>AuROC (Area under Receiver Operating Characteristic),<\/li><li>Precision<\/li><li>oraz Recall.<\/li><\/ul>\n\n\n\n<p>Pozwol\u0105 nam one na ro\u017cne sposoby oceni\u0107, jak dobrze radzi sobie nasz klasyfikator.<\/p>\n\n\n\n<p>Technik\u0105, kt\u00f3r\u0105 wykorzystamy w celu lepszego sprawdzenia wiarygodno\u015bci wynik\u00f3w, jest tzw. walidacja krzy\u017cowa (<em>cross-validation).&nbsp;<\/em>Polega ona na powtarzanym podziale zbioru na zbi\u00f3r testowy i treningowy tak, aby za ka\u017cdym razem model nie by\u0142 wyuczony na innej cz\u0119\u015bci danych.<\/p>\n\n\n\n<p>Powszechnie wykorzystywana jest pi\u0119ciokrotna walidacja krzy\u017cowa, w kt\u00f3rej pi\u0119\u0107 razy wy\u0142\u0105czamy inny podzbi\u00f3r testowy ze zbioru i sprawdzamy na nim efektywno\u015b\u0107 modelu. Poni\u017cszy kod prezentuje ewaluacj\u0119 modelu z wykorzystaniem tego schematu walidacji.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/Ewaluacja wynik\u00f3w\nvar testDataView = model.Transform(splitDataView.TestSet);\nvar cvResults = mlContext.BinaryClassification.CrossValidate(testDataView, mlContext.BinaryClassification.Trainers.LightGbm(), numberOfFolds: 5);\n<\/pre><\/div>\n\n\n<p>ML.NET zawiera gotowe metody do wykonania walidacji krzy\u017cowej, kt\u00f3re zwracaj\u0105 wyniki interesuj\u0105cych nas metryk dla ka\u017cdej iteracji tego procesu. W celu obliczenia ich warto\u015bci dla ca\u0142o\u015bci procesu, dokonamy obliczenia \u015bredniej arytmetycznej ka\u017cdej z nich.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/Obliczenie metryk\nvar accuracy = cvResults.Select(f =&gt; f.Metrics.Accuracy).Average();\nvar f1 = cvResults.Select(f =&gt; f.Metrics.F1Score).Average();\nvar auroc = cvResults.Select(f =&gt; f.Metrics.AreaUnderRocCurve).Average();\nvar precision = cvResults.Select(f =&gt; f.Metrics.PositivePrecision).Average();\nvar recall = cvResults.Select(f =&gt; f.Metrics.PositiveRecall).Average();\n<\/pre><\/div>\n\n\n<p>Poni\u017cej prezentuj\u0105 si\u0119 uzyskane wyniki efektywno\u015bci naszego modelu dla klasyfikacji binarnej:<\/p>\n\n\n\n<figure class=\"wp-block-table caption-align-center\"><table><thead><tr><th class=\"has-text-align-center\" data-align=\"center\"><strong>Metryka<\/strong><\/th><th class=\"has-text-align-center\" data-align=\"center\"><strong>Warto\u015b\u0107<\/strong><\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\">Accuracy<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.5906<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Precision<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.5948<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Recall<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.5795<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">F1 Score<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.5868<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">AuRoC<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.6538<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Jak mo\u017cemy zaobserwowa\u0107, wyniki klasyfikacji nie prezentuj\u0105 wymarzonej efektywno\u015bci stworzonego modelu. Metryka Accuracy z warto\u015bcia ok. 0,59 oznacza, i\u017c <strong>59% pr\u00f3bek zosta\u0142o poprawnie sklasyfikowanych<\/strong>. Jak wysok\u0105 celno\u015b\u0107 b\u0119dzie mia\u0142 nasz klasyfikator, zale\u017cy od wielu czynnik\u00f3w i naszym zadaniem podczas tworzenia i optymalizacji modeli uczenia maszynowego jest odkrycie, co ma wp\u0142yw na finalny wynik tej\u017ce skuteczno\u015bci. Jedn\u0105 z metod poprawy efektywno\u015bci jest optymalizacja parametr\u00f3w klasyfikatora.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Optymalizacja parametr\u00f3w klasyfikatora<\/h2>\n\n\n\n<p>Ka\u017cdy z dost\u0119pnych algorytm\u00f3w uczenia maszynowe dysponuje zestawem unikalnych parametr\u00f3w tzw. hiperparametr\u00f3w, pozwalaj\u0105cych dostroi\u0107 jego dzia\u0142anie do naszych potrzeb. Mo\u017cemy zmienia\u0107 te parametry, aby zwi\u0119kszy\u0107 czy to skuteczno\u015b\u0107, czy te\u017c wydajno\u015b\u0107 naszego modelu.<\/p>\n\n\n\n<p>W narz\u0119dziach dost\u0119pnych dla j\u0119zyka Python, takich jak scikit-learn, dost\u0119pne s\u0105 klasy np. <a href=\"https:\/\/scikit-learn.org\/stable\/modules\/generated\/sklearn.model_selection.GridSearchCV.html\" rel=\"nofollow\" >GridSearchCV<\/a> \u2013 jest to funkcja pozwalaj\u0105ca na automatyczne sprawdzenie warto\u015bci wielu r\u00f3\u017cnych hiperparametr\u00f3w naraz i wskazanie najlepszej ich kombinacji (bior\u0105c pod uwag\u0119 wskazane metryki).<\/p>\n\n\n\n<p>Framework ML.NET nie dysponuje dok\u0142adnym odpowiednikiem takich narz\u0119dzi, ale oferuje rozwi\u0105zanie nawet ciekawsze \u2013 <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/machine-learning\/concept-automated-ml\" rel=\"nofollow\" >AutoML<\/a>.<\/p>\n\n\n\n<p>AutoML jest narz\u0119dziem pozwalaj\u0105cym na wspomaganie pracy z uczeniem maszynowym, polegaj\u0105ce na automatycznym doborze najlepszych algorytm\u00f3w oraz hiperparametr\u00f3w dla naszego zbioru danych. Jest to rozwi\u0105zanie ciekawe zar\u00f3wno dla os\u00f3b z niewielk\u0105 znajomo\u015bci\u0105 r\u00f3\u017cnych technik uczenia maszynowego, kt\u00f3re chcia\u0142by uzyska\u0107 wysok\u0105 skuteczno\u015b\u0107 modeli, jak i tych, kt\u00f3re chc\u0105 oszcz\u0119dzi\u0107 czas na manualnym strojeniu tworzonych modeli.<\/p>\n\n\n\n<p>Aby skorzysta\u0107 z AutoML, nale\u017cy zainstalowa\u0107 pakiet Microsoft.ML.AutoML za po\u015brednictwem NuGet Package Manager, analogicznie do instalacji podstawowego &nbsp;frameworka ML.NET.<\/p>\n\n\n\n<p>\u017beby dokona\u0107 automatycznego strojenia dla naszych danych, tworzymy obiekt eksperymentu, zawieraj\u0105cy ustawienia, jakie chcemy wykorzysta\u0107 przy przeprowadzeniu tej operacji. Okre\u015blamy rodzaj problemu, nad kt\u00f3rym pracujemy (klasyfikacja binarna), metryk\u0119, wed\u0142ug kt\u00f3rej chcemy stroi\u0107 nasz model (Accuracy) oraz czas eksperymentu (w naszym przypadku wybierzmy 15 minut). Dokonujemy r\u00f3wnie\u017c niezb\u0119dnej transformacji danych, podobnie jak w manualnym uczeniu modelu, ale w tym przypadku wymagane jest tylko mapowanie dla atrybutu etykiety.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/Ustawienia eksperymentu\nvar experimentSettings = new BinaryExperimentSettings();\nexperimentSettings.MaxExperimentTimeInSeconds = 900;\nexperimentSettings.OptimizingMetric = BinaryClassificationMetric.Accuracy;\nexperimentSettings.CacheDirectoryName = null;\n \n\/\/Transformacja danych\nvar transformedData = mlContext.Transforms.Conversion.MapValue(&quot;Label&quot;, new Dictionary&lt;string, bool&gt; { { &quot;M&quot;, true }, { &quot;F&quot;, false } }).Fit(data).Transform(data);\n \n\/\/Przeprowadzenie eksperymentu\nvar experiment = mlContext.Auto().CreateBinaryClassificationExperiment(experimentSettings);\nvar experimentResult = experiment.Execute(transformedData);\n<\/pre><\/div>\n\n\n<p>Po uruchomieniu eksperymentu przez wskazany czas AutoML b\u0119dzie tworzy\u0107 modele z r\u00f3\u017cnymi kombinacjami algorytm\u00f3w oraz hiperparametr\u00f3w tak, aby uzyska\u0107 jak najlepszy wynik wskazanej metryki.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/Ewaluacja danych\nvar metrics = experimentResult.BestRun.ValidationMetrics;\nvar accuracyAuto = metrics.Accuracy;\nvar f1Auto = metrics.F1Score;\nvar aurocAuto = metrics.AreaUnderRocCurve;\nvar precisionAuto = metrics.PositivePrecision;\nvar recallAuto = metrics.PositiveRecall;\n<\/pre><\/div>\n\n\n<p>Wyniki naszego eksperymentu prezentuj\u0105 si\u0119 nast\u0119puj\u0105co: wykonane zosta\u0142o 131 pr\u00f3b i jako najlepszy wskazany zosta\u0142 algorytm FastTreeBinary. Poni\u017cej w tabeli znajduj\u0105 si\u0119 wyniki metryk dla najlepszej wykonanej pr\u00f3by. Jak mo\u017cemy zauwa\u017cy\u0107, w kr\u00f3tkim czasie bez jakiejkolwiek dodatkowej wiedzy uda\u0142o nam si\u0119 <strong>poprawi\u0107 wyniki wszystkich metryk<\/strong>, a zatem zwi\u0119kszy\u0107 skuteczno\u015b\u0107 naszego klasyfikatora.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th class=\"has-text-align-center\" data-align=\"center\"><strong>Metryka<\/strong><\/th><th class=\"has-text-align-center\" data-align=\"center\"><strong>Warto\u015b\u0107<\/strong><\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\">Accuracy<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.6176<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Precision<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.6126<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Recall<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.6273<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">F1 Score<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.6199<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">AuRoC<\/td><td class=\"has-text-align-center\" data-align=\"center\">0.6925<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Wydajno\u015b\u0107<\/h2>\n\n\n\n<p>Jednym z argument\u00f3w maj\u0105cych nas zach\u0119ci\u0107 do korzystania z ML.NET jest reklamowana przez tw\u00f3rc\u00f3w wydajno\u015b\u0107 frameworka. Na <a href=\"https:\/\/dotnet.microsoft.com\/en-us\/apps\/machinelearning-ai\/ml-dotnet\" rel=\"nofollow\" >oficjalnej stronie<\/a> mo\u017cemy znale\u017a\u0107 poni\u017csz\u0105 informacj\u0119:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Performance-1024x336-1.png\"><img decoding=\"async\" width=\"1024\" height=\"336\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Performance-1024x336-1.png\" alt=\"\" class=\"wp-image-18110\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Performance-1024x336-1.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Performance-1024x336-1-300x98.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Performance-1024x336-1-768x252.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Ryc. 5 Informacja na temat wydajno\u015bci z oficjalnej strony<\/figcaption><\/figure><\/div>\n\n\n\n<p>Czy w istocie niniejsze narz\u0119dzie potrafi zdeklasowa\u0107 popularne rozwi\u0105zania uczenia maszynowego oparte o scikit-learn, oferuj\u0105c niemal 6-krotny wzrost wydajno\u015bci, przy zbli\u017conym poziomie skuteczno\u015bci? Dost\u0119pny jest <a href=\"https:\/\/arxiv.org\/pdf\/1905.05715.pdf\" rel=\"nofollow\" >artyku\u0142<\/a> <a href=\"https:\/\/arxiv.org\/pdf\/1905.05715.pdf\" rel=\"nofollow\" >okre\u015blaj\u0105cy w jaki spos\u00f3b niniejsze wyniki zosta\u0142y uzyskane<\/a>, dzi\u0119ki niemu mo\u017cliwa jest pr\u00f3ba ich odtworzenia we w\u0142asnym zakresie.<\/p>\n\n\n\n<p>W niniejszym artykule spr\u00f3bujemy sprawdzi\u0107 rzekom\u0105 przepa\u015b\u0107 wydajno\u015bciow\u0105 ML.NET na podobnym zbiorze danych. Wykorzystamy w tym celu zbi\u00f3r <a href=\"https:\/\/ailab.criteo.com\/criteo-sponsored-search-conversion-log-dataset\/\" rel=\"nofollow\" >Criteo Sponsored Search Conversion Log Dataset.<\/a> Zawiera on dane na temat wy\u015bwietlanych na stronach internetowych reklam wraz<br>z informacj\u0105, czy reklama zosta\u0142a klikni\u0119ta i czy dosz\u0142o do zakupu reklamowanego produktu.<\/p>\n\n\n\n<p>Aby por\u00f3wna\u0107 wydajno\u015b\u0107 narz\u0119dzi dost\u0119pnych w j\u0119zyku Python oraz ML.NET, stworzone zosta\u0142y dwa rozwi\u0105zania, zawieraj\u0105cy analogiczne modele wytrenowane na tym samym zbiorze danych,<br>z wykorzystaniem algorytmu regresji logistycznej.<\/p>\n\n\n\n<p>Test zosta\u0142 wykonany na 10% zbioru Criteo (ok. 600 MB, 1&nbsp;599&nbsp;563 rekord\u00f3w) na komputerze klasy PC, a nast\u0119pnie por\u00f3wnany zosta\u0142 czas klasyfikacji dla obu narz\u0119dzi. Ka\u017cda z operacji zosta\u0142a wykonana trzykrotnie, a wyniki zosta\u0142y u\u015brednione.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/PerformanceChart.png\"><img decoding=\"async\" width=\"576\" height=\"336\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/PerformanceChart.png\" alt=\"\" class=\"wp-image-18112\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/PerformanceChart.png 576w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/PerformanceChart-300x175.png 300w\" sizes=\"(max-width: 576px) 100vw, 576px\" \/><\/a><figcaption>Ryc. 6 Por\u00f3wnanie klasyfikacji binarnej (regresja logistyczna)<\/figcaption><\/figure><\/div>\n\n\n\n<p>Cho\u0107 istnieje wiele czynnik\u00f3w decyduj\u0105cych o wydajno\u015bci klasyfikatora (implementacja, charakterystyka zbioru czy te\u017c ustawienia \u015brodowiska testowego), podczas kilkukrotnych pr\u00f3b wyra\u017anie da si\u0119 zauwa\u017cy\u0107 znaczn\u0105 przewag\u0119 wydajno\u015bciow\u0105 ML.NET \u2013 czas wykonania zmala\u0142 o ok.&nbsp;<strong>58%<\/strong>!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Podsumowanie<\/h2>\n\n\n\n<p>ML.NET jest ciekawym narz\u0119dziem, kt\u00f3re warto wypr\u00f3bowa\u0107 podczas wykonywana zada\u0144 zwi\u0105zanych z szeroko poj\u0119tym uczeniem maszynowym. Jest to szczeg\u00f3lnie interesuj\u0105ca opcja dla programist\u00f3w platformy .NET, gdy\u017c nie wymaga nauki j\u0119zyka Python, kt\u00f3ry jest powszechnie wykorzystywany do tych cel\u00f3w.<\/p>\n\n\n\n<p>Jedn\u0105 z najmocniejszych cech biblioteki jest jej wydajno\u015b\u0107. Zar\u00f3wno zapewnienia tw\u00f3rc\u00f3w, jak<br>i wykonane przeze mnie testy wskazuj\u0105 na znacznie lepsz\u0105 wydajno\u015b\u0107 w por\u00f3wnaniu do konkurencyjnych rozwi\u0105za\u0144. Mo\u017ce by\u0107 to istotne kryterium podczas podejmowania decyzji o wyborze narz\u0119dzia do uczenia maszynowego w \u015brodowisku produkcyjnym<\/p>\n\n\n\n<p>Framework jest ca\u0142y czas rozwijany na zasadach otwartego <a href=\"https:\/\/github.com\/dotnet\/machinelearning\" rel=\"nofollow\" >kodu \u017ar\u00f3d\u0142owego<\/a>, gdzie ka\u017cdy mo\u017ce mie\u0107 sw\u00f3j wk\u0142ad w rozw\u00f3j narz\u0119dzia. Ostatnie wydanie (wersja 1.7) z marca 2022 daje nadziej\u0119 na dalszy rozw\u00f3j i wsparcie w przysz\u0142o\u015bci.<\/p>\n\n\n\n<p>Warto jednak zaznaczy\u0107, i\u017c jest to stosunkowo m\u0142ode narz\u0119dzie (pierwsze wydanie powsta\u0142o w 2018 roku) i nadal nie dysponuje niekt\u00f3rymi funkcjonalno\u015bciami dost\u0119pnymi w ekosystemie j\u0119zyka Python. Podczas wyboru rozwi\u0105zania dla naszych problem\u00f3w uczenia maszynowego warto mie\u0107 to na uwadze.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Przydatne linki<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/dotnet.microsoft.com\/en-us\/apps\/machinelearning-ai\/ml-dotnet\" rel=\"nofollow\" >Strona projektu<\/a><\/li><li><a href=\"https:\/\/github.com\/dotnet\/machinelearning\" rel=\"nofollow\" >Repozytorium kodu \u017ar\u00f3d\u0142owego projektu<\/a><\/li><li><a href=\"https:\/\/github.com\/Wituch\/ML.NET\" rel=\"nofollow\" >Repozytorium kodu wykorzystanego w artykule<\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/machine-learning\/how-does-mldotnet-work\" rel=\"nofollow\" >Samouczek korzystania z ML.NET<\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/machine-learning\/how-to-choose-an-ml-net-algorithm\" rel=\"nofollow\" >Lista dost\u0119pnych algorytm\u00f3w<\/a><\/li><\/ul>\n\n\n\n<p>***<\/p>\n\n\n\n<p>Je\u015bli interesuje Ci\u0119 tematyka uczenia maszynowego, zach\u0119camy do zapoznania si\u0119 z innymi artyku\u0142ami naszych ekspert\u00f3w np.: <a href=\"https:\/\/sii.pl\/blog\/tinyml-uczenie-maszynowe-w-systemach-wbudowanych\/\">TinyML: Uczenie maszynowe w systemach wbudowanych<\/a> oraz <a href=\"https:\/\/sii.pl\/blog\/rpa-i-inteligentne-przetwarzanie-dokumentow\/\">RPA i inteligentne przetwarzanie dokument\u00f3w<\/a>.<\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;14213&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;12&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4.3&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4.3\\\/5 ( votes: 12)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;ML.NET \u2013 uczenie maszynowe w wydaniu Microsoftu&quot;,&quot;width&quot;:&quot;119.2&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 119.2px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            4.3\/5 ( votes: 12)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>ML.NET jest darmow\u0105 bibliotek\u0105 rozwijan\u0105 w ramach modelu open-source przeznaczon\u0105 do uczenia maszynowego na platformie .NET z wykorzystaniem j\u0119zyk\u00f3w C# &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/ml-net-uczenie-maszynowe-w-wydaniu-microsoftu\/\">Continued<\/a><\/p>\n","protected":false},"author":378,"featured_media":19683,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":10,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[287,129,272,1309,1163],"class_list":["post-14213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-software-development","tag-c","tag-net","tag-ml-net","tag-uczenie-maszynowe"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/07\/ML.NET-\u2013-uczenie-maszynowe-w-wydaniu-Microsoftu.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/14213"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/378"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=14213"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/14213\/revisions"}],"predecessor-version":[{"id":18446,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/14213\/revisions\/18446"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/19683"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=14213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=14213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=14213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}