Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Closed
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
2 changes: 1 addition & 1 deletion build/BranchInfo.props
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<MajorVersion>0</MajorVersion>
<MinorVersion>5</MinorVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseLabel>preview</PreReleaseLabel>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion build/Dependencies.props
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@
<LightGBMPackageVersion>2.1.2.2</LightGBMPackageVersion>
<MlNetMklDepsPackageVersion>0.0.0.5</MlNetMklDepsPackageVersion>
<SystemDrawingCommonPackageVersion>4.5.0</SystemDrawingCommonPackageVersion>
<BenchmarkDotNetVersion>0.11.0</BenchmarkDotNetVersion>
<BenchmarkDotNetVersion>0.11.1</BenchmarkDotNetVersion>
<TensorFlowVersion>1.10.0</TensorFlowVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Microsoft.ML.Console/Microsoft.ML.Console.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
<ProjectReference Include="..\Microsoft.ML.Ensemble\Microsoft.ML.Ensemble.csproj" />
<ProjectReference Include="..\Microsoft.ML.FastTree\Microsoft.ML.FastTree.csproj" />
<ProjectReference Include="..\Microsoft.ML.HalLearners\Microsoft.ML.HalLearners.csproj" />
<ProjectReference Include="..\Microsoft.ML.ImageAnalytics\Microsoft.ML.ImageAnalytics.csproj" />
<ProjectReference Include="..\Microsoft.ML.KMeansClustering\Microsoft.ML.KMeansClustering.csproj" />
<ProjectReference Include="..\Microsoft.ML.LightGBM\Microsoft.ML.LightGBM.csproj" />
<ProjectReference Include="..\Microsoft.ML.Maml\Microsoft.ML.Maml.csproj" />
Expand Down
40 changes: 32 additions & 8 deletions src/Microsoft.ML.Core/Data/IEstimator.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,20 +28,42 @@ public enum VectorKind
VariableVector
}

/// <summary>
/// The column name.
/// </summary>
public readonly string Name;

/// <summary>
/// The type of the column: scalar, fixed vector or variable vector.
/// </summary>
public readonly VectorKind Kind;
public readonly DataKind ItemKind;

/// <summary>
/// The 'raw' type of column item: must be a primitive type or a structured type.
/// </summary>
public readonly ColumnType ItemType;
/// <summary>
/// The flag whether the column is actually a key. If yes, <see cref="ItemType"/> is representing
/// the underlying primitive type.
/// </summary>
public readonly bool IsKey;
/// <summary>
/// The metadata kinds that are present for this column.
/// </summary>
public readonly string[] MetadataKinds;

public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, string[] metadataKinds = null)
public Column(string name, VectorKind vecKind, ColumnType itemType, bool isKey, string[] metadataKinds = null)
{
Contracts.CheckNonEmpty(name, nameof(name));
Contracts.CheckValueOrNull(metadataKinds);
Contracts.CheckParam(!itemType.IsKey, nameof(itemType), "Item type cannot be a key");
Contracts.CheckParam(!itemType.IsVector, nameof(itemType), "Item type cannot be a vector");

Contracts.CheckParam(!isKey || KeyType.IsValidDataKind(itemType.RawKind), nameof(itemType), "The item type must be valid for a key");

Name = name;
Kind = vecKind;
ItemKind = itemKind;
ItemType = itemType;
IsKey = isKey;
MetadataKinds = metadataKinds ?? new string[0];
}
Expand All@@ -51,7 +73,7 @@ public Column(string name, VectorKind vecKind, DataKind itemKind, bool isKey, st
/// requirement.
///
/// Namely, it returns true iff:
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemKind"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="Name"/>, <see cref="Kind"/>, <see cref="ItemType"/>, <see cref="IsKey"/> fields match.
/// - The <see cref="MetadataKinds"/> of <paramref name="inputColumn"/> is a superset of our <see cref="MetadataKinds"/>.
/// </summary>
public bool IsCompatibleWith(Column inputColumn)
Expand All@@ -61,7 +83,7 @@ public bool IsCompatibleWith(Column inputColumn)
return false;
if (Kind != inputColumn.Kind)
return false;
if (ItemKind != inputColumn.ItemKind)
if (!ItemType.Equals(inputColumn.ItemType))
return false;
if (IsKey != inputColumn.IsKey)
return false;
Expand All@@ -72,7 +94,7 @@ public bool IsCompatibleWith(Column inputColumn)

public string GetTypeString()
{
string result = ItemKind.ToString();
string result = ItemType.ToString();
if (IsKey)
result = $"Key<{result}>";
if (Kind == VectorKind.Vector)
Expand DownExpand Up@@ -110,13 +132,15 @@ public static SchemaShape Create(ISchema schema)
else
vecKind = Column.VectorKind.Scalar;

var kind = type.ItemType.RawKind;
ColumnType itemType = type.ItemType;
if (type.ItemType.IsKey)
itemType = PrimitiveType.FromKind(type.ItemType.RawKind);
var isKey = type.ItemType.IsKey;

var metadataNames = schema.GetMetadataTypes(iCol)
.Select(kvp => kvp.Key)
.ToArray();
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, kind, isKey, metadataNames));
cols.Add(new Column(schema.GetColumnName(iCol), vecKind, itemType, isKey, metadataNames));
}
}
return new SchemaShape(cols.ToArray());
Expand Down
35 changes: 35 additions & 0 deletions src/Microsoft.ML.Data/DataLoadSave/TrivialEstimator.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.ML.Core.Data;

