Skip to content

SDCA Regression and BinaryClassification Pigsty extensions - #837

Merged
TomFinley merged 5 commits into
dotnet:masterfrom
TomFinley:tfinley/Pigsty
Sep 6, 2018
Merged

SDCA Regression and BinaryClassification Pigsty extensions#837
TomFinley merged 5 commits into
dotnet:masterfrom
TomFinley:tfinley/Pigsty

Conversation

@TomFinley

Copy link
Copy Markdown
Contributor

Related to the closed #632 and the API overall. In here I introduce extensions for SDCA regression and binary classification. (No multiclass until I also write extensions for term.)

This also includes a sort of general purpose utilities for writing reconcilers for trainers, though, again, only regression, binary classification, and binary classification without probabilities so far.

Also a minor change to the linear classification trainer, as it was not identifying that it was producing probabilities sometimes.

/// Constructor for the base class.
/// </summary>
/// <param name="inputs">The set of inputs</param>
/// <param name="outputNames">The names of the outputs, which we assume cannot be changed</param>

@sfilipi sfilipi Sep 5, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

real question: do we put a period in the sentences of the

section, but not in the sentences in ? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Having complete sentences in the summary is essential. About params, I'm less sure about that, but I think I prefer to have them, I'll try to add them.


In reply to: 215322337 [](ancestors = 215322337)

namespace Microsoft.ML.Data.StaticPipe.Runtime
{
/// <summary>
/// General purpose reconciler for a typical case with trainers, where they accept some generally

@sfilipi sfilipi Sep 5, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

reconciler [](start = 24, length = 10)

I am still fuzzy on the purpose of reconcilers. Is it a bridge from estimators to trainers? #Closed

@TomFinley TomFinley Sep 5, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hi @sfilipi thanks for the question -- I covered this somewhat in #632, in particular, if you check out the section "one or two implementation details," paragraphs 2 through 4 of that section deal with the role of reconcilers. (As does I suppose the XML docs for reconcilers.)

The idea is that, the user has declaratively defined their delegate where they define what they want done, and the analyzer that calls that delegate does a lot of work to determine what should go where, but at the final last step there has to be something responsible for actually creating those IEstimator (or, in some cases, IDataReaderEstimator) objects. That thing is the reconciler.

It's not a great name. #Resolved

/// <summary>
/// Produces the estimator. Note that this is made out of <see cref="ReconcileCore(IHostEnvironment, string[])"/>'s
/// return value, plus whatever usages of <see cref="CopyColumnsEstimator"/> are necessary to avoid collisions with
/// the output names fed to the constructor. This class provides the implementation, and subclassses should instead

@sfilipi sfilipi Sep 5, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

subclassses [](start = 97, length = 11)

typo #Closed

return rec.Output;
}

private sealed class TrivialFactory : ISupportSdcaClassificationLossFactory

@sfilipi sfilipi Sep 5, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

TrivialFactory [](start = 29, length = 14)

would 'BaseLossFactory' be a better name? #Closed

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 the idea is that this 'factory' will always return an existing object, so it's more 'trivial' than it is 'base'


In reply to: 215330387 [](ancestors = 215330387)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Right, I agree with @Zruty0. I also do not like putting "base" in since we tend to reserve that word for abstract classes.


In reply to: 215369185 [](ancestors = 215369185,215330387)

int? maxIterations = null,
bool shuffle = true,
float biasLearningRate = 0,
Action<LinearBinaryPredictor, ParameterMixingCalibratedPredictor> onFit = null)

@sfilipi sfilipi Sep 5, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

onFit [](start = 82, length = 5)

is this so we can pass different types of calibrators? #Closed

@TomFinley TomFinley Sep 5, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, this is so the user of this method can be informed about the calibrator, so they know the slope, etc. I have added some XML docs for this, that will attempt to explain what onFit is.


In reply to: 215331242 [](ancestors = 215331242)

}

