-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Issue 4120, add reasonable exception when user try to use OnnxSequenceType attribute without specify sequence type #4272
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
Changes from 2 commits
ec26518
7958922
6c90cb2
b201e17
1885987
18eff2d
2067f7d
1c71e99
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -94,6 +94,12 @@ public override int GetHashCode() | |
| /// </summary> | ||
| public override void Register() | ||
| { | ||
| // this happens when use OnnxSequenceType attribute without specify sequence type | ||
| if (_elemType == null) | ||
| { | ||
| throw new Exception("Please specify sequence type when use OnnxSequenceType Attribute."); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps it is better to throw ArgumentNullException here? #Resolved
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Throwing just a plain https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/using-standard-exception-types X DO NOT throw System.Exception or System.SystemException. However, ArgumentNullException is not correct either, since there is no argument to this method. ✓ DO throw ArgumentException or one of its subtypes if bad arguments are passed to a member. In this case, InvalidOperationException is the most correct: ✓ DO throw an InvalidOperationException if the object is in an inappropriate state. #Resolved
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO - it the best approach would be to remove the empty constructor and verify the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, very good suggestion, InvalidOperationException is the most proper one to use here In reply to: 330652629 [](ancestors = 330652629)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I have a similar discussion with Harish about this yesterday, we agreed that remove empty constructor seems to be more ambiguous because when our customer use [OnnxSequenceType] attribute directly he/she will get error message like "method is inaccessible due to protection level". By throwing exception we can give user more specific error message. Make sense to you? In reply to: 330653643 [](ancestors = 330653643)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to take Eric's suggestion and use InvalidOperationException here. In reply to: 330649635 [](ancestors = 330649635)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's a compile time error - which is exactly what we want. We want to raise the error as early as possible, so the user knows they are doing something wrong. Also, when I get a different error message than what you are displaying: class Program
{
[My]
private int foo;
}
class MyAttribute : Attribute
{
public MyAttribute(int required)
{ }
}Pretty obvious what to do to fix it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think Eric's suggestion is the better approach here. Please modify it as per his suggestion.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| var enumerableType = typeof(IEnumerable<>); | ||
| var type = enumerableType.MakeGenericType(_elemType); | ||
| DataViewTypeManager.Register(new OnnxSequenceType(_elemType), type, this); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,37 +13,55 @@ | |
| using System.Linq; | ||
| using System.IO; | ||
| using Microsoft.ML.TestFramework.Attributes; | ||
| using System; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please place "using System" at the top and sort alphabetical order as done in source files. System libraries take preference over non-system libraries like Microsoft.ML.* #Resolved
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| namespace Microsoft.ML.Tests | ||
| { | ||
| public class OnnxSequenceTypeWithAttributesTest : BaseTestBaseline | ||
| public class OnnxSequenceTypeTest : BaseTestBaseline | ||
| { | ||
| public class OutputObj | ||
| { | ||
| [ColumnName("output")] | ||
| [OnnxSequenceType(typeof(IDictionary<string, float>))] | ||
| public IEnumerable<IDictionary<string, float>> Output; | ||
| } | ||
|
|
||
| public class ProblematicOutputObj | ||
| { | ||
|
|
||
| [ColumnName("output")] | ||
| // incorrect usage, should always specify sequence type when using OnnxSequenceType attribute | ||
| [OnnxSequenceType] | ||
| public IEnumerable<IDictionary<string, float>> Output; | ||
| } | ||
|
|
||
| public class FloatInput | ||
| { | ||
| [ColumnName("input")] | ||
| [VectorType(3)] | ||
| public float[] Input { get; set; } | ||
| } | ||
|
|
||
| public OnnxSequenceTypeWithAttributesTest(ITestOutputHelper output) : base(output) | ||
| public OnnxSequenceTypeTest(ITestOutputHelper output) : base(output) | ||
| { | ||
| } | ||
| public static PredictionEngine<FloatInput, OutputObj> LoadModel(string onnxModelFilePath) | ||
|
|
||
| private static OnnxTransformer PrepareModel(string onnxModelFilePath, MLContext ctx) | ||
| { | ||
| var ctx = new MLContext(); | ||
| var dataView = ctx.Data.LoadFromEnumerable(new List<FloatInput>()); | ||
|
|
||
| var pipeline = ctx.Transforms.ApplyOnnxModel( | ||
| modelFile: onnxModelFilePath, | ||
| outputColumnNames: new[] { "output" }, inputColumnNames: new[] { "input" }); | ||
|
|
||
| var model = pipeline.Fit(dataView); | ||
| return model; | ||
| } | ||
|
|
||
| public static PredictionEngine<FloatInput, OutputObj> LoadModel(string onnxModelFilePath) | ||
| { | ||
| var ctx = new MLContext(); | ||
| var model = PrepareModel(onnxModelFilePath, ctx); | ||
| return ctx.Model.CreatePredictionEngine<FloatInput, OutputObj>(model); | ||
| } | ||
|
|
||
|
|
@@ -64,5 +82,21 @@ public void OnnxSequenceTypeWithColumnNameAttributeTest() | |
| } | ||
|
|
||
| } | ||
|
|
||
| private static PredictionEngine<FloatInput, ProblematicOutputObj> CreatePredictorWithPronlematicOutputObj() | ||
| { | ||
| var onnxModelFilePath = Path.Combine(Directory.GetCurrentDirectory(), "zipmap", "TestZipMapString.onnx"); | ||
|
|
||
| var ctx = new MLContext(); | ||
| var model = PrepareModel(onnxModelFilePath, ctx); | ||
| return ctx.Model.CreatePredictionEngine<FloatInput, ProblematicOutputObj>(model); | ||
| } | ||
|
|
||
| [OnnxFact] | ||
| public void OnnxSequenceTypeWithouSpecifySequenceTypeTest() | ||
| { | ||
| Exception ex = Assert.Throws<Exception>(() => CreatePredictorWithPronlematicOutputObj()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
A small typo here with Problematic #Resolved
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| Assert.Equal("Please specify sequence type when use OnnxSequenceType Attribute.", ex.Message); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be better to assert on the type of exception rather than the specific message? #Resolved
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, the exception type is assert in previous line Assert.Throws, after change to use InvalidOperationException, it should look like Assert.Throws(....), so we can assert both on exception type and exception message. In reply to: 330651709 [](ancestors = 330651709) |
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
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.
please do not use braces for single line if condition #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.
Actually this is best practice to always use braces for if condition, in my previous team it is also suggested to always use braces for if condition to avoid further problem.
There is also some discussion online, please check out and see whether this make sense to you: https://softwareengineering.stackexchange.com/questions/16528/single-statement-if-block-braces-or-no
In reply to: 330344007 [](ancestors = 330344007)
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.
Offline discussed with Zeeshan, this can be debatable, I will just follow the coding style in this team, not a big issue
In reply to: 330672086 [](ancestors = 330672086,330344007)