Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/Microsoft.ML.AutoML/API/BinaryClassificationExperiment.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML.AutoML.Tuner;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
Expand All@@ -35,13 +36,19 @@ public sealed class BinaryExperimentSettings : ExperimentSettings
/// <value>The default value is a collection auto-populated with all possible trainers (all values of <see cref="BinaryClassificationTrainer" />).</value>
public ICollection<BinaryClassificationTrainer> Trainers { get; }

/// <summary>
/// Set if use <see cref="AutoZeroTuner"/> for hyper-parameter optimization, default to false.
/// </summary>
public bool UseAutoZeroTuner { get; set; }

/// <summary>
/// Initializes a new instance of <see cref="BinaryExperimentSettings"/>.
/// </summary>
public BinaryExperimentSettings()
{
OptimizingMetric = BinaryClassificationMetric.Accuracy;
Trainers = Enum.GetValues(typeof(BinaryClassificationTrainer)).OfType<BinaryClassificationTrainer>().ToList();
UseAutoZeroTuner = false;
}
}

Expand DownExpand Up@@ -133,7 +140,7 @@ public enum BinaryClassificationTrainer
/// </example>
public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private AutoMLExperiment _experiment;
private const string Features = "__Features__";
private SweepablePipeline _pipeline;

Expand All@@ -151,13 +158,13 @@ internal BinaryClassificationExperiment(MLContext context, BinaryExperimentSetti
_experiment.SetMaximumMemoryUsageInMegaByte(d);
}
_experiment.SetMaxModelToExplore(settings.MaxModels);
_experiment.SetTrainingTimeInSeconds(settings.MaxExperimentTimeInSeconds);
}

public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView trainData, ColumnInformation columnInformation, IEstimator<ITransformer> preFeaturizer = null, IProgress<RunDetail<BinaryClassificationMetrics>> progressHandler = null)
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);

// Cross val threshold for # of dataset rows --
// If dataset has < threshold # of rows, use cross val.
Expand DownExpand Up@@ -194,7 +201,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand All@@ -208,7 +215,6 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, validationData);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -228,7 +234,7 @@ public override ExperimentResult<BinaryClassificationMetrics> Execute(IDataView

return monitor;
});
_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -263,7 +269,6 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
{
var label = columnInformation.LabelColumnName;
_experiment.SetBinaryClassificationMetric(Settings.OptimizingMetric, label);
_experiment.SetTrainingTimeInSeconds(Settings.MaxExperimentTimeInSeconds);
_experiment.SetDataset(trainData, (int)numberOfCVFolds);
_pipeline = CreateBinaryClassificationPipeline(trainData, columnInformation, preFeaturizer);
_experiment.SetPipeline(_pipeline);
Expand All@@ -284,7 +289,7 @@ public override CrossValidationExperimentResult<BinaryClassificationMetrics> Exe
return monitor;
});

_experiment.SetTrialRunner<BinaryClassificationRunner>();
_experiment = PostConfigureAutoMLExperiment(_experiment);
_experiment.Run();

var runDetails = monitor.RunDetails.Select(e => BestResultUtil.ToCrossValidationRunDetail(Context, e, _pipeline));
Expand DownExpand Up@@ -335,6 +340,17 @@ private SweepablePipeline CreateBinaryClassificationPipeline(IDataView trainData
.Append(Context.Auto().BinaryClassification(labelColumnName: columnInformation.LabelColumnName, useSdcaLogisticRegression: useSdca, useFastTree: useFastTree, useLgbm: useLgbm, useLbfgsLogisticRegression: uselbfgs, useFastForest: useFastForest, featureColumnName: Features));
}
}

private AutoMLExperiment PostConfigureAutoMLExperiment(AutoMLExperiment experiment)
{
experiment.SetTrialRunner<BinaryClassificationRunner>();
if (Settings.UseAutoZeroTuner)
{
experiment.SetTuner<AutoZeroTuner>();
}

return experiment;
}
}

internal class BinaryClassificationRunner : ITrialRunner
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,12 @@
<AdditionalFiles Include="CodeGen\*-estimators.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Tuner\Portfolios.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<!--Include DLLs of Project References-->
Expand Down
142 changes: 142 additions & 0 deletions src/Microsoft.ML.AutoML/Tuner/AutoZeroTuner.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using Microsoft.ML.AutoML.CodeGen;
using Microsoft.ML.SearchSpace;

