Skip to content

Explicit implementation for IsRowToRowMapper and GetRowToRowMapper #2673

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 3 commits into from
Feb 25, 2019
Merged
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
9 changes: 5 additions & 4 deletions src/Microsoft.ML.Data/DataLoadSave/TransformWrapper.cs
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ public sealed class TransformWrapper : ITransformer
private readonly IHost _host;
private readonly IDataView _xf;
private readonly bool _allowSave;
private readonly bool _isRowToRowMapper;

public TransformWrapper(IHostEnvironment env, IDataView xf, bool allowSave = false)
{
@@ -33,7 +34,7 @@ public TransformWrapper(IHostEnvironment env, IDataView xf, bool allowSave = fal
_host.CheckValue(xf, nameof(xf));
_xf = xf;
_allowSave = allowSave;
IsRowToRowMapper = IsChainRowToRowMapper(_xf);
_isRowToRowMapper = IsChainRowToRowMapper(_xf);
}

public DataViewSchema GetOutputSchema(DataViewSchema inputSchema)
@@ -108,7 +109,7 @@ private TransformWrapper(IHostEnvironment env, ModelLoadContext ctx)
}

_xf = data;
IsRowToRowMapper = IsChainRowToRowMapper(_xf);
_isRowToRowMapper = IsChainRowToRowMapper(_xf);
}

public IDataView Transform(IDataView input) => ApplyTransformUtils.ApplyAllTransformsToData(_host, _xf, input);
@@ -123,9 +124,9 @@ private static bool IsChainRowToRowMapper(IDataView view)
return true;
}

public bool IsRowToRowMapper { get; }
bool ITransformer.IsRowToRowMapper => _isRowToRowMapper;

