public void TestWiki() { using (var vw = new VW.VowpalWabbit("-f rcv1.model")) { // 1 |f 13:3.9656971e-02 24:3.4781646e-02 69:4.6296168e-02 using (var exampleBuilder = new VW.VowpalWabbitExampleBuilder(vw)) { // important to dispose the namespace builder at the end, as data is only added to the example // if there is any feature added to the namespace using (var ns = exampleBuilder.AddNamespace('f')) { var namespaceHash = vw.HashSpace("f"); var featureHash = vw.HashFeature("13", namespaceHash); ns.AddFeature(featureHash, 8.5609287e-02f); featureHash = vw.HashFeature("24", namespaceHash); ns.AddFeature(featureHash, 3.4781646e-02f); featureHash = vw.HashFeature("69", namespaceHash); ns.AddFeature(featureHash, 4.6296168e-02f); } exampleBuilder.ApplyLabel(new SimpleLabel() { Label = 1 }); // hand over of memory management using (var example = exampleBuilder.CreateExample()) { VowpalWabbitExampleValidator.Validate("1 |f 13:8.5609287e-02 24:3.4781646e-02 69:4.6296168e-02", example, VowpalWabbitLabelComparator.Simple); vw.Learn(example); } } } }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { //if (this.vwAllReduce != null) //{ // this.vwAllReduce.Dispose(); // this.vwAllReduce = null; //} if (this.vw != null) { this.vw.Dispose(); this.vw = null; } if (this.referenceResolver != null) { this.referenceResolver.Dispose(); this.referenceResolver = null; } }
/// <summary> /// Initializes a new instance of the <see cref="VowpalWabbitDynamic"/> class. /// </summary> /// <param name="settings">Arguments passed to native instance.</param> public VowpalWabbitDynamic(VowpalWabbitSettings settings) { this.vw = new VowpalWabbit(settings); }
private async Task <bool> TryLoadModel() { // find the model blob if (string.IsNullOrEmpty(this.state.ModelName)) { this.telemetry.TrackTrace("Model not specified"); return(false); } var container = this.blobClient.GetContainerReference(this.settings.StorageContainerName); if (!await container.ExistsAsync()) { this.telemetry.TrackTrace($"Storage container missing '{this.settings.StorageContainerName}'"); return(false); } var modelBlob = container.GetBlockBlobReference(this.state.ModelName); if (!await modelBlob.ExistsAsync()) { this.telemetry.TrackTrace($"Model blob '{this.state.ModelName}' is missing"); return(false); } // load the model using (var modelStream = await modelBlob.OpenReadAsync()) { this.InitializeVowpalWabbit(new VowpalWabbitSettings { ModelStream = modelStream }); this.telemetry.TrackTrace($"Model loaded {this.state.ModelName}", SeverityLevel.Verbose); // validate that the loaded VW model has the same settings as requested by C&C var newSettings = new VowpalWabbitSettings(this.settings.Metadata.TrainArguments); using (var newVW = new VW.VowpalWabbit(newSettings)) { newVW.ID = this.vw.ID; // save the VW instance to a model and load again to get fully expanded parameters. string newVWarguments; using (var tempModel = new MemoryStream()) { newVW.SaveModel(tempModel); tempModel.Position = 0; using (var tempVW = new VW.VowpalWabbit(new VowpalWabbitSettings { ModelStream = tempModel })) { newVWarguments = CleanVowpalWabbitArguments(tempVW.Arguments.CommandLine); } } var oldVWarguments = CleanVowpalWabbitArguments(this.vw.Arguments.CommandLine); // this is the expanded command line if (newVWarguments != oldVWarguments) { this.telemetry.TrackTrace("New VowpalWabbit settings found. Discarding existing model", SeverityLevel.Information, new Dictionary <string, string> { { "TrainArguments", newVW.Arguments.CommandLine }, { "NewExpandedArguments", newVWarguments }, { "OldExpandedArgumentsCleaned", oldVWarguments }, { "OldExpandedArguments", this.vw.Arguments.CommandLine }, }); // discard old, use fresh this.vw.Dispose(); this.vw = null; this.InitializeVowpalWabbit(newSettings); } } } // store the initial model this.settings.InitialVowpalWabbitModel = this.state.ModelName; return(true); }
/// <summary> /// Simplify prediction of examples with action dependent features. /// </summary> /// <typeparam name="TExample">The type of the user example.</typeparam> /// <typeparam name="TActionDependentFeature">The type of the user action dependent features.</typeparam> /// <param name="vw">The vw instance.</param> /// <param name="serializer">The serializer for <typeparamref name="TExample"/>.</param> /// <param name="actionDependentFeatureSerializer">The serializer for <typeparamref name="TActionDependentFeature"/>.</param> /// <param name="example">The user example.</param> /// <param name="actionDependentFeatures">The action dependent features.</param> /// <returns>An ranked subset of predicted action indexes.</returns> public static int[] PredictIndex <TExample, TActionDependentFeature>( VowpalWabbit vw, VowpalWabbitSerializer <TExample> serializer, VowpalWabbitSerializer <TActionDependentFeature> actionDependentFeatureSerializer, TExample example, IEnumerable <TActionDependentFeature> actionDependentFeatures) { Contract.Requires(vw != null); Contract.Requires(serializer != null); Contract.Requires(actionDependentFeatureSerializer != null); Contract.Requires(example != null); Contract.Requires(actionDependentFeatures != null); // shared |userlda :.1 |che a:.1 // `doc1 |lda :.1 :.2 [1] // `doc2 |lda :.2 :.3 [2] // <new line> var examples = new List <VowpalWabbitExample>(); try { // contains prediction results var sharedExample = serializer.Serialize(vw, example); // check if we have shared features if (sharedExample != null) { examples.Add(sharedExample); vw.Predict(sharedExample); } // leave as loop (vs. linq) so if the serializer throws an exception, anything allocated so far can be free'd foreach (var actionDependentFeature in actionDependentFeatures) { var adfExample = actionDependentFeatureSerializer.Serialize(vw, actionDependentFeature); Contract.Assert(adfExample != null); examples.Add(adfExample); vw.Predict(adfExample); } // signal we're finished using an empty example var empty = vw.GetOrCreateEmptyExample(); examples.Add(empty); vw.Predict(empty); // Nasty workaround. Since the prediction result is stored in the first example // and we'll have to get an actual VowpalWabbitExampt var firstExample = examples.FirstOrDefault(); if (firstExample == null) { return(null); } return(firstExample.GetPrediction(vw, VowpalWabbitPredictionType.Multilabel)); } finally { // dispose examples // Note: must not dispose examples before final example // as the learning algorithm (such as cbf) keeps a reference // to the example foreach (var e in examples) { e.Dispose(); } } }
/// <summary> /// Extracts the prediction, orders the action depdendent feature objects accordingly and appends the /// action dependent feature objcts that did produce empty examples at the end. /// </summary> /// <typeparam name="TActionDependentFeature">The action dependent feature type.</typeparam> /// <param name="vw">The Vowpal Wabbit instance.></param> /// <param name="examples">The list of examples.</param> /// <param name="validActionDependentFeatures">The list of non-empty action dependent feature objects.</param> /// <param name="emptyActionDependentFeatures">The list of empty action dependent feature objects.</param> /// <returns>Returns the ranked list of action dependent features.</returns> public static ActionDependentFeature <TActionDependentFeature>[] GetPrediction <TActionDependentFeature>( VowpalWabbit vw, IReadOnlyList <VowpalWabbitExample> examples, IReadOnlyList <ActionDependentFeature <TActionDependentFeature> > validActionDependentFeatures, IReadOnlyList <ActionDependentFeature <TActionDependentFeature> > emptyActionDependentFeatures) { // Since the prediction result is stored in the first example // and we'll have to get an actual VowpalWabbitExampt var firstExample = examples.FirstOrDefault(); if (firstExample == null) { return(null); } ActionDependentFeature <TActionDependentFeature>[] result; int i = 0; var values = firstExample.GetPrediction(vw, VowpalWabbitPredictionType.Dynamic); var actionScores = values as ActionScore[]; if (actionScores != null) { if (actionScores.Length != validActionDependentFeatures.Count) { throw new InvalidOperationException("Number of predictions returned unequal number of examples fed"); } result = new ActionDependentFeature <TActionDependentFeature> [validActionDependentFeatures.Count + emptyActionDependentFeatures.Count]; foreach (var index in actionScores) { result[i] = validActionDependentFeatures[(int)index.Action]; result[i].Probability = index.Score; i++; } } else { var multilabel = values as int[]; if (multilabel != null) { if (multilabel.Length != validActionDependentFeatures.Count) { throw new InvalidOperationException("Number of predictions returned unequal number of examples fed"); } result = new ActionDependentFeature <TActionDependentFeature> [validActionDependentFeatures.Count + emptyActionDependentFeatures.Count]; foreach (var index in multilabel) { result[i++] = validActionDependentFeatures[index]; } result[0].Probability = 1f; } else { throw new NotSupportedException("Unsupported return type: " + values.GetType()); } } // append invalid ones at the end foreach (var f in emptyActionDependentFeatures) { result[i++] = f; } return(result); }
/// <summary> /// Predicts for these examples and returns the current prediction for it. /// </summary> /// <typeparam name="TPrediction">The prediction type.</typeparam> /// <param name="predictionFactory">The prediction factory to be used. See <see cref="VowpalWabbitPredictionType"/>.</param> /// <param name="vw">The native VW instance.</param> /// <returns>The prediction for the this example.</returns> protected override TPrediction PredictInternal <TPrediction>(IVowpalWabbitPredictionFactory <TPrediction> predictionFactory, VowpalWabbit vw) { return(this.Execute(vw, ex => vw.Predict(ex), predictionFactory)); }
/// <summary> /// Predicts for this example. /// </summary> protected override void PredictInternal(VowpalWabbit vw) { vw.Predict(this.Example); }
/// <summary> /// Predicts for this example. /// </summary> /// <param name="vw">Use this VW instance for prediction instead of the one the example was created from.</param> public void Predict(VowpalWabbit vw = null) { this.PredictInternal(vw ?? this.vw); }
/// <summary> /// Serializes the specifed example to VW native string format. /// </summary> /// <typeparam name="TExample">The user example type.</typeparam> /// <typeparam name="TActionDependentFeature">The user action dependent feature type.</typeparam> /// <param name="vw">The VW instance.</param> /// <param name="example">The shared example.</param> /// <param name="actionDependentFeatures">The action dependent features.</param> /// <param name="index">The optional index of the label example.</param> /// <param name="label">The optional label.</param> /// <param name="serializer">The example serializer.</param> /// <param name="actionDependentFeatureSerializer">The action dependent feature serializer.</param> /// <param name="dictionary">Dictionary used for dictify operation.</param> /// <param name="fastDictionary">Dictionary used for dictify operation.</param> /// <returns>The string serialized example.</returns> public static string SerializeToString <TExample, TActionDependentFeature>( VowpalWabbit vw, TExample example, IReadOnlyCollection <TActionDependentFeature> actionDependentFeatures, int?index = null, ILabel label = null, IVowpalWabbitSerializer <TExample> serializer = null, IVowpalWabbitSerializer <TActionDependentFeature> actionDependentFeatureSerializer = null, Dictionary <string, string> dictionary = null, Dictionary <object, string> fastDictionary = null) { if (vw == null) { throw new ArgumentNullException("vw"); } if (serializer == null) { serializer = VowpalWabbitSerializerFactory.CreateSerializer <TExample>(new VowpalWabbitSettings(enableStringExampleGeneration: true)).Create(vw); } else if (!serializer.EnableStringExampleGeneration) { throw new ArgumentException("Serializer must be compiled using EnableStringExampleGeneration = true"); } if (actionDependentFeatureSerializer == null) { actionDependentFeatureSerializer = VowpalWabbitSerializerFactory.CreateSerializer <TActionDependentFeature>(new VowpalWabbitSettings(enableStringExampleGeneration: true)).Create(vw); } else if (!actionDependentFeatureSerializer.EnableStringExampleGeneration) { throw new ArgumentException("Action dependent serializer must be compiled using EnableStringExampleGeneration = true"); } var stringExample = new StringBuilder(); var sharedExample = serializer.SerializeToString(example, SharedLabel.Instance, null, dictionary, fastDictionary); // check if we have shared features if (!string.IsNullOrWhiteSpace(sharedExample)) { stringExample.AppendLine(sharedExample); } var i = 0; foreach (var actionDependentFeature in actionDependentFeatures) { var adfExample = actionDependentFeatureSerializer.SerializeToString(actionDependentFeature, index != null && i == index ? label : null, null, dictionary, fastDictionary); if (!string.IsNullOrWhiteSpace(adfExample)) { stringExample.AppendLine(adfExample); } i++; } return(stringExample.ToString()); }
/// <summary> /// Initializes a new instance of the <see cref="VowpalWabbitExampleCollection"/> class. /// </summary> /// <param name="vw">The VW native instance.</param> protected VowpalWabbitExampleCollection(VowpalWabbit vw) { Contract.Requires(vw != null); this.vw = vw; }
public void Learn(VowpalWabbit vw = null) { this.LearnInternal(vw ?? this.vw); }
/// <summary> /// Initializes a new instance of the <see cref="VowpalWabbit{TExample}"/> class. /// </summary> /// <param name="vw">The native instance to wrap.</param> /// <remarks>This instance takes ownership of <paramref name="vw"/> instance and disposes it.</remarks> public VowpalWabbit(VowpalWabbit vw) : this(vw, VowpalWabbitSerializerFactory.CreateSerializer <TExample>(vw.Settings)) { }
/// <summary> /// Implementors create new VW wrapper instances. /// </summary> /// <param name="vw">The native VW instance.</param> /// <returns>The new VW wrapper instance.</returns> protected abstract TVowpalWabbit InternalCreate(VowpalWabbit vw);
/// <summary> /// Predicts for this example and returns the current prediction for it. /// </summary> /// <typeparam name="TPrediction">The prediction type.</typeparam> /// <param name="predictionFactory">The prediction factory to be used. See <see cref="VowpalWabbitPredictionType"/>.</param> /// <returns>The prediction for the this example.</returns> protected override TPrediction PredictInternal <TPrediction>(IVowpalWabbitPredictionFactory <TPrediction> predictionFactory, VowpalWabbit vw) { return(vw.Predict <TPrediction>(this.Example, predictionFactory)); }
/// <summary> /// Initializes a new instance of the <see cref="VowpalWabbitDynamic"/> class. /// </summary> /// <param name="settings">Arguments passed to native instance.</param> public VowpalWabbitDynamic(VowpalWabbitSettings settings) { this.vw = new VowpalWabbit(settings); this.serializers = new Dictionary <Type, IDisposable>(); this.serializeMethods = new Dictionary <Type, MethodInfo>(); }
/// <summary> /// Predicts for this example and returns the current prediction for it. /// </summary> /// <typeparam name="TPrediction">The prediction type.</typeparam> /// <param name="predictionFactory">The prediction factory to be used. See <see cref="VowpalWabbitPredictionType"/>.</param> /// <returns>The prediction for the this example.</returns> /// <param name="vw">Use this VW instance for prediction instead of the one the example was created from.</param> public TPrediction Predict <TPrediction>(IVowpalWabbitPredictionFactory <TPrediction> predictionFactory, VowpalWabbit vw = null) { return(this.PredictInternal(predictionFactory, vw ?? this.vw)); }
/// <summary> /// Simplify learning of examples with action dependent features. /// </summary> /// <typeparam name="TExample">User example type.</typeparam> /// <typeparam name="TActionDependentFeature">Action dependent feature type.</typeparam> /// <param name="vw">The VowpalWabbit instances.</param> /// <param name="serializer">The example serializer.</param> /// <param name="actionDependentFeatureSerializer">The action dependent feature serializer.</param> /// <param name="example">The example.</param> /// <param name="actionDependentFeatures">The action dependent features.</param> /// <param name="predictOrLearn">An action executed once the set of valid examples is determined. </param> /// <param name="index">The optional index of the action dependent feature this label belongs too.</param> /// <param name="label">The optional label to be used for learning or evaluation.</param> public static void Execute <TExample, TActionDependentFeature>( VowpalWabbit vw, VowpalWabbitSingleExampleSerializer <TExample> serializer, VowpalWabbitSingleExampleSerializer <TActionDependentFeature> actionDependentFeatureSerializer, TExample example, IReadOnlyCollection <TActionDependentFeature> actionDependentFeatures, LearnOrPredictAction <TActionDependentFeature> predictOrLearn, int?index = null, ILabel label = null) { Contract.Requires(vw != null); Contract.Requires(actionDependentFeatureSerializer != null); Contract.Requires(example != null); Contract.Requires(actionDependentFeatures != null); var examples = new List <VowpalWabbitExample>(actionDependentFeatures.Count + 1); var validExamples = new List <VowpalWabbitExample>(actionDependentFeatures.Count + 1); var validActionDependentFeatures = new List <ActionDependentFeature <TActionDependentFeature> >(actionDependentFeatures.Count + 1); var emptyActionDependentFeatures = new List <ActionDependentFeature <TActionDependentFeature> >(actionDependentFeatures.Count + 1); VowpalWabbitExample emptyExample = null; try { // contains prediction results if (serializer != null) { var sharedExample = serializer.Serialize(example, SharedLabel.Instance); // check if we have shared features if (sharedExample != null) { examples.Add(sharedExample); if (!sharedExample.IsNewLine) { validExamples.Add(sharedExample); } } } var i = 0; foreach (var actionDependentFeature in actionDependentFeatures) { var adfExample = actionDependentFeatureSerializer.Serialize(actionDependentFeature, index != null && i == index ? label : null); Contract.Assert(adfExample != null); examples.Add(adfExample); if (!adfExample.IsNewLine) { validExamples.Add(adfExample); validActionDependentFeatures.Add(new ActionDependentFeature <TActionDependentFeature>(i, actionDependentFeature)); } else { emptyActionDependentFeatures.Add(new ActionDependentFeature <TActionDependentFeature>(i, actionDependentFeature)); } i++; } if (validActionDependentFeatures.Count == 0) { return; } // signal we're finished using an empty example emptyExample = vw.GetOrCreateEmptyExample(); validExamples.Add(emptyExample); predictOrLearn(validExamples, validActionDependentFeatures, emptyActionDependentFeatures); } finally { if (emptyExample != null) { emptyExample.Dispose(); } // dispose examples // Note: must not dispose examples before final example // as the learning algorithm (such as cbf) keeps a reference // to the example foreach (var e in examples) { e.Dispose(); } } }
private async Task<bool> TryLoadModel() { // find the model blob if (string.IsNullOrEmpty(this.state.ModelName)) { this.telemetry.TrackTrace("Model not specified"); return false; } var container = this.blobClient.GetContainerReference(this.settings.StorageContainerName); if (!await container.ExistsAsync()) { this.telemetry.TrackTrace($"Storage container missing '{this.settings.StorageContainerName}'"); return false; } var modelBlob = container.GetBlockBlobReference(this.state.ModelName); if (!await modelBlob.ExistsAsync()) { this.telemetry.TrackTrace($"Model blob '{this.state.ModelName}' is missing"); return false; } // load the model using (var modelStream = await modelBlob.OpenReadAsync()) { this.InitializeVowpalWabbit(new VowpalWabbitSettings { ModelStream = modelStream }); this.telemetry.TrackTrace($"Model loaded {this.state.ModelName}", SeverityLevel.Verbose); // validate that the loaded VW model has the same settings as requested by C&C var newSettings = new VowpalWabbitSettings(this.settings.Metadata.TrainArguments); using (var newVW = new VW.VowpalWabbit(newSettings)) { newVW.ID = this.vw.ID; // save the VW instance to a model and load again to get fully expanded parameters. string newVWarguments; using (var tempModel = new MemoryStream()) { newVW.SaveModel(tempModel); tempModel.Position = 0; using (var tempVW = new VW.VowpalWabbit(new VowpalWabbitSettings { ModelStream = tempModel })) { newVWarguments = CleanVowpalWabbitArguments(tempVW.Arguments.CommandLine); } } var oldVWarguments = CleanVowpalWabbitArguments(this.vw.Arguments.CommandLine); // this is the expanded command line if (newVWarguments != oldVWarguments) { this.telemetry.TrackTrace("New VowpalWabbit settings found. Discarding existing model", SeverityLevel.Information, new Dictionary<string, string> { { "TrainArguments", newVW.Arguments.CommandLine }, { "NewExpandedArguments", newVWarguments }, { "OldExpandedArgumentsCleaned", oldVWarguments }, { "OldExpandedArguments", this.vw.Arguments.CommandLine }, }); // discard old, use fresh this.vw.Dispose(); this.vw = null; this.InitializeVowpalWabbit(newSettings); } } } // store the initial model this.settings.InitialVowpalWabbitModel = this.state.ModelName; return true; }
/// <summary> /// Predicts for these examples. /// </summary> protected override void PredictInternal(VowpalWabbit vw) { // unfortunately can't specify <void> this.Execute <int>(vw, ex => vw.Predict(ex)); }
/// <summary> /// Simplify learning of examples with action dependent features. /// </summary> public static void Learn <TExample, TActionDependentFeature>( VowpalWabbit vw, VowpalWabbitSerializer <TExample> serializer, VowpalWabbitSerializer <TActionDependentFeature> actionDependentFeatureSerializer, TExample example, IEnumerable <TActionDependentFeature> actionDependentFeatures, int index, ILabel label) { Contract.Requires(vw != null); Contract.Requires(serializer != null); Contract.Requires(actionDependentFeatureSerializer != null); Contract.Requires(example != null); Contract.Requires(actionDependentFeatures != null); Contract.Requires(index >= 0); Contract.Requires(label != null); #if DEBUG // only in debug, since it's a hot path if (actionDependentFeatureSerializer.CachesExamples) { throw new NotSupportedException("Cached examples cannot be used for learning"); } #endif var examples = new List <VowpalWabbitExample>(); try { // contains prediction results var sharedExample = serializer.Serialize(vw, example, SharedLabel.Instance); // check if we have shared features if (sharedExample != null) { examples.Add(sharedExample); vw.Learn(sharedExample); } var i = 0; foreach (var actionDependentFeature in actionDependentFeatures) { var adfExample = actionDependentFeatureSerializer.Serialize(vw, actionDependentFeature, i == index ? label : null); Contract.Assert(adfExample != null); examples.Add(adfExample); vw.Learn(adfExample); i++; } // signal we're finished using an empty example var empty = vw.GetOrCreateEmptyExample(); examples.Add(empty); vw.Learn(empty); // Dump input file for command line learning //File.AppendAllLines(@"c:\temp\msn.txt", // examples.OfType<VowpalWabbitDebugExample>() // .Select(e => e.VowpalWabbitString) // .Union(new[] { "" })); } finally { // dispose examples // Note: must not dispose examples before final example // as the learning algorithm (such as cbf) keeps a reference // to the example foreach (var e in examples) { e.Dispose(); } } }
/// <summary> /// Learns from this example. /// </summary> /// <param name="vw">Use this VW instance for learning instead of the one the example was created from.</param> protected abstract void LearnInternal(VowpalWabbit vw);
/// <summary> /// Learns from this example. /// </summary> protected override void LearnInternal(VowpalWabbit vw) { vw.Learn(this.Example); }
/// <summary> /// Predicts for this example. /// </summary> /// <param name="vw">Use this VW instance for prediction instead of the one the example was created from.</param> protected abstract void PredictInternal(VowpalWabbit vw);
/// <summary> /// Learn from this example and returns the current prediction for it. /// </summary> /// <typeparam name="TPrediction">The prediction type.</typeparam> /// <param name="predictionFactory">The prediction factory to be used. See <see cref="VowpalWabbitPredictionType"/>.</param> /// <returns>The prediction for the this example.</returns> /// <param name="vw">Use this VW instance for learning instead of the one the example was created from.</param> protected abstract TPrediction LearnInternal <TPrediction>(IVowpalWabbitPredictionFactory <TPrediction> predictionFactory, VowpalWabbit vw);
/// <summary> /// Simplify learning of examples with action dependent features. /// </summary> /// <typeparam name="TExample">The type of the user example.</typeparam> /// <typeparam name="TActionDependentFeature">The type of the user action dependent features.</typeparam> /// <param name="vw">The vw instance.</param> /// <param name="serializer">The serializer for <typeparamref name="TExample"/>.</param> /// <param name="actionDependentFeatureSerializer">The serializer for <typeparamref name="TActionDependentFeature"/>.</param> /// <param name="example">The user example.</param> /// <param name="actionDependentFeatures">The action dependent features.</param> /// <param name="index">The index of action dependent feature to label.</param> /// <param name="label">The label for the selected action dependent feature.</param> /// <returns>An ranked subset of predicted action indexes.</returns> public static int[] LearnAndPredictIndex <TExample, TActionDependentFeature>( VowpalWabbit vw, VowpalWabbitSerializer <TExample> serializer, VowpalWabbitSerializer <TActionDependentFeature> actionDependentFeatureSerializer, TExample example, IEnumerable <TActionDependentFeature> actionDependentFeatures, int index, ILabel label) { Contract.Requires(vw != null); Contract.Requires(serializer != null); Contract.Requires(actionDependentFeatureSerializer != null); Contract.Requires(example != null); Contract.Requires(actionDependentFeatures != null); Contract.Requires(index >= 0); Contract.Requires(label != null); #if DEBUG // only in debug, since it's a hot path if (actionDependentFeatureSerializer.CachesExamples) { throw new NotSupportedException("Cached examples cannot be used for learning"); } #endif var examples = new List <VowpalWabbitExample>(); try { // contains prediction results var sharedExample = serializer.Serialize(vw, example); // check if we have shared features if (sharedExample != null) { examples.Add(sharedExample); vw.Learn(sharedExample); } // leave as loop (vs. linq) so if the serializer throws an exception, anything allocated so far can be free'd var i = 0; foreach (var actionDependentFeature in actionDependentFeatures) { var adfExample = actionDependentFeatureSerializer.Serialize(vw, actionDependentFeature, i == index ? label : null); Contract.Assert(adfExample != null); examples.Add(adfExample); vw.Learn(adfExample); i++; } // signal we're finished using an empty example var empty = vw.GetOrCreateEmptyExample(); examples.Add(empty); vw.Learn(empty); // Nasty workaround. Since the prediction result is stored in the first example // and we'll have to get an actual VowpalWabbitExampt var firstExample = examples.FirstOrDefault(); if (firstExample == null) { return(null); } return(firstExample.GetPrediction(vw, VowpalWabbitPredictionType.Multilabel)); } finally { // dispose examples // Note: must not dispose examples before final example // as the learning algorithm (such as cbf) keeps a reference // to the example foreach (var e in examples) { e.Dispose(); } } }