namespace Microsoft.ML.AutoML.Tuner
{
internal class AutoZeroTuner : ITuner
{
private readonly List<Config> _configs = new List<Config>();
private readonly IEnumerator<Config> _configsEnumerator;
private readonly Dictionary<string, string> _pipelineStrings;
private readonly SweepablePipeline _sweepablePipeline;
private readonly Dictionary<int, Config> _configLookBook = new Dictionary<int, Config>();
private readonly string _metricName;

public AutoZeroTuner(SweepablePipeline pipeline, AggregateTrainingStopManager aggregateTrainingStopManager, IEvaluateMetricManager evaluateMetricManager, AutoMLExperiment.AutoMLExperimentSettings settings)
{
_configs = LoadConfigsFromJson();
_sweepablePipeline = pipeline;
_pipelineStrings = _sweepablePipeline.Schema.ToTerms().Select(t => new
{
schema = t.ToString(),
pipelineString = string.Join("=>", t.ValueEntities().Select(e => _sweepablePipeline.Estimators[e.ToString()].EstimatorType)),
}).ToDictionary(kv => kv.schema, kv => kv.pipelineString);

// todo
// filter configs on trainers
var trainerEstimators = _sweepablePipeline.Estimators.Where(e => e.Value.EstimatorType.IsTrainer()).Select(e => e.Value.EstimatorType.ToString()).ToList();
_configs = evaluateMetricManager switch
{
BinaryMetricManager => _configs.Where(c => c.Task == "binary-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
MultiClassMetricManager => _configs.Where(c => c.Task == "multi-classification" && trainerEstimators.Contains(c.Trainer)).ToList(),
RegressionMetricManager => _configs.Where(c => c.Task == "regression" && trainerEstimators.Contains(c.Trainer)).ToList(),
_ => throw new Exception(),
};
_metricName = evaluateMetricManager switch
{
BinaryMetricManager bm => bm.Metric.ToString(),
MultiClassMetricManager mm => mm.Metric.ToString(),
RegressionMetricManager rm => rm.Metric.ToString(),
_ => throw new Exception(),
};

if (_configs.Count == 0)
{
throw new ArgumentException($"Fail to find available configs for given trainers: {string.Join(",", trainerEstimators)}");
}

_configsEnumerator = _configs.GetEnumerator();
aggregateTrainingStopManager.AddTrainingStopManager(new MaxModelStopManager(_configs.Count, null));
}

private List<Config> LoadConfigsFromJson()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Microsoft.ML.AutoML.Tuner.Portfolios.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
var json = reader.ReadToEnd();
var res = JsonSerializer.Deserialize<List<Config>>(json);

return res;
}
}

public Parameter Propose(TrialSettings settings)
{
if (_configsEnumerator.MoveNext())
{
var config = _configsEnumerator.Current;
IEnumerable<KeyValuePair<string, string>> pipelineSchemas = default;
if (_pipelineStrings.Any(kv => kv.Value.Contains("OneHotHashEncoding") || kv.Value.Contains("OneHotEncoding")))
{
pipelineSchemas = _pipelineStrings.Where(kv => kv.Value.Contains(config.CatalogTransformer));
}
else
{
pipelineSchemas = _pipelineStrings;
}

pipelineSchemas = pipelineSchemas.Where(kv => kv.Value.Contains(config.Trainer));
var pipelineSchema = pipelineSchemas.First().Key;
var pipeline = _sweepablePipeline.BuildSweepableEstimatorPipeline(pipelineSchema);
var parameter = pipeline.SearchSpace.SampleFromFeatureSpace(pipeline.SearchSpace.Default);
var trainerEstimatorName = pipeline.Estimators.Where(kv => kv.Value.EstimatorType.IsTrainer()).First().Key;
var label = parameter[trainerEstimatorName]["LabelColumnName"].AsType<string>();
var feature = parameter[trainerEstimatorName]["FeatureColumnName"].AsType<string>();
parameter[trainerEstimatorName] = config.TrainerParameter;
parameter[trainerEstimatorName]["LabelColumnName"] = Parameter.FromString(label);
parameter[trainerEstimatorName]["FeatureColumnName"] = Parameter.FromString(feature);
settings.Parameter[AutoMLExperiment.PipelineSearchspaceName] = parameter;
_configLookBook[settings.TrialId] = config;
return settings.Parameter;
}

throw new OperationCanceledException();
}

public void Update(TrialResult result)
{
}

class Config
{
/// <summary>
/// one of OneHot, HashEncoding
/// </summary>
public string CatalogTransformer { get; set; }

/// <summary>
/// One of Lgbm, Sdca, FastTree,,,
/// </summary>
public string Trainer { get; set; }

public Parameter TrainerParameter { get; set; }

public string Task { get; set; }
}

class Rows
{
public string CustomDimensionsBestPipeline { get; set; }

public string CustomDimensionsOptionsTask { get; set; }

public Parameter CustomDimensionsParameter { get; set; }
}
}
}
Loading