public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
{
_host.CheckValue(inputSchema, nameof(inputSchema));
var input = new EmptyDataView(_host, inputSchema);
7 changes: 4 additions & 3 deletions src/Microsoft.ML.Data/DataLoadSave/TransformerChain.cs
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ public sealed class TransformerChain<TLastTransformer> : ITransformer, IEnumerab

private const string TransformDirTemplate = "Transform_{0:000}";

public bool IsRowToRowMapper => _transformers.All(t => t.IsRowToRowMapper);
bool ITransformer.IsRowToRowMapper => _transformers.All(t => t.IsRowToRowMapper);

ITransformer[] ITransformerChainAccessor.Transformers => _transformers;

@@ -216,10 +216,11 @@ public void SaveTo(IHostEnvironment env, Stream outputStream)

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
{
Contracts.CheckValue(inputSchema, nameof(inputSchema));
Contracts.Check(IsRowToRowMapper, nameof(GetRowToRowMapper) + " method called despite " + nameof(IsRowToRowMapper) + " being false.");
Contracts.Check(((ITransformer)this).IsRowToRowMapper, nameof(ITransformer.GetRowToRowMapper) + " method called despite " +
Copy link
Member

Choose a reason for hiding this comment

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

IsRowToRowMapper [](start = 49, length = 16)

I feel we should hide IsRowToRowMapper as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you are asking whether we can make IsRowToRowMapper internal.

I discussed this with Tom at length and the answer is that we should not make it internal. The reason is that when a ITransformer is a IRowToRowMapper, the performance of the prediction engine can be significantly increased compared to when it is not. Tom talked of a difference of orders of magnitude.

Since it is such an important characteristics of the ITransformer we think it is better to keep it as part of the public API. This is especially true when we think about possibly allowing expansion of the library with custom components in the future.

Copy link
Member

Choose a reason for hiding this comment

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

If its for potential use, I feel we should hide for this version because I don't think users will be able to control the performance of ML.NET in the near future.


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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will let @TomFinley explain his reasons.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think in general the policy is a good one, that we should try to limit the scope of the public API. However, I feel very strongly that something like IRowToRowMapper has to exist.

The reason why I think this is the case is that I think back to #973. Literally everything can be captured as mapping from IDataView to IDataView, as we have seen. But we see that if we have a more "specific" interface for this row-to-row mapping, we can gain some benefit -- in this case, orders of magnitude speedup and a far more clear interface from using this "bypass" mechanism, in the case where we can use it.

From this perspective, we might say, "very well, then IRowToRowMapper should just be internal and prediction engine will still be free to use it." Which is of course possible. But then I think to myself, if PredictionEngine is useful from a reflection-driven perspective (as it quite clearly is), what is the dynamic API's answer to this scenario? There is nothing except IRowToRowMapper.

So, I think the case for something like IRowToRowMapper is clear, so I think we should ship it. So does it have to be that specifically? I don't see any better proposal than that interface. (Though perhaps it could be refined, e.g., with @sfilipi making it operating over schema columns specifically rather than int => bool delegates, etc.) But I think the principle has proven itself useful and should be made public, just like IDataView has been around, proven itself useful, and should be made public.

Copy link
Contributor

Choose a reason for hiding this comment

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

(I know this already closed, but though I'd answer the direct question. 😄 )

nameof(ITransformer.IsRowToRowMapper) + " being false.");

IRowToRowMapper[] mappers = new IRowToRowMapper[_transformers.Length];
DataViewSchema schema = inputSchema;
4 changes: 2 additions & 2 deletions src/Microsoft.ML.Data/Prediction/PredictionEngine.cs
Original file line number Diff line number Diff line change
@@ -116,8 +116,8 @@ private static Func<DataViewSchema, IRowToRowMapper> StreamChecker(IHostEnvironm
{
var pipe = DataViewConstructionUtils.LoadPipeWithPredictor(env, modelStream, new EmptyDataView(env, schema));
var transformer = new TransformWrapper(env, pipe);
env.CheckParam(transformer.IsRowToRowMapper, nameof(transformer), "Must be a row to row mapper");
return transformer.GetRowToRowMapper(schema);
env.CheckParam(((ITransformer)transformer).IsRowToRowMapper, nameof(transformer), "Must be a row to row mapper");
return ((ITransformer)transformer).GetRowToRowMapper(schema);
};
}

6 changes: 3 additions & 3 deletions src/Microsoft.ML.Data/Scorers/PredictionTransformer.cs
Original file line number Diff line number Diff line change
@@ -55,10 +55,10 @@ public abstract class PredictionTransformerBase<TModel> : IPredictionTransformer
protected DataViewSchema TrainSchema;

/// <summary>
/// Whether a call to <see cref="GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// Whether a call to <see cref="ITransformer.GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// appropriate schema.
/// </summary>
public bool IsRowToRowMapper => true;
bool ITransformer.IsRowToRowMapper => true;

/// <summary>
/// This class is more or less a thin wrapper over the <see cref="IDataScorerTransform"/> implementing
@@ -132,7 +132,7 @@ public IDataView Transform(IDataView input)
/// </summary>
/// <param name="inputSchema"></param>
/// <returns></returns>
public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));
return (IRowToRowMapper)Scorer.ApplyToData(Host, new EmptyDataView(Host, inputSchema));
6 changes: 3 additions & 3 deletions src/Microsoft.ML.Data/Transforms/ColumnSelecting.cs
Original file line number Diff line number Diff line change
@@ -138,7 +138,7 @@ public sealed class ColumnSelectingTransformer : ITransformer
private readonly IHost _host;
private string[] _selectedColumns;

public bool IsRowToRowMapper => true;
bool ITransformer.IsRowToRowMapper => true;

public IEnumerable<string> SelectColumns => _selectedColumns.AsReadOnly();

@@ -458,13 +458,13 @@ public DataViewSchema GetOutputSchema(DataViewSchema inputSchema)
}

