CustomMappingCatalog.CustomMapping<TSrc,TDst> Метод
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
CustomMappingEstimator<TSrc,TDst>Создайте объект, который применяет настраиваемое сопоставление входных столбцов к выходным столбцам.
public static Microsoft.ML.Transforms.CustomMappingEstimator<TSrc,TDst> CustomMapping<TSrc,TDst> (this Microsoft.ML.TransformsCatalog catalog, Action<TSrc,TDst> mapAction, string contractName, Microsoft.ML.Data.SchemaDefinition inputSchemaDefinition = default, Microsoft.ML.Data.SchemaDefinition outputSchemaDefinition = default) where TSrc : class, new() where TDst : class, new();
static member CustomMapping : Microsoft.ML.TransformsCatalog * Action<'Src, 'Dst (requires 'Src : null and 'Src : (new : unit -> 'Src) and 'Dst : null and 'Dst : (new : unit -> 'Dst))> * string * Microsoft.ML.Data.SchemaDefinition * Microsoft.ML.Data.SchemaDefinition -> Microsoft.ML.Transforms.CustomMappingEstimator<'Src, 'Dst (requires 'Src : null and 'Src : (new : unit -> 'Src) and 'Dst : null and 'Dst : (new : unit -> 'Dst))> (requires 'Src : null and 'Src : (new : unit -> 'Src) and 'Dst : null and 'Dst : (new : unit -> 'Dst))
<Extension()>
Public Function CustomMapping(Of TSrc As {Class, New}, TDst As {Class, New}) (catalog As TransformsCatalog, mapAction As Action(Of TSrc, TDst), contractName As String, Optional inputSchemaDefinition As SchemaDefinition = Nothing, Optional outputSchemaDefinition As SchemaDefinition = Nothing) As CustomMappingEstimator(Of TSrc, TDst)
Параметры типа
- TSrc
Класс, определяющий, какие столбцы следует принимать из входящих данных.
- TDst
Класс, определяющий, какие новые столбцы добавляются в данные.
Параметры
- catalog
- TransformsCatalog
Каталог преобразований
- mapAction
- Action<TSrc,TDst>
Действие сопоставления. Это должно быть потокобезопасно и свободно от побочных эффектов.
Если результирующий mapAction
преобразователь должен быть способен сохранить, определение класса должно реализовываться CustomMappingFactory<TSrc,TDst> и должно быть украшено CustomMappingFactoryAttributeAttribute предоставленным.contractName
В версиях версии 1.5-preview2 и более ранних версиях сборка, содержащая класс, должна быть зарегистрирована в среде, где она загружается обратно с помощью RegisterAssembly(Assembly, Boolean).
- contractName
- String
Имя контракта, используемое ML.NET для загрузки модели.
Если null
этот параметр указан, результирующий преобразователь не сможет сохраняться.
- inputSchemaDefinition
- SchemaDefinition
Дополнительные параметры для сопоставления схем между TSrc
входным и входным данными.
Полезно при работе с заметками.
- outputSchemaDefinition
- SchemaDefinition
Дополнительные параметры для сопоставления схем между TDst
данными и выходными данными.
Полезно при работе с заметками.
Возвращаемое значение
Примеры
using System;
using System.Collections.Generic;
using Microsoft.ML;
namespace Samples.Dynamic
{
public static class CustomMapping
{
// This example shows how to define and apply a custom mapping of input
// columns to output columns without defining a contract. Since a contract
// is not defined, the pipeline containing this mapping cannot be saved and
// loaded back.
public static void Example()
{
// Create a new ML context, for ML.NET operations. It can be used for
// exception tracking and logging, as well as the source of randomness.
var mlContext = new MLContext();
// Get a small dataset as an IEnumerable and convert it to an IDataView.
var samples = new List<InputData>
{
new InputData { Age = 26 },
new InputData { Age = 35 },
new InputData { Age = 34 },
new InputData { Age = 28 },
};
var data = mlContext.Data.LoadFromEnumerable(samples);
// We define the custom mapping between input and output rows that will
// be applied by the transformation.
Action<InputData, CustomMappingOutput> mapping =
(input, output) => output.IsUnderThirty = input.Age < 30;
// Custom transformations can be used to transform data directly, or as
// part of a pipeline of estimators. Note: If contractName is null in
// the CustomMapping estimator, any pipeline of estimators containing
// it, cannot be saved and loaded back.
var pipeline = mlContext.Transforms.CustomMapping(mapping, contractName:
null);
// Now we can transform the data and look at the output to confirm the
// behavior of the estimator. This operation doesn't actually evaluate
// data until we read the data below.
var transformer = pipeline.Fit(data);
var transformedData = transformer.Transform(data);
var dataEnumerable = mlContext.Data.CreateEnumerable<TransformedData>(
transformedData, reuseRowObject: true);
Console.WriteLine("Age\t IsUnderThirty");
foreach (var row in dataEnumerable)
Console.WriteLine($"{row.Age}\t {row.IsUnderThirty}");
// Expected output:
// Age IsUnderThirty
// 26 True
// 35 False
// 34 False
// 28 True
}
// Defines only the column to be generated by the custom mapping
// transformation in addition to the columns already present.
private class CustomMappingOutput
{
public bool IsUnderThirty { get; set; }
}
// Defines the schema of the input data.
private class InputData
{
public float Age { get; set; }
}
// Defines the schema of the transformed data, which includes the new column
// IsUnderThirty.
private class TransformedData : InputData
{
public bool IsUnderThirty { get; set; }
}
}
}
using System;
using System.Collections.Generic;
using Microsoft.ML;
using Microsoft.ML.Transforms;
namespace Samples.Dynamic
{
public static class CustomMappingSaveAndLoad
{
// This example shows how to define and apply a custom mapping of input
// columns to output columns with a contract name. The contract name is
// used in the CustomMappingFactoryAttribute that decorates the custom
// mapping action. The pipeline containing the custom mapping can then be
// saved to disk, and it can be loaded back after the assembly containing
// the custom mapping action is registered.
public static void Example()
{
// Create a new ML context, for ML.NET operations. It can be used for
// exception tracking and logging, as well as the source of randomness.
var mlContext = new MLContext();
// Get a small dataset as an IEnumerable and convert it to an IDataView.
var samples = new List<InputData>
{
new InputData { Age = 26 },
new InputData { Age = 35 },
new InputData { Age = 34 },
new InputData { Age = 28 },
};
var data = mlContext.Data.LoadFromEnumerable(samples);
// Custom transformations can be used to transform data directly, or as
// part of a pipeline of estimators. The contractName must be provided
// in order for a pipeline containing a CustomMapping estimator to be
// saved and loaded back. The contractName must be the same as in the
// CustomMappingFactoryAttribute used to decorate the custom action
// defined by the user.
var pipeline = mlContext.Transforms.CustomMapping(new
IsUnderThirtyCustomAction().GetMapping(), contractName:
"IsUnderThirty");
var transformer = pipeline.Fit(data);
// To save and load the CustomMapping estimator, the assembly in which
// the custom action is defined needs to be registered in the
// environment. The following registers the assembly where
// IsUnderThirtyCustomAction is defined.
// This is necessary only in versions v1.5-preview2 and earlier
mlContext.ComponentCatalog.RegisterAssembly(typeof(
IsUnderThirtyCustomAction).Assembly);
// Now the transform pipeline can be saved and loaded through the usual
// MLContext method.
mlContext.Model.Save(transformer, data.Schema, "customTransform.zip");
var loadedTransform = mlContext.Model.Load("customTransform.zip", out
var inputSchema);
// Now we can transform the data and look at the output to confirm the
// behavior of the estimator. This operation doesn't actually evaluate
// data until we read the data below.
var transformedData = loadedTransform.Transform(data);
var dataEnumerable = mlContext.Data.CreateEnumerable<TransformedData>(
transformedData, reuseRowObject: true);
Console.WriteLine("Age\tIsUnderThirty");
foreach (var row in dataEnumerable)
Console.WriteLine($"{row.Age}\t {row.IsUnderThirty}");
// Expected output:
// Age IsUnderThirty
// 26 True
// 35 False
// 34 False
// 28 True
}
// The custom action needs to implement the abstract class
// CustomMappingFactory, and needs to have attribute
// CustomMappingFactoryAttribute with argument equal to the contractName
// used to define the CustomMapping estimator which uses the action.
[CustomMappingFactoryAttribute("IsUnderThirty")]
private class IsUnderThirtyCustomAction : CustomMappingFactory<InputData,
CustomMappingOutput>
{
// We define the custom mapping between input and output rows that will
// be applied by the transformation.
public static void CustomAction(InputData input, CustomMappingOutput
output) => output.IsUnderThirty = input.Age < 30;
public override Action<InputData, CustomMappingOutput> GetMapping()
=> CustomAction;
}
// Defines only the column to be generated by the custom mapping
// transformation in addition to the columns already present.
private class CustomMappingOutput
{
public bool IsUnderThirty { get; set; }
}
// Defines the schema of the input data.
private class InputData
{
public float Age { get; set; }
}
// Defines the schema of the transformed data, which includes the new column
// IsUnderThirty.
private class TransformedData : InputData
{
public bool IsUnderThirty { get; set; }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML;
using Microsoft.ML.Data;
namespace Samples.Dynamic
{
class CustomMappingWithInMemoryCustomType
{
// This example shows how custom mapping actions can be performed on custom data
// types that ML.NET doesn't know yet. The example tells a story of how two alien
// bodies are merged to form a super alien with a single body.
//
// Here, the type AlienHero represents a single alien entity with a member "Name"
// of type string and members "One" and "Two" of type AlienBody. It defines a custom
// mapping action AlienFusionProcess that takes an AlienHero and "fuses" its two
// AlienBody members to produce a SuperAlienHero entity with a "Name" member of type
// string and a single "Merged" member of type AlienBody, where the merger is just
// the addition of the various members of AlienBody.
public static void Example()
{
var mlContext = new MLContext();
// Build in-memory data.
var tribe = new List<AlienHero>() { new AlienHero("ML.NET", 2, 1000,
2000, 3000, 4000, 5000, 6000, 7000) };
// Build a ML.NET pipeline and make prediction.
var tribeDataView = mlContext.Data.LoadFromEnumerable(tribe);
var pipeline = mlContext.Transforms.CustomMapping(AlienFusionProcess
.GetMapping(), contractName: null);
var model = pipeline.Fit(tribeDataView);
var tribeTransformed = model.Transform(tribeDataView);
// Print out prediction produced by the model.
var firstAlien = mlContext.Data.CreateEnumerable<SuperAlienHero>(
tribeTransformed, false).First();
Console.WriteLine("We got a super alien with name " + firstAlien.Name +
", age " + firstAlien.Merged.Age + ", " + "height " + firstAlien
.Merged.Height + ", weight " + firstAlien.Merged.Weight + ", and "
+ firstAlien.Merged.HandCount + " hands.");
// Expected output:
// We got a super alien with name Super ML.NET, age 4002, height 6000, weight 8000, and 10000 hands.
// Create a prediction engine and print out its prediction.
var engine = mlContext.Model.CreatePredictionEngine<AlienHero,
SuperAlienHero>(model);
var alien = new AlienHero("TEN.LM", 1, 2, 3, 4, 5, 6, 7, 8);
var superAlien = engine.Predict(alien);
Console.Write("We got a super alien with name " + superAlien.Name +
", age " + superAlien.Merged.Age + ", height " +
superAlien.Merged.Height + ", weight " + superAlien.Merged.Weight +
", and " + superAlien.Merged.HandCount + " hands.");
// Expected output:
// We got a super alien with name Super TEN.LM, age 6, height 8, weight 10, and 12 hands.
}
// A custom type which ML.NET doesn't know yet. Its value will be loaded as
// a DataView column in this example.
//
// The type members represent the characteristics of an alien body that will
// be merged in the AlienFusionProcess.
private class AlienBody
{
public int Age { get; set; }
public float Height { get; set; }
public float Weight { get; set; }
public int HandCount { get; set; }
public AlienBody(int age, float height, float weight, int handCount)
{
Age = age;
Height = height;
Weight = weight;
HandCount = handCount;
}
}
// DataViewTypeAttribute applied to class AlienBody members. This attribute
// defines how class AlienBody is registered in ML.NET's type system. In this
// case, AlienBody is registered as DataViewAlienBodyType in ML.NET. The RaceId
// property allows different members of type AlienBody to be registered with
// different types in ML.NEt (see usage in class AlienHero).
private sealed class AlienTypeAttributeAttribute : DataViewTypeAttribute
{
public int RaceId { get; }
// Create an DataViewTypeAttribute> from raceId to a AlienBody.
public AlienTypeAttributeAttribute(int raceId)
{
RaceId = raceId;
}
// A function implicitly invoked by ML.NET when processing a custom
// type. It binds a DataViewType to a custom type plus its attributes.
public override void Register()
{
DataViewTypeManager.Register(new DataViewAlienBodyType(RaceId),
typeof(AlienBody), this);
}
public override bool Equals(DataViewTypeAttribute other)
{
if (other is AlienTypeAttributeAttribute alienTypeAttributeAttribute)
return RaceId == alienTypeAttributeAttribute.RaceId;
return false;
}
public override int GetHashCode() => RaceId.GetHashCode();
}
// A custom class with a type which ML.NET doesn't know yet. Its value will
// be loaded as a DataView row in this example. It will be the input of
// AlienFusionProcess.MergeBody(AlienHero, SuperAlienHero).
//
// The members One and Two would be mapped to different types inside
// ML.NET type system because they have different
// AlienTypeAttributeAttribute's. For example, the column type of One would
// be DataViewAlienBodyType with RaceId=100.
//
// This type represents a "Hero" Alien that is a single entity with two bodies.
// The "Hero" undergoes a fusion process defined in AlienFusionProcess to
// become a SuperAlienHero with a single body that is a merger of the two
// bodies.
private class AlienHero
{
public string Name { get; set; }
[AlienTypeAttribute(100)]
public AlienBody One { get; set; }
[AlienTypeAttribute(200)]
public AlienBody Two { get; set; }
public AlienHero()
{
Name = "Unknown";
One = new AlienBody(0, 0, 0, 0);
Two = new AlienBody(0, 0, 0, 0);
}
public AlienHero(string name,
int age, float height, float weight, int handCount,
int anotherAge, float anotherHeight, float anotherWeight, int
anotherHandCount)
{
Name = name;
One = new AlienBody(age, height, weight, handCount);
Two = new AlienBody(anotherAge, anotherHeight, anotherWeight,
anotherHandCount);
}
}
// Type of AlienBody in ML.NET's type system. This is the data view type that
// will represent AlienBody in ML.NET's type system when it is registered as
// such in AlienTypeAttributeAttribute.
// It usually shows up as DataViewSchema.Column.Type among IDataView.Schema.
private class DataViewAlienBodyType : StructuredDataViewType
{
public int RaceId { get; }
public DataViewAlienBodyType(int id) : base(typeof(AlienBody))
{
RaceId = id;
}
public override bool Equals(DataViewType other)
{
if (other is DataViewAlienBodyType otherAlien)
return otherAlien.RaceId == RaceId;
return false;
}
public override int GetHashCode()
{
return RaceId.GetHashCode();
}
}
// The output type of processing AlienHero using AlienFusionProcess
// .MergeBody(AlienHero, SuperAlienHero).
// This is a "fused" alien whose body is a merger of the two bodies
// of AlienHero.
private class SuperAlienHero
{
public string Name { get; set; }
[AlienTypeAttribute(007)]
public AlienBody Merged { get; set; }
public SuperAlienHero()
{
Name = "Unknown";
Merged = new AlienBody(0, 0, 0, 0);
}
}
// The implementation of custom mapping is MergeBody. It accepts AlienHero
// and produces SuperAlienHero.
private class AlienFusionProcess
{
public static void MergeBody(AlienHero input, SuperAlienHero output)
{
output.Name = "Super " + input.Name;
output.Merged.Age = input.One.Age + input.Two.Age;
output.Merged.Height = input.One.Height + input.Two.Height;
output.Merged.Weight = input.One.Weight + input.Two.Weight;
output.Merged.HandCount = input.One.HandCount + input.Two.HandCount;
}
public static Action<AlienHero, SuperAlienHero> GetMapping()
{
return MergeBody;
}
}
}
}