Skip to content

FFM XML Doc And Add One Missing Sample File #3374

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML;
using Microsoft.ML.Data;

namespace Samples.Dynamic.Trainers.BinaryClassification
{
public static class FactorizationMachine
{
public static void Example()
{
// Create a new context for ML.NET operations. It can be used for exception tracking and logging,
// as a catalog of available operations and as the source of randomness.
// Setting the seed to a fixed number in this example to make outputs deterministic.
var mlContext = new MLContext(seed: 0);

// Create a list of training data points.
var dataPoints = GenerateRandomDataPoints(1000);

// Convert the list of data points to an IDataView object, which is consumable by ML.NET API.
var trainingData = mlContext.Data.LoadFromEnumerable(dataPoints);

// ML.NET doesn't cache data set by default. Therefore, if one reads a data set from a file and accesses it many times,
// it can be slow due to expensive featurization and disk operations. When the considered data can fit into memory,
// a solution is to cache the data in memory. Caching is especially helpful when working with iterative algorithms
// which needs many data passes.
trainingData = mlContext.Data.Cache(trainingData);

// Define the trainer.
var pipeline = mlContext.BinaryClassification.Trainers.FieldAwareFactorizationMachine();

// Train the model.
var model = pipeline.Fit(trainingData);

// Create testing data. Use different random seed to make it different from training data.
var testData = mlContext.Data.LoadFromEnumerable(GenerateRandomDataPoints(500, seed:123));

// Run the model on test data set.
var transformedTestData = model.Transform(testData);

// Convert IDataView object to a list.
var predictions = mlContext.Data.CreateEnumerable<Prediction>(transformedTestData, reuseRowObject: false).ToList();

// Print 5 predictions.
foreach (var p in predictions.Take(5))
Console.WriteLine($"Label: {p.Label}, Prediction: {p.PredictedLabel}");

// Expected output:
// Label: True, Prediction: False
// Label: False, Prediction: False
// Label: True, Prediction: False
// Label: True, Prediction: False
// Label: False, Prediction: False

// Evaluate the overall metrics.
var metrics = mlContext.BinaryClassification.Evaluate(transformedTestData);
PrintMetrics(metrics);

// Expected output:
// Accuracy: 0.55
// AUC: 0.54
// F1 Score: 0.23
// Negative Precision: 0.54
// Negative Recall: 0.92
// Positive Precision: 0.62
// Positive Recall: 0.14
}

private static IEnumerable<DataPoint> GenerateRandomDataPoints(int count, int seed=0)
{
var random = new Random(seed);
float randomFloat() => (float)random.NextDouble();
for (int i = 0; i < count; i++)
{
var label = randomFloat() > 0.5f;
yield return new DataPoint
{
Label = label,
// Create random features that are correlated with the label.
// For data points with false label, the feature values are slightly increased by adding a constant.
Features = Enumerable.Repeat(label, 50).Select(x => x ? randomFloat() : randomFloat() + 0.1f).ToArray()
};
}
}

// Example with label and 50 feature values. A data set is a collection of such examples.
private class DataPoint
{
public bool Label { get; set; }
[VectorType(50)]
public float[] Features { get; set; }
}

// Class used to capture predictions.
private class Prediction
{
// Original label.
public bool Label { get; set; }
// Predicted label from the trainer.
public bool PredictedLabel { get; set; }
}

// Pretty-print BinaryClassificationMetrics objects.
private static void PrintMetrics(BinaryClassificationMetrics metrics)
{
Console.WriteLine($"Accuracy: {metrics.Accuracy:F2}");
Console.WriteLine($"AUC: {metrics.AreaUnderRocCurve:F2}");
Console.WriteLine($"F1 Score: {metrics.F1Score:F2}");
Console.WriteLine($"Negative Precision: {metrics.NegativePrecision:F2}");
Console.WriteLine($"Negative Recall: {metrics.NegativeRecall:F2}");
Console.WriteLine($"Positive Precision: {metrics.PositivePrecision:F2}");
Console.WriteLine($"Positive Recall: {metrics.PositiveRecall:F2}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<#@ include file="BinaryClassification.ttinclude"#>
<#+
string ClassName="FactorizationMachine";
string Trainer = "FieldAwareFactorizationMachine";
string TrainerOptions = null;
bool IsCalibrated = true;
bool CacheData = true;

string LabelThreshold = "0.5f";
string DataSepValue = "0.1f";
string OptionsInclude = "";
string Comments= "";

string ExpectedOutputPerInstance= @"// Expected output:
// Label: True, Prediction: False
// Label: False, Prediction: False
// Label: True, Prediction: False
// Label: True, Prediction: False
// Label: False, Prediction: False";

string ExpectedOutput = @"// Expected output:
// Accuracy: 0.55
// AUC: 0.54
// F1 Score: 0.23
// Negative Precision: 0.54
// Negative Recall: 0.92
// Positive Precision: 0.62
// Positive Recall: 0.14";
#>
9 changes: 9 additions & 0 deletions docs/samples/Microsoft.ML.Samples/Microsoft.ML.Samples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>FieldAwareFactorizationMachine.cs</LastGenOutput>
</None>
<None Update="Dynamic\Trainers\BinaryClassification\FactorizationMachine.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>FactorizationMachine.cs</LastGenOutput>
</None>
<None Update="Dynamic\Trainers\BinaryClassification\FieldAwareFactorizationMachineWithOptions.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>FieldAwareFactorizationMachineWithOptions.cs</LastGenOutput>
Expand Down Expand Up @@ -305,6 +309,11 @@
<AutoGen>True</AutoGen>
<DependentUpon>FieldAwareFactorizationMachine.tt</DependentUpon>
</Compile>
<Compile Update="Dynamic\Trainers\BinaryClassification\FactorizationMachine.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>FactorizationMachine.tt</DependentUpon>
</Compile>
<Compile Update="Dynamic\Trainers\BinaryClassification\FieldAwareFactorizationMachineWithOptions.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ namespace Microsoft.ML
public static class FactorizationMachineExtensions
{
/// <summary>
/// Predict a target using a field-aware factorization machine algorithm.
/// Create <see cref="FieldAwareFactorizationMachineTrainer"/>, which predicts a target using a field-aware factorization machine trained over boolean label data.
/// </summary>
/// <remarks>
/// Note that because there is only one feature column, the underlying model is equivalent to standard factorization machine.
/// </remarks>
/// <param name="catalog">The binary classification catalog trainer object.</param>
/// <param name="featureColumnName">The name of the feature column.</param>
/// <param name="labelColumnName">The name of the label column.</param>
/// <param name="labelColumnName">The name of the label column. The column data must be <see cref="System.Boolean"/>.</param>
/// <param name="featureColumnName">The name of the feature column. The column data must be a known-sized vector of <see cref="System.Single"/>.</param>
/// <param name="exampleWeightColumnName">The name of the example weight column (optional).</param>
/// <example>
/// <format type="text/markdown">
/// <![CDATA[
/// [!code-csharp[FieldAwareFactorizationMachineWithoutArguments](~/../docs/samples/docs/samples/Microsoft.ML.Samples/Dynamic/Trainers/BinaryClassification/FieldAwareFactorizationMachineWithoutArguments.cs)]
/// [!code-csharp[FieldAwareFactorizationMachineWithoutArguments](~/../docs/samples/docs/samples/Microsoft.ML.Samples/Dynamic/Trainers/BinaryClassification/FactorizationMachine.cs)]
/// ]]></format>
/// </example>
public static FieldAwareFactorizationMachineTrainer FieldAwareFactorizationMachine(this BinaryClassificationCatalog.BinaryClassificationTrainers catalog,
Expand All @@ -40,11 +40,11 @@ public static FieldAwareFactorizationMachineTrainer FieldAwareFactorizationMachi
}

/// <summary>
/// Predict a target using a field-aware factorization machine algorithm.
/// Create <see cref="FieldAwareFactorizationMachineTrainer"/>, which predicts a target using a field-aware factorization machine trained over boolean label data.
/// </summary>
/// <param name="catalog">The binary classification catalog trainer object.</param>
/// <param name="featureColumnNames">The name(s) of the feature columns.</param>
/// <param name="labelColumnName">The name of the label column.</param>
/// <param name="labelColumnName">The name of the label column. The column data must be <see cref="System.Boolean"/>.</param>
/// <param name="featureColumnNames">The names of the feature columns. The column data must be a known-sized vector of <see cref="System.Single"/>.</param>
/// <param name="exampleWeightColumnName">The name of the example weight column (optional).</param>
/// <example>
/// <format type="text/markdown">
Expand All @@ -63,10 +63,10 @@ public static FieldAwareFactorizationMachineTrainer FieldAwareFactorizationMachi
}

/// <summary>
/// Predict a target using a field-aware factorization machine algorithm.
/// Create <see cref="FieldAwareFactorizationMachineTrainer"/> using advanced options, which predicts a target using a field-aware factorization machine trained over boolean label data.
/// </summary>
/// <param name="catalog">The binary classification catalog trainer object.</param>
/// <param name="options">Advanced arguments to the algorithm.</param>
/// <param name="options">Trainer options.</param>
/// <example>
/// <format type="text/markdown">
/// <![CDATA[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,62 @@ namespace Microsoft.ML.Trainers
[2] https://www.csie.ntu.edu.tw/~cjlin/papers/ffm.pdf
[3] https://github.com/wschin/fast-ffm/blob/master/fast-ffm.pdf
*/
/// <include file='doc.xml' path='doc/members/member[@name="FieldAwareFactorizationMachineBinaryClassifier"]/*' />
/// <summary>
/// The <see cref="IEstimator{TTransformer}"/> to predict a target using a field-aware factorization machine model trained using a stochastic gradient method.
/// </summary>
/// <remarks>
/// <format type="text/markdown"><![CDATA[
/// [!include[io](~/../docs/samples/docs/api-reference/io-columns-binary-classification.md)]
/// To create this trainer, use [FieldAwareFactorizationMachine](xref:Microsoft.ML.FactorizationMachineExtensions.FieldAwareFactorizationMachine(Microsoft.ML.BinaryClassificationCatalog.BinaryClassificationTrainers,System.String,System.String,System.String))
/// [FieldAwareFactorizationMachine](xref:Microsoft.ML.FactorizationMachineExtensions.FieldAwareFactorizationMachine(Microsoft.ML.BinaryClassificationCatalog.BinaryClassificationTrainers,System.String[],System.String,System.String)),
/// or [FieldAwareFactorizationMachine(Options)](xref:Microsoft.ML.FactorizationMachineExtensions.FieldAwareFactorizationMachine(Microsoft.ML.BinaryClassificationCatalog.BinaryClassificationTrainers,Microsoft.ML.Trainers.FieldAwareFactorizationMachineTrainer.Options)).
///
/// In contrast to other binary classifiers which can only support one feature column, field-aware factorization machine can consume multiple feature columns.
/// Each column is viewed as a container of some features and such a container is called a field.
/// Note that all feature columns must be float vectors but their dimensions can be different.
/// The motivation of splitting features into different fields is to model features from different distributions independently.
/// For example, in online game store, features created from user profile and those from game profile can be assigned to two different fields.
///
/// ### Trainer Characteristics
/// | | |
/// | -- | -- |
/// | Machine learning task | Binary classification |
/// | Is normalization required? | Yes |
/// | Is caching required? | No |
/// | Required NuGet in addition to Microsoft.ML | None |
///
/// ### Background
/// Factorization machine family is a powerful model group for supervised learning problems.
/// It was first introduced in Steffen Rendle's [Factorization Machines](http://ieeexplore.ieee.org/document/5694074/?reload=true) paper in 2010.
/// Later, one of its generalized versions, field-aware factorization machine, became an important predictive module in recent recommender systems and click-through rate prediction contests.
/// For examples, see winning solutions in Steffen Rendle's KDD-Cup 2012 ([Track 1](http://www.kdd.org/kdd-cup/view/kdd-cup-2012-track-1) and [Track 2](http://www.kdd.org/kdd-cup/view/kdd-cup-2012-track-2)),
/// [Criteo's](https://www.kaggle.com/c/criteo-display-ad-challenge), [Avazu's](https://www.kaggle.com/c/avazu-ctr-prediction), and [Outbrain's](https://www.kaggle.com/c/outbrain-click-prediction) click prediction challenges on Kaggle.
///
/// Factorization machines are especially powerful when feature conjunctions are extremely correlated to the signal you want to predict.
/// An example of feature pairs which can form important conjunctions is user ID and music ID in music recommendation.
/// When a dataset consists of only dense numerical features, usage of factorization machine is not recommended or some featurizations should be performed.
///
/// ### Scoring Function
/// Field-aware factorization machine is a scoring function which maps feature vectors from different fields to a scalar score.
/// Assume that all $m$ feature columns are concatenated into a long feature vector $\boldsymbol{x}\in {\mathbb R}^n$ and ${\mathcal F}(j)$ denotes the $j$-th feature's field indentifier.
/// The corresponding score is $\hat{y}\left(\boldsymbol{x}\right) = \left\langle \boldsymbol{w}, \boldsymbol{x} \right\rangle + \sum_{j = 1}^n \sum_{j' = j + 1}^n \left\langle \boldsymbol{v}_{j, {\mathcal F}(j')} , \boldsymbol{v}_{j', {\mathcal F}(j)} \right\rangle x_j x_{j'}$,
/// where $\left\langle \cdot, \cdot \right\rangle$ is the inner product operator, $\boldsymbol{w}\in{\mathbb R}^n$ stores the linear coefficients, and $\boldsymbol{v}_{j, f}\in {\mathbb R}^k$ is the $j$-th feature's representation in the $f$-th field's latent space.
/// Note that $k$ is the latent dimension specified by the user.
/// The predicted label is the sign of $\hat{y}$. If $\hat{y} > 0$, this model predicts true. Otherwise, it predicts false.
/// For a systematic introduction to field-aware factorization machine, please see [this paper](https://www.csie.ntu.edu.tw/~cjlin/papers/ffm.pdf)
///
/// ### Training Algorithm Details
/// The implemented algorithm in <see cref="FieldAwareFactorizationMachineTrainer"/> is based on [a stochastic gradient method](http://jmlr.org/papers/volume12/duchi11a/duchi11a.pdf).
/// Algorithm details is described in Algorithm 3 in [a online document](https://github.com/wschin/fast-ffm/blob/master/fast-ffm.pdf).
/// The minimized loss function is [logistic loss](https://en.wikipedia.org/wiki/Loss_functions_for_classification), so the trained model can be viewed as a non-linear logistic regression.
///
/// ]]>
/// </format>
/// </remarks>
/// <seealso cref="Microsoft.ML.FactorizationMachineExtensions.FieldAwareFactorizationMachine(BinaryClassificationCatalog.BinaryClassificationTrainers, string, string, string)"/>
/// <seealso cref="Microsoft.ML.FactorizationMachineExtensions.FieldAwareFactorizationMachine(BinaryClassificationCatalog.BinaryClassificationTrainers, string[], string, string)"/>
/// <seealso cref="Microsoft.ML.FactorizationMachineExtensions.FieldAwareFactorizationMachine(BinaryClassificationCatalog.BinaryClassificationTrainers, FieldAwareFactorizationMachineTrainer.Options)"/>
/// <seealso cref="FieldAwareFactorizationMachineTrainer.Options"/>
public sealed class FieldAwareFactorizationMachineTrainer : ITrainer<FieldAwareFactorizationMachineModelParameters>,
IEstimator<FieldAwareFactorizationMachinePredictionTransformer>
{
Expand All @@ -39,6 +94,10 @@ public sealed class FieldAwareFactorizationMachineTrainer : ITrainer<FieldAwareF
internal const string LoadName = "FieldAwareFactorizationMachine";
internal const string ShortName = "ffm";

/// <summary>
/// <see cref="Options"/> for <see cref="FieldAwareFactorizationMachineTrainer"/> as used in
/// <see cref="Microsoft.ML.FactorizationMachineExtensions.FieldAwareFactorizationMachine(BinaryClassificationCatalog.BinaryClassificationTrainers, FieldAwareFactorizationMachineTrainer.Options)"/>.
/// </summary>
public sealed class Options : TrainerInputBaseWithWeight
{
/// <summary>
Expand Down