/// <summary>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="IsRowToRowMapper"/>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="ITransformer.IsRowToRowMapper"/>
/// is <c>false</c>, then an exception is thrown. If the input schema is in any way
/// unsuitable for constructing the mapper, an exception should likewise be thrown.
/// </summary>
/// <param name="inputSchema">The input schema for which we should get the mapper.</param>
/// <returns>The row to row mapper.</returns>
public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
{
_host.CheckValue(inputSchema, nameof(inputSchema));
if (!IgnoreMissing && !IsSchemaValid(inputSchema.Select(x => x.Name),
4 changes: 2 additions & 2 deletions src/Microsoft.ML.Data/Transforms/RowToRowTransformerBase.cs
Original file line number Diff line number Diff line change
@@ -26,9 +26,9 @@ protected RowToRowTransformerBase(IHost host)

private protected abstract void SaveModel(ModelSaveContext ctx);

public bool IsRowToRowMapper => true;
bool ITransformer.IsRowToRowMapper => true;

public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));
return new RowToRowMapperTransform(Host, new EmptyDataView(Host, inputSchema), MakeRowMapper(inputSchema), MakeRowMapper);
18 changes: 11 additions & 7 deletions src/Microsoft.ML.TimeSeries/IidAnomalyDetectionBase.cs
Original file line number Diff line number Diff line change
@@ -18,10 +18,10 @@ namespace Microsoft.ML.Transforms.TimeSeries
public class IidAnomalyDetectionBaseWrapper : IStatefulTransformer, ICanSaveModel
{
/// <summary>
/// Whether a call to <see cref="GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// Whether a call to <see cref="ITransformer.GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// appropriate schema.
/// </summary>
public bool IsRowToRowMapper => InternalTransform.IsRowToRowMapper;
bool ITransformer.IsRowToRowMapper => ((ITransformer)InternalTransform).IsRowToRowMapper;

/// <summary>
/// Creates a clone of the transfomer. Used for taking the snapshot of the state.
@@ -36,20 +36,22 @@ public class IidAnomalyDetectionBaseWrapper : IStatefulTransformer, ICanSaveMode
public DataViewSchema GetOutputSchema(DataViewSchema inputSchema) => InternalTransform.GetOutputSchema(inputSchema);

/// <summary>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="IsRowToRowMapper"/>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="ITransformer.IsRowToRowMapper"/>
/// is <c>false</c>, then an exception should be thrown. If the input schema is in any way
/// unsuitable for constructing the mapper, an exception should likewise be thrown.
/// </summary>
/// <param name="inputSchema">The input schema for which we should get the mapper.</param>
/// <returns>The row to row mapper.</returns>
public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema) => InternalTransform.GetRowToRowMapper(inputSchema);
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
=> ((ITransformer)InternalTransform).GetRowToRowMapper(inputSchema);

/// <summary>
/// Same as <see cref="ITransformer.GetRowToRowMapper(DataViewSchema)"/> but also supports mechanism to save the state.
/// </summary>
/// <param name="inputSchema">The input schema for which we should get the mapper.</param>
/// <returns>The row to row mapper.</returns>
public IRowToRowMapper GetStatefulRowToRowMapper(DataViewSchema inputSchema) => ((IStatefulTransformer)InternalTransform).GetStatefulRowToRowMapper(inputSchema);
public IRowToRowMapper GetStatefulRowToRowMapper(DataViewSchema inputSchema)
=> ((IStatefulTransformer)InternalTransform).GetStatefulRowToRowMapper(inputSchema);

/// <summary>
/// Take the data in, make transformations, output the data.
@@ -60,7 +62,9 @@ public class IidAnomalyDetectionBaseWrapper : IStatefulTransformer, ICanSaveMode
/// <summary>
/// For saving a model into a repository.
/// </summary>
public virtual void Save(ModelSaveContext ctx)
void ICanSaveModel.Save(ModelSaveContext ctx) => SaveModel(ctx);

private protected virtual void SaveModel(ModelSaveContext ctx)
{
InternalTransform.SaveThis(ctx);
}
@@ -129,7 +133,7 @@ public override DataViewSchema GetOutputSchema(DataViewSchema inputSchema)

private protected override void SaveModel(ModelSaveContext ctx)
{
Parent.Save(ctx);
((ICanSaveModel)Parent).Save(ctx);
}

internal void SaveThis(ModelSaveContext ctx)
4 changes: 2 additions & 2 deletions src/Microsoft.ML.TimeSeries/IidChangePointDetector.cs
Original file line number Diff line number Diff line change
@@ -172,7 +172,7 @@ private IidChangePointDetector(IHostEnvironment env, IidChangePointDetector tran
{
}

public override void Save(ModelSaveContext ctx)
private protected override void SaveModel(ModelSaveContext ctx)
{
InternalTransform.Host.CheckValue(ctx, nameof(ctx));
ctx.CheckAtModel();
@@ -184,7 +184,7 @@ public override void Save(ModelSaveContext ctx)
// *** Binary format ***
// <base>

base.Save(ctx);
base.SaveModel(ctx);
}

// Factory method for SignatureLoadRowMapper.
4 changes: 2 additions & 2 deletions src/Microsoft.ML.TimeSeries/IidSpikeDetector.cs
Original file line number Diff line number Diff line change
@@ -153,7 +153,7 @@ private IidSpikeDetector(IHostEnvironment env, IidSpikeDetector transform)
{
}

public override void Save(ModelSaveContext ctx)
private protected override void SaveModel(ModelSaveContext ctx)
{
InternalTransform.Host.CheckValue(ctx, nameof(ctx));
ctx.CheckAtModel();
@@ -164,7 +164,7 @@ public override void Save(ModelSaveContext ctx)
// *** Binary format ***
// <base>

base.Save(ctx);
base.SaveModel(ctx);
}

// Factory method for SignatureLoadRowMapper.
Original file line number Diff line number Diff line change
@@ -348,7 +348,7 @@ public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
return col => false;
}

public void Save(ModelSaveContext ctx) => _parent.SaveModel(ctx);
void ICanSaveModel.Save(ModelSaveContext ctx) => _parent.SaveModel(ctx);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This one was internal already, but in every other Mapper elsewhere we have made this one explicit despite it being internal for consistency.

public Delegate[] CreateGetters(DataViewRow input, Func<int, bool> activeOutput, out Action disposer)
{
2 changes: 1 addition & 1 deletion src/Microsoft.ML.TimeSeries/SequentialTransformerBase.cs
Original file line number Diff line number Diff line change
@@ -269,7 +269,7 @@ private protected virtual void CloneCore(TState state)
internal readonly string OutputColumnName;
private protected DataViewType OutputColumnType;

public bool IsRowToRowMapper => false;
bool ITransformer.IsRowToRowMapper => false;

internal TState StateRef { get; set; }

18 changes: 11 additions & 7 deletions src/Microsoft.ML.TimeSeries/SsaAnomalyDetectionBase.cs
Original file line number Diff line number Diff line change
@@ -87,10 +87,10 @@ public static Func<Double, Double, Double> GetErrorFunction(ErrorFunction errorF
public class SsaAnomalyDetectionBaseWrapper : IStatefulTransformer, ICanSaveModel
{
/// <summary>
/// Whether a call to <see cref="GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// Whether a call to <see cref="ITransformer.GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// appropriate schema.
/// </summary>
public bool IsRowToRowMapper => InternalTransform.IsRowToRowMapper;
bool ITransformer.IsRowToRowMapper => ((ITransformer)InternalTransform).IsRowToRowMapper;

/// <summary>
/// Creates a clone of the transfomer. Used for taking the snapshot of the state.
@@ -105,20 +105,22 @@ public class SsaAnomalyDetectionBaseWrapper : IStatefulTransformer, ICanSaveMode
public DataViewSchema GetOutputSchema(DataViewSchema inputSchema) => InternalTransform.GetOutputSchema(inputSchema);

/// <summary>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="IsRowToRowMapper"/>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="ITransformer.IsRowToRowMapper"/>
/// is <c>false</c>, then an exception should be thrown. If the input schema is in any way
/// unsuitable for constructing the mapper, an exception should likewise be thrown.
/// </summary>
/// <param name="inputSchema">The input schema for which we should get the mapper.</param>
/// <returns>The row to row mapper.</returns>
public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema) => InternalTransform.GetRowToRowMapper(inputSchema);
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
=> ((ITransformer)InternalTransform).GetRowToRowMapper(inputSchema);

/// <summary>
/// Same as <see cref="ITransformer.GetRowToRowMapper(DataViewSchema)"/> but also supports mechanism to save the state.
/// </summary>
/// <param name="inputSchema">The input schema for which we should get the mapper.</param>
/// <returns>The row to row mapper.</returns>
public IRowToRowMapper GetStatefulRowToRowMapper(DataViewSchema inputSchema) => ((IStatefulTransformer)InternalTransform).GetStatefulRowToRowMapper(inputSchema);
public IRowToRowMapper GetStatefulRowToRowMapper(DataViewSchema inputSchema)
=> ((IStatefulTransformer)InternalTransform).GetStatefulRowToRowMapper(inputSchema);

/// <summary>
/// Take the data in, make transformations, output the data.
@@ -129,7 +131,9 @@ public class SsaAnomalyDetectionBaseWrapper : IStatefulTransformer, ICanSaveMode
/// <summary>
/// For saving a model into a repository.
/// </summary>
public virtual void Save(ModelSaveContext ctx) => InternalTransform.SaveThis(ctx);
void ICanSaveModel.Save(ModelSaveContext ctx) => SaveModel(ctx);

private protected virtual void SaveModel(ModelSaveContext ctx) => InternalTransform.SaveThis(ctx);

/// <summary>
/// Creates a row mapper from Schema.
@@ -255,7 +259,7 @@ public override DataViewSchema GetOutputSchema(DataViewSchema inputSchema)

private protected override void SaveModel(ModelSaveContext ctx)
{
Parent.Save(ctx);
((ICanSaveModel)Parent).Save(ctx);
}

internal void SaveThis(ModelSaveContext ctx)
4 changes: 2 additions & 2 deletions src/Microsoft.ML.TimeSeries/SsaChangePointDetector.cs
Original file line number Diff line number Diff line change
@@ -180,7 +180,7 @@ internal SsaChangePointDetector(IHostEnvironment env, ModelLoadContext ctx)
InternalTransform.Host.CheckDecode(InternalTransform.IsAdaptive == false);
}

public override void Save(ModelSaveContext ctx)
private protected override void SaveModel(ModelSaveContext ctx)
{
InternalTransform.Host.CheckValue(ctx, nameof(ctx));
ctx.CheckAtModel();
@@ -194,7 +194,7 @@ public override void Save(ModelSaveContext ctx)
// *** Binary format ***
// <base>

base.Save(ctx);
base.SaveModel(ctx);
}

// Factory method for SignatureLoadRowMapper.
4 changes: 2 additions & 2 deletions src/Microsoft.ML.TimeSeries/SsaSpikeDetector.cs
Original file line number Diff line number Diff line change
@@ -162,7 +162,7 @@ internal SsaSpikeDetector(IHostEnvironment env, ModelLoadContext ctx)
InternalTransform.Host.CheckDecode(InternalTransform.IsAdaptive == false);
}

public override void Save(ModelSaveContext ctx)
private protected override void SaveModel(ModelSaveContext ctx)
Copy link
Contributor

Choose a reason for hiding this comment

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

private protected override void SaveModel [](start = 8, length = 41)

Ahh, thank you very much for finding more of these!!

Copy link
Contributor

@TomFinley TomFinley Feb 21, 2019

Choose a reason for hiding this comment

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

Actually wait, these are already internal, so probably not necessary... still, eh... I don't know. If you think it helps with consistency and readability.


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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the containing classes are public. The classes in which I made the implementation of ICanSaveModel,Save explicit derive from SsaAnomalyDetectionBaseWrapper or IidAnomalyDetectionBaseWrapper which are both public.
There is just one that does not, and that's the Mapper class in SequentialAnomalyDetectionTransformBase which is internal. This was the only instance where a mapper class does not have explicit implementation of the Save method. In the previous PR, we decided the that despite this being an internal class it was beneficial to do an explicit implementation for consistency as it implements ICanSaveModel. So all mappers elsewhere have an explicit implementation of that method.


In reply to: 258776058 [](ancestors = 258776058,258775986)

{
InternalTransform.Host.CheckValue(ctx, nameof(ctx));
ctx.CheckAtModel();
@@ -175,7 +175,7 @@ public override void Save(ModelSaveContext ctx)
// *** Binary format ***
// <base>

base.Save(ctx);
base.SaveModel(ctx);
}

// Factory method for SignatureLoadRowMapper.
8 changes: 4 additions & 4 deletions src/Microsoft.ML.Transforms/CustomMappingTransformer.cs
Original file line number Diff line number Diff line change
@@ -30,10 +30,10 @@ public sealed class CustomMappingTransformer<TSrc, TDst> : ITransformer
internal SchemaDefinition InputSchemaDefinition { get; }

/// <summary>
/// Whether a call to <see cref="GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// Whether a call to <see cref="ITransformer.GetRowToRowMapper(DataViewSchema)"/> should succeed, on an
/// appropriate schema.
/// </summary>
public bool IsRowToRowMapper => true;
bool ITransformer.IsRowToRowMapper => true;

/// <summary>
/// Create a custom mapping of input columns to output columns.
@@ -95,11 +95,11 @@ public IDataView Transform(IDataView input)
}

