Skip to content

Move Static API extensions to separate assembly #1930

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 15 commits into from
Jan 3, 2019
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static void AveragedPerceptronBinaryClassification()
var mlContext = new MLContext();

// Creating Data Reader with the initial schema based on the format of the data
var reader = TextLoader.CreateReader(
var reader = TextLoaderStatic.CreateReader(
mlContext,
c => (
Age: c.LoadFloat(0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static void FastTreeBinaryClassification()
var mlContext = new MLContext();

// Creating Data Reader with the initial schema based on the format of the data
var reader = TextLoader.CreateReader(
var reader = TextLoaderStatic.CreateReader(
mlContext,
c => (
Age: c.LoadFloat(0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static void FastTreeRegression()
var mlContext = new MLContext();

// Creating a data reader, based on the format of the data
var reader = TextLoader.CreateReader(mlContext, c => (
var reader = TextLoaderStatic.CreateReader(mlContext, c => (
label: c.LoadFloat(0),
features: c.LoadFloat(1, 6)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static void FeatureSelectionTransform()

// First, we define the reader: specify the data columns and where to find them in the text file. Notice that we combine entries from
// all the feature columns into entries of a vector of a single column named "Features".
var reader = TextLoader.CreateReader(ml, c => (
var reader = TextLoaderStatic.CreateReader(ml, c => (
Label: c.LoadBool(0),
Features: c.LoadFloat(1, 9)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static void LightGbmBinaryClassification()
var mlContext = new MLContext();

// Creating Data Reader with the initial schema based on the format of the data
var reader = TextLoader.CreateReader(
var reader = TextLoaderStatic.CreateReader(
mlContext,
c => (
Age: c.LoadFloat(0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.ML.Data;
using Microsoft.ML.LightGBM;
using Microsoft.ML.LightGBM.StaticPipe;
using Microsoft.ML.StaticPipe;

namespace Microsoft.ML.Samples.Static
{
Expand All @@ -19,7 +20,7 @@ public static void LightGbmRegression()
var mlContext = new MLContext();

// Creating a data reader, based on the format of the data
var reader = TextLoader.CreateReader(mlContext, c => (
var reader = TextLoaderStatic.CreateReader(mlContext, c => (
label: c.LoadFloat(0),
features: c.LoadFloat(1, 6)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static void SdcaBinaryClassification()
var mlContext = new MLContext();

// Creating Data Reader with the initial schema based on the format of the data
var reader = TextLoader.CreateReader(
var reader = TextLoaderStatic.CreateReader(
mlContext,
c => (
Age: c.LoadFloat(0),
Expand Down
2 changes: 1 addition & 1 deletion docs/samples/Microsoft.ML.Samples/Static/SDCARegression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static void SdcaRegression()
var mlContext = new MLContext();

// Creating a data reader, based on the format of the data
var reader = TextLoader.CreateReader(mlContext, c => (
var reader = TextLoaderStatic.CreateReader(mlContext, c => (
label: c.LoadFloat(0),
features: c.LoadFloat(1, 6)
),
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.ML.Data/DataLoadSave/DataOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Microsoft.ML
/// </summary>
public sealed class DataOperations
{
[BestFriend]
internal IHostEnvironment Environment { get; }

internal DataOperations(IHostEnvironment env)
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.ML.Data/DataLoadSave/EstimatorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ public static IEstimator<TTransformer> WithOnFitDelegate<TTransformer>(this IEst
return new DelegateEstimator<TTransformer>(estimator, onFit);
}

[BestFriend]
internal static T[] AppendElement<T>(this T[] array, T element)
{
T[] result = new T[Utils.Size(array) + 1];
Expand Down
6 changes: 4 additions & 2 deletions src/Microsoft.ML.Data/DataLoadSave/Text/TextLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ internal static class DefaultArguments
/// Used as an input column range.
/// A variable length segment (extending to the end of the input line) is represented by Lim == SrcLim.
/// </summary>
private struct Segment
internal struct Segment
{
public int Min;
public int Lim;
Expand Down Expand Up @@ -440,7 +440,7 @@ public Segment(int min)
/// <summary>
/// Information for an output column.
/// </summary>
private sealed class ColInfo
internal sealed class ColInfo
{
public readonly string Name;
// REVIEW: Fix this for keys.
Expand Down Expand Up @@ -1361,6 +1361,8 @@ public void Save(ModelSaveContext ctx)

public IDataView Read(string path) => Read(new MultiFileSource(path));

public IDataView Read(params string[] path) => Read(new MultiFileSource(path));

internal static TextLoader CreateTextReader<TInput>(IHostEnvironment host,
bool hasHeader = DefaultArguments.HasHeader,
char separator = DefaultArguments.Separator,
Expand Down
9 changes: 5 additions & 4 deletions src/Microsoft.ML.FastTree/FastTreeArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,13 @@ public enum Bundle : Byte
Adjacent = 2
}

[BestFriend]
internal static class Defaults
{
internal const int NumTrees = 100;
internal const int NumLeaves = 20;
internal const int MinDocumentsInLeaves = 10;
internal const double LearningRates = 0.2;
public const int NumTrees = 100;
public const int NumLeaves = 20;
public const int MinDocumentsInLeaves = 10;
public const double LearningRates = 0.2;
}

public abstract class TreeArgs : LearnerInputBaseWithGroupId
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.ML.FastTree/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@
[assembly: InternalsVisibleTo(assemblyName: "Microsoft.ML.LightGBM" + PublicKey.Value)]
[assembly: InternalsVisibleTo(assemblyName: "Microsoft.ML.Sweeper" + PublicKey.Value)]

[assembly: InternalsVisibleTo(assemblyName: "Microsoft.ML.StaticPipe" + PublicKey.Value)]

[assembly: WantsToBeBestFriends]
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<ItemGroup>
<ProjectReference Include="..\Microsoft.ML.Data\Microsoft.ML.Data.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.StaticPipe\Microsoft.ML.StaticPipe.csproj" />
Copy link
Contributor

@Ivanidzo4ka Ivanidzo4ka Jan 2, 2019

Choose a reason for hiding this comment

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

StaticPipe [](start = 71, length = 10)

why we have this? #Closed

Copy link
Member Author

Choose a reason for hiding this comment

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

Without this VectorWhiteningStaticExtensions.cs would complain of missing references.

Note previously the static extensions were part of the Microsoft.ML.Data assembly. In this PR we moved them to a separate assembly Microsoft.ML.StaticPipe


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

Copy link
Contributor

Choose a reason for hiding this comment

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

Make sense if this StaticPipe project


In reply to: 244829980 [](ancestors = 244829980,244826453)

</ItemGroup>

</Project>
48 changes: 0 additions & 48 deletions src/Microsoft.ML.ImageAnalytics/ImageGrayscaleTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
using Microsoft.ML.ImageAnalytics;
using Microsoft.ML.Internal.Utilities;
using Microsoft.ML.Model;
using Microsoft.ML.StaticPipe;
using Microsoft.ML.StaticPipe.Runtime;

[assembly: LoadableClass(ImageGrayscaleTransform.Summary, typeof(IDataTransform), typeof(ImageGrayscaleTransform), typeof(ImageGrayscaleTransform.Arguments), typeof(SignatureDataTransform),
ImageGrayscaleTransform.UserName, "ImageGrayscaleTransform", "ImageGrayscale")]
Expand Down Expand Up @@ -239,51 +237,5 @@ public override SchemaShape GetOutputSchema(SchemaShape inputSchema)

return new SchemaShape(result.Values);
}

private interface IColInput
{
PipelineColumn Input { get; }
}

internal sealed class OutPipelineColumn<T> : Custom<T>, IColInput
{
public PipelineColumn Input { get; }

public OutPipelineColumn(Custom<T> input)
: base(Reconciler.Inst, input)
{
Contracts.AssertValue(input);
Contracts.Assert(typeof(T) == typeof(Bitmap) || typeof(T) == typeof(UnknownSizeBitmap));
Input = input;
}
}

/// <summary>
/// Reconciler to an <see cref="ImageGrayscalingEstimator"/> for the <see cref="PipelineColumn"/>.
/// </summary>
/// <remarks>Because we want to use the same reconciler for </remarks>
/// <see cref="ImageStaticPipe.AsGrayscale(Custom{Bitmap})"/>
/// <see cref="ImageStaticPipe.AsGrayscale(Custom{UnknownSizeBitmap})"/>
private sealed class Reconciler : EstimatorReconciler
{
public static Reconciler Inst = new Reconciler();

private Reconciler() { }

public override IEstimator<ITransformer> Reconcile(IHostEnvironment env,
PipelineColumn[] toOutput,
IReadOnlyDictionary<PipelineColumn, string> inputNames,
IReadOnlyDictionary<PipelineColumn, string> outputNames,
IReadOnlyCollection<string> usedNames)
{
var cols = new (string input, string output)[toOutput.Length];
for (int i = 0; i < toOutput.Length; ++i)
{
var outCol = (IColInput)toOutput[i];
cols[i] = (inputNames[outCol.Input], outputNames[toOutput[i]]);
}
return new ImageGrayscalingEstimator(env, cols);
}
}
}
}
59 changes: 0 additions & 59 deletions src/Microsoft.ML.ImageAnalytics/ImageLoaderTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
using Microsoft.ML.ImageAnalytics;
using Microsoft.ML.Internal.Utilities;
using Microsoft.ML.Model;
using Microsoft.ML.StaticPipe;
using Microsoft.ML.StaticPipe.Runtime;

[assembly: LoadableClass(ImageLoaderTransform.Summary, typeof(IDataTransform), typeof(ImageLoaderTransform), typeof(ImageLoaderTransform.Arguments), typeof(SignatureDataTransform),
ImageLoaderTransform.UserName, "ImageLoaderTransform", "ImageLoader")]
Expand Down Expand Up @@ -242,62 +240,5 @@ public override SchemaShape GetOutputSchema(SchemaShape inputSchema)

return new SchemaShape(result.Values);
}

internal sealed class OutPipelineColumn : Custom<UnknownSizeBitmap>
{
private readonly Scalar<string> _input;

public OutPipelineColumn(Scalar<string> path, string relativeTo)
: base(new Reconciler(relativeTo), path)
{
Contracts.AssertValue(path);
_input = path;
}

/// <summary>
/// Reconciler to an <see cref="ImageLoadingEstimator"/> for the <see cref="PipelineColumn"/>.
/// </summary>
/// <remarks>
/// We must create a new reconciler per call, because the relative path of <see cref="ImageLoaderTransform.Arguments.ImageFolder"/>
/// is considered a transform-wide option, as it is not specified in <see cref="ImageLoaderTransform.Column"/>. However, we still
/// implement <see cref="IEquatable{T}"/> so the analyzer can still equate two of these things if they happen to share the same
/// path, so we can be a bit more efficient with respect to our estimator declarations.
/// </remarks>
/// <see cref="ImageStaticPipe.LoadAsImage(Scalar{string}, string)"/>
private sealed class Reconciler : EstimatorReconciler, IEquatable<Reconciler>
{
private readonly string _relTo;

public Reconciler(string relativeTo)
{
Contracts.AssertValueOrNull(relativeTo);
_relTo = relativeTo;
}

public bool Equals(Reconciler other)
=> other != null && other._relTo == _relTo;

public override bool Equals(object obj)
=> obj is Reconciler other && Equals(other);

public override int GetHashCode()
=> _relTo?.GetHashCode() ?? 0;

public override IEstimator<ITransformer> Reconcile(IHostEnvironment env,
PipelineColumn[] toOutput,
IReadOnlyDictionary<PipelineColumn, string> inputNames,
IReadOnlyDictionary<PipelineColumn, string> outputNames,
IReadOnlyCollection<string> usedNames)
{
var cols = new (string input, string output)[toOutput.Length];
for (int i = 0; i < toOutput.Length; ++i)
{
var outCol = (OutPipelineColumn)toOutput[i];
cols[i] = (inputNames[outCol._input], outputNames[outCol]);
}
return new ImageLoadingEstimator(env, _relTo, cols);
}
}
}
}
}
67 changes: 0 additions & 67 deletions src/Microsoft.ML.ImageAnalytics/ImagePixelExtractorTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
using Microsoft.ML.ImageAnalytics;
using Microsoft.ML.Internal.Utilities;
using Microsoft.ML.Model;
using Microsoft.ML.StaticPipe;
using Microsoft.ML.StaticPipe.Runtime;

[assembly: LoadableClass(ImagePixelExtractorTransform.Summary, typeof(IDataTransform), typeof(ImagePixelExtractorTransform), typeof(ImagePixelExtractorTransform.Arguments), typeof(SignatureDataTransform),
ImagePixelExtractorTransform.UserName, "ImagePixelExtractorTransform", "ImagePixelExtractor")]
Expand Down Expand Up @@ -648,70 +646,5 @@ public override SchemaShape GetOutputSchema(SchemaShape inputSchema)

return new SchemaShape(result.Values);
}

private interface IColInput
{
Custom<Bitmap> Input { get; }

ImagePixelExtractorTransform.ColumnInfo MakeColumnInfo(string input, string output);
}

internal sealed class OutPipelineColumn<T> : Vector<T>, IColInput
{
public Custom<Bitmap> Input { get; }
private static readonly ImagePixelExtractorTransform.Arguments _defaultArgs = new ImagePixelExtractorTransform.Arguments();
private readonly ImagePixelExtractorTransform.Column _colParam;

public OutPipelineColumn(Custom<Bitmap> input, ImagePixelExtractorTransform.Column col)
: base(Reconciler.Inst, input)
{
Contracts.AssertValue(input);
Contracts.Assert(typeof(T) == typeof(float) || typeof(T) == typeof(byte));
Input = input;
_colParam = col;
}

public ImagePixelExtractorTransform.ColumnInfo MakeColumnInfo(string input, string output)
{
// In principle, the analyzer should only call the the reconciler once for these columns.
Contracts.Assert(_colParam.Source == null);
Contracts.Assert(_colParam.Name == null);

_colParam.Name = output;
_colParam.Source = input;
return new ImagePixelExtractorTransform.ColumnInfo(_colParam, _defaultArgs);
}
}

/// <summary>
/// Reconciler to an <see cref="ImagePixelExtractingEstimator"/> for the <see cref="PipelineColumn"/>.
/// </summary>
/// <remarks>Because we want to use the same reconciler for </remarks>
/// <see cref="ImageStaticPipe.ExtractPixels(Custom{Bitmap}, bool, bool, bool, bool, bool, float, float)"/>
/// <see cref="ImageStaticPipe.ExtractPixelsAsBytes(Custom{Bitmap}, bool, bool, bool, bool, bool)"/>
private sealed class Reconciler : EstimatorReconciler
{
/// <summary>
/// Because there are no global settings that cannot be overridden, we can always just use the same reconciler.
/// </summary>
public static Reconciler Inst = new Reconciler();

private Reconciler() { }

public override IEstimator<ITransformer> Reconcile(IHostEnvironment env,
PipelineColumn[] toOutput,
IReadOnlyDictionary<PipelineColumn, string> inputNames,
IReadOnlyDictionary<PipelineColumn, string> outputNames,
IReadOnlyCollection<string> usedNames)
{
var cols = new ImagePixelExtractorTransform.ColumnInfo[toOutput.Length];
for (int i = 0; i < toOutput.Length; ++i)
{
var outCol = (IColInput)toOutput[i];
cols[i] = outCol.MakeColumnInfo(inputNames[outCol.Input], outputNames[toOutput[i]]);
}
return new ImagePixelExtractingEstimator(env, cols);
}
}
}
}
Loading