Skip to content

Commit daae78d

Browse files
fix recommendation Bug (#4774)
1 parent 982df42 commit daae78d

File tree

5 files changed

+49
-25
lines changed

5 files changed

+49
-25
lines changed

src/Microsoft.ML.CodeGenerator/CodeGenerator/CSharp/CodeGenerator.cs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -329,18 +329,11 @@ private string GenerateConsumeModelCSFileContent(string namespaceValue)
329329
{
330330
if (_pipeline == null)
331331
throw new ArgumentNullException(nameof(_pipeline));
332-
try
333-
{
334-
var node = _pipeline.Nodes.Where(t => t.NodeType == PipelineNodeType.Trainer).First();
335-
ITrainerGenerator generator = TrainerGeneratorFactory.GetInstance(node);
336-
var trainerString = generator.GenerateTrainer();
337-
var trainerUsings = generator.GenerateUsings();
338-
return (trainerString, trainerUsings);
339-
}
340-
catch (Exception)
341-
{
342-
return (string.Empty, new string[0]);
343-
}
332+
var node = _pipeline.Nodes.Where(t => t.NodeType == PipelineNodeType.Trainer).First();
333+
ITrainerGenerator generator = TrainerGeneratorFactory.GetInstance(node);
334+
var trainerString = generator.GenerateTrainer();
335+
var trainerUsings = generator.GenerateUsings();
336+
return (trainerString, trainerUsings);
344337
}
345338

346339
internal IList<string> GenerateClassLabels(IDictionary<string, CodeGeneratorSettings.ColumnMapping> columnMapping = default)

src/Microsoft.ML.CodeGenerator/CodeGenerator/CSharp/TrainerGeneratorBase.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ private void Initialize(PipelineNode node)
9797
value = "\"" + val + "\"";
9898
}
9999