/// <summary>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="IsRowToRowMapper"/>
/// Constructs a row-to-row mapper based on an input schema. If <see cref="ITransformer.IsRowToRowMapper"/>
/// is <c>false</c>, then an exception is thrown. If the <paramref name="inputSchema"/> is in any way
/// unsuitable for constructing the mapper, an exception is likewise thrown.
/// </summary>
public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema)
{
_host.CheckValue(inputSchema, nameof(inputSchema));
var simplerMapper = MakeRowMapper(inputSchema);
4 changes: 2 additions & 2 deletions src/Microsoft.ML.Transforms/OneHotEncoding.cs
Original file line number Diff line number Diff line change
@@ -166,9 +166,9 @@ internal OneHotEncodingTransformer(ValueToKeyMappingEstimator term, IEstimator<I

void ICanSaveModel.Save(ModelSaveContext ctx) => (_transformer as ICanSaveModel).Save(ctx);

public bool IsRowToRowMapper => _transformer.IsRowToRowMapper;
bool ITransformer.IsRowToRowMapper => ((ITransformer)_transformer).IsRowToRowMapper;

public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema) => _transformer.GetRowToRowMapper(inputSchema);
IRowToRowMapper ITransformer.GetRowToRowMapper(DataViewSchema inputSchema) => ((ITransformer)_transformer).GetRowToRowMapper(inputSchema);
}
/// <summary>
/// Estimator which takes set of columns and produce for each column indicator array.
Loading