Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
33 changes: 33 additions & 0 deletions src/Microsoft.ML.OnnxConverter/SaveOnnxCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.ML.Internal.Utilities;
using Microsoft.ML.Model.OnnxConverter;
using Microsoft.ML.Runtime;
using Microsoft.ML.Transforms;
using Newtonsoft.Json;
using static Microsoft.ML.Model.OnnxConverter.OnnxCSharpToProtoWrapper;

Expand Down Expand Up @@ -308,6 +309,16 @@ private void Run(IChannel ch)
Host.Assert(scorePipe.Source == end);
end = scorePipe;
transforms.AddLast(scoreOnnx);

if(rawPred.PredictionKind == PredictionKind.BinaryClassification || rawPred.PredictionKind == PredictionKind.MulticlassClassification)
{
if(scorePipe.Schema.GetColumnOrNull("PredictedLabel")?.Type is KeyDataViewType)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

is KeyDataViewType [](start = 84, length = 18)

This still doesn't mean that the KeyToValueMappingTransformer will work - there can be key type columns that don't have key value annotations. I think there is a utility method called something like HasKeyNames that you can use.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The HasKeyValues method requires me to specify the keyValueItemType. Does anyone know if there's a way to avoid having to specify it, since in here I don't care about the keyValueItemType, as long as it has key value annotations.? @ganik @harishsk (if I leave it null, it defaults to be TextDataViewType)

public static bool HasKeyValues(this DataViewSchema.Column column, PrimitiveDataViewType keyValueItemType = null)
{
// False if type is neither a key type, or a vector of key types.
if (!(column.Type.GetItemType() is KeyDataViewType keyType))
return false;
if (keyValueItemType == null)
keyValueItemType = TextDataViewType.Instance;
var metaColumn = column.Annotations.Schema.GetColumnOrNull(AnnotationUtils.Kinds.KeyValues);
return
metaColumn != null
&& metaColumn.Value.Type is VectorDataViewType vectorType
&& keyType.Count == (ulong)vectorType.Size
&& keyValueItemType.Equals(vectorType.ItemType);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How about you do something like:

ReadOnlyMemory tmp = default;
if (input.Data.Schema.TryGetAnnotation(TextDataViewType.Instance, AnnotationUtils.Kinds.ScoreValueKind, i, ref tmp) && ReadOnlyMemoryUtils.EqualsStr(AnnotationUtils.Const.ScoreValueKind.PredictedLabel, tmp))
{


In reply to: 382339571 [](ancestors = 382339571)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

More general advice: search for "ScoreValueKind.PredictedLabel" and see how in other places we check for such column


In reply to: 382745605 [](ancestors = 382745605,382339571)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can look at the implementation of HasKeyValues and filter out the checks that are relying on keyValueItemType . e.g.

            if (!(column.Type.GetItemType() is KeyDataViewType keyType))
                return false;
            var metaColumn = column.Annotations.Schema.GetColumnOrNull(AnnotationUtils.Kinds.KeyValues);
            return
                metaColumn != null
                && metaColumn.Value.Type is VectorDataViewType vectorType
                && keyType.Count == (ulong)vectorType.Size)


In reply to: 382339571 [](ancestors = 382339571)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've decided to go with @harishsk suggestion. Please, @yaeldekel let me know if you know about another way of doing this.


In reply to: 382804341 [](ancestors = 382804341,382339571)

Comment thread
antoniovs1029 marked this conversation as resolved.
Outdated
{
var outputData = new KeyToValueMappingTransformer(Host, "PredictedLabel").Transform(scorePipe);
end = outputData;
transforms.AddLast(outputData as ITransformCanSaveOnnx);
}
}
}
else
{
Expand All @@ -322,6 +333,28 @@ private void Run(IChannel ch)
nameof(Arguments.LoadPredictor), "We were explicitly told to load the predictor but one was not present.");
}

// Convert back to values the KeyDataViewType columns that appear both in input and output
// (i.e those that remained untouched by the model).
var outputNames = new HashSet<string>();
foreach (var col in end.Schema)
if (col.Type is KeyDataViewType && col.IsHidden == false)
outputNames.Add(col.Name);

var inputNames = new HashSet<string>();
foreach (var col in source.Schema)
if (col.Type is KeyDataViewType && col.IsHidden == false)
inputNames.Add(col.Name);

outputNames.IntersectWith(inputNames);

foreach (var name in outputNames)
{
// MYTODO: Add in here any check necessary to see if the column actually has KeyValue Annotations
var outputData = new KeyToValueMappingTransformer(Host, name).Transform(end);
end = outputData;
transforms.AddLast(end as ITransformCanSaveOnnx);
}

var model = ConvertTransformListToOnnxModel(ctx, ch, source, end, transforms, _inputsToDrop, _outputsToDrop);

using (var file = Host.CreateOutputFile(_outputModelPath))
Expand Down
1 change: 0 additions & 1 deletion test/Microsoft.ML.Tests/OnnxConversionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,6 @@ public void LoadingPredictorModelAndOnnxConversionTest()
Done();
}


[Fact]
public void RemoveVariablesInPipelineTest()
{
Expand Down