-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Redesign DnnCatalog methods API for ease of use and consistency. #4362
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
Conversation
@ashbhandare - please don't use https://github.blog/2019-02-14-introducing-draft-pull-requests/ #Resolved |
src/Microsoft.ML.Dnn/DnnCatalog.cs
Outdated
/// <summary> | ||
/// The options for the <see cref="ImageClassificationTransformer"/>. | ||
/// </summary> | ||
public sealed class Options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need 2 "Options" classes. We only need one.
This appears to be a duplicate of the ImageClassificationEstimator.Options
class. One of these should be removed. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should happen is the nested ImageClassificationEstimator.Options
class should become public, and then this one can be deleted.
In reply to: 337563694 [](ancestors = 337563694)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two classes have most members in common, except that DnnCatalog.Options has featuresColumnName, and ImageClassificationEstimator.Options() takes in InputColumns and OutputColumns. Using ImageClassificationEstimator.Options directly would change the necessary arguments that ImageClassification() would take. I can make that change if that is acceptable.
In reply to: 337568602 [](ancestors = 337568602,337563694)
src/Microsoft.ML.Dnn/DnnCatalog.cs
Outdated
}; | ||
|
||
if (!File.Exists(options.ModelLocation)) | ||
var env = CatalogUtils.GetEnvironment(catalog); | ||
return new ImageClassificationEstimator(env, options, DnnUtils.LoadDnnModel(env, options.Arch, true)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should just call into the ImageClassification
overload below that takes an Options
class. #Resolved
src/Microsoft.ML.Dnn/DnnCatalog.cs
Outdated
@@ -83,6 +83,120 @@ public static class DnnCatalog | |||
return new DnnRetrainEstimator(env, options, DnnUtils.LoadDnnModel(env, modelPath, true)); | |||
} | |||
|
|||
/// <summary> | |||
/// The options for the <see cref="ImageClassificationTransformer"/>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should say it is the options for the Estimator, not the Transformer. These options are used to create the Estimator. #Resolved
src/Microsoft.ML.Dnn/DnnCatalog.cs
Outdated
/// <param name="reuseTrainSetBottleneckCachedValues">Indicates to not re-compute cached trainset bottleneck values if already available in the bin folder.</param> | ||
/// <param name="reuseValidationSetBottleneckCachedValues">Indicates to not re-compute validataionset cached bottleneck validationset values if already available in the bin folder.</param> | ||
/// <param name="trainSetBottleneckCachedValuesFilePath">Indicates the file path to store trainset bottleneck values for caching.</param> | ||
/// <param name="validationSetBottleneckCachedValuesFilePath">Indicates the file path to store validationset bottleneck values for caching.</param> | ||
/// <remarks> | ||
/// The support for image classification is under preview. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@codemzs - When should this remark
get removed? I'm assuming we don't want to ship with this in the documentation. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/Microsoft.ML.Dnn/DnnCatalog.cs
Outdated
/// <summary> | ||
/// The names of the model inputs. | ||
/// </summary> | ||
[Argument(ArgumentType.Multiple | ArgumentType.Required, HelpText = "The names of the model inputs", ShortName = "inputs", SortOrder = 1)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this marked with ArgumentType.Multiple
? We only support a single Features
column name, correct? #Resolved
src/Microsoft.ML.Dnn/DnnCatalog.cs
Outdated
/// Validation set. | ||
/// </summary> | ||
[Argument(ArgumentType.AtMostOnce, HelpText = "Validation set.", SortOrder = 15)] | ||
public IDataView ValidationSet = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reference types are null
by default. You don't need to explicitly put = null
at the end here, and below. #Resolved
@@ -15,7 +15,7 @@ internal static void RunAll() | |||
{ | |||
var sample = type.GetMethod("Example", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); | |||
|
|||
if (sample != null) | |||
if (sample != null && type.Name == "ResnetV2101TransferLearningTrainTestSplit") | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this get accidentally left behind? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… addressed review comments.
@@ -46,7 +46,7 @@ public static class DnnCatalog | |||
/// <remarks> | |||
/// The support for retraining is under preview. | |||
/// </remarks> | |||
public static DnnRetrainEstimator RetrainDnnModel( | |||
internal static DnnRetrainEstimator RetrainDnnModel( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the DnnRetrainTransformer
and DnnRetrainEstimator
classes also be marked as internal
? #Resolved
/// The names of the model input features. | ||
/// </summary> | ||
[Argument(ArgumentType.AtMostOnce | ArgumentType.Required, HelpText = "The names of the model inputs", ShortName = "features", SortOrder = 1)] | ||
public string FeaturesColumnName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have both InputColumns
and FeaturesColumnName
? We should only have 1. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same applies for LabelColumnName
.
And also for OutputColumns
and ScoreColumnName
.
In reply to: 337694012 [](ancestors = 337694012)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OutputColumns is an array of ScoreColumn and PredictedLabelColumn. Users can have a choice of setting either one or both of these names. I could make OutputColumns internal if that's cleaner.
In reply to: 337694812 [](ancestors = 337694812,337694012)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this API take more than one input at any point, as InputColumn is an array? I could either make InputColumn internal or get rid of one of InputColumns and FeaturesColumnName.
In reply to: 337694012 [](ancestors = 337694012)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making InputColumns and OutputColumns internal after talking with @[email protected] offline.
In reply to: 337712848 [](ancestors = 337712848,337694012)
@@ -1341,31 +1340,31 @@ public enum Dataset | |||
/// <summary> | |||
/// The options for the <see cref="ImageClassificationTransformer"/>. | |||
/// </summary> | |||
internal sealed class Options : TransformInputBase | |||
public sealed class Options : TransformInputBase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't inherit from TransformInputBase
. That class is for data transforms, and this is a trainer. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return false; | ||
} | ||
|
||
var wc = new WebClient(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to fix this pattern. This is becoming pervasive in our repo.
It is not recommended to use WebClient. We should use HttpClient instead.
https://docs.microsoft.com/en-us/dotnet/api/system.net.webclient?view=netframework-4.8#remarks #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (File.Exists(Path.Combine(destFolder, flag))) return; | ||
|
||
Console.WriteLine($"Extracting."); | ||
var task = Task.Run(() => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no reason to do a Task.Run
here, and then Thread.Sleep later. Just call ZipFile.ExtractToDirectory
inline in the method. #Resolved
src/Microsoft.ML.Dnn/DnnCatalog.cs
Outdated
@@ -6,11 +6,11 @@ | |||
using System.IO; | |||
using System.IO.Compression; | |||
using System.Net; | |||
using Microsoft.ML.CommandLine; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need this using? #Resolved
} | ||
} | ||
} | ||
public static ImageClassificationEstimator ImageClassification( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have XML docs since it is a public method. #Resolved
[Argument(ArgumentType.AtMostOnce, HelpText = "Training labels.", ShortName = "label", SortOrder = 4)] | ||
public string LabelColumn; | ||
[Argument(ArgumentType.AtMostOnce | ArgumentType.Required, HelpText = "Training labels.", ShortName = "label", SortOrder = 4)] | ||
public string LabelColumnName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between this and TensorFlowLabel
? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can understand, TensorFlowLabel is the name of the TF node in the model that contains the label, while the LabelColumn is the name of the column in the IDataView. They are assigned the same value, so working on removing one of them.
In reply to: 337697817 [](ancestors = 337697817)
[Argument(ArgumentType.Multiple | ArgumentType.Required, HelpText = "The names of the model inputs", ShortName = "inputs", SortOrder = 1)] | ||
public string[] InputColumns; | ||
[Argument(ArgumentType.Multiple , HelpText = "The names of the model inputs", ShortName = "inputs", SortOrder = 1)] | ||
internal string[] InputColumns; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
internal string[] InputColumns; [](start = 11, length = 32)
probably don't need this or Output coliumns but I will remove this in my PR where I will refactor all this code and convert to ITrainerEstimator
@eerhardt I need this change for my AutoML integration change and also the change where I convert this API from IEstimator to ITrainerEstimator, hence I will try to check-in as it mostly looks good and if there is any other feedback from you I will take it as part of my PR. |
Codecov Report
@@ Coverage Diff @@
## master #4362 +/- ##
==========================================
+ Coverage 74.61% 74.62% +<.01%
==========================================
Files 882 882
Lines 154848 154899 +51
Branches 16913 16914 +1
==========================================
+ Hits 115539 115591 +52
+ Misses 34563 34557 -6
- Partials 4746 4751 +5
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static ImageClassificationEstimator ImageClassification( | ||
this ModelOperationsCatalog catalog, Options options) | ||
{ | ||
options.EarlyStoppingCriteria = options.DisableEarlyStopping ? null : options.EarlyStoppingCriteria ?? new EarlyStopping(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this acts in a surprising behavior. What if we changed it to the following?
- Remove
options.DisableEarlyStopping
. - Default
options.EarlyStoppingCriteria = new EarlyStopping();
Then, by default the EarlyStopping is enabled to the default EarlyStopping. If someone wants to disable EarlyStopping, they set options.EarlyStoppingCriteria = null;
when calling this API. If they want to change EarlyStopping to a different criteria, they can just set options.EarlyStoppingCriteria = new EarlyStopping(metric: EarlyStoppingMetric.Loss)
(or whatever criteria they need).
This feels like a better API design choice because then the caller doesn't have 2 properties to deal with - DisableEarlyStopping
and EarlyStoppingCriteria
. There is only 1 to consider, that either they leave to the default, or set it as appropriate. If they want to disable EarlyStopping - they just set it to null
.
I have left the above 2 pieces of feedback. Can you address them in your PR? Thanks. |
…net#4362) * WIP initial change * Changed API design, changed tests and samples to use new API * Combined DnnCatalog.Options and ImageClassificationEstimator.Options, addressed review comments. * Added unit test and sample * Removed duplicate members in Options class, addresses PR comments * Removed preview remark for ImageClassification.
Fixes #4307
Initially the methods in the DnnCatalog took a lot of optional arguments which would confuse users and adding features to the ImageClassification API would require breaking changes in the future.
To be consistent with the rest of ML .Net, this change follows the pattern where we have 2 overloads:
1)An overload that takes the required parameters, and optionally the most important/common parameters to a method.
2)An overload that takes an Options object, which contains all the options to the method
This changes also removes a couple of unused options for the ImageClassification API, while making RetrainDnnModel internal to enable further testing before releasing.
WIP to get initial feedback/add necessary tests.