Migrate remaining inprogress samples to v1.0.0-preview (#360)
* Minor changes in ReadMe.md Changed the scenarios wording from real time to cross cutting * Casing changes in Readme File * Migrating BikeSharingDemand sample to ML.Net v1.0.0-preview. -added new solution file with v1.0.0 -Changed common Directory.Build.props file to v1.0.0-preview * Changed ReadMe file of BikeSharing Demand sample. Added build.Props file in remaining samples to fix build errors * Minor change: BikesharingDemand sample -Removed unnecessary nuget package * Migrated Credit Card Fraud Detection Sample. * Migrated sample Customer segmentation * Commiting model file of migrated sample Customer Segmentation * Migrated Heart Disease Console APP. * WIP: Migrating IRIS Classification sample * Migrated IRIS Clustering sample to v1.0.0-preview * Migrated Movie Recommender Sample to v1.0.0-preview. * Migrated Movie Recommender E2e Sample to v1.0.0-preview * Migrated Timeseries -PowerAnomalyDetection sample to ML.Net v1.0.0-preview * Migrated Product Recommendation sample to v1.0.0-preview * Power Anomaly Detection sample: some minor changes and updated ReadMe file to ML.Net 1.0.0-preview * Migrated Sentiment Anlysis Sample to ML.Net v1.0.0-preview. Commented Previewing of features column as it displays a number of 0's which is difficult to read. * Migrated ShampooSales Spike Detection sample to v1.0.0-preview * Migrated TaxiFare Prediction sample to ML.net v1.0.0-preview * Migrated TensorFlow scorer-Image Classification Sample * Migrated Sales Forecast sample to v1.0.0-preview * changes in common files. * Changed the solution file name * Removed the unnecessary solution files. * Migrated MNIST sample to ML.Net 1.0.0-preview. Changed the trainer name to sdcaMaximumEntropy. * ReadMe file of MNIST sample. * Updated version number in Readme file of MNIST sample. * Migrated MultiClass Classification_Iris sample to ML.Net 1.0.0-preview * Migrated Github labeler sample to Ml.Net 1.0.0-preview. * updated solution file * migrated Scalable WEBAPI sample to v1.0.0-preview * Minor changes in GITHUB labeler sample * Minor changes in Sentiment Anlaysis sample. Using the model path directly intead of filestream. * WIP: migrating TensorFlow Estimator sample. * For TesnorFlow Estiamtor sample, the model got updated. storing the updated model in Predict project. * Minor change * Migrated Spam Detection Sample to Ml.Net 1.0.0-preview * Updated sln file. * Refactored Bike Sharing sample code to directly pass the filepath instead of file stream * Refactored CreditCard Fraus Detection sample to use filepath instead of filestream * Minor changes in Customer Segmenation sample * no need to use filestream * Removed old build.props file. * Heart Disease Sample: Replaced file stream with filepath * Iris Clustering Sample: Replaced file stream with filepath * IRIS Classification sample: Replaced file stream with filepath * Movei Recommender E2E sample: Refactored code to replace filestream with fielpath * Minor changes * Sales Forecast sample: Refactored code to replace filestream with file path * Migrated shampoosales spike detection sample to Ml.Net 1.0.0-preview * Migrated ReadMe file for Shampoo sales E2E sample. * ReadMe file of TensorFlow Estimator is migrated to 1.0.0-preview * Refactored TaxiFare sample to replace filestream with filepath * Refactored Powet Anomaly detection sample to repalce filestream with filepath * Changed the training algorithm to use linear classification * Refactored SpamDetection Sample and ReadMe file. * Updated ReadMe of Github Labeler sample * minor change * Changed the name of sample in ReadME file * Minor changes * Minor changes * updated build file. Changed solution file. Added new solution to include only cosnole proj to make the build successful
This commit is contained in:
Родитель
13178fec25
Коммит
109be9ed3a
|
@ -142,4 +142,4 @@ phases:
|
|||
- task: DotNetCoreCLI@2
|
||||
displayName: Build Shampoo Sales spike and change Detection E2E(Time Series)
|
||||
inputs:
|
||||
projects: '.\samples\csharp\csharp\end-to-end-apps\AnomalyDetection-ShampooSales-WinForms\AnomalyDetectionConsoleApp\AnomalyDetectionConsoleApp.csproj'
|
||||
projects: '.\samples\csharp\end-to-end-apps\SpikeDetection-ShampooSales-WinForms\ShampooSalesSpikeDetectionConsole.sln'
|
||||
|
|
|
@ -120,7 +120,7 @@ The official ML.NET samples are divided in multiple categories depending on the
|
|||
<td>
|
||||
<h4>Spike Detection-Shampoo Sales
|
||||
<a href="samples/csharp/getting-started/SpikeDetection_ShampooSales">C#</a> <img src="images/app-type-getting-started.png" alt="Getting started icon">
|
||||
<a href="samples/csharp/end-to-end-apps/AnomalyDetection-ShampooSales-WinForms">C#</a> <img src="images/app-type-e2e.png" alt="End-to-end app icon"></h4>
|
||||
<a href="samples/csharp/end-to-end-apps/SpikeDetection-ShampooSales-WinForms">C#</a> <img src="images/app-type-e2e.png" alt="End-to-end app icon"></h4>
|
||||
<h4>Spike Detection-PowerMeter Readings
|
||||
<a href="samples/csharp/getting-started/TimeSeries_PowerAnomalyDetection">C#</a> <img src="images/app-type-getting-started.png" alt="Getting started icon"></h4>
|
||||
</td>
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace Common
|
|||
|
||||
public static void PrintMulticlassClassificationFoldsAverageMetrics(
|
||||
string algorithmName,
|
||||
CrossValidationResult<MulticlassClassificationMetrics>[] crossValResults
|
||||
IReadOnlyList<CrossValidationResult<MulticlassClassificationMetrics>> crossValResults
|
||||
)
|
||||
{
|
||||
var metricsInMultipleFolds = crossValResults.Select(r => r.Metrics);
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<MicrosoftMLVersion>0.11.0</MicrosoftMLVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -1,291 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.ML.Data;
|
||||
using Microsoft.ML;
|
||||
using Microsoft.Data.DataView;
|
||||
using static Microsoft.ML.TrainCatalogBase;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
public static class ConsoleHelper
|
||||
{
|
||||
public static void PrintPrediction(string prediction)
|
||||
{
|
||||
Console.WriteLine($"*************************************************");
|
||||
Console.WriteLine($"Predicted : {prediction}");
|
||||
Console.WriteLine($"*************************************************");
|
||||
}
|
||||
|
||||
public static void PrintRegressionPredictionVersusObserved(string predictionCount, string observedCount)
|
||||
{
|
||||
Console.WriteLine($"-------------------------------------------------");
|
||||
Console.WriteLine($"Predicted : {predictionCount}");
|
||||
Console.WriteLine($"Actual: {observedCount}");
|
||||
Console.WriteLine($"-------------------------------------------------");
|
||||
}
|
||||
|
||||
public static void PrintRegressionMetrics(string name, RegressionMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"*************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} regression model ");
|
||||
Console.WriteLine($"*------------------------------------------------");
|
||||
Console.WriteLine($"* LossFn: {metrics.LossFn:0.##}");
|
||||
Console.WriteLine($"* R2 Score: {metrics.RSquared:0.##}");
|
||||
Console.WriteLine($"* Absolute loss: {metrics.L1:#.##}");
|
||||
Console.WriteLine($"* Squared loss: {metrics.L2:#.##}");
|
||||
Console.WriteLine($"* RMS loss: {metrics.Rms:#.##}");
|
||||
Console.WriteLine($"*************************************************");
|
||||
}
|
||||
|
||||
public static void PrintBinaryClassificationMetrics(string name, CalibratedBinaryClassificationMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"************************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} binary classification model ");
|
||||
Console.WriteLine($"*-----------------------------------------------------------");
|
||||
Console.WriteLine($"* Accuracy: {metrics.Accuracy:P2}");
|
||||
Console.WriteLine($"* Auc: {metrics.Auc:P2}");
|
||||
Console.WriteLine($"* Auprc: {metrics.Auprc:P2}");
|
||||
Console.WriteLine($"* F1Score: {metrics.F1Score:P2}");
|
||||
Console.WriteLine($"* LogLoss: {metrics.LogLoss:#.##}");
|
||||
Console.WriteLine($"* LogLossReduction: {metrics.LogLossReduction:#.##}");
|
||||
Console.WriteLine($"* PositivePrecision: {metrics.PositivePrecision:#.##}");
|
||||
Console.WriteLine($"* PositiveRecall: {metrics.PositiveRecall:#.##}");
|
||||
Console.WriteLine($"* NegativePrecision: {metrics.NegativePrecision:#.##}");
|
||||
Console.WriteLine($"* NegativeRecall: {metrics.NegativeRecall:P2}");
|
||||
Console.WriteLine($"************************************************************");
|
||||
}
|
||||
|
||||
public static void PrintMultiClassClassificationMetrics(string name, MultiClassClassifierMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"************************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} multi-class classification model ");
|
||||
Console.WriteLine($"*-----------------------------------------------------------");
|
||||
Console.WriteLine($" AccuracyMacro = {metrics.AccuracyMacro:0.####}, a value between 0 and 1, the closer to 1, the better");
|
||||
Console.WriteLine($" AccuracyMicro = {metrics.AccuracyMicro:0.####}, a value between 0 and 1, the closer to 1, the better");
|
||||
Console.WriteLine($" LogLoss = {metrics.LogLoss:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($" LogLoss for class 1 = {metrics.PerClassLogLoss[0]:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($" LogLoss for class 2 = {metrics.PerClassLogLoss[1]:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($" LogLoss for class 3 = {metrics.PerClassLogLoss[2]:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($"************************************************************");
|
||||
}
|
||||
|
||||
public static void PrintRegressionFoldsAverageMetrics(string algorithmName,CrossValidationResult<RegressionMetrics>[] crossValidationResults)
|
||||
{
|
||||
var L1 = crossValidationResults.Select(r => r.Metrics.L1);
|
||||
var L2 = crossValidationResults.Select(r => r.Metrics.L2);
|
||||
var RMS = crossValidationResults.Select(r => r.Metrics.L1);
|
||||
var lossFunction = crossValidationResults.Select(r => r.Metrics.LossFn);
|
||||
var R2 = crossValidationResults.Select(r => r.Metrics.RSquared);
|
||||
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
Console.WriteLine($"* Metrics for {algorithmName} Regression model ");
|
||||
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
|
||||
Console.WriteLine($"* Average L1 Loss: {L1.Average():0.###} ");
|
||||
Console.WriteLine($"* Average L2 Loss: {L2.Average():0.###} ");
|
||||
Console.WriteLine($"* Average RMS: {RMS.Average():0.###} ");
|
||||
Console.WriteLine($"* Average Loss Function: {lossFunction.Average():0.###} ");
|
||||
Console.WriteLine($"* Average R-squared: {R2.Average():0.###} ");
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
}
|
||||
|
||||
public static void PrintMulticlassClassificationFoldsAverageMetrics(
|
||||
string algorithmName,
|
||||
CrossValidationResult<MultiClassClassifierMetrics>[] crossValResults
|
||||
)
|
||||
{
|
||||
var metricsInMultipleFolds = crossValResults.Select(r => r.Metrics);
|
||||
|
||||
var microAccuracyValues = metricsInMultipleFolds.Select(m => m.AccuracyMicro);
|
||||
var microAccuracyAverage = microAccuracyValues.Average();
|
||||
var microAccuraciesStdDeviation = CalculateStandardDeviation(microAccuracyValues);
|
||||
var microAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(microAccuracyValues);
|
||||
|
||||
var macroAccuracyValues = metricsInMultipleFolds.Select(m => m.AccuracyMacro);
|
||||
var macroAccuracyAverage = macroAccuracyValues.Average();
|
||||
var macroAccuraciesStdDeviation = CalculateStandardDeviation(macroAccuracyValues);
|
||||
var macroAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(macroAccuracyValues);
|
||||
|
||||
var logLossValues = metricsInMultipleFolds.Select(m => m.LogLoss);
|
||||
var logLossAverage = logLossValues.Average();
|
||||
var logLossStdDeviation = CalculateStandardDeviation(logLossValues);
|
||||
var logLossConfidenceInterval95 = CalculateConfidenceInterval95(logLossValues);
|
||||
|
||||
var logLossReductionValues = metricsInMultipleFolds.Select(m => m.LogLossReduction);
|
||||
var logLossReductionAverage = logLossReductionValues.Average();
|
||||
var logLossReductionStdDeviation = CalculateStandardDeviation(logLossReductionValues);
|
||||
var logLossReductionConfidenceInterval95 = CalculateConfidenceInterval95(logLossReductionValues);
|
||||
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
Console.WriteLine($"* Metrics for {algorithmName} Multi-class Classification model ");
|
||||
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
|
||||
Console.WriteLine($"* Average MicroAccuracy: {microAccuracyAverage:0.###} - Standard deviation: ({microAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({microAccuraciesConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"* Average MacroAccuracy: {macroAccuracyAverage:0.###} - Standard deviation: ({macroAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({macroAccuraciesConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"* Average LogLoss: {logLossAverage:#.###} - Standard deviation: ({logLossStdDeviation:#.###}) - Confidence Interval 95%: ({logLossConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"* Average LogLossReduction: {logLossReductionAverage:#.###} - Standard deviation: ({logLossReductionStdDeviation:#.###}) - Confidence Interval 95%: ({logLossReductionConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
|
||||
}
|
||||
|
||||
public static double CalculateStandardDeviation (IEnumerable<double> values)
|
||||
{
|
||||
double average = values.Average();
|
||||
double sumOfSquaresOfDifferences = values.Select(val => (val - average) * (val - average)).Sum();
|
||||
double standardDeviation = Math.Sqrt(sumOfSquaresOfDifferences / (values.Count()-1));
|
||||
return standardDeviation;
|
||||
}
|
||||
|
||||
public static double CalculateConfidenceInterval95(IEnumerable<double> values)
|
||||
{
|
||||
double confidenceInterval95 = 1.96 * CalculateStandardDeviation(values) / Math.Sqrt((values.Count()-1));
|
||||
return confidenceInterval95;
|
||||
}
|
||||
|
||||
public static void PrintClusteringMetrics(string name, ClusteringMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"*************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} clustering model ");
|
||||
Console.WriteLine($"*------------------------------------------------");
|
||||
Console.WriteLine($"* AvgMinScore: {metrics.AvgMinScore}");
|
||||
Console.WriteLine($"* DBI is: {metrics.Dbi}");
|
||||
Console.WriteLine($"*************************************************");
|
||||
}
|
||||
|
||||
public static void ShowDataViewInConsole(MLContext mlContext, IDataView dataView, int numberOfRows = 4)
|
||||
{
|
||||
string msg = string.Format("Show data in DataView: Showing {0} rows with the columns", numberOfRows.ToString());
|
||||
ConsoleWriteHeader(msg);
|
||||
|
||||
var preViewTransformedData = dataView.Preview(maxRows: numberOfRows);
|
||||
|
||||
foreach (var row in preViewTransformedData.RowView)
|
||||
{
|
||||
var ColumnCollection = row.Values;
|
||||
string lineToPrint = "Row--> ";
|
||||
foreach (KeyValuePair<string, object> column in ColumnCollection)
|
||||
{
|
||||
lineToPrint += $"| {column.Key}:{column.Value}";
|
||||
}
|
||||
Console.WriteLine(lineToPrint + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
public static void PeekDataViewInConsole(MLContext mlContext, IDataView dataView, IEstimator<ITransformer> pipeline, int numberOfRows = 4)
|
||||
{
|
||||
string msg = string.Format("Peek data in DataView: Showing {0} rows with the columns", numberOfRows.ToString());
|
||||
ConsoleWriteHeader(msg);
|
||||
|
||||
//https://github.com/dotnet/machinelearning/blob/master/docs/code/MlNetCookBook.md#how-do-i-look-at-the-intermediate-data
|
||||
var transformer = pipeline.Fit(dataView);
|
||||
var transformedData = transformer.Transform(dataView);
|
||||
|
||||
// 'transformedData' is a 'promise' of data, lazy-loading. call Preview
|
||||
//and iterate through the returned collection from preview.
|
||||
|
||||
var preViewTransformedData = transformedData.Preview(maxRows: numberOfRows);
|
||||
|
||||
foreach (var row in preViewTransformedData.RowView)
|
||||
{
|
||||
var ColumnCollection = row.Values;
|
||||
string lineToPrint = "Row--> ";
|
||||
foreach (KeyValuePair<string, object> column in ColumnCollection)
|
||||
{
|
||||
lineToPrint += $"| {column.Key}:{column.Value}";
|
||||
}
|
||||
Console.WriteLine(lineToPrint + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<float[]> PeekVectorColumnDataInConsole(MLContext mlContext, string columnName, IDataView dataView, IEstimator<ITransformer> pipeline, int numberOfRows = 4)
|
||||
{
|
||||
string msg = string.Format("Peek data in DataView: : Show {0} rows with just the '{1}' column", numberOfRows, columnName );
|
||||
ConsoleWriteHeader(msg);
|
||||
|
||||
var transformer = pipeline.Fit(dataView);
|
||||
var transformedData = transformer.Transform(dataView);
|
||||
|
||||
// Extract the 'Features' column.
|
||||
var someColumnData = transformedData.GetColumn<float[]>(mlContext, columnName)
|
||||
.Take(numberOfRows).ToList();
|
||||
|
||||
// print to console the peeked rows
|
||||
someColumnData.ForEach(row => {
|
||||
String concatColumn = String.Empty;
|
||||
foreach (float f in row)
|
||||
{
|
||||
concatColumn += f.ToString();
|
||||
}
|
||||
Console.WriteLine(concatColumn);
|
||||
});
|
||||
|
||||
return someColumnData;
|
||||
}
|
||||
|
||||
public static void ConsoleWriteHeader(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine(" ");
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
var maxLength = lines.Select(x => x.Length).Max();
|
||||
Console.WriteLine(new string('#', maxLength));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
}
|
||||
|
||||
public static void ConsoleWriterSection(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
Console.WriteLine(" ");
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
var maxLength = lines.Select(x => x.Length).Max();
|
||||
Console.WriteLine(new string('-', maxLength));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
}
|
||||
|
||||
public static void ConsolePressAnyKey()
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine(" ");
|
||||
Console.WriteLine("Press any key to finish.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
public static void ConsoleWriteException(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
const string exceptionTitle = "EXCEPTION";
|
||||
Console.WriteLine(" ");
|
||||
Console.WriteLine(exceptionTitle);
|
||||
Console.WriteLine(new string('#', exceptionTitle.Length));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ConsoleWriteWarning(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.DarkMagenta;
|
||||
const string warningTitle = "WARNING";
|
||||
Console.WriteLine(" ");
|
||||
Console.WriteLine(warningTitle);
|
||||
Console.WriteLine(new string('#', warningTitle.Length));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,10 @@
|
|||
<None Remove="datasets\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\..\common\ConsoleHelper.cs" Link="Common\ConsoleHelper.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||
|
@ -27,6 +31,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Common\" />
|
||||
<Folder Include="Data\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -33,14 +33,10 @@ namespace GitHubLabeler
|
|||
_mlContext = new MLContext();
|
||||
|
||||
//Load model from file
|
||||
|
||||
using (var stream = new FileStream(_modelPath, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
_trainedModel = _mlContext.Model.Load(stream);
|
||||
}
|
||||
_trainedModel = _mlContext.Model.Load(_modelPath, out var modelInputSchema);
|
||||
|
||||
// Create prediction engine related to the loaded trained model
|
||||
_predEngine = _trainedModel.CreatePredictionEngine<GitHubIssue, GitHubIssuePrediction>(_mlContext);
|
||||
_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, GitHubIssuePrediction>(_trainedModel);
|
||||
|
||||
//Configure Client to access a GitHub repo
|
||||
if (accessToken != string.Empty)
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace GitHubLabeler
|
|||
SetupAppConfiguration();
|
||||
|
||||
//1. ChainedBuilderExtensions and Train the model
|
||||
BuildAndTrainModel(DataSetLocation, ModelPath, MyTrainerStrategy.SdcaMultiClassTrainer);
|
||||
BuildAndTrainModel(DataSetLocation, ModelPath, MyTrainerStrategy.OVAAveragedPerceptronTrainer);
|
||||
|
||||
//2. Try/test to predict a label for a single hard-coded Issue
|
||||
TestSingleLabelPrediction(ModelPath);
|
||||
|
@ -56,10 +56,10 @@ namespace GitHubLabeler
|
|||
var trainingDataView = mlContext.Data.LoadFromTextFile<GitHubIssue>(DataSetLocation, hasHeader: true, separatorChar:'\t', allowSparse: false);
|
||||
|
||||
// STEP 2: Common data process configuration with pipeline data transformations
|
||||
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: DefaultColumnNames.Label,inputColumnName:nameof(GitHubIssue.Area))
|
||||
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "Label",inputColumnName:nameof(GitHubIssue.Area))
|
||||
.Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "TitleFeaturized",inputColumnName:nameof(GitHubIssue.Title)))
|
||||
.Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "DescriptionFeaturized", inputColumnName: nameof(GitHubIssue.Description)))
|
||||
.Append(mlContext.Transforms.Concatenate(outputColumnName:DefaultColumnNames.Features, "TitleFeaturized", "DescriptionFeaturized"))
|
||||
.Append(mlContext.Transforms.Concatenate(outputColumnName:"Features", "TitleFeaturized", "DescriptionFeaturized"))
|
||||
.AppendCacheCheckpoint(mlContext);
|
||||
// Use in-memory cache for small/medium datasets to lower training time.
|
||||
// Do NOT use it (remove .AppendCacheCheckpoint()) when handling very large datasets.
|
||||
|
@ -72,15 +72,12 @@ namespace GitHubLabeler
|
|||
switch(selectedStrategy)
|
||||
{
|
||||
case MyTrainerStrategy.SdcaMultiClassTrainer:
|
||||
trainer = mlContext.MulticlassClassification.Trainers.StochasticDualCoordinateAscent(DefaultColumnNames.Label,
|
||||
DefaultColumnNames.Features);
|
||||
trainer = mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy("Label", "Features");
|
||||
break;
|
||||
case MyTrainerStrategy.OVAAveragedPerceptronTrainer:
|
||||
{
|
||||
// Create a binary classification trainer.
|
||||
var averagedPerceptronBinaryTrainer = mlContext.BinaryClassification.Trainers.AveragedPerceptron(DefaultColumnNames.Label,
|
||||
DefaultColumnNames.Features,
|
||||
numIterations: 10);
|
||||
var averagedPerceptronBinaryTrainer = mlContext.BinaryClassification.Trainers.AveragedPerceptron("Label", "Features",numberOfIterations: 10);
|
||||
// Compose an OVA (One-Versus-All) trainer with the BinaryTrainer.
|
||||
// In this strategy, a binary classification algorithm is used to train one classifier for each class, "
|
||||
// which distinguishes that class from all other classes. Prediction is then performed by running these binary classifiers, "
|
||||
|
@ -95,7 +92,7 @@ namespace GitHubLabeler
|
|||
|
||||
//Set the trainer/algorithm and map label to value (original readable state)
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer)
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue(DefaultColumnNames.PredictedLabel));
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
|
||||
|
||||
// STEP 4: Cross-Validate with single dataset (since we don't have two datasets, one for training and for evaluate)
|
||||
// in order to evaluate and get the model's accuracy metrics
|
||||
|
@ -105,7 +102,7 @@ namespace GitHubLabeler
|
|||
//Measure cross-validation time
|
||||
var watchCrossValTime = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
CrossValidationResult<MultiClassClassifierMetrics>[] crossValidationResults = mlContext.MulticlassClassification.CrossValidate(data:trainingDataView, estimator:trainingPipeline, numFolds: 6, labelColumn:DefaultColumnNames.Label);
|
||||
var crossValidationResults= mlContext.MulticlassClassification.CrossValidate(data:trainingDataView, estimator:trainingPipeline, numberOfFolds: 6, labelColumnName:"Label");
|
||||
|
||||
//Stop measuring time
|
||||
watchCrossValTime.Stop();
|
||||
|
@ -131,7 +128,7 @@ namespace GitHubLabeler
|
|||
// (OPTIONAL) Try/test a single prediction with the "just-trained model" (Before saving the model)
|
||||
GitHubIssue issue = new GitHubIssue() { ID = "Any-ID", Title = "WebSockets communication is slow in my machine", Description = "The WebSockets communication used under the covers by SignalR looks like is going slow in my development machine.." };
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = trainedModel.CreatePredictionEngine<GitHubIssue, GitHubIssuePrediction>(mlContext);
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<GitHubIssue, GitHubIssuePrediction>(trainedModel);
|
||||
//Score
|
||||
var prediction = predEngine.Predict(issue);
|
||||
Console.WriteLine($"=============== Single Prediction just-trained-model - Result: {prediction.Area} ===============");
|
||||
|
@ -139,8 +136,7 @@ namespace GitHubLabeler
|
|||
|
||||
// STEP 6: Save/persist the trained model to a .ZIP file
|
||||
Console.WriteLine("=============== Saving the model to a file ===============");
|
||||
using (var fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel, fs);
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, ModelPath);
|
||||
|
||||
Common.ConsoleHelper.ConsoleWriteHeader("Training process finalized");
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data sources | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v0.11 | Dynamic API | Up-to-date | Console app | .csv file and GitHub issues | Issues classification | Multi-class classification | SDCA multi-class classifier |
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .csv file and GitHub issues | Issues classification | Multi-class classification | SDCA multi-class classifier, AveragedPerceptronTrainer |
|
||||
|
||||
|
||||
This is a simple prototype application to demonstrate how to use [ML.NET](https://www.nuget.org/packages/Microsoft.ML/) APIs. The main focus is on creating, training, and using ML (Machine Learning) model that is implemented in Predictor.cs class.
|
||||
|
|
|
@ -44,12 +44,8 @@ namespace movierecommender.Controllers
|
|||
// 1. Create the ML.NET environment and load the already trained model
|
||||
MLContext mlContext = new MLContext();
|
||||
|
||||
ITransformer trainedModel;
|
||||
using (FileStream stream = new FileStream(_movieService.GetModelPath(), FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream, out var modelInputSchema);
|
||||
}
|
||||
|
||||
ITransformer trainedModel = mlContext.Model.Load(_movieService.GetModelPath(), out var modelInputSchema);
|
||||
|
||||
//2. Create a prediction function
|
||||
var predictionEngine = mlContext.Model.CreatePredictionEngine<MovieRating, MovieRatingPrediction>(trainedModel);
|
||||
|
||||
|
|
Двоичный файл не отображается.
|
@ -5,16 +5,6 @@
|
|||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Models\model.zip" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Models\model.zip">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CsvHelper" Version="12.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
|
@ -34,5 +24,11 @@
|
|||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Models\model.zip">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
|
Двоичный файл не отображается.
|
@ -86,12 +86,7 @@ namespace MovieRecommenderModel
|
|||
|
||||
//STEP 8: Save model to disk
|
||||
Console.WriteLine("=============== Writing model to the disk ===============", color);
|
||||
Console.WriteLine();
|
||||
|
||||
using (FileStream fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
{
|
||||
mlContext.Model.Save(model, trainingDataView.Schema, fs);
|
||||
}
|
||||
Console.WriteLine();mlContext.Model.Save(model, trainingDataView.Schema, ModelPath);
|
||||
|
||||
Console.WriteLine("=============== Re-Loading model from the disk ===============", color);
|
||||
Console.WriteLine();
|
||||
|
|
|
@ -55,9 +55,8 @@ namespace eShopForecastModelsTrainer
|
|||
|
||||
// Create and Train the model
|
||||
var model = trainingPipeline.Fit(trainingDataView);
|
||||
|
||||
using (var file = File.OpenWrite(outputModelPath))
|
||||
mlContext.Model.Save(model, trainingDataView.Schema, file);
|
||||
//Save model
|
||||
mlContext.Model.Save(model, trainingDataView.Schema, outputModelPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -56,8 +56,7 @@ namespace eShopForecastModelsTrainer
|
|||
var model = trainingPipeline.Fit(trainingDataView);
|
||||
|
||||
// Save the model for later comsumption from end-user apps
|
||||
using (var file = File.OpenWrite(outputModelPath))
|
||||
mlContext.Model.Save(model, trainingDataView.Schema, file);
|
||||
mlContext.Model.Save(model, trainingDataView.Schema, outputModelPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<MicrosoftMLVersion>0.11.0</MicrosoftMLVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
| ML.NET version | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v0.11 | Up-to-date | ASP.NET Core 2.2 WebAPI | Single data sample | Sentiment Analysis | Binary classification | Linear Classification |
|
||||
| v1.0.0-preview | Up-to-date | ASP.NET Core 2.2 WebAPI | Single data sample | Sentiment Analysis | Binary classification | Linear Classification |
|
||||
|
||||
|
||||
**This posts explains how to optimize your code when running an ML.NET model on an ASP.NET Core WebAPI service.** The code would be very similar when running it on an ASP.NET Core MVC or Razor web app, too.
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using Microsoft.ML;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using System.IO;
|
||||
using Microsoft.Data.DataView;
|
||||
|
||||
namespace Scalable.Model.Engine
|
||||
{
|
||||
{
|
||||
public class MLModelEngine<TData, TPrediction>
|
||||
where TData : class
|
||||
where TPrediction : class, new()
|
||||
|
@ -33,7 +32,7 @@ namespace Scalable.Model.Engine
|
|||
//Load the ProductSalesForecast model from the .ZIP file
|
||||
using (var fileStream = File.OpenRead(modelFilePathName))
|
||||
{
|
||||
_mlModel = _mlContext.Model.Load(fileStream);
|
||||
_mlModel = _mlContext.Model.Load(fileStream, out var modelInputSchema);
|
||||
}
|
||||
|
||||
_maxObjectsRetained = maxObjectsRetained;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Scalable.Model.Engine
|
|||
// Measuring CreatePredictionengine() time
|
||||
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
var predictionEngine = _model.CreatePredictionEngine<TData, TPrediction>(_mlContext);
|
||||
var predictionEngine = _mlContext.Model.CreatePredictionEngine<TData, TPrediction>(_model);
|
||||
|
||||
watch.Stop();
|
||||
long elapsedMs = watch.ElapsedMilliseconds;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.ML" Version="0.11.0" />
|
||||
<PackageReference Include="Microsoft.ML" Version="$(MicrosoftMLVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML" Version="0.11.0" />
|
||||
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.ML.FastTree" Version="1.0.0-preview" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v0.11 | Dynamic API | Up-to-date | WinForms app | .csv files | Spike and Change Point Detection of Shampoo Sales | Anomaly Detection | IID Spike Detection and IID Change point Detection |
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | WinForms app | .csv files | Spike and Change Point Detection of Shampoo Sales | Anomaly Detection | IID Spike Detection and IID Change point Detection |
|
||||
|
||||
![Alt Text](./ShampooSalesAnomalyDetection/images/shampoosales.gif)
|
||||
|
||||
|
@ -77,7 +77,7 @@ IDataView dataView = mlcontext.Data.LoadFromTextFile<AnomalyExample>(path: fileP
|
|||
string outputColumnName = nameof(AnomalyPrediction.Prediction);
|
||||
string inputColumnName = nameof(AnomalyExample.numReported);
|
||||
|
||||
var trainingPipeline = mlcontext.Transforms.IidSpikeEstimator(outputColumnName, inputColumnName, confidenceLevel, pValue);
|
||||
var trainingPipeLine = mlcontext.Transforms.DetectIidSpike(outputColumnName: nameof(ShampooSalesPrediction.Prediction), inputColumnName: nameof(ShampooSalesData.numSales),confidence: 95, pvalueHistoryLength: size / 4);
|
||||
```
|
||||
|
||||
### 2. Train model
|
||||
|
@ -100,7 +100,7 @@ ITransformer trainedModel;
|
|||
// Load model
|
||||
using (FileStream stream = new FileStream(modelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlcontext.Model.Load(stream);
|
||||
trainedModel = mlcontext.Model.Load(stream,out var modelInputSchema);
|
||||
}
|
||||
|
||||
// Apply data transformation to create predictions
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using Microsoft.ML;
|
||||
using System.IO;
|
||||
using Microsoft.Data.DataView;
|
||||
|
||||
namespace ShampooSalesAnomalyDetection
|
||||
{
|
||||
|
@ -37,10 +36,9 @@ namespace ShampooSalesAnomalyDetection
|
|||
|
||||
// Detect persistent change in the pattern
|
||||
ITransformer trainedChangePointModel = DetectChangepoint(mlcontext, size, dataView);
|
||||
|
||||
|
||||
SaveModel(mlcontext, trainedSpikeModel, SpikeModelPath);
|
||||
SaveModel(mlcontext, trainedChangePointModel, ChangePointModelPath);
|
||||
|
||||
SaveModel(mlcontext, trainedSpikeModel, SpikeModelPath, dataView);
|
||||
SaveModel(mlcontext, trainedChangePointModel, ChangePointModelPath, dataView);
|
||||
|
||||
Console.WriteLine("=============== End of process, hit any key to finish ===============");
|
||||
|
||||
|
@ -54,7 +52,7 @@ namespace ShampooSalesAnomalyDetection
|
|||
// STEP 2: Set the training algorithm
|
||||
// Note -- This confidence level and p-value work well for the shampoo-sales dataset;
|
||||
// you may need to adjust for different datasets
|
||||
var trainingPipeLine = mlcontext.Transforms.IidSpikeEstimator(outputColumnName: nameof(ShampooSalesPrediction.Prediction), inputColumnName: nameof(ShampooSalesData.numSales),confidence: 95, pvalueHistoryLength: size / 4);
|
||||
var trainingPipeLine = mlcontext.Transforms.DetectIidSpike(outputColumnName: nameof(ShampooSalesPrediction.Prediction), inputColumnName: nameof(ShampooSalesData.numSales),confidence: 95, pvalueHistoryLength: size / 4);
|
||||
|
||||
// STEP 3: Train the model by fitting the dataview
|
||||
Console.WriteLine("=============== Training the model using Spike Detection algorithm ===============");
|
||||
|
@ -87,7 +85,7 @@ namespace ShampooSalesAnomalyDetection
|
|||
Console.WriteLine("Detect Persistent changes in pattern");
|
||||
|
||||
//STEP 2: Set the training algorithm
|
||||
var trainingPipeLine = mlcontext.Transforms.IidChangePointEstimator(outputColumnName: nameof(ShampooSalesPrediction.Prediction), inputColumnName: nameof(ShampooSalesData.numSales), confidence: 95, changeHistoryLength: size / 4);
|
||||
var trainingPipeLine = mlcontext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ShampooSalesPrediction.Prediction), inputColumnName: nameof(ShampooSalesData.numSales), confidence: 95, changeHistoryLength: size / 4);
|
||||
|
||||
//STEP 3:Train the model by fitting the dataview
|
||||
Console.WriteLine("=============== Training the model Using Change Point Detection Algorithm===============");
|
||||
|
@ -117,11 +115,10 @@ namespace ShampooSalesAnomalyDetection
|
|||
return trainedModel;
|
||||
}
|
||||
|
||||
private static void SaveModel(MLContext mlcontext, ITransformer trainedModel, string modelPath)
|
||||
private static void SaveModel(MLContext mlcontext, ITransformer trainedModel, string modelPath, IDataView dataView)
|
||||
{
|
||||
Console.WriteLine("=============== Saving model ===============");
|
||||
using (var fs = new FileStream(modelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlcontext.Model.Save(trainedModel, fs);
|
||||
mlcontext.Model.Save(trainedModel,dataView.Schema, modelPath);
|
||||
|
||||
Console.WriteLine("The model is saved to {0}", modelPath);
|
||||
}
|
|
@ -5,11 +5,6 @@
|
|||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML" Version="0.11.0" />
|
||||
<PackageReference Include="Microsoft.ML.TimeSeries" Version="0.11.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Data\shampoo-sales.csv">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
|
@ -20,4 +15,9 @@
|
|||
<Folder Include="MLModels\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview" />
|
||||
<PackageReference Include="Microsoft.ML.TimeSeries" Version="0.12.0-preview" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28719.210
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.539
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnomalyDetectionConsoleApp", "AnomalyDetectionConsoleApp\AnomalyDetectionConsoleApp.csproj", "{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShampooSalesSpikesConsoleApp", "ShampooSalesConsoleApp\ShampooSalesSpikesConsoleApp.csproj", "{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShampooSalesAnomalyDetection", "ShampooSalesAnomalyDetection\ShampooSalesAnomalyDetection.csproj", "{8B051595-03CD-4026-91BB-403F90CF8526}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShampooSalesSpikesWinForms", "ShampooSalesWinforms\ShampooSalesSpikesWinForms.csproj", "{8B051595-03CD-4026-91BB-403F90CF8526}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -15,14 +15,14 @@ Global
|
|||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BEFD552F-4D22-4D86-97E8-177C14D4B2D2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Debug|x64.ActiveCfg = Debug|x64
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.539
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShampooSalesSpikesConsoleApp", "ShampooSalesConsoleApp\ShampooSalesSpikesConsoleApp.csproj", "{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7845CC34-9B79-4834-9BE6-53ED7DFCA64A}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1DF01FBE-19B3-401E-8A69-EAE343E0AF38}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,17 +1,10 @@
|
|||
using Microsoft.Data.DataView;
|
||||
using Microsoft.ML;
|
||||
using Microsoft.ML.Data;
|
||||
using Microsoft.ML.Transforms.TimeSeries;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Forms.DataVisualization.Charting;
|
||||
|
||||
|
@ -147,8 +140,8 @@ namespace ShampooSalesAnomalyDetection
|
|||
|
||||
// Step 2: Load & use model
|
||||
// Note -- The model is trained with the shampoo-sales dataset in a separate console app (see AnomalyDetectionConsoleApp)
|
||||
string spikeModelPath = @"../../../AnomalyDetectionConsoleApp/MLModels/ShampooSalesSpikeModel.zip";
|
||||
string changePointModelPath = @"../../../AnomalyDetectionConsoleApp/MLModels/ShampooSalesChangePointModel.zip";
|
||||
string spikeModelPath = @"../../../ShampooSalesConsoleApp/MLModels/ShampooSalesSpikeModel.zip";
|
||||
string changePointModelPath = @"../../../ShampooSalesConsoleApp/MLModels/ShampooSalesChangePointModel.zip";
|
||||
|
||||
if (spikeDet.Checked)
|
||||
{
|
||||
|
@ -177,12 +170,8 @@ namespace ShampooSalesAnomalyDetection
|
|||
|
||||
private void loadAndUseModel(MLContext mlcontext, IDataView dataView, String modelPath, String type, Color color)
|
||||
{
|
||||
ITransformer trainedModel;
|
||||
using (FileStream stream = new FileStream(modelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlcontext.Model.Load(stream);
|
||||
}
|
||||
|
||||
ITransformer trainedModel = mlcontext.Model.Load(modelPath, out var modelInputSchema);
|
||||
|
||||
// Step 3: Apply data transformation to create predictions
|
||||
IDataView transformedData = trainedModel.Transform(dataView);
|
||||
var predictions = mlcontext.Data.CreateEnumerable<ShampooSalesPrediction>(transformedData, reuseRowObject: false);
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
|
@ -105,20 +105,17 @@
|
|||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.DataView">
|
||||
<Version>0.11.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.ML">
|
||||
<Version>0.11.0</Version>
|
||||
<Version>1.0.0-preview</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.ML.CpuMath">
|
||||
<Version>0.11.0</Version>
|
||||
<Version>1.0.0-preview</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.ML.Mkl.Redist">
|
||||
<Version>0.11.0</Version>
|
||||
<Version>1.0.0-preview</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.ML.TimeSeries">
|
||||
<Version>0.11.0</Version>
|
||||
<Version>0.12.0-preview</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>10.0.3</Version>
|
До Ширина: | Высота: | Размер: 902 KiB После Ширина: | Высота: | Размер: 902 KiB |
|
@ -25,12 +25,7 @@ namespace CreditCardFraudDetection.Predictor
|
|||
|
||||
Console.WriteLine($"Predictions from saved model:");
|
||||
|
||||
ITransformer model;
|
||||
DataViewSchema inputSchema;
|
||||
using (var file = File.OpenRead(_modelfile))
|
||||
{
|
||||
model = mlContext.Model.Load(file,out inputSchema);
|
||||
}
|
||||
ITransformer model = mlContext.Model.Load(_modelfile, out var inputSchema);
|
||||
|
||||
var predictionEngine = mlContext.Model.CreatePredictionEngine<TransactionObservation, TransactionFraudPrediction>(model);
|
||||
Console.WriteLine($"\n \n Test {numberOfPredictions} transactions, from the test datasource, that should be predicted as fraud (true):");
|
||||
|
|
|
@ -21,7 +21,6 @@ namespace CreditCardFraudDetection.Trainer
|
|||
string trainDataSetFilePath = Path.Combine(assetsPath, "output", "trainData.csv");
|
||||
string testDataSetFilePath = Path.Combine(assetsPath, "output", "testData.csv");
|
||||
string modelFilePath = Path.Combine(assetsPath, "output", "fastTree.zip");
|
||||
//
|
||||
|
||||
// Unzip the original dataset as it is too large for GitHub repo if not zipped
|
||||
UnZipDataSet(zipDataSet, fullDataSetFilePath);
|
||||
|
@ -183,8 +182,7 @@ namespace CreditCardFraudDetection.Trainer
|
|||
|
||||
private static void SaveModel(MLContext mlContext, ITransformer model, string modelFilePath, DataViewSchema trainingDataSchema)
|
||||
{
|
||||
using (var fs = new FileStream(modelFilePath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(model,trainingDataSchema,fs);
|
||||
mlContext.Model.Save(model,trainingDataSchema, modelFilePath);
|
||||
|
||||
Console.WriteLine("Saved model to " + modelFilePath);
|
||||
}
|
||||
|
|
|
@ -72,9 +72,9 @@ namespace HeartDiseasePredictionConsoleApp
|
|||
Console.WriteLine($"************************************************************");
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine("");
|
||||
|
||||
Console.WriteLine("=============== Saving the model to a file ===============");
|
||||
using (var fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, fs);
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, ModelPath);
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine("=============== Model Saved ============= ");
|
||||
|
@ -83,16 +83,9 @@ namespace HeartDiseasePredictionConsoleApp
|
|||
|
||||
private static void TestPrediction(MLContext mlContext)
|
||||
{
|
||||
ITransformer trainedModel;
|
||||
DataViewSchema inputSchema;
|
||||
ITransformer trainedModel = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream, out inputSchema);
|
||||
}
|
||||
var predictionEngine = mlContext.Model.CreatePredictionEngine<HeartData, HeartPrediction>(trainedModel);
|
||||
|
||||
|
||||
var predictionEngine = mlContext.Model.CreatePredictionEngine<HeartData, HeartPrediction>(trainedModel);
|
||||
|
||||
foreach (var heartData in HeartSampleData.heartDatas)
|
||||
{
|
||||
|
|
|
@ -35,7 +35,7 @@ Building a model includes:
|
|||
|
||||
* Create an Estimator and transform the data to numeric vectors so it can be used effectively by an ML algorithm (with `FeaturizeText`)
|
||||
|
||||
* Choosing a trainer/learning algorithm (such as `FastTree`) to train the model with.
|
||||
* Choosing a trainer/learning algorithm (such as `SdcaLogisticRegression`) to train the model with.
|
||||
|
||||
The initial code is similar to the following:
|
||||
|
||||
|
@ -50,10 +50,8 @@ IDataView testData = trainTestSplit.TestSet;
|
|||
// STEP 2: Common data process configuration with pipeline data transformations
|
||||
var dataProcessPipeline = mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName:nameof(SentimentIssue.Text));
|
||||
|
||||
|
||||
|
||||
// STEP 3: Set the training algorithm, then create and config the modelBuilder
|
||||
var trainer = mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Label", featureColumnName: "Features");
|
||||
var trainer = mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features");
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer);
|
||||
```
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace SentimentAnalysisConsoleApp
|
|||
//ConsoleHelper.PeekVectorColumnDataInConsole(mlContext, "Features", dataView, dataProcessPipeline, 1);
|
||||
|
||||
// STEP 3: Set the training algorithm, then create and config the modelBuilder
|
||||
var trainer = mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Label", featureColumnName: "Features");
|
||||
var trainer = mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features");
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer);
|
||||
|
||||
//Measure training time
|
||||
|
@ -80,9 +80,7 @@ namespace SentimentAnalysisConsoleApp
|
|||
ConsoleHelper.PrintBinaryClassificationMetrics(trainer.ToString(), metrics);
|
||||
|
||||
// STEP 6: Save/persist the trained model to a .ZIP file
|
||||
|
||||
using (var fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel,trainingData.Schema, fs);
|
||||
mlContext.Model.Save(trainedModel, trainingData.Schema, ModelPath);
|
||||
|
||||
Console.WriteLine("The model is saved to {0}", ModelPath);
|
||||
|
||||
|
@ -94,11 +92,7 @@ namespace SentimentAnalysisConsoleApp
|
|||
{
|
||||
SentimentIssue sampleStatement = new SentimentIssue { Text = "This is a very rude movie" };
|
||||
|
||||
ITransformer trainedModel;
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream, out var modelInputSchema);
|
||||
}
|
||||
ITransformer trainedModel = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine= mlContext.Model.CreatePredictionEngine<SentimentIssue, SentimentPrediction>(trainedModel);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML" Version="$(MicrosoftMLVersion)" />
|
||||
<PackageReference Include="Microsoft.ML.FastTree" Version="1.0.0-preview" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<MicrosoftMLVersion>0.10.0</MicrosoftMLVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v0.10 | Dynamic API | Might need to update project structure to match template | Console app | .tsv files | Spam detection | Two-class classification | SDCA (linear learner), also showing the CustomMapping estimator, which enables adding custom code to an ML.NET pipeline |
|
||||
| v1.0.0-preview | Dynamic API | Might need to update project structure to match template | Console app | .tsv files | Spam detection | Two-class classification | Averaged Perceptron (linear learner) |
|
||||
|
||||
In this sample, you'll see how to use [ML.NET](https://www.microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet) to predict whether a text message is spam. In the world of machine learning, this type of prediction is known as **binary classification**.
|
||||
|
||||
|
@ -37,15 +37,23 @@ The initial code is similar to the following:
|
|||
MLContext mlContext = new MLContext();
|
||||
|
||||
// Specify the schema for spam data and read it into DataView.
|
||||
var data = mlContext.Data.ReadFromTextFile<SpamInput>(path: TrainDataPath, hasHeader: true, separatorChar: '\t');
|
||||
var data = mlContext.Data.LoadFromTextFile<SpamInput>(path: TrainDataPath, hasHeader: true, separatorChar: '\t');
|
||||
|
||||
// Create the estimator which converts the text label to boolean, featurizes the text, and adds a linear trainer.
|
||||
var dataProcessPipeLine = mlContext.Transforms.CustomMapping<MyInput, MyOutput>(mapAction: MyLambda.MyAction, contractName: MyLambda")
|
||||
.Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: DefaultColumnNames.Features, inputColumnName: nameofSpamInput.Message)));
|
||||
|
||||
//Create the training pipeline
|
||||
var trainingPipeLine = dataProcessPipeLine.Append(mlContext.BinaryClassification.Trainers.StochasticDualCoordinateAscent());
|
||||
// Data process configuration with pipeline data transformations
|
||||
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Label")
|
||||
.Append(mlContext.Transforms.Text.FeaturizeText("FeaturesText", new Microsoft.ML.Transforms.Text.TextFeaturizingEstimator.Options
|
||||
{
|
||||
WordFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 2, UseAllLengths = true },
|
||||
CharFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 3, UseAllLengths = false },
|
||||
}, "Message"))
|
||||
.Append(mlContext.Transforms.CopyColumns("Features", "FeaturesText"))
|
||||
.Append(mlContext.Transforms.NormalizeLpNorm("Features", "Features"))
|
||||
.AppendCacheCheckpoint(mlContext);
|
||||
|
||||
// Set the training algorithm
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.OneVersusAll(mlContext.BinaryClassification.Trainers.AveragedPerceptron(labelColumnName: "Label", numberOfIterations: 10, featureColumnName: "Features"), labelColumnName: "Label")
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
|
||||
var trainingPipeLine = dataProcessPipeline.Append(trainer);
|
||||
```
|
||||
|
||||
### 2. Evaluate model
|
||||
|
@ -53,9 +61,7 @@ var trainingPipeLine = dataProcessPipeLine.Append(mlContext.BinaryClassification
|
|||
For this dataset, we will use [cross-validation](https://en.wikipedia.org/wiki/Cross-validation_(statistics)) to evaluate our model. This will partition the data into 5 'folds', train 5 models (on each combination of 4 folds), and test them on the fold that wasn't used in training.
|
||||
|
||||
```CSharp
|
||||
var crossValidationResults = mlContext.BinaryClassification.CrossValidate(data:data, estimator:trainingPipeLine, numFolds: 5);
|
||||
var aucs = cvResults.Select(r => r.metrics.Auc);
|
||||
Console.WriteLine("The AUC is {0}", aucs.Average());
|
||||
var crossValidationResults = mlContext.MulticlassClassification.CrossValidate(data: data, estimator: trainingPipeLine, numberOfFolds: 5);
|
||||
```
|
||||
|
||||
Note that usually we evaluate a model after training it. However, cross-validation includes the model training part so we don't need to do `Fit()` first. However, we will later train the model on the full dataset to take advantage of the additional data.
|
||||
|
@ -69,24 +75,13 @@ var model = trainingPipeLine.Fit(data);
|
|||
|
||||
### 4. Consume model
|
||||
|
||||
After the model is trained, you can use the `Predict()` API to predict whether new text is spam. In this case, we change the threshold of the model to get better predictions. We do this because our data is skewed with most messages not being spam.
|
||||
After the model is trained, you can use the `Predict()` API to predict whether new text is spam.
|
||||
|
||||
```CSharp
|
||||
// The dataset we have is skewed, as there are many more non-spam messages than spam messages.
|
||||
// While our model is relatively good at detecting the difference, this skewness leads it to always
|
||||
// say the message is not spam. We deal with this by lowering the threshold of the predictor. In reality,
|
||||
// it is useful to look at the precision-recall curve to identify the best possible threshold.
|
||||
var inPipe = new TransformerChain<ITransformer>(model.Take(model.Count() - 1).ToArray());
|
||||
var lastTransformer = new BinaryPredictionTransformer<IPredictorProducing<float>>(mlContext, model.LastTransformer.Model, inPipe.GetOutputSchema(data.Schema), model.LastTransformer.FeatureColumn, threshold: 0.15f, thresholdColumn: DefaultColumnNames.Probability);
|
||||
|
||||
ITransformer[] parts = model.ToArray();
|
||||
parts[parts.Length - 1] = lastTransformer;
|
||||
var newModel = new TransformerChain<ITransformer>(parts);
|
||||
|
||||
// Create a PredictionFunction from our model
|
||||
var predictor = newModel.MakePredictionFunction<SpamInput, SpamPrediction>(mlContext);
|
||||
//Create a PredictionFunction from our model
|
||||
var predictor = mlContext.Model.CreatePredictionEngine<SpamInput, SpamPrediction>(model);
|
||||
|
||||
var input = new SpamInput { Message = "free medicine winner! congratulations" };
|
||||
Console.WriteLine("The message '{0}' is {1}", input.Message, predictor.Predict(input).isSpam ? "spam" : "not spam");
|
||||
Console.WriteLine("The message '{0}' is {1}", input.Message, prediction.isSpam == "spam" ? "spam" : "not spam");
|
||||
|
||||
```
|
||||
|
|
|
@ -5,9 +5,6 @@ namespace SpamDetectionConsoleApp.MLDataStructures
|
|||
class SpamPrediction
|
||||
{
|
||||
[ColumnName("PredictedLabel")]
|
||||
public bool isSpam { get; set; }
|
||||
|
||||
public float Score { get; set; }
|
||||
public float Probability { get; set; }
|
||||
public string isSpam { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Composition;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Common;
|
||||
using Microsoft.ML;
|
||||
using Microsoft.ML.Core.Data;
|
||||
using Microsoft.ML.Data;
|
||||
using Microsoft.ML.Transforms;
|
||||
using SpamDetectionConsoleApp.MLDataStructures;
|
||||
|
||||
namespace SpamDetectionConsoleApp
|
||||
|
@ -36,41 +37,38 @@ namespace SpamDetectionConsoleApp
|
|||
MLContext mlContext = new MLContext();
|
||||
|
||||
// Specify the schema for spam data and read it into DataView.
|
||||
var data = mlContext.Data.ReadFromTextFile<SpamInput>(path: TrainDataPath, hasHeader: true, separatorChar: '\t');
|
||||
var data = mlContext.Data.LoadFromTextFile<SpamInput>(path: TrainDataPath, hasHeader: true, separatorChar: '\t');
|
||||
|
||||
// Create the estimator which converts the text label to boolean, featurizes the text, and adds a linear trainer.
|
||||
var dataProcessPipeLine = mlContext.Transforms.CustomMapping<MyInput, MyOutput>(mapAction: MyLambda.MyAction, contractName: "MyLambda")
|
||||
.Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: DefaultColumnNames.Features, inputColumnName: nameof(SpamInput.Message)));
|
||||
|
||||
//Create the training pipeline
|
||||
Console.WriteLine("=============== Training the model ===============");
|
||||
var trainingPipeLine = dataProcessPipeLine.Append(mlContext.BinaryClassification.Trainers.StochasticDualCoordinateAscent());
|
||||
// Data process configuration with pipeline data transformations
|
||||
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Label")
|
||||
.Append(mlContext.Transforms.Text.FeaturizeText("FeaturesText", new Microsoft.ML.Transforms.Text.TextFeaturizingEstimator.Options
|
||||
{
|
||||
WordFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 2, UseAllLengths = true },
|
||||
CharFeatureExtractor = new Microsoft.ML.Transforms.Text.WordBagEstimator.Options { NgramLength = 3, UseAllLengths = false },
|
||||
}, "Message"))
|
||||
.Append(mlContext.Transforms.CopyColumns("Features", "FeaturesText"))
|
||||
.Append(mlContext.Transforms.NormalizeLpNorm("Features", "Features"))
|
||||
.AppendCacheCheckpoint(mlContext);
|
||||
|
||||
// Set the training algorithm
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.OneVersusAll(mlContext.BinaryClassification.Trainers.AveragedPerceptron(labelColumnName: "Label", numberOfIterations: 10, featureColumnName: "Features"), labelColumnName: "Label")
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
|
||||
var trainingPipeLine = dataProcessPipeline.Append(trainer);
|
||||
|
||||
// Evaluate the model using cross-validation.
|
||||
// Cross-validation splits our dataset into 'folds', trains a model on some folds and
|
||||
// evaluates it on the remaining fold. We are using 5 folds so we get back 5 sets of scores.
|
||||
// Let's compute the average AUC, which should be between 0.5 and 1 (higher is better).
|
||||
Console.WriteLine("=============== Cross-validating to get model's accuracy metrics ===============");
|
||||
var crossValidationResults = mlContext.BinaryClassification.CrossValidate(data:data, estimator:trainingPipeLine, numFolds: 5);
|
||||
var aucs = crossValidationResults.Select(r => r.metrics.Auc);
|
||||
Console.WriteLine("The AUC is {0}", aucs.Average());
|
||||
|
||||
var crossValidationResults = mlContext.MulticlassClassification.CrossValidate(data: data, estimator: trainingPipeLine, numberOfFolds: 5);
|
||||
ConsoleHelper.PrintMulticlassClassificationFoldsAverageMetrics(trainer.ToString(), crossValidationResults);
|
||||
|
||||
// Now let's train a model on the full dataset to help us get better results
|
||||
var model = trainingPipeLine.Fit(data);
|
||||
|
||||
// The dataset we have is skewed, as there are many more non-spam messages than spam messages.
|
||||
// While our model is relatively good at detecting the difference, this skewness leads it to always
|
||||
// say the message is not spam. We deal with this by lowering the threshold of the predictor. In reality,
|
||||
// it is useful to look at the precision-recall curve to identify the best possible threshold.
|
||||
var inPipe = new TransformerChain<ITransformer>(model.Take(model.Count() - 1).ToArray());
|
||||
var lastTransformer = new BinaryPredictionTransformer<IPredictorProducing<float>>(mlContext, model.LastTransformer.Model, inPipe.GetOutputSchema(data.Schema), model.LastTransformer.FeatureColumn, threshold: 0.15f, thresholdColumn: DefaultColumnNames.Probability);
|
||||
|
||||
ITransformer[] parts = model.ToArray();
|
||||
parts[parts.Length - 1] = lastTransformer;
|
||||
ITransformer newModel = new TransformerChain<ITransformer>(parts);
|
||||
|
||||
// Create a PredictionFunction from our model
|
||||
var predictor = newModel.CreatePredictionEngine<SpamInput, SpamPrediction>(mlContext);
|
||||
//Create a PredictionFunction from our model
|
||||
var predictor = mlContext.Model.CreatePredictionEngine<SpamInput, SpamPrediction>(model);
|
||||
|
||||
Console.WriteLine("=============== Predictions for below data===============");
|
||||
// Test a few examples
|
||||
|
@ -93,26 +91,12 @@ namespace SpamDetectionConsoleApp
|
|||
public bool Label { get; set; }
|
||||
}
|
||||
|
||||
public class MyLambda
|
||||
{
|
||||
[Export("MyLambda")]
|
||||
public ITransformer MyTransformer => ML.Transforms.CustomMappingTransformer<MyInput, MyOutput>(MyAction, "MyLambda");
|
||||
|
||||
[Import]
|
||||
public MLContext ML { get; set; }
|
||||
|
||||
public static void MyAction(MyInput input, MyOutput output)
|
||||
{
|
||||
output.Label = input.Label == "spam" ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClassifyMessage(PredictionEngine<SpamInput, SpamPrediction> predictor, string message)
|
||||
{
|
||||
var input = new SpamInput { Message = message };
|
||||
var prediction = predictor.Predict(input);
|
||||
|
||||
Console.WriteLine("The message '{0}' is {1}", input.Message, prediction.isSpam ? "spam" : "not spam");
|
||||
Console.WriteLine("The message '{0}' is {1}", input.Message, prediction.isSpam == "spam" ? "spam" : "not spam");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,23 @@
|
|||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\common\ConsoleHelper.cs" Link="Common\ConsoleHelper.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML" Version="$(MicrosoftMLVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Common\" />
|
||||
<Folder Include="Data\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Composition.AttributedModel">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\system.composition.attributedmodel\1.0.31\lib\netstandard1.0\System.Composition.AttributedModel.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -30,14 +30,9 @@ namespace CustomerSegmentation.Model
|
|||
_mlContext = mlContext;
|
||||
}
|
||||
|
||||
public ITransformer LoadModelFromZipFile(string modelPath)
|
||||
public ITransformer LoadModel(string modelPath)
|
||||
{
|
||||
DataViewSchema inputSchema;
|
||||
using (var stream = new FileStream(modelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
_trainedModel = _mlContext.Model.Load(stream, out inputSchema);
|
||||
}
|
||||
|
||||
_trainedModel = _mlContext.Model.Load(modelPath, out var modelInputSchema);
|
||||
return _trainedModel;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace CustomerSegmentation
|
|||
string assetsPath = GetAbsolutePath(assetsRelativePath);
|
||||
|
||||
var pivotCsv = Path.Combine(assetsPath, "inputs", "pivot.csv");
|
||||
var modelZipFilePath = Path.Combine(assetsPath, "inputs", "retailClustering.zip");
|
||||
var modelPath = Path.Combine(assetsPath, "inputs", "retailClustering.zip");
|
||||
var plotSvg = Path.Combine(assetsPath, "outputs", "customerSegmentation.svg");
|
||||
var plotCsv = Path.Combine(assetsPath, "outputs", "customerSegmentation.csv");
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace CustomerSegmentation
|
|||
|
||||
//Create the clusters: Create data files and plot a chart
|
||||
var clusteringModelScorer = new ClusteringModelScorer(mlContext, pivotCsv, plotSvg, plotCsv);
|
||||
clusteringModelScorer.LoadModelFromZipFile(modelZipFilePath);
|
||||
clusteringModelScorer.LoadModel(modelPath);
|
||||
|
||||
clusteringModelScorer.CreateCustomerClusters();
|
||||
} catch (Exception ex)
|
||||
|
|
Двоичный файл не отображается.
|
@ -18,7 +18,7 @@ namespace CustomerSegmentation
|
|||
string transactionsCsv = Path.Combine(assetsPath, "inputs", "transactions.csv");
|
||||
string offersCsv = Path.Combine(assetsPath, "inputs", "offers.csv");
|
||||
string pivotCsv = Path.Combine(assetsPath, "inputs", "pivot.csv");
|
||||
string modelZip = Path.Combine(assetsPath, "outputs", "retailClustering.zip");
|
||||
string modelPath = Path.Combine(assetsPath, "outputs", "retailClustering.zip");
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -63,10 +63,9 @@ namespace CustomerSegmentation
|
|||
ConsoleHelper.PrintClusteringMetrics(trainer.ToString(), metrics);
|
||||
|
||||
//STEP 6: Save/persist the trained model to a .ZIP file
|
||||
using (var fs = new FileStream(modelZip, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel, pivotDataView.Schema, fs);
|
||||
mlContext.Model.Save(trainedModel, pivotDataView.Schema, modelPath);
|
||||
|
||||
Console.WriteLine("The model is saved to {0}", modelZip);
|
||||
Console.WriteLine("The model is saved to {0}", modelPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
Двоичный файл не отображается.
|
@ -65,8 +65,7 @@ namespace Clustering_Iris
|
|||
ConsoleHelper.PrintClusteringMetrics(trainer.ToString(), metrics);
|
||||
|
||||
// STEP5: Save/persist the model as a .ZIP file
|
||||
using (var fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, fs);
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, ModelPath);
|
||||
|
||||
Console.WriteLine("=============== End of training process ===============");
|
||||
|
||||
|
@ -81,18 +80,15 @@ namespace Clustering_Iris
|
|||
PetalWidth = 5.1f,
|
||||
};
|
||||
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
ITransformer model = mlContext.Model.Load(stream, out var modelInputSchema);
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<IrisData, IrisPrediction>(model);
|
||||
ITransformer model = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<IrisData, IrisPrediction>(model);
|
||||
|
||||
//Score
|
||||
var resultprediction = predEngine.Predict(sampleIrisData);
|
||||
|
||||
Console.WriteLine($"Cluster assigned for setosa flowers:" + resultprediction.SelectedClusterId);
|
||||
}
|
||||
//Score
|
||||
var resultprediction = predEngine.Predict(sampleIrisData);
|
||||
|
||||
Console.WriteLine($"Cluster assigned for setosa flowers:" + resultprediction.SelectedClusterId);
|
||||
|
||||
Console.WriteLine("=============== End of process, hit any key to finish ===============");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<MicrosoftMLVersion>0.10.0</MicrosoftMLVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -16,7 +16,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML" Version="$(MicrosoftMLVersion)" />
|
||||
<PackageReference Include="Microsoft.ML.ImageAnalytics" Version="$(MicrosoftMLVersion)" />
|
||||
<PackageReference Include="Microsoft.ML.TensorFlow" Version="$(MicrosoftMLVersion)" />
|
||||
<PackageReference Include="Microsoft.ML.TensorFlow" Version="0.12.0-preview" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -3,8 +3,6 @@ using System.Linq;
|
|||
using ImageClassification.ImageData;
|
||||
using System.IO;
|
||||
using Microsoft.ML;
|
||||
using Microsoft.ML.Core.Data;
|
||||
using Microsoft.ML.Data;
|
||||
using static ImageClassification.Model.ConsoleHelpers;
|
||||
|
||||
namespace ImageClassification.Model
|
||||
|
@ -30,12 +28,10 @@ namespace ImageClassification.Model
|
|||
Console.WriteLine($"Model loaded: {modelLocation}");
|
||||
|
||||
// Load the model
|
||||
ITransformer loadedModel;
|
||||
using (var f = new FileStream(modelLocation, FileMode.Open))
|
||||
loadedModel = mlContext.Model.Load(f);
|
||||
ITransformer loadedModel = mlContext.Model.Load(modelLocation,out var modelInputSchema);
|
||||
|
||||
// Make prediction function (input = ImageNetData, output = ImageNetPrediction)
|
||||
var predictor = loadedModel.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(mlContext);
|
||||
var predictor = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(loadedModel);
|
||||
// Read csv file into List<ImageNetData>
|
||||
var imageListToPredict = ImageNetData.ReadFromCsv(dataLocation, imagesFolder).ToList();
|
||||
|
||||
|
|
Двоичный файл не отображается.
|
@ -10,7 +10,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML" Version="$(MicrosoftMLVersion)" />
|
||||
<PackageReference Include="Microsoft.ML.ImageAnalytics" Version="$(MicrosoftMLVersion)" />
|
||||
<PackageReference Include="Microsoft.ML.TensorFlow" Version="$(MicrosoftMLVersion)" />
|
||||
<PackageReference Include="Microsoft.ML.TensorFlow" Version="0.12.0-preview" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.ML;
|
||||
using Microsoft.ML.Data;
|
||||
using Microsoft.ML.ImageAnalytics;
|
||||
using ImageClassification.ImageData;
|
||||
using static ImageClassification.Model.ConsoleHelpers;
|
||||
using Microsoft.ML.Core.Data;
|
||||
|
||||
namespace ImageClassification.Model
|
||||
{
|
||||
|
@ -51,16 +48,19 @@ namespace ImageClassification.Model
|
|||
|
||||
|
||||
|
||||
var data = mlContext.Data.ReadFromTextFile<ImageNetData>(path:dataLocation, hasHeader: false);
|
||||
var data = mlContext.Data.LoadFromTextFile<ImageNetData>(path:dataLocation, hasHeader: false);
|
||||
|
||||
var pipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: LabelTokey,inputColumnName:DefaultColumnNames.Label)
|
||||
.Append(mlContext.Transforms.LoadImages(imagesFolder, (ImageReal, nameof(ImageNetData.ImagePath))))
|
||||
.Append(mlContext.Transforms.Resize(outputColumnName:ImageReal, imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: ImageReal))
|
||||
.Append(mlContext.Transforms.ExtractPixels(new ImagePixelExtractorTransformer.ColumnInfo(name: "input",inputColumnName: ImageReal, interleave: ImageNetSettings.channelsLast, offset: ImageNetSettings.mean)))
|
||||
.Append(mlContext.Transforms.ScoreTensorFlowModel(modelLocation:featurizerModelLocation, outputColumnNames: new[] { "softmax2_pre_activation" },inputColumnNames: new[] { "input" }))
|
||||
.Append(mlContext.MulticlassClassification.Trainers.LogisticRegression(labelColumn:LabelTokey, featureColumn:"softmax2_pre_activation"))
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue((PredictedLabelValue,DefaultColumnNames.PredictedLabel)));
|
||||
var pipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: LabelTokey,inputColumnName:"Label")
|
||||
.Append(mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: imagesFolder, inputColumnName: nameof(ImageNetData.ImagePath)))
|
||||
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input"))
|
||||
.Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean))
|
||||
.Append(mlContext.Model.LoadTensorFlowModel(featurizerModelLocation).
|
||||
ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
|
||||
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName:LabelTokey, featureColumnName:"softmax2_pre_activation"))
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue(PredictedLabelValue,"PredictedLabel"))
|
||||
.AppendCacheCheckpoint(mlContext);
|
||||
|
||||
|
||||
// Train the model
|
||||
ConsoleWriteHeader("Training classification model");
|
||||
ITransformer model = pipeline.Fit(data);
|
||||
|
@ -70,21 +70,21 @@ namespace ImageClassification.Model
|
|||
var trainData = model.Transform(data);
|
||||
var loadedModelOutputColumnNames = trainData.Schema
|
||||
.Where(col => !col.IsHidden).Select(col => col.Name);
|
||||
var trainData2 = mlContext.CreateEnumerable<ImageNetPipeline>(trainData, false, true).ToList();
|
||||
var trainData2 = mlContext.Data.CreateEnumerable<ImageNetPipeline>(trainData, false, true).ToList();
|
||||
trainData2.ForEach(pr => ConsoleWriteImagePrediction(pr.ImagePath,pr.PredictedLabelValue, pr.Score.Max()));
|
||||
|
||||
// Get some performance metric on the model using training data
|
||||
var classificationContext = new MulticlassClassificationCatalog(mlContext);
|
||||
var classificationContext = mlContext.MulticlassClassification;
|
||||
ConsoleWriteHeader("Classification metrics");
|
||||
var metrics = classificationContext.Evaluate(trainData, label: LabelTokey, predictedLabel: DefaultColumnNames.PredictedLabel);
|
||||
var metrics = classificationContext.Evaluate(trainData, labelColumnName: LabelTokey, predictedLabelColumnName: "PredictedLabel");
|
||||
Console.WriteLine($"LogLoss is: {metrics.LogLoss}");
|
||||
Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
|
||||
|
||||
// Save the model to assets/outputs
|
||||
ConsoleWriteHeader("Save model to local file");
|
||||
ModelHelpers.DeleteAssets(outputModelLocation);
|
||||
using (var f = new FileStream(outputModelLocation, FileMode.Create))
|
||||
mlContext.Model.Save(model, f);
|
||||
|
||||
mlContext.Model.Save(model, trainData.Schema, outputModelLocation);
|
||||
|
||||
Console.WriteLine($"Model saved: {outputModelLocation}");
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
|
@ -2,14 +2,14 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v0.10 | Dynamic API | Needs to update to v0.8 | Console app | .tsv + image files | Image classification | featurization + classification | deep neural network + SDCA |
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .tsv + image files | Image classification | featurization + classification | deep neural network + SDCA |
|
||||
|
||||
## Problem
|
||||
Image classification is a common problem which has been solved quite a while using Machine Learning techniques. In this sample, we will review an approach that mixes new techniques (deep learning) and old school (SDCA) techniques.
|
||||
Image classification is a common problem which has been solved quite a while using Machine Learning techniques. In this sample, we will review an approach that mixes new techniques (deep learning) and old school (LbfgsMaximumEntropy) techniques.
|
||||
|
||||
In this model, we use the [Inception model](https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip) as a *featurizer* (the model is already stored in the [assets folder](./ImageClassification.Train/assets/inputs/inception/) ). This means that the model will process input images through the neural network, and then it will use the output of the tensor which precedes the classification. This tensor contains the *image features*, which allows to identify an image.
|
||||
|
||||
Finally, these image features will be feed to an SDCA algorithm which will learn how to classify different sets of image features.
|
||||
Finally, these image features will be feed to an LbfgsMaximumEntropy algorithm which will learn how to classify different sets of image features.
|
||||
|
||||
## DataSet
|
||||
There are two data sources: the `tsv` file and the image files. The [tsv file](./ImageClassification.Train/assets/inputs/data/tags.tsv) contains two columns: the first one is defined as `ImagePath` and the second one is the `Label` corresponding to the image. As you can observe, the file does not have a header row, and looks like this:
|
||||
|
@ -67,19 +67,21 @@ public class ImageNetData
|
|||
Load the training data using Text loader
|
||||
|
||||
```csharp
|
||||
var data = mlContext.Data.ReadFromTextFile<ImageNetData>(path:dataLocation, hasHeader: true);
|
||||
var data = mlContext.Data.LoadFromTextFile<ImageNetData>(path:dataLocation, hasHeader: false);
|
||||
```
|
||||
|
||||
The following step is to define the estimator pipe. Usually, when dealing with deep neural networks, you must adapt the images to the format expected by the network. This is the reason images are resized and then transformed (mainly, pixel values are normalized across all R,G,B channels).
|
||||
|
||||
```csharp
|
||||
var pipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: LabelTokey,inputColumnName:DefaultColumnNames.Label)
|
||||
.Append(mlContext.Transforms.LoadImages(imagesFolder, (ImageReal, nameof(ImageNetData.ImagePath))))
|
||||
.Append(mlContext.Transforms.Resize(outputColumnName:ImageReal, imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: ImageReal))
|
||||
.Append(mlContext.Transforms.ExtractPixels(new ImagePixelExtractorTransformer.ColumnInfo(name: "input",inputColumnName: ImageReal, interleave: ImageNetSettings.channelsLast, offset: ImageNetSettings.mean)))
|
||||
.Append(mlContext.Transforms.ScoreTensorFlowModel(modelLocation:featurizerModelLocation, outputColumnNames: new[] { "softmax2_pre_activation" },inputColumnNames: new[] { "input" }))
|
||||
.Append(mlContext.MulticlassClassification.Trainers.LogisticRegression(labelColumn:LabelTokey, featureColumn:"softmax2_pre_activation"))
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue((PredictedLabelValue,DefaultColumnNames.PredictedLabel)));
|
||||
var pipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: LabelTokey,inputColumnName:"Label")
|
||||
.Append(mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: imagesFolder, inputColumnName: nameof(ImageNetData.ImagePath)))
|
||||
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input"))
|
||||
.Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean))
|
||||
.Append(mlContext.Model.LoadTensorFlowModel(featurizerModelLocation).
|
||||
ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
|
||||
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName:LabelTokey, featureColumnName:"softmax2_pre_activation"))
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue(PredictedLabelValue,"PredictedLabel"))
|
||||
.AppendCacheCheckpoint(mlContext);
|
||||
```
|
||||
|
||||
### 2. Train model
|
||||
|
@ -94,17 +96,15 @@ As a reference, In the following screenshot, you can check the DataView used to
|
|||
### 3. Evaluate model
|
||||
After the training, we evaluate the model using the training data. The `Evaluate` function needs a `IDataView` as parameter, so we apply `Transform` to the model, and then take the `AsDynamic` value.
|
||||
```csharp
|
||||
var sdcaContext = new MulticlassClassificationCatalog(mlContext);
|
||||
ConsoleWriteHeader("Classification metrics");
|
||||
var metrics = sdcaContext.Evaluate(trainData, label: LabelTokey, predictedLabel: DefaultColumnNames.PredictedLabel);
|
||||
Console.WriteLine($"LogLoss is: {metrics.LogLoss}");
|
||||
Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
|
||||
ConsoleWriteHeader("Classification metrics");
|
||||
var metrics = classificationContext.Evaluate(trainData, labelColumnName: LabelTokey, predictedLabelColumnName: "PredictedLabel");
|
||||
Console.WriteLine($"LogLoss is: {metrics.LogLoss}");
|
||||
Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
|
||||
```
|
||||
|
||||
Finally, we save the model:
|
||||
```csharp
|
||||
using (var f = new FileStream(outputModelLocation, FileMode.Create))
|
||||
model.SaveTo(env, f);
|
||||
mlContext.Model.Save(model, trainData.Schema, outputModelLocation);
|
||||
```
|
||||
|
||||
#### Model training
|
||||
|
@ -116,15 +116,18 @@ You should proceed as follows in order to train a model your model:
|
|||
### 4. Consume model
|
||||
First, we need to load the model created during Model training
|
||||
```csharp
|
||||
ITransformer loadedModel;
|
||||
using (var f = new FileStream(modelLocation, FileMode.Open))
|
||||
loadedModel = TransformerChain.LoadFrom(env, f);
|
||||
ITransformer loadedModel = mlContext.Model.Load(modelLocation,out var modelInputSchema);
|
||||
```
|
||||
|
||||
Then, we proceed to create a predictor function, and make predictions:
|
||||
```csharp
|
||||
var predictor = loadedModel.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(mlContext);
|
||||
var pred = predictor.Predict(testImage);
|
||||
var predictor = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(loadedModel);
|
||||
var imageListToPredict = ImageNetData.ReadFromCsv(dataLocation, imagesFolder).ToList();
|
||||
imageListToPredict
|
||||
.Select(td => new { td, pred = predictor.Predict(td) })
|
||||
.Select(pr => (pr.td.ImagePath, pr.pred.PredictedLabelValue, pr.pred.Score))
|
||||
.ToList()
|
||||
.ForEach(pr => ConsoleWriteImagePrediction(pr.ImagePath, pr.PredictedLabelValue, pr.Score.Max()));
|
||||
```
|
||||
The prediction function receives as parameter an object of type `ImageNetData` (containing 2 properties: `ImagePath` and `Label`). Then returns and object of type `ImagePrediction`, which holds the `PredictedLabel` and `Score` (*probability* value between 0 and 1) properties.
|
||||
|
||||
|
|
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 35 KiB После Ширина: | Высота: | Размер: 40 KiB |
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
|1.0.0-preview | Dynamic API | Up-to-date | Console app | .txt files | Recommendation | Matrix Factorization | MatrixFactorizationTrainer (One Class)|
|
||||
|v1.0.0-preview | Dynamic API | Up-to-date | Console app | .txt files | Recommendation | Matrix Factorization | MatrixFactorizationTrainer (One Class)|
|
||||
|
||||
In this sample, you can see how to use ML.NET to build a product recommendation scenario.
|
||||
|
||||
|
|
|
@ -57,13 +57,12 @@ namespace MulticlassClassification_Iris
|
|||
// Do NOT use it (remove .AppendCacheCheckpoint()) when handling very large datasets.
|
||||
|
||||
// STEP 3: Set the training algorithm, then append the trainer to the pipeline
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.SdcaNonCalibrated(labelColumnName: "KeyColumn", featureColumnName: "Features")
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
|
||||
//Append(mlContext.Transforms.Conversion.MapKeyToValue(outputColumnName: nameof(IrisData.Label) , inputColumnName: "KeyColumn"));
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy(labelColumnName: "KeyColumn", featureColumnName: "Features")
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue(outputColumnName: nameof(IrisData.Label) , inputColumnName: "KeyColumn"));
|
||||
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer);
|
||||
|
||||
// STEP 4: Train the model fitting to the DataSet
|
||||
|
||||
//Measure training time
|
||||
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
|
@ -84,25 +83,19 @@ namespace MulticlassClassification_Iris
|
|||
Common.ConsoleHelper.PrintMultiClassClassificationMetrics(trainer.ToString(), metrics);
|
||||
|
||||
// STEP 6: Save/persist the trained model to a .ZIP file
|
||||
using (var fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, fs);
|
||||
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, ModelPath);
|
||||
Console.WriteLine("The model is saved to {0}", ModelPath);
|
||||
}
|
||||
|
||||
private static void TestSomePredictions(MLContext mlContext)
|
||||
{
|
||||
//Test Classification Predictions with some hard-coded samples
|
||||
|
||||
ITransformer trainedModel;
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream, out var modelInputSchema);
|
||||
}
|
||||
ITransformer trainedModel = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<IrisData, IrisPrediction>(trainedModel);
|
||||
|
||||
Console.WriteLine("=====Predicting using model====");
|
||||
//Score sample 1
|
||||
var resultprediction1 = predEngine.Predict(SampleIrisData.Iris1);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v0.11 | Dynamic API | Up-to-date | Console app | .txt files | Iris flowers classification | Multi-class classification | Sdca Multi-class |
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .txt files | Iris flowers classification | Multi-class classification | Sdca Multi-class |
|
||||
|
||||
In this introductory sample, you'll see how to use [ML.NET](https://www.microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet) to predict the type of iris flower. In the world of machine learning, this type of prediction is known as **multiclass classification**.
|
||||
|
||||
|
@ -56,14 +56,21 @@ var trainingDataView = mlContext.Data.LoadFromTextFile<IrisData>(TrainDataPath,
|
|||
var testDataView = mlContext.Data.LoadFromTextFile<IrisData>(TestDataPath, hasHeader: true);
|
||||
|
||||
// STEP 2: Common data process configuration with pipeline data transformations
|
||||
var dataProcessPipeline = mlContext.Transforms.Concatenate("Features", "SepalLength",
|
||||
"SepalWidth",
|
||||
"PetalLength",
|
||||
"PetalWidth" );
|
||||
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "KeyColumn", inputColumnName: nameof(IrisData.Label))
|
||||
.Append(mlContext.Transforms.Concatenate("Features", nameof(IrisData.SepalLength),
|
||||
nameof(IrisData.SepalWidth),
|
||||
nameof(IrisData.PetalLength),
|
||||
nameof(IrisData.PetalWidth))
|
||||
.AppendCacheCheckpoint(mlContext));
|
||||
// Use in-memory cache for small/medium datasets to lower training time.
|
||||
// Do NOT use it (remove .AppendCacheCheckpoint()) when handling very large datasets.
|
||||
|
||||
|
||||
// STEP 3: Set the training algorithm, then create and config the modelBuilder
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.StochasticDualCoordinateAscent(labelColumnName: DefaultColumnNames.Label, featureColumnName: DefaultColumnNames.Features);
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer);
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy(labelColumnName: "KeyColumn", featureColumnName: "Features")
|
||||
.Append(mlContext.Transforms.Conversion.MapKeyToValue(outputColumnName: nameof(IrisData.Label) , inputColumnName: "KeyColumn"));
|
||||
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer);
|
||||
```
|
||||
|
||||
### 2. Train model
|
||||
|
|
|
@ -5,9 +5,8 @@ using System.Text;
|
|||
|
||||
namespace mnist.DataStructures
|
||||
{
|
||||
class OutPutNum
|
||||
class OutPutData
|
||||
{
|
||||
|
||||
[ColumnName("Score")]
|
||||
public float[] Score;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<MicrosoftMLVersion>0.11.0</MicrosoftMLVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v0.11 | Dynamic API | Up-to-date | Console app | .csv files | MNIST classification | Multi-class classification | Sdca Multi-class |
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .csv files | MNIST classification | Multi-class classification | Sdca Multi-class |
|
||||
|
||||
In this introductory sample, you'll see how to use [ML.NET](https://www.microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet) to classify handwritten digits from 0 to 9 using the MNIST dataset. This is a **multiclass classification** problem that we will solve using SDCA (Stochastic Dual Coordinate Ascent) algorithm.
|
||||
|
||||
|
@ -33,7 +33,7 @@ Building a model includes:
|
|||
The initial code is similar to the following:
|
||||
```CSharp
|
||||
// STEP 1: Common data loading configuration
|
||||
var trainData = mLContext.Data.LoadFromTextFile(path: TrainDataPath,
|
||||
var trainData = mlContext.Data.LoadFromTextFile(path: TrainDataPath,
|
||||
columns : new[]
|
||||
{
|
||||
new TextLoader.Column(nameof(InputData.PixelValues), DataKind.Single, 0, 63),
|
||||
|
@ -44,7 +44,7 @@ var trainData = mLContext.Data.LoadFromTextFile(path: TrainDataPath,
|
|||
);
|
||||
|
||||
|
||||
var testData = mLContext.Data.LoadFromTextFile(path: TestDataPath,
|
||||
var testData = mlContext.Data.LoadFromTextFile(path: TestDataPath,
|
||||
columns: new[]
|
||||
{
|
||||
new TextLoader.Column(nameof(InputData.PixelValues), DataKind.Single, 0, 63),
|
||||
|
@ -55,13 +55,13 @@ var testData = mLContext.Data.LoadFromTextFile(path: TestDataPath,
|
|||
);
|
||||
|
||||
// STEP 2: Common data process configuration with pipeline data transformations
|
||||
var dataProcessPipeline = mLContext.Transforms.Concatenate(DefaultColumnNames.Features, nameof(InputData.PixelValues)).AppendCacheCheckpoint(mLContext);
|
||||
|
||||
|
||||
// Use in-memory cache for small/medium datasets to lower training time. Do NOT use it (remove .AppendCacheCheckpoint()) when handling very large datasets.
|
||||
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Number").
|
||||
Append(mlContext.Transforms.Concatenate("Features", nameof(InputData.PixelValues)).AppendCacheCheckpoint(mlContext));
|
||||
|
||||
// STEP 3: Set the training algorithm, then create and config the modelBuilder
|
||||
var trainer = mLContext.MulticlassClassification.Trainers.StochasticDualCoordinateAscent(labelColumnName: "Number", featureColumnName: DefaultColumnNames.Features);
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer);
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy(labelColumnName: "Label", featureColumnName: "Features");
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer).Append(mlContext.Transforms.Conversion.MapKeyToValue("Number","Label"));
|
||||
```
|
||||
|
||||
### 2. Train model
|
||||
|
@ -79,7 +79,7 @@ We need this step to conclude how accurate our model operates on new data. To do
|
|||
|
||||
```CSharp
|
||||
var predictions = trainedModel.Transform(testData);
|
||||
var metrics = mLContext.MulticlassClassification.Evaluate(data:predictions, label:"Number", score:DefaultColumnNames.Score);
|
||||
var metrics = mlContext.MulticlassClassification.Evaluate(data:predictions, labelColumnName:"Number", scoreColumnName:"Score");
|
||||
|
||||
Common.ConsoleHelper.PrintMultiClassClassificationMetrics(trainer.ToString(), metrics);
|
||||
```
|
||||
|
@ -93,19 +93,15 @@ After the model is trained, we can use the `Predict()` API to predict the probab
|
|||
|
||||
```CSharp
|
||||
|
||||
ITransformer trainedModel;
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream);
|
||||
}
|
||||
ITransformer trainedModel = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = trainedModel.CreatePredictionEngine<InputData, OutPutNum>(mlContext);
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<InputData, OutPutData>(trainedModel);
|
||||
|
||||
//InputData data1 = SampleMNISTData.MNIST1;
|
||||
var resultprediction1 = predEngine.Predict(SampleMNISTData.MNIST1);
|
||||
|
||||
Console.WriteLine($"Actual: 1 Predicted probability: zero: {resultprediction1.Score[0]:0.####}");
|
||||
Console.WriteLine($"Actual: 7 Predicted probability: zero: {resultprediction1.Score[0]:0.####}");
|
||||
Console.WriteLine($" One : {resultprediction1.Score[1]:0.####}");
|
||||
Console.WriteLine($" two: {resultprediction1.Score[2]:0.####}");
|
||||
Console.WriteLine($" three: {resultprediction1.Score[3]:0.####}");
|
||||
|
|
|
@ -1,291 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.ML.Data;
|
||||
using Microsoft.ML;
|
||||
using Microsoft.Data.DataView;
|
||||
using static Microsoft.ML.TrainCatalogBase;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
public static class ConsoleHelper
|
||||
{
|
||||
public static void PrintPrediction(string prediction)
|
||||
{
|
||||
Console.WriteLine($"*************************************************");
|
||||
Console.WriteLine($"Predicted : {prediction}");
|
||||
Console.WriteLine($"*************************************************");
|
||||
}
|
||||
|
||||
public static void PrintRegressionPredictionVersusObserved(string predictionCount, string observedCount)
|
||||
{
|
||||
Console.WriteLine($"-------------------------------------------------");
|
||||
Console.WriteLine($"Predicted : {predictionCount}");
|
||||
Console.WriteLine($"Actual: {observedCount}");
|
||||
Console.WriteLine($"-------------------------------------------------");
|
||||
}
|
||||
|
||||
public static void PrintRegressionMetrics(string name, RegressionMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"*************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} regression model ");
|
||||
Console.WriteLine($"*------------------------------------------------");
|
||||
Console.WriteLine($"* LossFn: {metrics.LossFn:0.##}");
|
||||
Console.WriteLine($"* R2 Score: {metrics.RSquared:0.##}");
|
||||
Console.WriteLine($"* Absolute loss: {metrics.L1:#.##}");
|
||||
Console.WriteLine($"* Squared loss: {metrics.L2:#.##}");
|
||||
Console.WriteLine($"* RMS loss: {metrics.Rms:#.##}");
|
||||
Console.WriteLine($"*************************************************");
|
||||
}
|
||||
|
||||
public static void PrintBinaryClassificationMetrics(string name, CalibratedBinaryClassificationMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"************************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} binary classification model ");
|
||||
Console.WriteLine($"*-----------------------------------------------------------");
|
||||
Console.WriteLine($"* Accuracy: {metrics.Accuracy:P2}");
|
||||
Console.WriteLine($"* Auc: {metrics.Auc:P2}");
|
||||
Console.WriteLine($"* Auprc: {metrics.Auprc:P2}");
|
||||
Console.WriteLine($"* F1Score: {metrics.F1Score:P2}");
|
||||
Console.WriteLine($"* LogLoss: {metrics.LogLoss:#.##}");
|
||||
Console.WriteLine($"* LogLossReduction: {metrics.LogLossReduction:#.##}");
|
||||
Console.WriteLine($"* PositivePrecision: {metrics.PositivePrecision:#.##}");
|
||||
Console.WriteLine($"* PositiveRecall: {metrics.PositiveRecall:#.##}");
|
||||
Console.WriteLine($"* NegativePrecision: {metrics.NegativePrecision:#.##}");
|
||||
Console.WriteLine($"* NegativeRecall: {metrics.NegativeRecall:P2}");
|
||||
Console.WriteLine($"************************************************************");
|
||||
}
|
||||
|
||||
public static void PrintMultiClassClassificationMetrics(string name, MultiClassClassifierMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"************************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} multi-class classification model ");
|
||||
Console.WriteLine($"*-----------------------------------------------------------");
|
||||
Console.WriteLine($" AccuracyMacro = {metrics.AccuracyMacro:0.####}, a value between 0 and 1, the closer to 1, the better");
|
||||
Console.WriteLine($" AccuracyMicro = {metrics.AccuracyMicro:0.####}, a value between 0 and 1, the closer to 1, the better");
|
||||
Console.WriteLine($" LogLoss = {metrics.LogLoss:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($" LogLoss for class 1 = {metrics.PerClassLogLoss[0]:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($" LogLoss for class 2 = {metrics.PerClassLogLoss[1]:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($" LogLoss for class 3 = {metrics.PerClassLogLoss[2]:0.####}, the closer to 0, the better");
|
||||
Console.WriteLine($"************************************************************");
|
||||
}
|
||||
|
||||
public static void PrintRegressionFoldsAverageMetrics(string algorithmName,CrossValidationResult<RegressionMetrics>[] crossValidationResults)
|
||||
{
|
||||
var L1 = crossValidationResults.Select(r => r.Metrics.L1);
|
||||
var L2 = crossValidationResults.Select(r => r.Metrics.L2);
|
||||
var RMS = crossValidationResults.Select(r => r.Metrics.L1);
|
||||
var lossFunction = crossValidationResults.Select(r => r.Metrics.LossFn);
|
||||
var R2 = crossValidationResults.Select(r => r.Metrics.RSquared);
|
||||
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
Console.WriteLine($"* Metrics for {algorithmName} Regression model ");
|
||||
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
|
||||
Console.WriteLine($"* Average L1 Loss: {L1.Average():0.###} ");
|
||||
Console.WriteLine($"* Average L2 Loss: {L2.Average():0.###} ");
|
||||
Console.WriteLine($"* Average RMS: {RMS.Average():0.###} ");
|
||||
Console.WriteLine($"* Average Loss Function: {lossFunction.Average():0.###} ");
|
||||
Console.WriteLine($"* Average R-squared: {R2.Average():0.###} ");
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
}
|
||||
|
||||
public static void PrintMulticlassClassificationFoldsAverageMetrics(
|
||||
string algorithmName,
|
||||
CrossValidationResult<MultiClassClassifierMetrics>[] crossValResults
|
||||
)
|
||||
{
|
||||
var metricsInMultipleFolds = crossValResults.Select(r => r.Metrics);
|
||||
|
||||
var microAccuracyValues = metricsInMultipleFolds.Select(m => m.AccuracyMicro);
|
||||
var microAccuracyAverage = microAccuracyValues.Average();
|
||||
var microAccuraciesStdDeviation = CalculateStandardDeviation(microAccuracyValues);
|
||||
var microAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(microAccuracyValues);
|
||||
|
||||
var macroAccuracyValues = metricsInMultipleFolds.Select(m => m.AccuracyMacro);
|
||||
var macroAccuracyAverage = macroAccuracyValues.Average();
|
||||
var macroAccuraciesStdDeviation = CalculateStandardDeviation(macroAccuracyValues);
|
||||
var macroAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(macroAccuracyValues);
|
||||
|
||||
var logLossValues = metricsInMultipleFolds.Select(m => m.LogLoss);
|
||||
var logLossAverage = logLossValues.Average();
|
||||
var logLossStdDeviation = CalculateStandardDeviation(logLossValues);
|
||||
var logLossConfidenceInterval95 = CalculateConfidenceInterval95(logLossValues);
|
||||
|
||||
var logLossReductionValues = metricsInMultipleFolds.Select(m => m.LogLossReduction);
|
||||
var logLossReductionAverage = logLossReductionValues.Average();
|
||||
var logLossReductionStdDeviation = CalculateStandardDeviation(logLossReductionValues);
|
||||
var logLossReductionConfidenceInterval95 = CalculateConfidenceInterval95(logLossReductionValues);
|
||||
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
Console.WriteLine($"* Metrics for {algorithmName} Multi-class Classification model ");
|
||||
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
|
||||
Console.WriteLine($"* Average MicroAccuracy: {microAccuracyAverage:0.###} - Standard deviation: ({microAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({microAccuraciesConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"* Average MacroAccuracy: {macroAccuracyAverage:0.###} - Standard deviation: ({macroAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({macroAccuraciesConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"* Average LogLoss: {logLossAverage:#.###} - Standard deviation: ({logLossStdDeviation:#.###}) - Confidence Interval 95%: ({logLossConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"* Average LogLossReduction: {logLossReductionAverage:#.###} - Standard deviation: ({logLossReductionStdDeviation:#.###}) - Confidence Interval 95%: ({logLossReductionConfidenceInterval95:#.###})");
|
||||
Console.WriteLine($"*************************************************************************************************************");
|
||||
|
||||
}
|
||||
|
||||
public static double CalculateStandardDeviation (IEnumerable<double> values)
|
||||
{
|
||||
double average = values.Average();
|
||||
double sumOfSquaresOfDifferences = values.Select(val => (val - average) * (val - average)).Sum();
|
||||
double standardDeviation = Math.Sqrt(sumOfSquaresOfDifferences / (values.Count()-1));
|
||||
return standardDeviation;
|
||||
}
|
||||
|
||||
public static double CalculateConfidenceInterval95(IEnumerable<double> values)
|
||||
{
|
||||
double confidenceInterval95 = 1.96 * CalculateStandardDeviation(values) / Math.Sqrt((values.Count()-1));
|
||||
return confidenceInterval95;
|
||||
}
|
||||
|
||||
public static void PrintClusteringMetrics(string name, ClusteringMetrics metrics)
|
||||
{
|
||||
Console.WriteLine($"*************************************************");
|
||||
Console.WriteLine($"* Metrics for {name} clustering model ");
|
||||
Console.WriteLine($"*------------------------------------------------");
|
||||
Console.WriteLine($"* AvgMinScore: {metrics.AvgMinScore}");
|
||||
Console.WriteLine($"* DBI is: {metrics.Dbi}");
|
||||
Console.WriteLine($"*************************************************");
|
||||
}
|
||||
|
||||
public static void ShowDataViewInConsole(MLContext mlContext, IDataView dataView, int numberOfRows = 4)
|
||||
{
|
||||
string msg = string.Format("Show data in DataView: Showing {0} rows with the columns", numberOfRows.ToString());
|
||||
ConsoleWriteHeader(msg);
|
||||
|
||||
var preViewTransformedData = dataView.Preview(maxRows: numberOfRows);
|
||||
|
||||
foreach (var row in preViewTransformedData.RowView)
|
||||
{
|
||||
var ColumnCollection = row.Values;
|
||||
string lineToPrint = "Row--> ";
|
||||
foreach (KeyValuePair<string, object> column in ColumnCollection)
|
||||
{
|
||||
lineToPrint += $"| {column.Key}:{column.Value}";
|
||||
}
|
||||
Console.WriteLine(lineToPrint + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
public static void PeekDataViewInConsole(MLContext mlContext, IDataView dataView, IEstimator<ITransformer> pipeline, int numberOfRows = 4)
|
||||
{
|
||||
string msg = string.Format("Peek data in DataView: Showing {0} rows with the columns", numberOfRows.ToString());
|
||||
ConsoleWriteHeader(msg);
|
||||
|
||||
//https://github.com/dotnet/machinelearning/blob/master/docs/code/MlNetCookBook.md#how-do-i-look-at-the-intermediate-data
|
||||
var transformer = pipeline.Fit(dataView);
|
||||
var transformedData = transformer.Transform(dataView);
|
||||
|
||||
// 'transformedData' is a 'promise' of data, lazy-loading. call Preview
|
||||
//and iterate through the returned collection from preview.
|
||||
|
||||
var preViewTransformedData = transformedData.Preview(maxRows: numberOfRows);
|
||||
|
||||
foreach (var row in preViewTransformedData.RowView)
|
||||
{
|
||||
var ColumnCollection = row.Values;
|
||||
string lineToPrint = "Row--> ";
|
||||
foreach (KeyValuePair<string, object> column in ColumnCollection)
|
||||
{
|
||||
lineToPrint += $"| {column.Key}:{column.Value}";
|
||||
}
|
||||
Console.WriteLine(lineToPrint + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<float[]> PeekVectorColumnDataInConsole(MLContext mlContext, string columnName, IDataView dataView, IEstimator<ITransformer> pipeline, int numberOfRows = 4)
|
||||
{
|
||||
string msg = string.Format("Peek data in DataView: : Show {0} rows with just the '{1}' column", numberOfRows, columnName );
|
||||
ConsoleWriteHeader(msg);
|
||||
|
||||
var transformer = pipeline.Fit(dataView);
|
||||
var transformedData = transformer.Transform(dataView);
|
||||
|
||||
// Extract the 'Features' column.
|
||||
var someColumnData = transformedData.GetColumn<float[]>(mlContext, columnName)
|
||||
.Take(numberOfRows).ToList();
|
||||
|
||||
// print to console the peeked rows
|
||||
someColumnData.ForEach(row => {
|
||||
String concatColumn = String.Empty;
|
||||
foreach (float f in row)
|
||||
{
|
||||
concatColumn += f.ToString();
|
||||
}
|
||||
Console.WriteLine(concatColumn);
|
||||
});
|
||||
|
||||
return someColumnData;
|
||||
}
|
||||
|
||||
public static void ConsoleWriteHeader(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine(" ");
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
var maxLength = lines.Select(x => x.Length).Max();
|
||||
Console.WriteLine(new string('#', maxLength));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
}
|
||||
|
||||
public static void ConsoleWriterSection(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
Console.WriteLine(" ");
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
var maxLength = lines.Select(x => x.Length).Max();
|
||||
Console.WriteLine(new string('-', maxLength));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
}
|
||||
|
||||
public static void ConsolePressAnyKey()
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine(" ");
|
||||
Console.WriteLine("Press any key to finish.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
public static void ConsoleWriteException(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
const string exceptionTitle = "EXCEPTION";
|
||||
Console.WriteLine(" ");
|
||||
Console.WriteLine(exceptionTitle);
|
||||
Console.WriteLine(new string('#', exceptionTitle.Length));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ConsoleWriteWarning(params string[] lines)
|
||||
{
|
||||
var defaultColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.DarkMagenta;
|
||||
const string warningTitle = "WARNING";
|
||||
Console.WriteLine(" ");
|
||||
Console.WriteLine(warningTitle);
|
||||
Console.WriteLine(new string('#', warningTitle.Length));
|
||||
Console.ForegroundColor = defaultColor;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,5 +10,8 @@ namespace mnist.DataStructures
|
|||
[ColumnName("PixelValues")]
|
||||
[VectorType(64)]
|
||||
public float[] PixelValues;
|
||||
|
||||
[LoadColumn(64)]
|
||||
public float Number;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,20 +22,20 @@ namespace mnist
|
|||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
MLContext mLContext = new MLContext();
|
||||
Train(mLContext);
|
||||
TestSomePredictions(mLContext);
|
||||
MLContext mlContext = new MLContext();
|
||||
Train(mlContext);
|
||||
TestSomePredictions(mlContext);
|
||||
|
||||
Console.WriteLine("Hit any key to finish the app");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
public static void Train(MLContext mLContext)
|
||||
public static void Train(MLContext mlContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
// STEP 1: Common data loading configuration
|
||||
var trainData = mLContext.Data.LoadFromTextFile(path: TrainDataPath,
|
||||
var trainData = mlContext.Data.LoadFromTextFile(path: TrainDataPath,
|
||||
columns : new[]
|
||||
{
|
||||
new TextLoader.Column(nameof(InputData.PixelValues), DataKind.Single, 0, 63),
|
||||
|
@ -46,7 +46,7 @@ namespace mnist
|
|||
);
|
||||
|
||||
|
||||
var testData = mLContext.Data.LoadFromTextFile(path: TestDataPath,
|
||||
var testData = mlContext.Data.LoadFromTextFile(path: TestDataPath,
|
||||
columns: new[]
|
||||
{
|
||||
new TextLoader.Column(nameof(InputData.PixelValues), DataKind.Single, 0, 63),
|
||||
|
@ -58,11 +58,12 @@ namespace mnist
|
|||
|
||||
// STEP 2: Common data process configuration with pipeline data transformations
|
||||
// Use in-memory cache for small/medium datasets to lower training time. Do NOT use it (remove .AppendCacheCheckpoint()) when handling very large datasets.
|
||||
var dataProcessPipeline = mLContext.Transforms.Concatenate(DefaultColumnNames.Features, nameof(InputData.PixelValues)).AppendCacheCheckpoint(mLContext);
|
||||
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("Label", "Number").
|
||||
Append(mlContext.Transforms.Concatenate("Features", nameof(InputData.PixelValues)).AppendCacheCheckpoint(mlContext));
|
||||
|
||||
// STEP 3: Set the training algorithm, then create and config the modelBuilder
|
||||
var trainer = mLContext.MulticlassClassification.Trainers.StochasticDualCoordinateAscent(labelColumnName: "Number", featureColumnName: DefaultColumnNames.Features);
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer);
|
||||
var trainer = mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy(labelColumnName: "Label", featureColumnName: "Features");
|
||||
var trainingPipeline = dataProcessPipeline.Append(trainer).Append(mlContext.Transforms.Conversion.MapKeyToValue("Number","Label"));
|
||||
|
||||
// STEP 4: Train the model fitting to the DataSet
|
||||
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
@ -74,12 +75,11 @@ namespace mnist
|
|||
|
||||
Console.WriteLine("===== Evaluating Model's accuracy with Test data =====");
|
||||
var predictions = trainedModel.Transform(testData);
|
||||
var metrics = mLContext.MulticlassClassification.Evaluate(data:predictions, label:"Number", score:DefaultColumnNames.Score);
|
||||
var metrics = mlContext.MulticlassClassification.Evaluate(data:predictions, labelColumnName:"Number", scoreColumnName:"Score");
|
||||
|
||||
Common.ConsoleHelper.PrintMultiClassClassificationMetrics(trainer.ToString(), metrics);
|
||||
|
||||
using (var fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mLContext.Model.Save(trainedModel, fs);
|
||||
mlContext.Model.Save(trainedModel, trainData.Schema, ModelPath);
|
||||
|
||||
Console.WriteLine("The model is saved to {0}", ModelPath);
|
||||
}
|
||||
|
@ -102,19 +102,15 @@ namespace mnist
|
|||
|
||||
private static void TestSomePredictions(MLContext mlContext)
|
||||
{
|
||||
ITransformer trainedModel;
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream);
|
||||
}
|
||||
ITransformer trainedModel = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = trainedModel.CreatePredictionEngine<InputData, OutPutNum>(mlContext);
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<InputData, OutPutData>(trainedModel);
|
||||
|
||||
//InputData data1 = SampleMNISTData.MNIST1;
|
||||
var resultprediction1 = predEngine.Predict(SampleMNISTData.MNIST1);
|
||||
|
||||
Console.WriteLine($"Actual: 1 Predicted probability: zero: {resultprediction1.Score[0]:0.####}");
|
||||
Console.WriteLine($"Actual: 7 Predicted probability: zero: {resultprediction1.Score[0]:0.####}");
|
||||
Console.WriteLine($" One : {resultprediction1.Score[1]:0.####}");
|
||||
Console.WriteLine($" two: {resultprediction1.Score[2]:0.####}");
|
||||
Console.WriteLine($" three: {resultprediction1.Score[3]:0.####}");
|
||||
|
@ -125,11 +121,10 @@ namespace mnist
|
|||
Console.WriteLine($" eight: {resultprediction1.Score[8]:0.####}");
|
||||
Console.WriteLine($" nine: {resultprediction1.Score[9]:0.####}");
|
||||
Console.WriteLine();
|
||||
|
||||
//InputData data2 = SampleMNISTData.MNIST2;
|
||||
|
||||
var resultprediction2 = predEngine.Predict(SampleMNISTData.MNIST2);
|
||||
|
||||
Console.WriteLine($"Actual: 7 Predicted probability: zero: {resultprediction2.Score[0]:0.####}");
|
||||
Console.WriteLine($"Actual: 1 Predicted probability: zero: {resultprediction2.Score[0]:0.####}");
|
||||
Console.WriteLine($" One : {resultprediction2.Score[1]:0.####}");
|
||||
Console.WriteLine($" two: {resultprediction2.Score[2]:0.####}");
|
||||
Console.WriteLine($" three: {resultprediction2.Score[3]:0.####}");
|
||||
|
@ -141,7 +136,6 @@ namespace mnist
|
|||
Console.WriteLine($" nine: {resultprediction2.Score[9]:0.####}");
|
||||
Console.WriteLine();
|
||||
|
||||
//InputData data3 = SampleMNISTData.MNIST3;
|
||||
var resultprediction3 = predEngine.Predict(SampleMNISTData.MNIST3);
|
||||
|
||||
Console.WriteLine($"Actual: 9 Predicted probability: zero: {resultprediction3.Score[0]:0.####}");
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\common\ConsoleHelper.cs" Link="Common\ConsoleHelper.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Data\optdigits-train.csv">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
|
@ -21,4 +25,8 @@
|
|||
<PackageReference Include="Microsoft.ML" Version="$(MicrosoftMLVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Common\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -74,9 +74,7 @@ namespace BikeSharingDemand
|
|||
//Save the model file that can be used by any application
|
||||
string modelRelativeLocation = $"{ModelsLocation}/{trainer.name}Model.zip";
|
||||
string modelPath = GetAbsolutePath(modelRelativeLocation);
|
||||
using (var fs = new FileStream(modelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, fs);
|
||||
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, modelPath);
|
||||
Console.WriteLine("The model is saved to {0}", modelPath);
|
||||
}
|
||||
|
||||
|
@ -87,14 +85,9 @@ namespace BikeSharingDemand
|
|||
foreach (var learner in regressionLearners)
|
||||
{
|
||||
//Load current model from .ZIP file
|
||||
ITransformer trainedModel;
|
||||
DataViewSchema inputSchema;
|
||||
string modelRelativeLocation = $"{ModelsLocation}/{learner.name}Model.zip";
|
||||
string modelPath = GetAbsolutePath(modelRelativeLocation);
|
||||
using (var stream = new FileStream(modelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream, out inputSchema);
|
||||
}
|
||||
ITransformer trainedModel = mlContext.Model.Load(modelPath, out var modelInputSchema);
|
||||
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<DemandObservation, DemandPrediction>(trainedModel);
|
||||
|
|
|
@ -89,9 +89,7 @@ namespace Regression_TaxiFarePrediction
|
|||
Common.ConsoleHelper.PrintRegressionMetrics(trainer.ToString(), metrics);
|
||||
|
||||
// STEP 6: Save/persist the trained model to a .ZIP file
|
||||
|
||||
using (var fs = File.Create(ModelPath))
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, fs);
|
||||
mlContext.Model.Save(trainedModel, trainingDataView.Schema, ModelPath);
|
||||
|
||||
Console.WriteLine("The model is saved to {0}", ModelPath);
|
||||
|
||||
|
@ -116,11 +114,7 @@ namespace Regression_TaxiFarePrediction
|
|||
};
|
||||
|
||||
///
|
||||
ITransformer trainedModel;
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream, out var modelInputSchema);
|
||||
}
|
||||
ITransformer trainedModel = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
|
||||
// Create prediction engine related to the loaded trained model
|
||||
var predEngine = mlContext.Model.CreatePredictionEngine<TaxiTrip, TaxiTripFarePrediction>(trainedModel);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .csv files | SpikeDetection of Shampoo sales | Anomaly Detection | IID Spike Detection and IID Change point Detection |
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .csv files | Shampoo sales Spike detection| Time Series - Anomaly Detection | IID Spike Detection and IID Change point Detection |
|
||||
|
||||
In this introductory sample, you'll see how to use [ML.NET](https://www.microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet) to detect **spikes** and **Change points** in shampoo sales. In the world of machine learning, this type of task is called TimeSeries Anomaly Detection.
|
||||
|
||||
|
|
|
@ -77,8 +77,7 @@ namespace myApp
|
|||
ITransformer trainedModel = trainigPipeLine.Fit(dataView);
|
||||
|
||||
// STEP 6: Save/persist the trained model to a .ZIP file
|
||||
using (var fs = new FileStream(ModelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
mlContext.Model.Save(trainedModel, dataView.Schema, fs);
|
||||
mlContext.Model.Save(trainedModel, dataView.Schema, ModelPath);
|
||||
|
||||
Console.WriteLine("The model is saved to {0}", ModelPath);
|
||||
Console.WriteLine("");
|
||||
|
@ -86,11 +85,7 @@ namespace myApp
|
|||
|
||||
public static void DetectAnomalies(MLContext mlContext,IDataView dataView)
|
||||
{
|
||||
ITransformer trainedModel;
|
||||
using (var stream = new FileStream(ModelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
trainedModel = mlContext.Model.Load(stream, out var modelInputSchema);
|
||||
}
|
||||
ITransformer trainedModel = mlContext.Model.Load(ModelPath, out var modelInputSchema);
|
||||
|
||||
var transformedData = trainedModel.Transform(dataView);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
| ML.NET version | API type | Status | App Type | Data type | Scenario | ML Task | Algorithms |
|
||||
|----------------|-------------------|-------------------------------|-------------|-----------|---------------------|---------------------------|-----------------------------|
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .csv files | Time Series Anomaly Detection | Time Series | SsaSpikeDetection |
|
||||
| v1.0.0-preview | Dynamic API | Up-to-date | Console app | .csv files | Power Meter Anomaly Detection | Time Series- Anomaly Detection | SsaSpikeDetection |
|
||||
|
||||
In this sample, you'll see how to use [ML.NET](https://www.microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet) to detect anomalies in time series data.
|
||||
|
||||
|
|
|
@ -71,9 +71,43 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "eShopForecastModelsTrainer"
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestObjectPoolingConsoleApp", "end-to-end-apps\Regression-SalesForecast\src\TestObjectPoolingConsoleApp\TestObjectPoolingConsoleApp.csproj", "{F42FA597-EA36-48C6-A6E7-F0D78D4EF9D6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TensorFlowScorer.Solution", "TensorFlowScorer.Solution", "{EE2FC8A3-0AC2-48A6-BC02-5C18A7E6814D}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHubIssuesLabeler.Solution", "GitHubIssuesLabeler.Solution", "{8A89D367-7DA3-44F5-BE84-060C8E0F4508}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageClassification.Score", "getting-started\DeepLearning_ImageClassification_TensorFlow\ImageClassification\ImageClassification.Score.csproj", "{C1A29617-448B-48F2-AC34-1533FB9D660C}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TensorFlowEstimator.Solution", "TensorFlowEstimator.Solution", "{98A6C59F-472D-4B0B-A526-022C5C78E3A4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageClassification.Train", "getting-started\DeepLearning_TensorFlowEstimator\ImageClassification.Train\ImageClassification.Train.csproj", "{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageClassification.Predict", "getting-started\DeepLearning_TensorFlowEstimator\ImageClassification.Predict\ImageClassification.Predict.csproj", "{9CDEC24F-DB84-48D2-92AF-376159D772B8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GitHubLabeler", "end-to-end-apps\MulticlassClassification-GitHubLabeler\GitHubLabeler\GitHubLabelerConsoleApp\GitHubLabeler.csproj", "{F8ACB739-BE35-4E61-883A-00452BBFF624}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MNIST.Solution", "MNIST.Solution", "{376F0910-A939-4D81-9192-2A5799E3650E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MNIST", "getting-started\MulticlassClassification_Mnist\MNIST\MNIST.csproj", "{722EC223-F442-4F04-9F81-088721DE1D93}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IrisClassification.Solution", "IrisClassification.Solution", "{33E14CDF-9FD4-494F-8B12-9F4309F93977}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MulticlassClassification_Iris", "getting-started\MulticlassClassification_Iris\IrisClassification\IrisClassificationConsoleApp\MulticlassClassification_Iris.csproj", "{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScalableModel.Solution", "ScalableModel.Solution", "{F84EBD4C-C163-42C2-9014-72E857976B1F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalable.Model", "end-to-end-apps\ScalableMLModelOnWebAPI\src\Scalable.Model\Scalable.Model.csproj", "{FD5B2260-F240-44C5-88D5-CABCD8649D8C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalable.WebAPI", "end-to-end-apps\ScalableMLModelOnWebAPI\src\Scalable.WebAPI\Scalable.WebAPI.csproj", "{2B5409B5-3CEE-432E-963A-3AD71C12B896}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShampooSalesSpikeDetectE2E.Solution", "ShampooSalesSpikeDetectE2E.Solution", "{6D589303-EC5C-405C-B9F6-06FE3500FCCB}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TensorFlowScorer.Solution", "TensorFlowScorer.Solution", "{4F49A908-25A6-4CC0-A9AC-1FC4072834CC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageClassification.Score", "getting-started\DeepLearning_ImageClassification_TensorFlow\ImageClassification\ImageClassification.Score.csproj", "{E87A197D-7132-47F1-A4D7-75A1D264C60A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SpamDetection.Solution", "SpamDetection.Solution", "{C08DFF62-80B6-4B05-869A-D9394A8BE6C7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpamDetectionConsoleApp", "getting-started\BinaryClassification_SpamDetection\SpamDetectionConsoleApp\SpamDetectionConsoleApp.csproj", "{735CBED7-1C84-4C4E-B126-8C2780F539DE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShampooSalesSpikesConsoleApp", "end-to-end-apps\SpikeDetection-ShampooSales-WinForms\ShampooSalesConsoleApp\ShampooSalesSpikesConsoleApp.csproj", "{348B84A0-5990-4206-A67B-24A1E664AF75}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShampooSalesSpikesWinForms", "end-to-end-apps\SpikeDetection-ShampooSales-WinForms\ShampooSalesWinforms\ShampooSalesSpikesWinForms.csproj", "{8B051595-03CD-4026-91BB-403F90CF8526}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -243,14 +277,94 @@ Global
|
|||
{F42FA597-EA36-48C6-A6E7-F0D78D4EF9D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F42FA597-EA36-48C6-A6E7-F0D78D4EF9D6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F42FA597-EA36-48C6-A6E7-F0D78D4EF9D6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624}.Release|x64.Build.0 = Release|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Debug|x64.Build.0 = Debug|x64
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Release|x64.ActiveCfg = Release|x64
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -276,7 +390,17 @@ Global
|
|||
{EF0B8B59-6114-4F69-9191-54192D176755} = {A56C7785-F74C-41F4-92C7-E98CB2287B90}
|
||||
{D80D5DBC-ACB8-4137-8F6C-FF82948C8752} = {A56C7785-F74C-41F4-92C7-E98CB2287B90}
|
||||
{F42FA597-EA36-48C6-A6E7-F0D78D4EF9D6} = {A56C7785-F74C-41F4-92C7-E98CB2287B90}
|
||||
{C1A29617-448B-48F2-AC34-1533FB9D660C} = {EE2FC8A3-0AC2-48A6-BC02-5C18A7E6814D}
|
||||
{BD8DFF87-481D-4821-BBBE-A44E2ABE18B0} = {98A6C59F-472D-4B0B-A526-022C5C78E3A4}
|
||||
{9CDEC24F-DB84-48D2-92AF-376159D772B8} = {98A6C59F-472D-4B0B-A526-022C5C78E3A4}
|
||||
{F8ACB739-BE35-4E61-883A-00452BBFF624} = {8A89D367-7DA3-44F5-BE84-060C8E0F4508}
|
||||
{722EC223-F442-4F04-9F81-088721DE1D93} = {376F0910-A939-4D81-9192-2A5799E3650E}
|
||||
{BD2407DD-A929-4DF7-BF16-0C1EAD7A0D5D} = {33E14CDF-9FD4-494F-8B12-9F4309F93977}
|
||||
{FD5B2260-F240-44C5-88D5-CABCD8649D8C} = {F84EBD4C-C163-42C2-9014-72E857976B1F}
|
||||
{2B5409B5-3CEE-432E-963A-3AD71C12B896} = {F84EBD4C-C163-42C2-9014-72E857976B1F}
|
||||
{E87A197D-7132-47F1-A4D7-75A1D264C60A} = {4F49A908-25A6-4CC0-A9AC-1FC4072834CC}
|
||||
{735CBED7-1C84-4C4E-B126-8C2780F539DE} = {C08DFF62-80B6-4B05-869A-D9394A8BE6C7}
|
||||
{348B84A0-5990-4206-A67B-24A1E664AF75} = {6D589303-EC5C-405C-B9F6-06FE3500FCCB}
|
||||
{8B051595-03CD-4026-91BB-403F90CF8526} = {6D589303-EC5C-405C-B9F6-06FE3500FCCB}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {98369941-33DD-450C-A410-B9A91C8CDE91}
|
||||
|
|
Загрузка…
Ссылка в новой задаче