{"id":29311,"date":"2020-08-20T16:03:37","date_gmt":"2020-08-20T23:03:37","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=29311"},"modified":"2020-08-20T16:05:12","modified_gmt":"2020-08-20T23:05:12","slug":"august-ml-net-api-and-tooling-updates","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/august-ml-net-api-and-tooling-updates\/","title":{"rendered":"August ML.NET API and Tooling Updates"},"content":{"rendered":"<p><a href=\"https:\/\/dot.net\/ml\">ML.NET<\/a> is an open-source, cross-platform machine learning framework for .NET developers. It enables integrating machine learning into your .NET apps without requiring you to leave the .NET ecosystem or even have a background in ML or data science. ML.NET provides tooling (Model Builder UI in Visual Studio and the cross platform ML.NET CLI) that automatically trains custom machine learning models for you based on your scenario and data.<\/p>\n<p>We recently released ML.NET 1.5 and 1.5.1 as well as a new version of Model Builder. These releases include numerous bug fixes and enhancements, as well as new features for anomaly detection and time series data, improvements to the TextLoader, local GPU training for image classification in Model Builder, and more.<\/p>\n<p>In this post, we&#8217;ll cover the following items:<\/p>\n<ol>\n<li><a href=\"#new-algorithms-and-features-for-anomaly-detection-and-time-series-data\">New algorithms and features for anomaly detection and time series data<\/a><\/li>\n<li><a href=\"#automl-for-ranking-scenario\">AutoML for ranking scenario<\/a><\/li>\n<li><a href=\"#updates-to-textloader\">Updates to TextLoader<\/a><\/li>\n<li><a href=\"#model-builder-local-gpu-training-for-image-classification\">Model Builder local GPU training for image classification<\/a><\/li>\n<li><a href=\"#feedback-button-in-model-builder\">Feedback button in Model Builder<\/a><\/li>\n<li><a href=\"#thanks-to-our-contributors\">Thanks to our contributors<\/a><\/li>\n<li><a href=\"#feedback\">Feedback<\/a><\/li>\n<li><a href=\"#get-started-and-resources\">Get started and Resources<\/a><\/li>\n<\/ol>\n<h2>What\u2019s new with the ML.NET API?<\/h2>\n<h2>New algorithms and features for anomaly detection and time series data<\/h2>\n<p>Time series data is a series of data points over time. A common example of time series data is monthly number of product sales over a year:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-29326\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/time-series-data.png\" alt=\"Image time series data example\" width=\"862\" height=\"475\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/time-series-data.png 862w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/time-series-data-300x165.png 300w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/time-series-data-768x423.png 768w\" sizes=\"(max-width: 862px) 100vw, 862px\" \/><\/p>\n<p>There are many applications for time series data in machine learning. Anomaly detection and forecasting are two of the most commons scenarios supported by ML.NET:<\/p>\n<ul>\n<li>With <strong>anomaly detection<\/strong>, you can find abnormal spikes in your time series data; for example, you could use anomaly detection to identify potentially fraudulent transactions on your credit card or spikes in power consumption based on daily readings from a meter.<\/li>\n<li>With <strong>forecasting<\/strong>, you can use past time series data to make predictions about future behavior; for example, you could use forecasting to project monthly sales based on previous months&#8217; sales or to predict the weather.<\/li>\n<\/ul>\n<h3>Detect Entire Anomaly by SrCnn algorithm<\/h3>\n<p><span style=\"font-size: 12pt;\">The ML.NET 1.5 update added a new anomaly detection algorithm called <a style=\"background-color: #f7f7f9;\" href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.ml.timeseriescatalog.detectentireanomalybysrcnn?view=ml-dotnet\" target=\"_blank\" rel=\"noopener noreferrer\">DetectEntireAnomalyBySrCnn.<\/a> This algorithm allows you to detect anomalies for an entire dataset at once. This is in contrast to the existing <a style=\"background-color: #f7f7f9;\" href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.ml.timeseriescatalog.detectanomalybysrcnn?view=ml-dotnet\" target=\"_blank\" rel=\"noopener noreferrer\">DetectAnomalyBySrCnn<\/a>\u00a0algorithm, which streams parts of the dataset and examines a window around points to find anomalies.<\/span><\/p>\n<p>This new algorithm is faster than the DetectAnomalyBySrCnn algorithm and can work on arbitrarily-sized datasets since it can train on batches of a fixed size. However, it also consumes more memory since it loads the entire dataset in memory. You can use the new DetectEntireAnomalyBySrCnn algorithm if you have all your data on hand.<\/p>\n<p>However,\u00a0if\u00a0your\u00a0time\u00a0series\u00a0data\u00a0is\u00a0streaming,\u00a0you\u00a0don\u2019t\u00a0have\u00a0all\u00a0your\u00a0data\u00a0on\u00a0hand,\u00a0or\u00a0your\u00a0data\u00a0is\u00a0too\u00a0large\u00a0to\u00a0fit\u00a0in\u00a0memory,\u00a0you\u00a0can\u00a0still\u00a0use\u00a0the\u00a0previous\u00a0DetectAnomalyBySrCnn\u00a0algorithm.<\/p>\n<p>Check out this <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.ml.timeseriescatalog.detectentireanomalybysrcnn?view=ml-dotnet#examples\" target=\"_blank\" rel=\"noopener noreferrer\">sample<\/a>\u00a0to see how to use the DetectEntireAnomalyBySrCnn algorithm.<\/p>\n<h3>Root cause detection<\/h3>\n<p>This update also added <a href=\"https:\/\/github.com\/dotnet\/machinelearning\/blob\/master\/docs\/api-reference\/time-series-root-cause-localization.md\" target=\"_blank\" rel=\"noopener noreferrer\">root cause detection<\/a>, which is a feature that can identify which inputs likely caused an anomaly. For example, say you have housing data for Seattle, and one of the house listings shows an abnormally high price (e.g. an anomaly) on August 6. Using root cause detection, you may find that the neighborhood and property type are the contributing factors to the abnormally high price. The 1.5.1 update also added the ability for you to define a threshold for root cause analysis which can influence which features are chosen as root causes.<\/p>\n<p>The code below shows how to implement root cause detection and print the results (full sample can be found <a href=\"https:\/\/github.com\/dotnet\/machinelearning\/blob\/master\/docs\/samples\/Microsoft.ML.Samples\/Dynamic\/Transforms\/TimeSeries\/LocalizeRootCause.cs\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>).<\/p>\n<pre><code class=\"lang-csharp\">\/\/ Create a new ML context for ML.NET operations\r\nvar mlContext = new MLContext();\r\n\r\n\/\/ Create a root cause localization input instance\r\nDateTime timestamp = GetTimestamp();\r\n\r\nvar data = new RootCauseLocalizationInput(timestamp, GetAnomalyDimension(), new List(){ new MetricSlice(timestamp, GetPoints())\r\n}, AggregateType.Sum, AGG_SYMBOL);\r\n\r\n\/\/ Get the root cause localization result\r\nRootCause prediction = mlContext.AnomalyDetection.LocalizeRootCause(data);\r\n\r\n\/\/ Print the localization result\r\nint count = 0;\r\nforeach (RootCauseItem item in prediction.Items)\r\n{\r\n    count++;\r\n    Console.WriteLine($\"Root cause item #{count} ...\");\r\n    Console.WriteLine($\"Score: {item.Score}, Path: {String.Join(\" \",item.Path)}, Direction: {item.Direction}, Dimension:{String.Join(\" \", item.Dimension)}\");\r\n}\r\n\r\n\/\/Item #1 ...\r\n\/\/Score: 0.26670448876705927, Path: DataCenter, Direction: Up, Dimension:[Country, UK] [DeviceType, ##SUM##] [DataCenter, DC1]\r\n<\/code><\/pre>\n<h3>Time series seasonality and de-seasonality<\/h3>\n<p>The 1.5.1 update also added new capabilities for working with time series data, including <a href=\"https:\/\/github.com\/dotnet\/machinelearning\/blob\/master\/docs\/samples\/Microsoft.ML.Samples\/Dynamic\/Transforms\/TimeSeries\/DetectSeasonality.cs\" target=\"_blank\" rel=\"noopener noreferrer\">seasonality detection<\/a> and the ability to <a href=\"https:\/\/github.com\/dotnet\/machinelearning\/blob\/master\/test\/Microsoft.ML.TimeSeries.Tests\/TimeSeriesDirectApi.cs#L727\" target=\"_blank\" rel=\"noopener noreferrer\">de-seasonalize<\/a> seasonal data prior to anomaly detection. For example, say you had sales data from the past 5 years, and you noticed that sales always go up in the holiday months. Normally, this spike in sales would be counted as an anomaly, but now you can use ML.NET\u2019s seasonality detection feature to identify this yearly occurrence and normalize the data against the seasonality before your anomaly detection analysis so that it does not show up as an anomaly.<\/p>\n<h2>AutoML for ranking scenario<\/h2>\n<p>While ML.NET has supported the <a href=\"https:\/\/github.com\/dotnet\/machinelearning-samples\/tree\/master\/samples\/csharp\/getting-started\/Ranking_Web\" target=\"_blank\" rel=\"noopener noreferrer\">ranking scenario<\/a> for a while, it is now also supported by local AutoML. This means that you don\u2019t have to worry about selecting an algorithm or manually tuning algorithm settings; instead, you can simply choose the ranking scenario and input your data, and AutoML will give you the best model based on your inputs.<\/p>\n<p>Currently,\u00a0you\u00a0can\u00a0use\u00a0the\u00a0AutoML.NET\u00a0API\u00a0for\u00a0the\u00a0ranking\u00a0scenario,\u00a0but\u00a0we\u00a0are\u00a0working\u00a0on\u00a0adding\u00a0AutoML\u00a0ranking\u00a0to\u00a0tooling\u00a0(Model\u00a0Builder\u00a0and\u00a0the\u00a0ML.NET\u00a0CLI)\u00a0as\u00a0well.<\/p>\n<p>The code below shows how to use the AutoML.NET API to create a ranking experiment and print the results (full sample can be found <a href=\"https:\/\/github.com\/dotnet\/machinelearning\/blob\/master\/docs\/samples\/Microsoft.ML.AutoML.Samples\/RankingExperiment.cs\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>).<\/p>\n<pre><code class=\"lang-csharp\">MLContext mlContext = new MLContext();\r\n\r\n\/\/ Load data\r\nIDataView trainDataView = mlContext.Data.LoadFromTextFile(TrainDataPath, hasHeader: true, separatorChar: ',');\r\n\r\n\/\/ Run AutoML Ranking experiment\r\nExperimentResult experimentResult = mlContext.Auto()\r\n    .CreateRankingExperiment(new RankingExperimentSettings(){\r\n        MaxExperimentTimeInSeconds = ExperimentTime })\r\n    .Execute(trainDataView, testDataView, new ColumnInformation(){ LabelColumnName = LabelColumnName, GroupIdColumnName = GroupColumnName });\r\n\r\n\/\/ Print metric from best model\r\nRunDetail bestRun = experimentResult.BestRun;\r\n\r\nConsole.WriteLine($\"Total models produced: {experimentResult.RunDetails.Count()}\");\r\nConsole.WriteLine($\"Best model's trainer: {bestRun.TrainerName}\");\r\nConsole.WriteLine($\"Metrics of best model from validation data --\");\r\nPrintMetrics(bestRun.ValidationMetrics);\r\n<\/code><\/pre>\n<h2>Updates to TextLoader<\/h2>\n<p>The 1.5 update also improved the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.ml.data.textloader?view=ml-dotnet\">TextLoader<\/a> experience, which includes adding the following features:<\/p>\n<ul>\n<li>Enabling the TextLoader to accept new lines in quoted fields.<\/li>\n<li>Support for escapeChar.<\/li>\n<li>Adding public generic methods to the TextLoader catalog that accept Options objects.<\/li>\n<li>Decimal marker option in the TextLoader.<\/li>\n<\/ul>\n<p>You can see more updates to ML.NET in the <a href=\"https:\/\/github.com\/dotnet\/machinelearning\/blob\/master\/docs\/release-notes\/1.5.0\/release-1.5.0.md\" target=\"_blank\" rel=\"noopener noreferrer\">1.5<\/a> and <a href=\"https:\/\/github.com\/dotnet\/machinelearning\/blob\/master\/docs\/release-notes\/1.5.1\/release-1.5.1.md\" target=\"_blank\" rel=\"noopener noreferrer\">1.5.1<\/a>\u00a0release notes.<\/p>\n<h2>What\u2019s new with ML.NET tooling?<\/h2>\n<h2>Model Builder local GPU training for image classification<\/h2>\n<p>You\u00a0can\u00a0now\u00a0utilize\u00a0your\u00a0local\u00a0GPU\u00a0for\u00a0faster\u00a0Image\u00a0Classification\u00a0training\u00a0via\u00a0Model\u00a0Builder\u00a0in\u00a0Visual\u00a0Studio.<\/p>\n<p>We tested local training with a dataset of ~77K images. Comparing CPU with GPU, we got the following results:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-29323\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/cpu-vs-gpu-training-1024x665.png\" alt=\"Image cpu vs gpu training\" width=\"500\" height=\"325\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/cpu-vs-gpu-training-1024x665.png 1024w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/cpu-vs-gpu-training-300x195.png 300w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/cpu-vs-gpu-training-768x499.png 768w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/cpu-vs-gpu-training.png 1411w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>When\u00a0you\u00a0open\u00a0Model\u00a0Builder\u00a0and\u00a0select\u00a0the\u00a0Image\u00a0Classification\u00a0scenario,\u00a0you\u00a0will\u00a0now\u00a0see\u00a0a\u00a03rd\u00a0option\u00a0for\u00a0Local\u00a0GPU\u00a0training\u00a0(in\u00a0addition\u00a0to\u00a0Local\u00a0CPU\u00a0training\u00a0and\u00a0Azure\u00a0training).<\/p>\n<p>After\u00a0selecting\u00a0Local\u00a0(GPU)\u00a0as\u00a0your\u00a0training\u00a0environment,\u00a0you\u00a0can\u00a0check\u00a0to\u00a0see\u00a0if\u00a0your\u00a0machine\u00a0is\u00a0compatible\u00a0for\u00a0GPU\u00a0training\u00a0right\u00a0in\u00a0the\u00a0Model\u00a0Builder\u00a0UI.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-29324\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/gpu-compatability.png\" alt=\"Image gpu compatability\" width=\"500\" height=\"211\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/gpu-compatability.png 864w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/gpu-compatability-300x127.png 300w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/gpu-compatability-768x324.png 768w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>Compatibility\u00a0requirements\u00a0include:<\/p>\n<ol>\n<li>Installing the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=MLNET.ModelBuilderGPU\" target=\"_blank\" rel=\"noopener noreferrer\">ML.NET Model Builder GPU Support extension<\/a> in the Visual Studio Marketplace or in the Extensions Manager in VS.<\/li>\n<li>A CUDA-compatible GPU.<\/li>\n<li>Installing <a href=\"https:\/\/developer.nvidia.com\/cuda-10.0-download-archive\" target=\"_blank\" rel=\"noopener noreferrer\">CUDA v10.0<\/a> (make sure you get v.10.0, and not any newer version \u2013 you can\u2019t have multiple version of CUDA installed).<\/li>\n<li>Installing <a href=\"https:\/\/developer.nvidia.com\/rdp\/cudnn-download\" target=\"_blank\" rel=\"noopener noreferrer\">cuDNN v7.6.4 for CUDA 10.0<\/a> (you can\u2019t have multiple versions of cuDNN installed).<\/li>\n<\/ol>\n<p>Currently, Model Builder can check that you have a CUDA-compatible GPU and the GPU extension installed. However, it can\u2019t yet check that you have the correct versions of CUDA and cuDNN. We are working to add this compatibility check in a future release.<\/p>\n<p>Don\u2019t have a CUDA-compatible GPU but still want faster training? You can train in Azure, either by selecting the Azure training environment in Model Builder to utilize Azure ML or by creating an Azure VM with GPU and using Model Builder\u2019s local GPU option for training.<\/p>\n<p>You can read more about how to set up GPU training in the <a href=\"https:\/\/aka.ms\/vsmbgpu\" target=\"_blank\" rel=\"noopener noreferrer\">ML.NET Docs<\/a>.<\/p>\n<h2>Feedback button in Model Builder<\/h2>\n<p>It\u2019s\u00a0now\u00a0even\u00a0easier\u00a0to\u00a0open\u00a0GitHub\u00a0issues\u00a0for\u00a0Model\u00a0Builder.\u00a0We\u2019ve\u00a0added\u00a0a\u00a0Feedback\u00a0button\u00a0so\u00a0that\u00a0you\u00a0can\u00a0start\u00a0to\u00a0file\u00a0bugs\u00a0or\u00a0suggest\u00a0features\u00a0from\u00a0the\u00a0UI\u00a0in\u00a0Visual\u00a0Studio.<\/p>\n<p>Selecting\u00a0\u201cReport\u00a0a\u00a0bug\u201d\u00a0or\u00a0\u201cSuggest\u00a0a\u00a0feature\u201d\u00a0will\u00a0open\u00a0up\u00a0GitHub\u00a0in\u00a0your\u00a0browser\u00a0with\u00a0the\u00a0corresponding\u00a0template\u00a0to\u00a0fill\u00a0out.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-29325 size-large\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/mb-feedback-1024x723.png\" alt=\"Image Model Builder feedback\" width=\"640\" height=\"452\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/mb-feedback-1024x723.png 1024w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/mb-feedback-300x212.png 300w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/mb-feedback-768x543.png 768w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/08\/mb-feedback.png 1049w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/p>\n<h2>Thanks to our contributors<\/h2>\n<p>For\u00a0these\u00a0updates,\u00a0we\u00a0had\u00a0help\u00a0from\u00a0some\u00a0other\u00a0teams\u00a0at\u00a0Microsoft!<\/p>\n<p>Thanks to <a href=\"https:\/\/github.com\/klausmh\" target=\"_blank\" rel=\"noopener noreferrer\">Klaus Marius Hansen<\/a> and <a href=\"https:\/\/github.com\/lisahua\" target=\"_blank\" rel=\"noopener noreferrer\">Lisa Hua<\/a> from the PowerBI team and <a href=\"https:\/\/github.com\/suxi-ms\" target=\"_blank\" rel=\"noopener noreferrer\">Shakira Sun<\/a> and <a href=\"https:\/\/github.com\/mengaims\" target=\"_blank\" rel=\"noopener noreferrer\">Meng Ai<\/a> from the Kensho team for all of your contributions!<\/p>\n<h2>Feedback<\/h2>\n<p>We\u00a0would\u00a0love\u00a0to\u00a0hear\u00a0your\u00a0feedback!<\/p>\n<p>If\u00a0you\u00a0run\u00a0into\u00a0any\u00a0issues,\u00a0please\u00a0let\u00a0us\u00a0know\u00a0by\u00a0creating\u00a0an\u00a0issue\u00a0in\u00a0our\u00a0GitHub\u00a0repos\u00a0(or\u00a0use\u00a0the\u00a0new\u00a0Feedback\u00a0button\u00a0in\u00a0Model\u00a0Builder!):<\/p>\n<ul>\n<li>ML.NET API: <a href=\"http:\/\/www.github.com\/dotnet\/machinelearning\" target=\"_blank\" rel=\"noopener noreferrer\">github.com\/dotnet\/machinelearning<\/a><\/li>\n<li>ML.NET Tooling (Model Builder &amp; ML.NET CLI): <a href=\"http:\/\/www.github.com\/dotnet\/machinelearning-modelbuilder\" target=\"_blank\" rel=\"noopener noreferrer\">github.com\/dotnet\/machinelearning-modelbuilder<\/a><\/li>\n<\/ul>\n<h2>Get Started and Resources<\/h2>\n<p>Get started with ML.NET in this <a href=\"https:\/\/dotnet.microsoft.com\/learn\/ml-dotnet\/get-started-tutorial\/intro\" target=\"_blank\" rel=\"noopener noreferrer\">tutorial<\/a>.<\/p>\n<p>Learn more about ML.NET and Model Builder in <a href=\"https:\/\/aka.ms\/mlnet-docs\" target=\"_blank\" rel=\"noopener noreferrer\">Microsoft Docs<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>ML.NET is an open-source, cross-platform machine learning framework for .NET developers. It enables integrating machine learning into your .NET apps without requiring you to leave the .NET ecosystem or even have a background in ML or data science. ML.NET provides tooling (Model Builder UI in Visual Studio and the cross platform ML.NET CLI) that automatically [&hellip;]<\/p>\n","protected":false},"author":721,"featured_media":24299,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,688,691],"tags":[4,93,96],"class_list":["post-29311","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-machine-learning","category-ml-dotnet","tag-net","tag-machine-learning","tag-ml-net"],"acf":[],"blog_post_summary":"<p>ML.NET is an open-source, cross-platform machine learning framework for .NET developers. It enables integrating machine learning into your .NET apps without requiring you to leave the .NET ecosystem or even have a background in ML or data science. ML.NET provides tooling (Model Builder UI in Visual Studio and the cross platform ML.NET CLI) that automatically [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/29311","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/721"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=29311"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/29311\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/24299"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=29311"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=29311"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=29311"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}