public static (Scalar<float> score, Scalar<bool> predictedLabel)
PredictSdcaBinaryClassificationCustomLoss(this Scalar<bool> label, Vector<float> features, Scalar<float> weights = null,

@sfilipi sfilipi Sep 5, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

PredictSdcaBinaryClassificationCustomLoss [](start = 12, length = 41)

Are we going to test those methods through the samples code we're doing later? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess so. But I wanted to test them now.


In reply to: 215332900 [](ancestors = 215332900)

/// <param name="features">The features column name</param>
/// <param name="weights">The weights column name, or <c>null</c> if the reconciler was constructed with <c>null</c> weights</param>
/// <returns>Some sort of estimator producing columns with the fixed name <see cref="DefaultColumnNames.Score"/></returns>
public delegate IEstimator<ITransformer> EstimatorMaker(IHostEnvironment env, string label, string features, string weights);

@Zruty0 Zruty0 Sep 5, 2018

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.

Maker [](start = 62, length = 5)

Either 'builder' or 'factory' seems a bit more common for a factory method like this #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let's do factory I guess.


In reply to: 215366624 [](ancestors = 215366624)

/// </summary>
public static class SdcaStatic
{
public static Scalar<float> PredictSdcaRegression(this Scalar<float> label, Vector<float> features, Scalar<float> weights = null,

@Zruty0 Zruty0 Sep 5, 2018

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.

PredictSdcaRegression [](start = 36, length = 21)

Let's get into habit of writing extensive summary comments for these, since this is our public API now #Pending

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let me know if you like my documentation.


In reply to: 215367489 [](ancestors = 215367489)

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 do


In reply to: 215430305 [](ancestors = 215430305,215367489)

var rec = new TrainerEstimatorReconciler.Regression(
(env, labelName, featuresName, weightsName) =>
{
var trainer = new SdcaRegressionTrainer(env, args, featuresName, labelName, weightsName);

@Zruty0 Zruty0 Sep 5, 2018

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.

args [](start = 65, length = 4)

Yuck, args! In transforms, I was trying to get rid of them. I think we should do the same for trainers? #Closed

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.

asking for a friend :)
That is, not insisting that you do so now.


In reply to: 215368077 [](ancestors = 215368077)

@TomFinley TomFinley Sep 5, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hi @Zruty0 , I agree with you. I can make an issue on this subject. This will of course not be resolved in this PR, but it is important we begin to think about it.


In reply to: 215368265 [](ancestors = 215368265,215368077)


public ISupportSdcaClassificationLoss CreateComponent(IHostEnvironment env)
{
// REVIEW: We are ignoring env?

@Zruty0 Zruty0 Sep 5, 2018

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.

REVIEW: We are ignoring env? [](start = 19, length = 28)

well, in this case the loss has been given to us, so no need to use env to manufacture anything, right? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's fair I suppose.


In reply to: 215369392 [](ancestors = 215369392)

}

/// <summary>
/// A reconciler for regression capable of handling the most common cases for binary classification

@Zruty0 Zruty0 Sep 5, 2018

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.

regression [](start = 29, length = 10)

binary classification? #Closed

}

/// <summary>
/// A reconciler for regression capable of handling the most common cases for binary classifier with calibrated outputs.

@Zruty0 Zruty0 Sep 5, 2018

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.

regression [](start = 29, length = 10)

seems like a copypasta error #Closed

/// </summary>
public (Scalar<float> score, Scalar<bool> predictedLabel) Output { get; }

protected override IEnumerable<PipelineColumn> Outputs { get; }

@Zruty0 Zruty0 Sep 5, 2018

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'm not sure I fully grasp the difference between Output and Outputs... #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll add a comment. They only really differ in content in this one class, due to the fact that are compile time we can only be sure two are present, while at runtime we also have to be sensitive as to whether we are in fact producing that extra probability column.


In reply to: 215371730 [](ancestors = 215371730)


namespace Microsoft.ML.StaticPipelineTesting
{
public sealed class Training : MakeConsoleWork

@Zruty0 Zruty0 Sep 5, 2018

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.

MakeConsoleWork [](start = 35, length = 15)

can we rename this to something that indicates that it's a base class for tests?
Like BaseTestClassWithConsole ? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

:D


In reply to: 215372112 [](ancestors = 215372112)

}

public static (Scalar<float> score, Scalar<bool> predictedLabel)
PredictSdcaBinaryClassificationCustomLoss(this Scalar<bool> label, Vector<float> features, Scalar<float> weights = null,

@Zruty0 Zruty0 Sep 5, 2018

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.

PredictSdcaBinaryClassificationCustomLoss [](start = 12, length = 41)

Maybe make this an overload instead of a method with a different name? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OK. In order to encourage "early" resolution I will also move the loss argument to be right after the delegate, and make it a non-default argument to encourage people to actually set it.


In reply to: 215378059 [](ancestors = 215378059)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ooo... hmmm. Maybe it has to go after features, but before weights. Hmmm. Hmmm.


In reply to: 215414897 [](ancestors = 215414897,215378059)

/// </summary>
internal Estimator<TTupleShape, TTupleShape, ITransformer> MakeNewEstimator()
/// <returns>An empty estimator with the same shape as the object on which it was created</returns>
public Estimator<TTupleShape, TTupleShape, ITransformer> MakeNewEstimator()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

public [](start = 8, length = 6)

As discussed here I believe the POR for right now until we change our minds again is for the method to create new estimator pipes to exist directly on these schema bearing objects (whatever they may be).

/// <param name="onFit">A delegate that is called every time the
/// <see cref="Estimator{TTupleInShape, TTupleOutShape, TTransformer}.Fit(DataView{TTupleInShape})"/> method is called on the
/// <see cref="Estimator{TTupleInShape, TTupleOutShape, TTransformer}"/> instance created out of this. This delegate will receive
/// the linear model that was learnt. Note that this action cannot change the result in any way; it is only a way for the caller to

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.

learnt [](start = 38, length = 6)

maybe 'trained'? :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. I think the first instance can be trained, but I feel like the trailing word has to be learnt or something.

@Zruty0 Zruty0 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:

@sfilipi sfilipi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

:shipit:

@TomFinley
TomFinley merged commit 5654d72 into dotnet:master Sep 6, 2018
@TomFinley
TomFinley deleted the tfinley/Pigsty branch September 6, 2018 01:39
@ghost ghost locked as resolved and limited conversation to collaborators Mar 29, 2022
Sign up for free to 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.

Direct API: Static Typing of Data Pipelines

3 participants