namespace Microsoft.ML.Runtime.Data
{
/// <summary>
/// The trivial implementation of <see cref="IEstimator{TTransformer}"/> that already has
/// the transformer and returns it on every call to <see cref="Fit(IDataView)"/>.
///
/// Concrete implementations still have to provide the schema propagation mechanism, since
/// there is no easy way to infer it from the transformer.
/// </summary>
public abstract class TrivialEstimator<TTransformer> : IEstimator<TTransformer>
where TTransformer : class, ITransformer
{
protected readonly IHost Host;
protected readonly TTransformer Transformer;

protected TrivialEstimator(IHost host, TTransformer transformer)
{
Contracts.AssertValue(host);

Host = host;
Host.CheckValue(transformer, nameof(transformer));
Transformer = transformer;
}

public TTransformer Fit(IDataView input) => Transformer;

public abstract SchemaShape GetOutputSchema(SchemaShape inputSchema);
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.ML.Data/Transforms/CopyColumnsTransform.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,7 +70,7 @@ public SchemaShape GetOutputSchema(SchemaShape inputSchema)
var originalColumn = inputSchema.FindColumn(column.Source);
if (originalColumn != null)
{
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemKind, originalColumn.IsKey, originalColumn.MetadataKinds);
var col = new SchemaShape.Column(column.Name, originalColumn.Kind, originalColumn.ItemType, originalColumn.IsKey, originalColumn.MetadataKinds);
resultDic[column.Name] = col;
}
else
Expand Down
177 changes: 177 additions & 0 deletions src/Microsoft.ML.Data/Transforms/OneToOneTransformerBase.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Model;

namespace Microsoft.ML.Runtime.Data
{
public abstract class OneToOneTransformerBase : ITransformer, ICanSaveModel
{
protected readonly IHost Host;
protected readonly (string input, string output)[] ColumnPairs;

protected OneToOneTransformerBase(IHost host, (string input, string output)[] columns)
{
Contracts.AssertValue(host);
host.CheckValue(columns, nameof(columns));

var newNames = new HashSet<string>();
foreach (var column in columns)
{
host.CheckNonEmpty(column.input, nameof(columns));
host.CheckNonEmpty(column.output, nameof(columns));

if (!newNames.Add(column.output))
throw Contracts.ExceptParam(nameof(columns), $"Output column '{column.output}' specified multiple times");
}

Host = host;
ColumnPairs = columns;
}

protected OneToOneTransformerBase(IHost host, ModelLoadContext ctx)
{
Host = host;
// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

int n = ctx.Reader.ReadInt32();
ColumnPairs = new (string input, string output)[n];
for (int i = 0; i < n; i++)
{
string output = ctx.LoadNonEmptyString();
string input = ctx.LoadNonEmptyString();
ColumnPairs[i] = (input, output);
}
}

public abstract void Save(ModelSaveContext ctx);

protected void SaveColumns(ModelSaveContext ctx)
{
Host.CheckValue(ctx, nameof(ctx));

// *** Binary format ***
// int: number of added columns
// for each added column
// int: id of output column name
// int: id of input column name

ctx.Writer.Write(ColumnPairs.Length);
for (int i = 0; i < ColumnPairs.Length; i++)
{
ctx.SaveNonEmptyString(ColumnPairs[i].output);
ctx.SaveNonEmptyString(ColumnPairs[i].input);
}
}

private void CheckInput(ISchema inputSchema, int col, out int srcCol)
{
Contracts.AssertValue(inputSchema);
Contracts.Assert(0 <= col && col < ColumnPairs.Length);

if (!inputSchema.TryGetColumnIndex(ColumnPairs[col].input, out srcCol))
throw Host.ExceptSchemaMismatch(nameof(inputSchema), "input", ColumnPairs[col].input);
CheckInputColumn(inputSchema, col, srcCol);
}

protected virtual void CheckInputColumn(ISchema inputSchema, int col, int srcCol)
{
// By default, there are no extra checks.
}

protected abstract IRowMapper MakeRowMapper(ISchema schema);

public ISchema GetOutputSchema(ISchema inputSchema)
{
Host.CheckValue(inputSchema, nameof(inputSchema));

// Check that all the input columns are present and correct.
for (int i = 0; i < ColumnPairs.Length; i++)
CheckInput(inputSchema, i, out int col);

return Transform(new EmptyDataView(Host, inputSchema)).Schema;
}

public IDataView Transform(IDataView input) => MakeDataTransform(input);

protected RowToRowMapperTransform MakeDataTransform(IDataView input)
{
Host.CheckValue(input, nameof(input));
return new RowToRowMapperTransform(Host, input, MakeRowMapper(input.Schema));
}

protected abstract class MapperBase : IRowMapper
{
protected readonly IHost Host;
protected readonly Dictionary<int, int> ColMapNewToOld;
protected readonly ISchema InputSchema;
private readonly OneToOneTransformerBase _parent;

protected MapperBase(IHost host, OneToOneTransformerBase parent, ISchema inputSchema)
{
Contracts.AssertValue(host);
Contracts.AssertValue(parent);
Contracts.AssertValue(inputSchema);

Host = host;
_parent = parent;

ColMapNewToOld = new Dictionary<int, int>();
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
_parent.CheckInput(inputSchema, i, out int srcCol);
ColMapNewToOld.Add(i, srcCol);
}
InputSchema = inputSchema;
}
public Func<int, bool> GetDependencies(Func<int, bool> activeOutput)
{
var active = new bool[InputSchema.ColumnCount];
foreach (var pair in ColMapNewToOld)
if (activeOutput(pair.Key))
active[pair.Value] = true;
return col => active[col];
}

public abstract RowMapperColumnInfo[] GetOutputColumns();

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

public Delegate[] CreateGetters(IRow input, Func<int, bool> activeOutput, out Action disposer)
{
Contracts.Assert(input.Schema == InputSchema);
var result = new Delegate[_parent.ColumnPairs.Length];
var disposers = new Action[_parent.ColumnPairs.Length];
for (int i = 0; i < _parent.ColumnPairs.Length; i++)
{
if (!activeOutput(i))
continue;
int srcCol = ColMapNewToOld[i];
result[i] = MakeGetter(input, i, out disposers[i]);
}
if (disposers.Any(x => x != null))
{
disposer = () =>
{
foreach (var act in disposers)
act();
};
}
else
disposer = null;
return result;
}

protected abstract Delegate MakeGetter(IRow input, int iinfo, out Action disposer);
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ public static class ImageAnalytics
public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, ImageLoaderTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageLoaderTransform", input);
var xf = new ImageLoaderTransform(h, input, input.Data);
var xf = ImageLoaderTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -29,7 +29,7 @@ public static CommonOutputs.TransformOutput ImageLoader(IHostEnvironment env, Im
public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, ImageResizerTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageResizerTransform", input);
var xf = new ImageResizerTransform(h, input, input.Data);
var xf = ImageResizerTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -42,7 +42,7 @@ public static CommonOutputs.TransformOutput ImageResizer(IHostEnvironment env, I
public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment env, ImagePixelExtractorTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImagePixelExtractorTransform", input);
var xf = new ImagePixelExtractorTransform(h, input, input.Data);
var xf = ImagePixelExtractorTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand All@@ -55,7 +55,7 @@ public static CommonOutputs.TransformOutput ImagePixelExtractor(IHostEnvironment
public static CommonOutputs.TransformOutput ImageGrayscale(IHostEnvironment env, ImageGrayscaleTransform.Arguments input)
{
var h = EntryPointUtils.CheckArgsAndCreateHost(env, "ImageGrayscaleTransform", input);
var xf = new ImageGrayscaleTransform(h, input, input.Data);
var xf = ImageGrayscaleTransform.Create(h, input, input.Data);
return new CommonOutputs.TransformOutput()
{
Model = new TransformModel(h, xf, input.Data),
Expand Down
Loading