public SchemaShape GetOutputSchema(SchemaShape inputSchema) { _host.CheckValue(inputSchema, nameof(inputSchema)); var result = inputSchema.Columns.ToDictionary(x => x.Name); foreach (var colInfo in _columns) { var col = inputSchema.FindColumn(colInfo.Input); if (col == null) { throw _host.ExceptSchemaMismatch(nameof(inputSchema), "input", colInfo.Input); } if ((col.ItemType.ItemType.RawKind == default) || !(col.ItemType.IsVector || col.ItemType.IsPrimitive)) { throw _host.ExceptSchemaMismatch(nameof(inputSchema), "input", colInfo.Input); } string[] metadata; if (col.MetadataKinds.Contains(MetadataUtils.Kinds.SlotNames)) { metadata = new[] { MetadataUtils.Kinds.SlotNames, MetadataUtils.Kinds.KeyValues } } ; else { metadata = new[] { MetadataUtils.Kinds.KeyValues } }; result[colInfo.Output] = new SchemaShape.Column(colInfo.Output, col.Kind, NumberType.U4, true, metadata); } return(new SchemaShape(result.Values)); } }
private void CheckInputSchema(SchemaShape inputSchema) { // Verify that all required input columns are present, and are of the same type. var featureCol = inputSchema.FindColumn(FeatureColumn.Name); if (featureCol == null) { throw Host.Except($"Feature column '{FeatureColumn.Name}' is not found"); } if (!FeatureColumn.IsCompatibleWith(featureCol)) { throw Host.Except($"Feature column '{FeatureColumn.Name}' is not compatible"); } if (WeightColumn != null) { var weightCol = inputSchema.FindColumn(WeightColumn.Name); if (weightCol == null) { throw Host.Except($"Weight column '{WeightColumn.Name}' is not found"); } if (!WeightColumn.IsCompatibleWith(weightCol)) { throw Host.Except($"Weight column '{WeightColumn.Name}' is not compatible"); } } // Special treatment for label column: we allow different types of labels, so the trainers // may define their own requirements on the label column. if (LabelColumn != null) { var labelCol = inputSchema.FindColumn(LabelColumn.Name); if (labelCol == null) { throw Host.Except($"Label column '{LabelColumn.Name}' is not found"); } CheckLabelCompatible(labelCol); } }
/// <summary> /// Checks whether this object is consistent with an actual schema shape from a dynamic object, /// throwing exceptions if not. /// </summary> /// <param name="ectx">The context on which to throw exceptions</param> /// <param name="shape">The schema shape to check</param> public void Check(IExceptionContext ectx, SchemaShape shape) { Contracts.AssertValue(ectx); ectx.AssertValue(shape); foreach (var pair in Pairs) { var col = shape.FindColumn(pair.Key); if (col == null) { throw ectx.ExceptParam(nameof(shape), $"Column named '{pair.Key}' was not found"); } var type = GetTypeOrNull(col); if ((type != null && !pair.Value.IsAssignableFromStaticPipeline(type)) || (type == null && IsStandard(ectx, pair.Value))) { // When not null, we can use IsAssignableFrom to indicate we could assign to this, so as to allow // for example Key<uint, string> to be considered to be compatible with Key<uint>. // In the null case, while we cannot directly verify an unrecognized type, we can at least verify // that the statically declared type should not have corresponded to a recognized type. if (!pair.Value.IsAssignableFromStaticPipeline(type)) { // This is generally an error, unless it's the situation where the asserted type is Key<,> but we could // only resolve it so far as Key<>, since for the moment the SchemaShape cannot determine the type of key // value metadata. In which case, we can check if the declared type is a subtype of the key that was determined // from the analysis. if (pair.Value.IsGenericType && pair.Value.GetGenericTypeDefinition() == typeof(Key <,>) && type.IsAssignableFromStaticPipeline(pair.Value)) { continue; } throw ectx.ExceptParam(nameof(shape), $"Column '{pair.Key}' of type '{col.GetTypeString()}' cannot be expressed statically as type '{pair.Value}'."); } } } }