private void AddMetadata(int iinfo, DataViewSchema.Annotations.Builder builder) { builder.Add(InputSchema[_parent.ColumnPairs[iinfo].inputColumnName].Annotations, name => name == AnnotationUtils.Kinds.SlotNames); ValueGetter <VBuffer <ReadOnlyMemory <char> > > getter = (ref VBuffer <ReadOnlyMemory <char> > dst) => { GetKeyValues(iinfo, ref dst); }; builder.AddKeyValues(CharsCount, TextDataViewType.Instance, getter); }
protected override DataViewSchema.DetachedColumn[] GetOutputColumnsCore() { var result = new DataViewSchema.DetachedColumn[_parent.ColumnPairs.Length]; for (int i = 0; i < _parent.ColumnPairs.Length; i++) { var builder = new DataViewSchema.Annotations.Builder(); AddMetadata(i, builder); result[i] = new DataViewSchema.DetachedColumn(_parent.ColumnPairs[i].outputColumnName, _type, builder.ToAnnotations()); } return(result); }
protected override DataViewSchema.DetachedColumn[] GetOutputColumnsCore() { var result = new DataViewSchema.DetachedColumn[_parent.ColumnPairs.Length]; for (int i = 0; i < _parent.ColumnPairs.Length; i++) { var builder = new DataViewSchema.Annotations.Builder(); builder.Add(InputSchema[ColMapNewToOld[i]].Annotations, x => x == AnnotationUtils.Kinds.KeyValues || x == AnnotationUtils.Kinds.IsNormalized); result[i] = new DataViewSchema.DetachedColumn(_parent.ColumnPairs[i].outputColumnName, _types[i], builder.ToAnnotations()); } return(result); }
protected override DataViewSchema.DetachedColumn[] GetOutputColumnsCore() { var result = new DataViewSchema.DetachedColumn[_parent.ColumnPairs.Length]; for (int i = 0; i < _parent.ColumnPairs.Length; i++) { var meta = new DataViewSchema.Annotations.Builder(); meta.Add(InputSchema[ColMapNewToOld[i]].Annotations, name => name == AnnotationUtils.Kinds.SlotNames); result[i] = new DataViewSchema.DetachedColumn(_parent.ColumnPairs[i].outputColumnName, _types[i], meta.ToAnnotations()); } return(result); }
public UngroupBinding(IExceptionContext ectx, DataViewSchema inputSchema, UngroupMode mode, string[] pivotColumns) { Contracts.AssertValueOrNull(ectx); _ectx = ectx; _ectx.AssertValue(inputSchema); _ectx.AssertNonEmpty(pivotColumns); _inputSchema = inputSchema; // This also makes InputColumnCount valid. Mode = mode; Bind(_ectx, inputSchema, pivotColumns, out _infos); _pivotIndex = Utils.CreateArray(InputColumnCount, -1); for (int i = 0; i < _infos.Length; i++) { var info = _infos[i]; _ectx.Assert(_pivotIndex[info.Index] == -1); _pivotIndex[info.Index] = i; } var schemaBuilder = new DataViewSchema.Builder(); // Iterate through input columns. Input columns which are not pivot columns will be copied to output schema with the same column index unchanged. // Input columns which are pivot columns would also be copied but with different data types and different metadata. for (int i = 0; i < InputColumnCount; ++i) { if (_pivotIndex[i] < 0) { // i-th input column is not a pivot column. Let's do a naive copy. schemaBuilder.AddColumn(inputSchema[i].Name, inputSchema[i].Type, inputSchema[i].Annotations); } else { // i-th input column is a pivot column. Let's calculate proper type and metadata for it. var metadataBuilder = new DataViewSchema.Annotations.Builder(); metadataBuilder.Add(inputSchema[i].Annotations, metadataName => ShouldPreserveMetadata(metadataName)); // To explain the output type of pivot columns, let's consider a row // Age UserID // 18 {"Amy", "Willy"} // where "Age" and "UserID" are column names and 18/{"Amy", "Willy"} is "Age"/"UserID" column in this example row. // If the only pivot column is "UserID", the ungroup may produce // Age UserID // 18 "Amy" // 18 "Willy" // One can see that "UserID" column (in output data) has a type identical to the element's type of the "UserID" column in input data. schemaBuilder.AddColumn(inputSchema[i].Name, inputSchema[i].Type.GetItemType(), metadataBuilder.ToAnnotations()); } } OutputSchema = schemaBuilder.ToSchema(); }
public RowMapper(IHostEnvironment env, BindableMapper parent, RoleMappedSchema schema) { Contracts.AssertValue(env); _env = env; _env.AssertValue(schema); _env.AssertValue(parent); _env.Assert(schema.Feature.HasValue); _parent = parent; InputRoleMappedSchema = schema; var genericMapper = parent.GenericMapper.Bind(_env, schema); _genericRowMapper = genericMapper as ISchemaBoundRowMapper; var featureSize = FeatureColumn.Type.GetVectorSize(); if (parent.Stringify) { var builder = new DataViewSchema.Builder(); builder.AddColumn(DefaultColumnNames.FeatureContributions, TextDataViewType.Instance, null); _outputSchema = builder.ToSchema(); if (FeatureColumn.HasSlotNames(featureSize)) { FeatureColumn.Annotations.GetValue(AnnotationUtils.Kinds.SlotNames, ref _slotNames); } else { _slotNames = VBufferUtils.CreateEmpty <ReadOnlyMemory <char> >(featureSize); } } else { var metadataBuilder = new DataViewSchema.Annotations.Builder(); if (InputSchema[FeatureColumn.Index].HasSlotNames(featureSize)) { metadataBuilder.AddSlotNames(featureSize, (ref VBuffer <ReadOnlyMemory <char> > value) => FeatureColumn.Annotations.GetValue(AnnotationUtils.Kinds.SlotNames, ref value)); } var schemaBuilder = new DataViewSchema.Builder(); var featureContributionType = new VectorType(NumberDataViewType.Single, FeatureColumn.Type as VectorType); schemaBuilder.AddColumn(DefaultColumnNames.FeatureContributions, featureContributionType, metadataBuilder.ToAnnotations()); _outputSchema = schemaBuilder.ToSchema(); } _outputGenericSchema = _genericRowMapper.OutputSchema; OutputSchema = new ZipBinding(new DataViewSchema[] { _outputGenericSchema, _outputSchema, }).OutputSchema; }
public FeatureNameCollectionBinding(FeatureNameCollection collection) { Contracts.CheckValue(collection, nameof(collection)); _collection = collection; _colType = new VectorType(NumberDataViewType.Single, collection.Count); _slotNamesType = new VectorType(TextDataViewType.Instance, collection.Count); var metadataBuilder = new DataViewSchema.Annotations.Builder(); metadataBuilder.Add(AnnotationUtils.Kinds.SlotNames, _slotNamesType, (ref VBuffer <ReadOnlyMemory <char> > slotNames) => { GetSlotNames(0, ref slotNames); }); var schemaBuilder = new DataViewSchema.Builder(); schemaBuilder.AddColumn(RoleMappedSchema.ColumnRole.Feature.Value, _colType, metadataBuilder.ToAnnotations()); FeatureNameCollectionSchema = schemaBuilder.ToSchema(); }
protected override DataViewSchema.DetachedColumn[] GetOutputColumnsCore() { var stdSuffix = ".output"; var info = new DataViewSchema.DetachedColumn[_parent.Outputs.Length]; for (int i = 0; i < _parent.Outputs.Length; i++) { var onnxOutputName = _parent.Outputs[i]; var columnName = onnxOutputName.EndsWith(stdSuffix) ? onnxOutputName.Replace(stdSuffix, "") : onnxOutputName; var builder = new DataViewSchema.Annotations.Builder(); AddSlotNames(columnName, builder); info[i] = new DataViewSchema.DetachedColumn(columnName, _parent.OutputTypes[i], builder.ToAnnotations()); } return(info); }
/// <summary> /// Manufacture an instance of <see cref="DataViewSchema"/> out of any <see cref="ISchema"/>. /// </summary> public static DataViewSchema Create(ISchema inputSchema) { Contracts.CheckValue(inputSchema, nameof(inputSchema)); var builder = new DataViewSchema.Builder(); for (int i = 0; i < inputSchema.ColumnCount; i++) { var meta = new DataViewSchema.Annotations.Builder(); foreach (var kvp in inputSchema.GetMetadataTypes(i)) { var getter = Utils.MarshalInvoke(GetMetadataGetterDelegate <int>, kvp.Value.RawType, inputSchema, i, kvp.Key); meta.Add(kvp.Key, kvp.Value, getter); } builder.AddColumn(inputSchema.GetColumnName(i), inputSchema.GetColumnType(i), meta.ToAnnotations()); } return(builder.ToSchema()); }
private static DataViewSchema CreateSchema(ColumnBindingsBase inputBindings) { Contracts.CheckValue(inputBindings, nameof(inputBindings)); var builder = new DataViewSchema.Builder(); for (int i = 0; i < inputBindings.ColumnCount; i++) { var meta = new DataViewSchema.Annotations.Builder(); foreach (var kvp in inputBindings.GetAnnotationTypes(i)) { var getter = Utils.MarshalInvoke(GetAnnotationGetterDelegate <int>, kvp.Value.RawType, inputBindings, i, kvp.Key); meta.Add(kvp.Key, kvp.Value, getter); } builder.AddColumn(inputBindings.GetColumnName(i), inputBindings.GetColumnType(i), meta.ToAnnotations()); } return(builder.ToSchema()); }
/// <summary> /// Return a <see cref="DataViewSchema"/> which contains a single score column. /// </summary> /// <param name="scoreType">The type of the score column.</param> /// <param name="scoreColumnKindValue">The kind of the score column. It's the value of <see cref="AnnotationUtils.Kinds.ScoreColumnKind"/> in the score column's metadata.</param> /// <param name="scoreColumnName">The score column's name in the generated <see cref="DataViewSchema"/>.</param> /// <returns><see cref="DataViewSchema"/> which contains only one column.</returns> public static DataViewSchema Create(DataViewType scoreType, string scoreColumnKindValue, string scoreColumnName = AnnotationUtils.Const.ScoreValueKind.Score) { Contracts.CheckValue(scoreType, nameof(scoreType)); Contracts.CheckNonEmpty(scoreColumnKindValue, nameof(scoreColumnKindValue)); // Two metadata fields. One can set up by caller of this function while the other one is a constant. var metadataBuilder = new DataViewSchema.Annotations.Builder(); metadataBuilder.Add(AnnotationUtils.Kinds.ScoreColumnKind, TextDataViewType.Instance, (ref ReadOnlyMemory <char> value) => { value = scoreColumnKindValue.AsMemory(); }); metadataBuilder.Add(AnnotationUtils.Kinds.ScoreValueKind, TextDataViewType.Instance, (ref ReadOnlyMemory <char> value) => { value = AnnotationUtils.Const.ScoreValueKind.Score.AsMemory(); }); // Build a schema consisting of a single column. var schemaBuilder = new DataViewSchema.Builder(); schemaBuilder.AddColumn(scoreColumnName, scoreType, metadataBuilder.ToAnnotations()); return(schemaBuilder.ToSchema()); }
private protected override DataViewSchema.DetachedColumn[] GetOutputColumnsCore() { var infos = new DataViewSchema.DetachedColumn[3]; infos[ClusterIdCol] = new DataViewSchema.DetachedColumn(ClusterId, _types[ClusterIdCol], null); var slotNamesType = new VectorType(TextDataViewType.Instance, _numClusters); var sortedClusters = new DataViewSchema.Annotations.Builder(); int vectorSize = slotNamesType.GetVectorSize(); sortedClusters.AddSlotNames(vectorSize, CreateSlotNamesGetter(_numClusters, "Cluster")); var builder = new DataViewSchema.Annotations.Builder(); builder.AddSlotNames(vectorSize, CreateSlotNamesGetter(_numClusters, "Score")); infos[SortedClusterCol] = new DataViewSchema.DetachedColumn(SortedClusters, _types[SortedClusterCol], sortedClusters.ToAnnotations()); infos[SortedClusterScoreCol] = new DataViewSchema.DetachedColumn(SortedClusterScores, _types[SortedClusterScoreCol], builder.ToAnnotations()); return(infos); }
void SimpleTest() { var metadataBuilder = new DataViewSchema.Annotations.Builder(); metadataBuilder.Add("M", NumberDataViewType.Single, (ref float v) => v = 484f); var schemaBuilder = new DataViewSchema.Builder(); schemaBuilder.AddColumn("A", new VectorDataViewType(NumberDataViewType.Single, 94)); schemaBuilder.AddColumn("B", new KeyDataViewType(typeof(uint), 17)); schemaBuilder.AddColumn("C", NumberDataViewType.Int32, metadataBuilder.ToAnnotations()); var shape = SchemaShape.Create(schemaBuilder.ToSchema()); var fakeSchema = FakeSchemaFactory.Create(shape); var columnA = fakeSchema[0]; var columnB = fakeSchema[1]; var columnC = fakeSchema[2]; Assert.Equal("A", columnA.Name); Assert.Equal(NumberDataViewType.Single, columnA.Type.GetItemType()); Assert.Equal(10, columnA.Type.GetValueCount()); Assert.Equal("B", columnB.Name); Assert.Equal(InternalDataKind.U4, columnB.Type.GetRawKind()); Assert.Equal(10u, columnB.Type.GetKeyCount()); Assert.Equal("C", columnC.Name); Assert.Equal(NumberDataViewType.Int32, columnC.Type); var metaC = columnC.Annotations; Assert.Single(metaC.Schema); float mValue = -1; metaC.GetValue("M", ref mValue); Assert.Equal(default, mValue);
public BoundMapper(IExceptionContext ectx, TreeEnsembleFeaturizerBindableMapper owner, RoleMappedSchema schema, string treesColumnName, string leavesColumnName, string pathsColumnName) { Contracts.AssertValue(ectx); ectx.AssertValue(owner); ectx.AssertValue(schema); ectx.Assert(schema.Feature.HasValue); _ectx = ectx; _owner = owner; InputRoleMappedSchema = schema; // A vector containing the output of each tree on a given example. var treeValueType = new VectorDataViewType(NumberDataViewType.Single, owner._ensemble.TrainedEnsemble.NumTrees); // An indicator vector with length = the total number of leaves in the ensemble, indicating which leaf the example // ends up in all the trees in the ensemble. var leafIdType = new VectorDataViewType(NumberDataViewType.Single, owner._totalLeafCount); // An indicator vector with length = the total number of nodes in the ensemble, indicating the nodes on // the paths of the example in all the trees in the ensemble. // The total number of nodes in a binary tree is equal to the number of internal nodes + the number of leaf nodes, // and it is also equal to the number of children of internal nodes (which is 2 * the number of internal nodes) // plus one (since the root node is not a child of any node). So we have #internal + #leaf = 2*(#internal) + 1, // which means that #internal = #leaf - 1. // Therefore, the number of internal nodes in the ensemble is #leaf - #trees. var pathIdType = new VectorDataViewType(NumberDataViewType.Single, owner._totalLeafCount - owner._ensemble.TrainedEnsemble.NumTrees); // Start creating output schema with types derived above. var schemaBuilder = new DataViewSchema.Builder(); _treesColumnName = treesColumnName; if (treesColumnName != null) { // Metadata of tree values. var treeIdMetadataBuilder = new DataViewSchema.Annotations.Builder(); treeIdMetadataBuilder.Add(AnnotationUtils.Kinds.SlotNames, AnnotationUtils.GetNamesType(treeValueType.Size), (ValueGetter <VBuffer <ReadOnlyMemory <char> > >)owner.GetTreeSlotNames); // Add the column of trees' output values schemaBuilder.AddColumn(treesColumnName, treeValueType, treeIdMetadataBuilder.ToAnnotations()); } _leavesColumnName = leavesColumnName; if (leavesColumnName != null) { // Metadata of leaf IDs. var leafIdMetadataBuilder = new DataViewSchema.Annotations.Builder(); leafIdMetadataBuilder.Add(AnnotationUtils.Kinds.SlotNames, AnnotationUtils.GetNamesType(leafIdType.Size), (ValueGetter <VBuffer <ReadOnlyMemory <char> > >)owner.GetLeafSlotNames); leafIdMetadataBuilder.Add(AnnotationUtils.Kinds.IsNormalized, BooleanDataViewType.Instance, (ref bool value) => value = true); // Add the column of leaves' IDs where the input example reaches. schemaBuilder.AddColumn(leavesColumnName, leafIdType, leafIdMetadataBuilder.ToAnnotations()); } _pathsColumnName = pathsColumnName; if (pathsColumnName != null) { // Metadata of path IDs. var pathIdMetadataBuilder = new DataViewSchema.Annotations.Builder(); pathIdMetadataBuilder.Add(AnnotationUtils.Kinds.SlotNames, AnnotationUtils.GetNamesType(pathIdType.Size), (ValueGetter <VBuffer <ReadOnlyMemory <char> > >)owner.GetPathSlotNames); pathIdMetadataBuilder.Add(AnnotationUtils.Kinds.IsNormalized, BooleanDataViewType.Instance, (ref bool value) => value = true); // Add the column of encoded paths which the input example passes. schemaBuilder.AddColumn(pathsColumnName, pathIdType, pathIdMetadataBuilder.ToAnnotations()); } OutputSchema = schemaBuilder.ToSchema(); }
internal static DataViewSchema GetModelSchema(IExceptionContext ectx, Graph graph, string opType = null) { var schemaBuilder = new DataViewSchema.Builder(); foreach (Operation op in graph) { if (opType != null && opType != op.OpType) { continue; } var tfType = op.OutputType(0); // Determine element type in Tensorflow tensor. For example, a vector of floats may get NumberType.R4 here. var mlType = Tf2MlNetTypeOrNull(tfType); // If the type is not supported in ML.NET then we cannot represent it as a column in an Schema. // We also cannot output it with a TensorFlowTransform, so we skip it. // Furthermore, operators which have NumOutputs <= 0 needs to be filtered. // The 'GetTensorShape' method crashes TensorFlow runtime // (https://github.com/dotnet/machinelearning/issues/2156) when the operator has no outputs. if (mlType == null || op.NumOutputs <= 0) { continue; } // Construct the final ML.NET type of a Tensorflow variable. var tensorShape = op.output.TensorShape.dims; var columnType = new VectorDataViewType(mlType); if (!(Utils.Size(tensorShape) == 1 && tensorShape[0] <= 0) && (Utils.Size(tensorShape) > 0 && tensorShape.Skip(1).All(x => x > 0))) { columnType = new VectorDataViewType(mlType, tensorShape[0] > 0 ? tensorShape : tensorShape.Skip(1).ToArray()); } // There can be at most two metadata fields. // 1. The first field always presents. Its value is this operator's type. For example, // if an output is produced by an "Softmax" operator, the value of this field should be "Softmax". // 2. The second field stores operators whose outputs are consumed by this operator. In other words, // these values are names of some upstream operators which should be evaluated before executing // the current operator. It's possible that one operator doesn't need any input, so this field // can be missing. var metadataBuilder = new DataViewSchema.Annotations.Builder(); // Create the first metadata field. metadataBuilder.Add(TensorflowOperatorTypeKind, TextDataViewType.Instance, (ref ReadOnlyMemory <char> value) => value = op.OpType.AsMemory()); if (op.NumInputs > 0) { // Put upstream operators' names to an array (type: VBuffer) of string (type: ReadOnlyMemory<char>). VBuffer <ReadOnlyMemory <char> > upstreamOperatorNames = default; var bufferEditor = VBufferEditor.Create(ref upstreamOperatorNames, op.NumInputs); for (int i = 0; i < op.NumInputs; ++i) { bufferEditor.Values[i] = op.inputs[i].op.name.AsMemory(); } upstreamOperatorNames = bufferEditor.Commit(); // Used in metadata's getter. // Create the second metadata field. metadataBuilder.Add(TensorflowUpstreamOperatorsKind, new VectorDataViewType(TextDataViewType.Instance, op.NumInputs), (ref VBuffer <ReadOnlyMemory <char> > value) => { upstreamOperatorNames.CopyTo(ref value); }); } schemaBuilder.AddColumn(op.name, columnType, metadataBuilder.ToAnnotations()); } return(schemaBuilder.ToSchema()); }
private void HashTestCore <T>(T val, PrimitiveDataViewType type, uint expected, uint expectedOrdered, uint expectedOrdered3, uint expectedCombined, uint expectedCombinedSparse) { const int bits = 10; var builder = new DataViewSchema.Annotations.Builder(); builder.AddPrimitiveValue("Foo", type, val); var inRow = AnnotationUtils.AnnotationsAsRow(builder.ToAnnotations()); //helper ValueGetter <TType> hashGetter <TType>(HashingEstimator.ColumnOptions colInfo) { var xf = new HashingTransformer(Env, new[] { colInfo }); var mapper = ((ITransformer)xf).GetRowToRowMapper(inRow.Schema); var col = mapper.OutputSchema["Bar"]; var outRow = mapper.GetRow(inRow, col); return(outRow.GetGetter <TType>(col)); }; // First do an unordered hash. var info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits); var getter = hashGetter <uint>(info); uint result = 0; getter(ref result); Assert.Equal(expected, result); // Next do an ordered hash. info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits, useOrderedHashing: true); getter = hashGetter <uint>(info); getter(ref result); Assert.Equal(expectedOrdered, result); // Next build up a vector to make sure that hashing is consistent between scalar values // at least in the first position, and in the unordered case, the last position. const int vecLen = 5; var denseVec = new VBuffer <T>(vecLen, Utils.CreateArray(vecLen, val)); builder = new DataViewSchema.Annotations.Builder(); builder.Add("Foo", new VectorDataViewType(type, vecLen), (ref VBuffer <T> dst) => denseVec.CopyTo(ref dst)); inRow = AnnotationUtils.AnnotationsAsRow(builder.ToAnnotations()); info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits, useOrderedHashing: false); var vecGetter = hashGetter <VBuffer <uint> >(info); VBuffer <uint> vecResult = default; vecGetter(ref vecResult); Assert.Equal(vecLen, vecResult.Length); // They all should equal this in this case. Assert.All(vecResult.DenseValues(), v => Assert.Equal(expected, v)); // Now do ordered with the dense vector. info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits, useOrderedHashing: true); vecGetter = hashGetter <VBuffer <uint> >(info); vecGetter(ref vecResult); Assert.Equal(vecLen, vecResult.Length); Assert.Equal(expectedOrdered, vecResult.GetItemOrDefault(0)); Assert.Equal(expectedOrdered3, vecResult.GetItemOrDefault(3)); Assert.All(vecResult.DenseValues(), v => Assert.True((v == 0) == (expectedOrdered == 0))); // Now combine into one hash. info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits, combine: true); getter = hashGetter <uint>(info); getter(ref result); Assert.Equal(expectedCombined, result); // Let's now do a sparse vector. var sparseVec = new VBuffer <T>(10, 3, Utils.CreateArray(3, val), new[] { 0, 3, 7 }); builder = new DataViewSchema.Annotations.Builder(); builder.Add("Foo", new VectorDataViewType(type, vecLen), (ref VBuffer <T> dst) => sparseVec.CopyTo(ref dst)); inRow = AnnotationUtils.AnnotationsAsRow(builder.ToAnnotations()); info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits, useOrderedHashing: false); vecGetter = hashGetter <VBuffer <uint> >(info); vecGetter(ref vecResult); Assert.Equal(10, vecResult.Length); Assert.Equal(expected, vecResult.GetItemOrDefault(0)); Assert.Equal(expected, vecResult.GetItemOrDefault(3)); Assert.Equal(expected, vecResult.GetItemOrDefault(7)); info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits, useOrderedHashing: true); vecGetter = hashGetter <VBuffer <uint> >(info); vecGetter(ref vecResult); Assert.Equal(10, vecResult.Length); Assert.Equal(expectedOrdered, vecResult.GetItemOrDefault(0)); Assert.Equal(expectedOrdered3, vecResult.GetItemOrDefault(3)); info = new HashingEstimator.ColumnOptions("Bar", "Foo", numberOfBits: bits, combine: true); getter = hashGetter <uint>(info); getter(ref result); Assert.Equal(expectedCombinedSparse, result); }
/// <summary> /// Add key values annotation. /// </summary> /// <typeparam name="TValue">The value type of key values.</typeparam> /// <param name="builder">The <see cref="DataViewSchema.Annotations.Builder"/> to which to add the key values.</param> /// <param name="size">The size of key values vector.</param> /// <param name="valueType">The value type of key values. Its raw type must match <typeparamref name="TValue"/>.</param> /// <param name="getter">The getter delegate for the key values.</param> public static void AddKeyValues <TValue>(this DataViewSchema.Annotations.Builder builder, int size, PrimitiveDataViewType valueType, ValueGetter <VBuffer <TValue> > getter) => builder.Add(AnnotationUtils.Kinds.KeyValues, new VectorType(valueType, size), getter);
/// <summary> /// Add slot names annotation. /// </summary> /// <param name="builder">The <see cref="DataViewSchema.Annotations.Builder"/> to which to add the slot names.</param> /// <param name="size">The size of the slot names vector.</param> /// <param name="getter">The getter delegate for the slot names.</param> public static void AddSlotNames(this DataViewSchema.Annotations.Builder builder, int size, ValueGetter <VBuffer <ReadOnlyMemory <char> > > getter) => builder.Add(AnnotationUtils.Kinds.SlotNames, new VectorType(TextDataViewType.Instance, size), getter);