reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp
, '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

reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp
, '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

reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp
, '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

reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp
, '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

reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp
, '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

reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp
, '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

reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp
, '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

reimplement binary experiment using AutoMLExperiment - #6246

Merged
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary
Jul 18, 2022
Merged

reimplement binary experiment using AutoMLExperiment#6246
LittleLittleCloud merged 7 commits into
dotnet:mainfrom
LittleLittleCloud:u/xiaoyun/reimplement-binary

Conversation

@LittleLittleCloud

@LittleLittleCloudLittleLittleCloud commented Jul 6, 2022

Copy link
Copy Markdown
Member

We are excited to review your PR.

So we can do the best job, please check:

  • There's a descriptive title that will make sense to other developers some time from now.
  • There's associated issues. All PR's should have issue(s) associated - unless a trivial self-evident change such as fixing a typo. You can use the format Fixes #nnnn in your description to cause GitHub to automatically close the issue(s) when your PR is merged.
  • Your change description explains what the change does, why you chose your approach, and anything else that reviewers should know.
  • You have included any necessary tests in the same PR.

This PR reimplements binary classification experiment using AutoMLExperiment, while keeping all the API unchanged so the existing documents don't need to be updated.

public sealed class BinaryClassificationExperiment : ExperimentBase<BinaryClassificationMetrics, BinaryExperimentSettings>
{
private readonly AutoMLExperiment _experiment;
private const string Features = "__Features__";

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output column name for Concatenating all features

/// Depending on the size of your data, the AutoML experiment could take a long time to execute.
/// </remarks>
public ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,
public virtual ExperimentResult<TMetrics> Execute(IDataView trainData, string labelColumnName = DefaultColumnNames.Label,

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add virtual keyword so it can be overrided

{ EstimatorType.SdcaMaximumEntropyMulti, 1.129 },
{ EstimatorType.SdcaLogisticRegressionOva, 3.16 },
{ EstimatorType.LightGbmMulti, 4.765 },
{ EstimatorType.SdcaMaximumEntropyMulti, 10.129 },

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sdca converges slower than I expected. The original cost for sdca is calculated with subsampling prerposer so it's much smaller than what it costs on the entire dataset.

Considering that it's very, very unlikely for sdca to be the ace trainer among all available trainers, which means the time spent on Sdca is in most case a waste, it's acceptable to increase the initial cost of Sdca so it will have the least priority in the entire trainer selection.

context = new MLContext(1);
var modelTrainTest = context.Auto()
.CreateBinaryClassificationExperiment(0)
.CreateBinaryClassificationExperiment(10)

@LittleLittleCloudLittleLittleCloudJul 6, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to increase the maximize training time from 0 because the logic for max time limitation is a bit different comparing the old and new implementations. In the old implementations, binary classification experiment will wait for the final trial to complete even the time budget is used up. In the new implementation however, binary classification experiment will try to cancel all trials running on that context.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this behavior back to the old behavior. I don't think cancelling all running trials is a good idea. If I don't know how long my data will take to train and I set it for 2 hours and nothing finished by then, I would probably be pretty annoyed to have it cancel part of the way through.

Or maybe what would be better would be to have both ways possible. 1 way to force cancel everything, and 1 way to cancel but let it finish gracefully. Until we are able to have that though, I don't think we should forcefully cancel all running pipelines especially if non have finished yet.

@LittleLittleCloudLittleLittleCloudJul 13, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still vote for forcing canceling trial because the only situation for force canceling running trial ruins user experience is when there's no trial completed and user waits a few hours for nothing. That situation can be avoided by making the first trial end quickly, by starting from a small model or starting from a portion of dataset. ModelBuilder uses those techniques and it goes pretty well. The new AutoML also starts from a small model, and I'm working on a PR for starting from a portion of dataset when necessary.

Gracefully canceling, however, has more annoying situations that are easier to encounter. For example, when time is up and AutoML is training a large model, it would be really frustrating to wait another few minutes for the final trial to complete, especially in notebook running cell

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do a mixed way: force canceling when there's completed trial, and wait for the first trial to complete if there's no completed trials.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a mixed way is a good idea for now. But I don't think we should just cancel when nothing has finished. Is that a complex change for you to add?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already made that change
8446e6e

@codecov

codecovBot commented Jul 6, 2022

Copy link
Copy Markdown

Codecov Report

Merging #6246 (ae4148c) into main (924ae7a) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## main #6246 +/- ##
=======================================
Coverage 68.44% 68.45% =======================================
Files 1141 1141 Lines 244790 244820 +30 Branches 25405 25405 =======================================
+ Hits 167551 167580 +29 - Misses 70599 70602 +3 + Partials 6640 6638 -2 
FlagCoverage Δ
Debug68.45% <100.00%> (+<0.01%)⬆️
production62.91% <ø> (+<0.01%)⬆️
test88.98% <100.00%> (-0.02%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted FilesCoverage Δ
test/Microsoft.ML.AutoML.Tests/AutoFitTests.cs85.75% <100.00%> (-1.33%)⬇️
.../Evaluators/Metrics/BinaryClassificationMetrics.cs84.78% <0.00%> (-10.87%)⬇️
src/Microsoft.ML.Core/Data/IHostEnvironment.cs95.12% <0.00%> (-2.44%)⬇️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.38% <0.00%> (-0.15%)⬇️
src/Microsoft.ML.LightGbm/LightGbmTrainerBase.cs79.75% <0.00%> (+0.55%)⬆️
src/Microsoft.ML.Data/TrainCatalog.cs83.03% <0.00%> (+2.67%)⬆️
src/Microsoft.ML.FastTree/Training/StepSearch.cs62.37% <0.00%> (+4.95%)⬆️

}
else
{
// TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I wouldn't abort the whole thing for a single failure (though there still should be some threshold. Not a blocker for this PR, just agreeing with your comment.

/// <summary>
/// TrialResult with Binary Classification Metrics
/// </summary>
internal class BinaryClassificationTrialResult : TrialResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not want the user to have access to this class?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we just want user to have access to TrialResult only. The difference between BinaryClassificationTrialResult and TrialResult is the first one contains all binary classification metrics, which is for backward compatibility and avoid changing the behavoir of old AutoML only. So I'd rather BinaryClassificationTrialResult not expose to public

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they not need the extra information? If not then sounds good.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they shouldn't need those extra metric informations. I don't understand why the old AutoML.Net API returns all metrics together even though the tuner only optimizes based on one of them. It's probably just a mis-design.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly questions, but the issue with the trail cancellation does need to be resolved.

@michaelgsharpmichaelgsharp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelgsharp

Copy link
Copy Markdown
Contributor

@LittleLittleCloud looks like this test, AutoFitWithPresplittedData, should also be changed to a LightGbmFact instead of just fact.

@LittleLittleCloud

Copy link
Copy Markdown
MemberAuthor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@LittleLittleCloud
LittleLittleCloud merged commit 24df355 into dotnet:mainJul 18, 2022
@ghostghost locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LittleLittleCloud@michaelgsharp