public void ValueToKeyFromSideData() { // In this case, whatever the value of the input, the term mapping should come from the optional side data if specified. var data = new[] { new TestStringClass() { A = "Stay" }, new TestStringClass() { A = "awhile and listen" } }; var mlContext = new MLContext(); var dataView = mlContext.Data.LoadFromEnumerable(data); var sideDataBuilder = new ArrayDataViewBuilder(mlContext); sideDataBuilder.AddColumn("Hello", "hello", "my", "friend"); var sideData = sideDataBuilder.GetDataView(); // For some reason the column info is on the *transformer*, not the estimator. Already tracked as issue #1760. var ci = new ValueToKeyMappingEstimator.ColumnOptions("CatA", "A"); var pipe = mlContext.Transforms.Conversion.MapValueToKey(new[] { ci }, sideData); var output = pipe.Fit(dataView).Transform(dataView); VBuffer <ReadOnlyMemory <char> > slotNames = default; output.Schema["CatA"].Annotations.GetValue(AnnotationUtils.Kinds.KeyValues, ref slotNames); Assert.Equal(3, slotNames.Length); Assert.Equal("hello", slotNames.GetItemOrDefault(0).ToString()); Assert.Equal("my", slotNames.GetItemOrDefault(1).ToString()); Assert.Equal("friend", slotNames.GetItemOrDefault(2).ToString()); Done(); }
internal static IEstimator <ITransformer> CreateEstimator(IHostEnvironment env, Options options, SchemaShape inputSchema, TermLoaderArguments termLoaderArgs = null) { Contracts.CheckValue(env, nameof(env)); var h = env.Register(LoaderSignature); h.CheckValue(options, nameof(options)); h.CheckUserArg(Utils.Size(options.Columns) > 0, nameof(options.Columns), "Columns must be specified"); var chain = new EstimatorChain <ITransformer>(); var termCols = new List <Column>(); var isTermCol = new bool[options.Columns.Length]; for (int i = 0; i < options.Columns.Length; i++) { var col = options.Columns[i]; h.CheckNonWhiteSpace(col.Name, nameof(col.Name)); h.CheckNonWhiteSpace(col.Source, nameof(col.Source)); if (inputSchema.TryFindColumn(col.Source, out var colShape) && colShape.ItemType is TextDataViewType) { termCols.Add(col); isTermCol[i] = true; } } // If the column types of args.column are text, apply term transform to convert them to keys. // Otherwise, skip term transform and apply n-gram transform directly. // This logic allows NgramExtractorTransform to handle both text and key input columns. // Note: n-gram transform handles the validation of the types natively (in case the types // of args.column are not text nor keys). if (termCols.Count > 0) { var columnOptions = new List <ValueToKeyMappingEstimator.ColumnOptionsBase>(); string[] missingDropColumns = termLoaderArgs != null && termLoaderArgs.DropUnknowns ? new string[termCols.Count] : null; for (int iinfo = 0; iinfo < termCols.Count; iinfo++) { var column = termCols[iinfo]; var colOptions = new ValueToKeyMappingEstimator.ColumnOptions( column.Name, column.Source, maximumNumberOfKeys: Utils.Size(column.MaxNumTerms) > 0 ? column.MaxNumTerms[0] : Utils.Size(options.MaxNumTerms) > 0 ? options.MaxNumTerms[0] : termLoaderArgs == null ? NgramExtractingEstimator.Defaults.MaximumNgramsCount : int.MaxValue, keyOrdinality: termLoaderArgs?.Sort ?? ValueToKeyMappingEstimator.KeyOrdinality.ByOccurrence); if (termLoaderArgs != null) { colOptions.Key = termLoaderArgs.Term; colOptions.Keys = termLoaderArgs.Terms; } columnOptions.Add(colOptions); if (missingDropColumns != null) { missingDropColumns[iinfo] = column.Name; } } IDataView keyData = null; if (termLoaderArgs?.DataFile != null) { using (var ch = env.Start("Create key data view")) keyData = ValueToKeyMappingTransformer.GetKeyDataViewOrNull(env, ch, termLoaderArgs.DataFile, termLoaderArgs.TermsColumn, termLoaderArgs.Loader, out var autoConvert); } chain = chain.Append <ITransformer>(new ValueToKeyMappingEstimator(h, columnOptions.ToArray(), keyData)); if (missingDropColumns != null) { chain = chain.Append <ITransformer>(new MissingValueDroppingEstimator(h, missingDropColumns.Select(x => (x, x)).ToArray())); } } var ngramColumns = new NgramExtractingEstimator.ColumnOptions[options.Columns.Length]; for (int iinfo = 0; iinfo < options.Columns.Length; iinfo++) { var column = options.Columns[iinfo]; ngramColumns[iinfo] = new NgramExtractingEstimator.ColumnOptions(column.Name, column.NgramLength ?? options.NgramLength, column.SkipLength ?? options.SkipLength, column.UseAllLengths ?? options.UseAllLengths, column.Weighting ?? options.Weighting, column.MaxNumTerms ?? options.MaxNumTerms, isTermCol[iinfo] ? column.Name : column.Source ); } return(chain.Append <ITransformer>(new NgramExtractingEstimator(env, ngramColumns))); }