Skip to content

Commit

Permalink
ch07 / ch08
Browse files Browse the repository at this point in the history
  • Loading branch information
Romain Dabadie committed Sep 28, 2024
1 parent 372b4c9 commit 2a3cfd1
Show file tree
Hide file tree
Showing 73 changed files with 3,435 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,17 @@
/ch06/CarApi/obj
/ch06/CarApi/.vs/CarApi/FileContentIndex
/ch06/CarApi/.vs
/ch07/MachineLearning/.vs
/ch07/MachineLearning/MachineLearning/bin/Debug/net8.0
/ch07/MachineLearning/MachineLearning/obj
/ch07/MachineLearning/SampleML_WebApi/bin/Debug/net6.0
/ch07/MachineLearning/SampleML_WebApi/obj
/ch08/SampleAspireApp/.vs/SampleAspireApp
/ch08/SampleAspireApp/SampleAspireApp.ApiService/bin/Debug/net8.0
/ch08/SampleAspireApp/SampleAspireApp.ApiService/obj
/ch08/SampleAspireApp/SampleAspireApp.AppHost/bin/Debug/net8.0
/ch08/SampleAspireApp/SampleAspireApp.AppHost/obj
/ch08/SampleAspireApp/SampleAspireApp.ServiceDefaults/bin/Debug/net8.0
/ch08/SampleAspireApp/SampleAspireApp.ServiceDefaults/obj
/ch08/SampleAspireApp/SampleAspireApp.Web/bin/Debug/net8.0
/ch08/SampleAspireApp/SampleAspireApp.Web/obj
37 changes: 37 additions & 0 deletions ch07/MachineLearning/MachineLearning.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.34607.79
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MachineLearning", "MachineLearning\MachineLearning.csproj", "{5D303F78-8327-46C0-8ECF-1E5B0CEA5A51}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleML_WebApi", "SampleML_WebApi\SampleML_WebApi.csproj", "{0781E771-DF9B-4285-B542-5389BC7423E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleML_AzureFunction", "SampleML_AzureFunction\SampleML_AzureFunction.csproj", "{99FA86FA-1751-47BE-95DC-771F32744A5B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5D303F78-8327-46C0-8ECF-1E5B0CEA5A51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D303F78-8327-46C0-8ECF-1E5B0CEA5A51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D303F78-8327-46C0-8ECF-1E5B0CEA5A51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D303F78-8327-46C0-8ECF-1E5B0CEA5A51}.Release|Any CPU.Build.0 = Release|Any CPU
{0781E771-DF9B-4285-B542-5389BC7423E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0781E771-DF9B-4285-B542-5389BC7423E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0781E771-DF9B-4285-B542-5389BC7423E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0781E771-DF9B-4285-B542-5389BC7423E4}.Release|Any CPU.Build.0 = Release|Any CPU
{99FA86FA-1751-47BE-95DC-771F32744A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99FA86FA-1751-47BE-95DC-771F32744A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99FA86FA-1751-47BE-95DC-771F32744A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99FA86FA-1751-47BE-95DC-771F32744A5B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AA8D540E-39C4-4B14-919E-3FE70BD177FA}
EndGlobalSection
EndGlobal
17 changes: 17 additions & 0 deletions ch07/MachineLearning/MachineLearning/MachineLearning.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="3.0.1" />
<PackageReference Include="Microsoft.ML.FastTree" Version="3.0.1" />
</ItemGroup>
<ItemGroup Label="SampleML">
<None Include="SampleML.mlnet">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
11 changes: 11 additions & 0 deletions ch07/MachineLearning/MachineLearning/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//Load sample data
using MachineLearning;

var sampleData = new SampleML.ModelInput()
{
Month = @"2-Jan",
};

//Load model and predict output
var result = SampleML.Predict(sampleData);
Console.WriteLine(result.ProductSales);
134 changes: 134 additions & 0 deletions ch07/MachineLearning/MachineLearning/SampleML.consumption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// This file was auto-generated by ML.NET Model Builder.
using Microsoft.ML;
using Microsoft.ML.Data;
using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
namespace MachineLearning
{
public partial class SampleML
{
/// <summary>
/// model input class for SampleML.
/// </summary>
#region model input class
public class ModelInput
{
[LoadColumn(0)]
[ColumnName(@"Month")]
public string Month { get; set; }

[LoadColumn(1)]
[ColumnName(@"ProductSales")]
public float ProductSales { get; set; }

}

#endregion

/// <summary>
/// model output class for SampleML.
/// </summary>
#region model output class
public class ModelOutput
{
[ColumnName(@"Month")]
public float[] Month { get; set; }

[ColumnName(@"ProductSales")]
public uint ProductSales { get; set; }

[ColumnName(@"Features")]
public float[] Features { get; set; }

[ColumnName(@"PredictedLabel")]
public float PredictedLabel { get; set; }

[ColumnName(@"Score")]
public float[] Score { get; set; }

}

#endregion

private static string MLNetModelPath = Path.GetFullPath("SampleML.mlnet");

public static readonly Lazy<PredictionEngine<ModelInput, ModelOutput>> PredictEngine = new Lazy<PredictionEngine<ModelInput, ModelOutput>>(() => CreatePredictEngine(), true);


private static PredictionEngine<ModelInput, ModelOutput> CreatePredictEngine()
{
var mlContext = new MLContext();
ITransformer mlModel = mlContext.Model.Load(MLNetModelPath, out var _);
return mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
}

/// <summary>
/// Use this method to predict scores for all possible labels.
/// </summary>
/// <param name="input">model input.</param>
/// <returns><seealso cref=" ModelOutput"/></returns>
public static IOrderedEnumerable<KeyValuePair<string, float>> PredictAllLabels(ModelInput input)
{
var predEngine = PredictEngine.Value;
var result = predEngine.Predict(input);
return GetSortedScoresWithLabels(result);
}

/// <summary>
/// Map the unlabeled result score array to the predicted label names.
/// </summary>
/// <param name="result">Prediction to get the labeled scores from.</param>
/// <returns>Ordered list of label and score.</returns>
/// <exception cref="Exception"></exception>
public static IOrderedEnumerable<KeyValuePair<string, float>> GetSortedScoresWithLabels(ModelOutput result)
{
var unlabeledScores = result.Score;
var labelNames = GetLabels(result);

Dictionary<string, float> labledScores = new Dictionary<string, float>();
for (int i = 0; i < labelNames.Count(); i++)
{
// Map the names to the predicted result score array
var labelName = labelNames.ElementAt(i);
labledScores.Add(labelName.ToString(), unlabeledScores[i]);
}

return labledScores.OrderByDescending(c => c.Value);
}

/// <summary>
/// Get the ordered label names.
/// </summary>
/// <param name="result">Predicted result to get the labels from.</param>
/// <returns>List of labels.</returns>
/// <exception cref="Exception"></exception>
private static IEnumerable<string> GetLabels(ModelOutput result)
{
var schema = PredictEngine.Value.OutputSchema;

var labelColumn = schema.GetColumnOrNull("ProductSales");
if (labelColumn == null)
{
throw new Exception("ProductSales column not found. Make sure the name searched for matches the name in the schema.");
}

// Key values contains an ordered array of the possible labels. This allows us to map the results to the correct label value.
var keyNames = new VBuffer<float>();
labelColumn.Value.GetKeyValues(ref keyNames);
return keyNames.DenseValues().Select(x => x.ToString());
}

/// <summary>
/// Use this method to predict on <see cref="ModelInput"/>.
/// </summary>
/// <param name="input">model input.</param>
/// <returns><seealso cref=" ModelOutput"/></returns>
public static ModelOutput Predict(ModelInput input)
{
var predEngine = PredictEngine.Value;
return predEngine.Predict(input);
}
}
}
59 changes: 59 additions & 0 deletions ch07/MachineLearning/MachineLearning/SampleML.evaluate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// This file was auto-generated by ML.NET Model Builder.

using Microsoft.ML.Data;
using Microsoft.ML;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MachineLearning
{
public partial class SampleML
{
/// <summary>
/// Permutation feature importance (PFI) is a technique to determine the importance
/// of features in a trained machine learning model. PFI works by taking a labeled dataset,
/// choosing a feature, and permuting the values for that feature across all the examples,
/// so that each example now has a random value for the feature and the original values for all other features.
/// The evaluation metric (e.g. R-squared) is then calculated for this modified dataset,
/// and the change in the evaluation metric from the original dataset is computed.
/// The larger the change in the evaluation metric, the more important the feature is to the model.
///
/// PFI typically takes a long time to compute, as the evaluation metric is calculated
/// many times to determine the importance of each feature.
///
/// </summary>
/// <param name="mlContext">The common context for all ML.NET operations.</param>
/// <param name="trainData">IDataView used to evaluate the model.</param>
/// <param name="model">Model to evaluate.</param>
/// <param name="labelColumnName">Label column being predicted.</param>
/// <returns>A list of each feature and its importance.</returns>
public static List<Tuple<string, double>> CalculatePFI(MLContext mlContext, IDataView trainData, ITransformer model, string labelColumnName)
{
var preprocessedTrainData = model.Transform(trainData);

var permutationFeatureImportance =
mlContext.MulticlassClassification
.PermutationFeatureImportance(
model,
preprocessedTrainData,
labelColumnName: labelColumnName);

var featureImportanceMetrics =
permutationFeatureImportance
.Select((kvp) => new { kvp.Key, kvp.Value.MacroAccuracy })
.OrderByDescending(myFeatures => Math.Abs(myFeatures.MacroAccuracy.Mean));

var featurePFI = new List<Tuple<string, double>>();
foreach (var feature in featureImportanceMetrics)
{
var pfiValue = Math.Abs(feature.MacroAccuracy.Mean);
featurePFI.Add(new Tuple<string, double>(feature.Key, pfiValue));
}

return featurePFI;
}
}
}


Loading

0 comments on commit 2a3cfd1

Please sign in to comment.