Skip to content

Moved TensorFlow samples to its own directory in Samples project. #2429

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 5 commits into from
Feb 7, 2019
Merged
Show file tree
Hide file tree
Changes from 4 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
Expand Up @@ -2,14 +2,14 @@
using System.Linq;
using Microsoft.ML.Data;

namespace Microsoft.ML.Samples.Dynamic
namespace Microsoft.ML.Samples.Dynamic.TensorFlow
{
class TensorFlowTransformExample
class ImageClassification
{
/// <summary>
/// Example use of the TensorFlowEstimator in a ML.NET pipeline.
/// Example use of the TensorFlow image model in a ML.NET pipeline.
/// </summary>
public static void TensorFlowScoringSample()
public static void ScoringWithImageClassificationModelSample()
{
// Download the ResNet 101 model from the location below.
// https://storage.googleapis.com/download.tensorflow.org/models/tflite_11_05_08/resnet_v2_101.tgz
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using System;
using System.IO;
using System.Linq;
using Microsoft.ML.Data;
using Microsoft.ML.Transforms.TensorFlow;

namespace Microsoft.ML.Samples.Dynamic.TensorFlow
{
class TextClassification
{
public const int MaxSentenceLenth = 600;
/// <summary>
/// Example use of the TensorFlow sentiment classification model.
/// </summary>
public static void ScoringWithTextClassificationModelSample()
{
string modelLocation = SamplesUtils.DatasetUtils.DownloadTensorFlowSentimentModel();

var mlContext = new MLContext();
var data = new[] { new IMDBSentiment() {
Sentiment_Text = "this film was just brilliant casting location scenery story direction " +
"everyone's really suited the part they played and you could just imagine being there robert " +
"is an amazing actor and now the same being director father came from the same scottish " +
"island as myself so i loved the fact there was a real connection with this film the witty " +
"remarks throughout the film were great it was just brilliant so much that i bought the " +
"film as soon as it was released for and would recommend it to everyone to watch and the " +
"fly fishing was amazing really cried at the end it was so sad and you know what they say " +
"if you cry at a film it must have been good and this definitely was also to the two " +
"little boy's that played the of norman and paul they were just brilliant children are " +
"often left out of the list i think because the stars that play them all grown up are " +
"such a big profile for the whole film but these children are amazing and should be praised " +
"for what they have done don't you think the whole story was so lovely because it was true " +
"and was someone's life after all that was shared with us all" } };
var dataView = mlContext.Data.ReadFromEnumerable(data);

// This is the dictionary to convert words into the integer indexes.
var lookupMap = mlContext.Data.ReadFromTextFile(Path.Combine(modelLocation, "imdb_word_index.csv"),
columns: new[]
{
new TextLoader.Column("Words", DataKind.TX, 0),
new TextLoader.Column("Ids", DataKind.I4, 1),
},
separatorChar: ','
);

// Load the TensorFlow model once.
// - Use it for quering the schema for input and output in the model
// - Use it for prediction in the pipeline.
var modelInfo = TensorFlowUtils.LoadTensorFlowModel(mlContext, modelLocation);
var schema = modelInfo.GetModelSchema();
var featuresType = (VectorType)schema["Features"].Type;
Console.WriteLine("Name: {0}, Type: {1}, Shape: (-1, {2})", "Features", featuresType.ItemType.RawType, featuresType.Dimensions[0]);
var predictionType = (VectorType)schema["Prediction/Softmax"].Type;
Console.WriteLine("Name: {0}, Type: {1}, Shape: (-1, {2})", "Prediction/Softmax", predictionType.ItemType.RawType, predictionType.Dimensions[0]);

// The model expects the input feature vector to be a fixed length vector.
// In this sample, CustomMappingEstimator is used to resize variable length vector to fixed length vector.
// The following ML.NET pipeline
// 1. tokenzies the string into words,
// 2. maps each word to an integer which is an index in the dictionary ('lookupMap'),
// 3. Resizes the integer vector to a fixed length vector using CustomMappingEstimator ('ResizeFeaturesAction')
// 4. Passes the data to TensorFlow for scoring.
// 5. Retreives the 'Prediction' from TensorFlow and put it into ML.NET Pipeline

Action<IMDBSentiment, IntermediateFeatures> ResizeFeaturesAction = (i, j) =>
{
j.Sentiment_Text = i.Sentiment_Text;
var features = i.VariableLenghtFeatures;
Array.Resize(ref features, MaxSentenceLenth);
j.Features = features;
};

var engine = mlContext.Transforms.Text.TokenizeWords("TokenizedWords", "Sentiment_Text")
.Append(mlContext.Transforms.Conversion.ValueMap(lookupMap, "Words", "Ids", new[] { ("VariableLenghtFeatures", "TokenizedWords") }))
.Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
.Append(mlContext.Transforms.ScoreTensorFlowModel(modelInfo, new[] { "Prediction/Softmax" }, new[] { "Features" }))
.Append(mlContext.Transforms.CopyColumns(("Prediction", "Prediction/Softmax")))
.Fit(dataView)
.CreatePredictionEngine<IMDBSentiment, OutputScores>(mlContext);

// Predict with TensorFlow pipeline.
var prediction = engine.Predict(data[0]);

Console.WriteLine("Number of classes: {0}", prediction.Prediction.Length);
Console.WriteLine("Is sentiment/review positive? {0}", prediction.Prediction[1] > 0.5 ? "Yes." : "No.");
Console.WriteLine("Prediction Confidence: {0}", prediction.Prediction[1].ToString("0.00"));

/////////////////////////////////// Expected output ///////////////////////////////////
//
// Name: Features, Type: System.Int32, Shape: (-1, 600)
// Name: Prediction/Softmax, Type: System.Single, Shape: (-1, 2)
//
// Number of classes: 2
// Is sentiment/review positive ? Yes
// Prediction Confidence: 0.65
}


/// <summary>
/// Class to hold original sentiment data.
/// </summary>
public class IMDBSentiment
{
public string Sentiment_Text { get; set; }

/// <summary>
/// This is a variable length vector designated by VectorType(0) attribute.
/// Variable length vectors are produced by applying operations such as 'TokenizeWords' on strings
/// resulting in vectors of tokens of variable lengths.
/// </summary>
[VectorType(0)]
public int[] VariableLenghtFeatures { get; set; }
}

/// <summary>
/// Class to hold intermediate data. Mostly used by CustomMapping Estimator
/// </summary>
public class IntermediateFeatures
{
public string Sentiment_Text { get; set; }

[VectorType(MaxSentenceLenth)]
public int[] Features { get; set; }
}

/// <summary>
/// Class to contain the output values from the transformation.
/// </summary>
class OutputScores
{
[VectorType(2)]
public float[] Prediction { get; set; }
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<NativeAssemblyReference Include="FastTreeNative" />
<NativeAssemblyReference Include="MatrixFactorizationNative" />
<NativeAssemblyReference Include="LdaNative" />
<PackageReference Include="Microsoft.ML.TensorFlow.Redist" Version="0.7.0" />
<PackageReference Include="Microsoft.ML.TensorFlow.Redist" Version="0.10.0" />

<ProjectReference Include="..\..\..\src\Microsoft.ML.Analyzer\Microsoft.ML.Analyzer.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
Expand Down
29 changes: 29 additions & 0 deletions src/Microsoft.ML.SamplesUtils/SamplesDatasetUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,35 @@ public static string DownloadImages()
return $"{path}{Path.DirectorySeparatorChar}images.tsv";
}

/// <summary>
/// Downloads sentiment_model from the dotnet/machinelearning-testdata repo.
/// </summary>
/// <remarks>
/// The model is downloaded from
/// https://github.com/dotnet/machinelearning-testdata/blob/master/Microsoft.ML.TensorFlow.TestModels/sentiment_model
/// The model is in 'SavedModel' format. For further explanation on how was the `sentiment_model` created
/// c.f. https://github.com/dotnet/machinelearning-testdata/blob/master/Microsoft.ML.TensorFlow.TestModels/sentiment_model/README.md
/// </remarks>
public static string DownloadTensorFlowSentimentModel()
{
string remotePath = "https://github.com/dotnet/machinelearning-testdata/raw/master/Microsoft.ML.TensorFlow.TestModels/sentiment_model/";

string path = "sentiment_model";
if(!Directory.Exists(path))
Directory.CreateDirectory(path);

string varPath = Path.Combine(path, "variables");
if (!Directory.Exists(varPath))
Directory.CreateDirectory(varPath);

Download(Path.Combine(remotePath, "saved_model.pb"), Path.Combine(path,"saved_model.pb"));
Download(Path.Combine(remotePath, "imdb_word_index.csv"), Path.Combine(path, "imdb_word_index.csv"));
Download(Path.Combine(remotePath, "variables", "variables.data-00000-of-00001"), Path.Combine(varPath, "variables.data-00000-of-00001"));
Download(Path.Combine(remotePath, "variables", "variables.index"), Path.Combine(varPath, "variables.index"));

return path;
}

private static string Download(string baseGitPath, string dataFile)
{
using (WebClient client = new WebClient())
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.ML.TensorFlow/TensorFlowModelInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal TensorFlowModelInfo(IHostEnvironment env, TFSession session, string mod
/// <summary>
/// Get <see cref="Schema"/> for complete model. Every node in the TensorFlow model will be included in the <see cref="Schema"/> object.
/// </summary>
internal Schema GetModelSchema()
public Schema GetModelSchema()
Copy link
Contributor Author

@zeahmed zeahmed Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public [](start = 8, length = 6)

This need to be public. Its helpful to get the schema without loading model again. #Resolved

{
return TensorFlowUtils.GetModelSchema(_env, Session.Graph);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.ML.TensorFlow/TensorflowCatalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public static class TensorflowCatalog
/// <example>
/// <format type="text/markdown">
/// <![CDATA[
/// [!code-csharp[ScoreTensorFlowModel](~/../docs/samples/docs/samples/Microsoft.ML.Samples/Dynamic/TensorFlowTransform.cs)]
/// [!code-csharp[ScoreTensorFlowModel](~/../docs/samples/docs/samples/Microsoft.ML.Samples/Dynamic/TensorFlow/ImageClassification.cs)]
/// [!code-csharp[ScoreTensorFlowModel](~/../docs/samples/docs/samples/Microsoft.ML.Samples/Dynamic/TensorFlow/TextClassification.cs)]
/// ]]>
/// </format>
/// </example>
Expand Down