100+
if (type.IsEnum)
101+
{
102+
//example: "MatrixFactorizationTrainer.LossFunctionType.SquareLossRegression"
103+
value = $"{type.ReflectedType.Name}.{type.Name}.{kv.Value.ToString()}";
104+
}
105+
100106
if (type == typeof(CustomProperty))
101107
{
102108
value = kv.Value;

test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.Recommendation_GenerateConsoleAppProjectContents_VerifyModelBuilder.approved.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ using System.Linq;
1111
using Microsoft.ML;
1212
using Microsoft.ML.Data;
1313
using TestNamespace.Model;
14+
using Microsoft.ML.Trainers;
1415

1516
namespace TestNamespace.ConsoleApp
1617
{
@@ -55,9 +56,10 @@ namespace TestNamespace.ConsoleApp
5556
public static IEstimator<ITransformer> BuildTrainingPipeline(MLContext mlContext)
5657
{
5758
// Data process configuration with pipeline data transformations
58-
var dataProcessPipeline = mlContext.Transforms.Concatenate("Out", new[] { "In" });
59+
var dataProcessPipeline = mlContext.Transforms.Conversion.MapValueToKey("userId", "userId")
60+
.Append(mlContext.Transforms.Conversion.MapValueToKey("movieId", "movieId"));
5961
// Set the training algorithm
60-
var trainer = mlContext.Recommendation().Trainers.MatrixFactorization(labelColumnName: "Label", matrixColumnIndexColumnName: "userId", matrixRowIndexColumnName: "movieId");
62+
var trainer = mlContext.Recommendation().Trainers.MatrixFactorization(new MatrixFactorizationTrainer.Options() { MatrixColumnIndexColumnName = "userId", MatrixRowIndexColumnName = "movieId", LabelColumnName = "Label", NumberOfIterations = 10, LearningRate = 0.01f, ApproximationRank = 8, Lambda = 0.01f, LossFunction = MatrixFactorizationTrainer.LossFunctionType.SquareLossRegression, Alpha = 1f, C = 1E-05f });
6163

6264
var trainingPipeline = dataProcessPipeline.Append(trainer);
6365

test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.cs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Microsoft.ML.CodeGenerator.Templates.Console;
2020
using Microsoft.ML.CodeGenerator.Utilities;
2121
using Microsoft.ML.Data;
22+
using Microsoft.ML.Trainers;
2223
using Xunit;
2324
using CodeGenerator = Microsoft.ML.CodeGenerator.CSharp.CodeGenerator;
2425

@@ -466,16 +467,30 @@ private CodeGenerator PrepareForRecommendationTask()
466467
if (mockedPipeline == null)
467468
{
468469
MLContext context = new MLContext();
470+
var hyperParam = new Dictionary<string, object>()
471+
{
472+
{"MatrixColumnIndexColumnName","userId" },
473+
{"MatrixRowIndexColumnName","movieId" },
474+
{"LabelColumnName","Label" },
475+
{nameof(MatrixFactorizationTrainer.Options.NumberOfIterations), 10 },
476+
{nameof(MatrixFactorizationTrainer.Options.LearningRate), 0.01f },
477+
{nameof(MatrixFactorizationTrainer.Options.ApproximationRank), 8 },
478+
{nameof(MatrixFactorizationTrainer.Options.Lambda), 0.01f },
479+
{nameof(MatrixFactorizationTrainer.Options.LossFunction), MatrixFactorizationTrainer.LossFunctionType.SquareLossRegression },
480+
{nameof(MatrixFactorizationTrainer.Options.Alpha), 1f },
481+
{nameof(MatrixFactorizationTrainer.Options.C), 0.00001f },
482+
};
483+
var valueToKeyPipelineNode1 = new PipelineNode(nameof(EstimatorName.ValueToKeyMapping), PipelineNodeType.Transform, "userId", "userId");
484+
var valueToKeyPipelineNode2 = new PipelineNode(nameof(EstimatorName.ValueToKeyMapping), PipelineNodeType.Transform, "movieId", "movieId");
485+
var matrixPipelineNode = new PipelineNode(nameof(TrainerName.MatrixFactorization), PipelineNodeType.Trainer, "Features", "Score", hyperParam);
486+
var pipeline = new Pipeline(new PipelineNode[]
487+
{
488+
valueToKeyPipelineNode1,
489+
valueToKeyPipelineNode2,
490+
matrixPipelineNode
491+
});
469492

470-
var trainer1 = new SuggestedTrainer(context, new MatrixFactorizationExtension(), new ColumnInformation() {
471-
LabelColumnName = "Label",
472-
UserIdColumnName = "userId",
473-
ItemIdColumnName = "movieId",
474-
}, hyperParamSet: null);
475-
var transforms1 = new List<SuggestedTransform>() { ColumnConcatenatingExtension.CreateSuggestedTransform(context, new[] { "In" }, "Out") };
476-
var inferredPipeline1 = new SuggestedPipeline(transforms1, new List<SuggestedTransform>(), trainer1, context, false);
477-
478-
mockedPipeline = inferredPipeline1.ToPipeline();
493+
mockedPipeline = pipeline;
479494
var textLoaderArgs = new TextLoader.Options()
480495
{
481496
Columns = new[] {

test/Microsoft.ML.CodeGenerator.Tests/TrainerGeneratorTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Microsoft.ML;
99
using Microsoft.ML.AutoML;
1010
using Microsoft.ML.CodeGenerator.CSharp;
11+
using Microsoft.ML.Trainers;
1112
using Xunit;
1213

1314
namespace mlnet.Tests
@@ -295,14 +296,21 @@ public void MatrixFactorizationAdvancedTest()
295296
{"MatrixColumnIndexColumnName","userId" },
296297
{"MatrixRowIndexColumnName","movieId" },
297298
{"LabelColumnName","rating" },
299+
{nameof(MatrixFactorizationTrainer.Options.NumberOfIterations), 10 },
300+
{nameof(MatrixFactorizationTrainer.Options.LearningRate), 0.01f },
301+
{nameof(MatrixFactorizationTrainer.Options.ApproximationRank), 8 },
302+
{nameof(MatrixFactorizationTrainer.Options.Lambda), 0.01f },
303+
{nameof(MatrixFactorizationTrainer.Options.LossFunction), MatrixFactorizationTrainer.LossFunctionType.SquareLossRegression },
304+
{nameof(MatrixFactorizationTrainer.Options.Alpha), 1f },
305+
{nameof(MatrixFactorizationTrainer.Options.C), 0.00001f },
298306
};
299307
PipelineNode node = new PipelineNode("MatrixFactorization", PipelineNodeType.Trainer, default(string[]), default(string), elementProperties);
300308
Pipeline pipeline = new Pipeline(new PipelineNode[] { node });
301309
CodeGenerator codeGenerator = new CodeGenerator(pipeline, null, null);
302310
var actual = codeGenerator.GenerateTrainerAndUsings();
303-
string expectedTrainerString = "MatrixFactorization(matrixColumnIndexColumnName:\"userId\",matrixRowIndexColumnName:\"movieId\",labelColumnName:\"rating\")";
311+
string expectedTrainerString = "MatrixFactorization(new MatrixFactorizationTrainer.Options(){MatrixColumnIndexColumnName=\"userId\",MatrixRowIndexColumnName=\"movieId\",LabelColumnName=\"rating\",NumberOfIterations=10,LearningRate=0.01f,ApproximationRank=8,Lambda=0.01f,LossFunction=MatrixFactorizationTrainer.LossFunctionType.SquareLossRegression,Alpha=1f,C=1E-05f})";
304312
Assert.Equal(expectedTrainerString, actual.Item1);
305-
Assert.Null(actual.Item2);
313+
Assert.Equal(new string[] { "using Microsoft.ML.Trainers;\r\n" },actual.Item2);
306314
}
307315

308316
[Fact]

0 commit comments

Comments
 (0)