-
Notifications
You must be signed in to change notification settings - Fork 18
Loss augmented inference using SparseNetworks #445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
be2f7b4
b6acc34
4d4d979
75a071e
e1a106e
9f40b24
4a578c4
cd57748
55a808c
09f4aaa
bca4262
ea0198b
ed706a3
da9b768
b15189e
0776234
053f965
77b0a13
73c67a0
4ad5840
c104fff
e668bdd
dce32e9
8059746
f91e18d
e006bb9
ff5c9f3
754d694
92de796
9cf1f25
5186251
e1ea9a4
aba475b
a65cd4e
bcdba7e
dab55f1
4d8f361
b0baf94
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,101 @@ | ||
| * Designing flexible learning models including various configurations such as: | ||
|
|
||
| * Local models i.e. single classifiers. (Learning only models (LO)). | ||
| * Constrained conditional models (CCM)[1] for training independent classifiers and using them jointly for global decision making in prediction time. (Learning+Inference (L+I)). | ||
| * Global models for joint training and joint inference (Inference-Based-Training (IBT)). | ||
| * Pipeline models for complex problems where the output of each layer is used as the input of the next layer. | ||
| //Documented by Parisa Kordjamshidi | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a new tradition? |
||
|
|
||
| Designing flexible learning models including various configurations such as: | ||
|
|
||
| * [Local models](#local) i.e. single classifiers. (Learning only models (LO)). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drop the dot "." before parenthesis? |
||
| * [Constrained conditional models (CCM)](#L+I)[1] for training independent classifiers and using them jointly for global decision making in prediction time. (Learning+Inference (L+I)). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this [1] citation?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drop the dot "." before parenthesis? |
||
| * [Global models](#IBT) for joint training and joint inference (Inference-Based-Training (IBT)). | ||
| * [Pipeline models](#pipeline) for complex problems where the output of each layer is used as the input of the next layer. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about replacing "layer" with "model"? (we never talked about "layer" before.) |
||
|
|
||
| The above mentioned paradigms can be tested using this simple badge classifier example, [here](saul-examples/src/main/scala/edu/illinois/cs/cogcomp/saulexamples/Badge/BagesApp.scala). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drop this?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drop what? the link to the example? why? isn't it useful? |
||
| <a name="local"> | ||
| ##Local models. | ||
| These models are classic classifiers. They are defined with the `Learnable` construct. This construct requires specifying | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not everyone reading this might have several years of experience. How about we replace "classic classifiers" with "single independent classifiers" or something simpler? |
||
| the name of a single output variable, that is, a label which is itself a property in the data model, and the features which is also a | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drop "the name of"? |
||
| comma separated list of properties. | ||
|
|
||
| ```scala | ||
| object ClassifierName extends Learnable (node) { | ||
| def label = property1 | ||
| def feature = using(property2,property3,...) | ||
| //a comma separated list of properties | ||
| } | ||
| ``` | ||
|
|
||
| For the details about the `Learnable` construct see [here](SAULLANGUAGE.md). | ||
|
|
||
| <a name="L+I"> | ||
| ##Learning+Inference models. | ||
| These models are useful for when we need to consider the global relations between the outputs of a bunch of classifiers during the | ||
| prediction time. Each classifier is defined with the same `Learnable` construct as a local model. In addition to the Learnable definitions, the programmer | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change to |
||
| has the possibility to define a number of logical constraints between the output of the classifiers. | ||
| Having the constraint definitions in place (see [here](SAULLANGUAGE.md) for syntax details), the programmer is able to define | ||
| new constraint classifiers that use the Learnables and constraints. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either "constraint classifier" or "constrained classifier", we should always use one. I suggest the latter, as it's been used more in the repository. |
||
|
|
||
| ```scala | ||
| object ConstraintClassifierName extends ConstraintClassifier[local_node,global_node](DataModelName, localClassifier_Name) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drop |
||
| { | ||
| def subjectTo = constraintExpression | ||
| // Logical constraint expression comes here, it defines the relations between the | ||
| // localClassifier_Name and other Learnables defined before | ||
| } | ||
| ``` | ||
| When we use the above `ConstraintClassifierName` to call test or make predictions, the `localClassifier_Name` is used | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drop |
||
| but the predictions are made in way that `constraintExpression` is hold. There is no limitation for the type of local classifiers. | ||
| They can be SVMs, decision trees or any other learning models available in Saul, [here](https://github.com/IllinoisCogComp/lbjava/blob/master/lbjava/doc/ALGORITHMS.md) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relative url?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. which part of the address should be removed? |
||
| and [here](https://github.com/IllinoisCogComp/saul/blob/master/saul-core/src/main/java/edu/illinois/cs/cogcomp/saul/learn/SaulWekaWrapper.md). | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relative url?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. which part of the address should be removed?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make these links relative (i.e. drop |
||
| <a name="IBT"> | ||
| ##Inference-based Learning. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Drop the line at the end of titles? |
||
|
|
||
| For the inference based models the basic definitions are exactly similar to the L+I models. In other words, the programmer | ||
| just needs to define the `Learnables` and `ConstrainedClassifiers`. However, to train the ConstrainedClassifiers jointly, instead of | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change to
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change to |
||
| training local classifiers independently, there are a couple of joint training functions that can be called. | ||
| These functions receive the list of constrained classifiers as input and train their parameters jointly. In contrast to | ||
| L+I models here the local classifiers can be defined as `SparsePerceptrons` or `SparseNetworks` only. This is because the | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| joint training should have its own strategy for the wight updates of the involved variables (those variables come down to be the outputs of the local classifiers here). | ||
| For the two cases the programmer can use | ||
|
|
||
| ```scala | ||
| JointTrainSparseNetwork.train(param1,param2,...) /* a list of parameters go here*/ | ||
| JointTrainSparsePerceptron.train(param1,param2,...) /*a list of parameters here*/ | ||
| ``` | ||
|
|
||
| JointTrainSparseNetwork.train(badge, cls, 5, init = true, lossAugmented = true) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add code style to this?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or just drop it? |
||
|
|
||
| The list of parameters are the following: | ||
|
|
||
| -param1: The name of a global node in the data model that itself or the connected nodes to it are used by the involved `Learnable`s. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add space after "-"s so that they are rendered as bullets. |
||
|
|
||
| -param2: The list of ConstainedClassifiers | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and instead of "list", say "collection"? |
||
|
|
||
| -param3: The number of iterations over the training data. | ||
|
|
||
| -param4: If the local classifiers should be cleaned from the possibly pre-trained values and initialized by zero weights, this parameter should be true. | ||
|
|
||
| -param5: If the approach uses the loss augmented objective for making inference, see below for description. | ||
|
|
||
| ###Basic approach | ||
|
|
||
| The Basic approach for training the models jointly is to do a global prediction at each step of the training and if the | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lower case "Basic"? |
||
| predictions are wrong update the weights of the related variables. | ||
|
|
||
| ###Loss augmented | ||
|
|
||
| The loss-augmented approach adds the loss of the prediction explicitly to the objective of the training and finds the most violated output; | ||
| it updates the weights of the model according to the errors made in the most violated output. | ||
| This is an approach that is used in structured SVMs and Structured Perceptrons. However, considering an arbitrary loss in the objective | ||
| will make complexities in the optimization, therefore in the implemented version, here, we assume the loss is decomposed similar to | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change "will make complexities in the optimization" to "will result in computationally intractable problems"?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, I meant to say in general "complexities in the optimization" not only computational intractability. Sometimes, it can be even tractable but not straightforward to solve using the same objective's structure.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then could you make it more clear in the text then? |
||
| feature function. That is, the loss is a hamming loss defined per classifier. The loss of the whole output will be the weighted sum of | ||
| the all predicted components of the output structure. | ||
| In Saul, the programmer can indicate if he/she needs to consider this global hamming loss in the objective or not. And this can be done by passing | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This whole paragraph is very ambiguous. Could you add more details, examples, or anything to make this more clear? |
||
| the above mentioned `param5` as true in the `JointTrainingSparseNetwork` algorithm. | ||
|
|
||
| <a name="pipeline"> | ||
| ##Pipelines. | ||
| Building pipelines is naturally granted in Saul. The programmer can simply define properties that are the predictions of | ||
| the classifiers and use those outputs as the input of other classifiers by mentioning them in the list of the features. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change "features" to "properties"? |
||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't we include an imaginary example (like the imaginary scenario above for constrained classifier) explaining how things work. The one I mentioned is not good? object ClassifierLayer1 extends Learnable (node) {
def label = labelProperty1
def feature = using(property2, property3,...)
}
object ClassifierLayer2 extends Learnable (node) {
def label = labelProperty2
def feature = using(classifier1Labels, ,...) // using the prediction of the classifier in the previous layer
}
// defined in data-model object
val classifier1Labels = new Property(node){ x: Type => ClassifierLayer1(x) }
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought a link to the actual working example, which is similar to this one would be enough. I can add this too to the documentation if you really like it. |
||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be great if we add a very simple example. For example sth like this: object ClassifierLayer1 extends Learnable (node) {
def label = labelProperty1
def feature = using(property2, property3,...)
}
object ClassifierLayer2 extends Learnable (node) {
def label = labelProperty2
def feature = using(classifier1Labels, ,...) // using the prediction of the classifier in the previous layer
}
// defined in data-model
val classifier1Labels = new Property(node){ x: Type => ClassifierLayer1(x) } |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,16 +18,16 @@ object JointTrainSparseNetwork { | |
|
|
||
| val logger: Logger = LoggerFactory.getLogger(this.getClass) | ||
| var difference = 0 | ||
| def apply[HEAD <: AnyRef](node: Node[HEAD], cls: List[ConstrainedClassifier[_, HEAD]], init: Boolean)(implicit headTag: ClassTag[HEAD]) = { | ||
| train[HEAD](node, cls, 1, init) | ||
| def apply[HEAD <: AnyRef](node: Node[HEAD], cls: List[ConstrainedClassifier[_, HEAD]], init: Boolean, lossAugmented: Boolean)(implicit headTag: ClassTag[HEAD]) = { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you add a doc to this function and explain what it does as well as the parameters?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually here what I meant was documentation for the function. |
||
| train[HEAD](node, cls, 1, init, lossAugmented) | ||
| } | ||
|
|
||
| def apply[HEAD <: AnyRef](node: Node[HEAD], cls: List[ConstrainedClassifier[_, HEAD]], it: Int, init: Boolean)(implicit headTag: ClassTag[HEAD]) = { | ||
| train[HEAD](node, cls, it, init) | ||
| def apply[HEAD <: AnyRef](node: Node[HEAD], cls: List[ConstrainedClassifier[_, HEAD]], it: Int, init: Boolean, lossAugmented: Boolean = false)(implicit headTag: ClassTag[HEAD]) = { | ||
| train[HEAD](node, cls, it, init, lossAugmented) | ||
| } | ||
|
|
||
| @scala.annotation.tailrec | ||
| def train[HEAD <: AnyRef](node: Node[HEAD], cls: List[ConstrainedClassifier[_, HEAD]], it: Int, init: Boolean)(implicit headTag: ClassTag[HEAD]): Unit = { | ||
| def train[HEAD <: AnyRef](node: Node[HEAD], cls: List[ConstrainedClassifier[_, HEAD]], it: Int, init: Boolean, lossAugmented: Boolean = false)(implicit headTag: ClassTag[HEAD]): Unit = { | ||
| // forall members in collection of the head (dm.t) do | ||
| logger.info("Training iteration: " + it) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add an assertion here to check that the base classifiers are of the type
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I already had a line about it in the new documentation. |
||
| if (init) ClassifierUtils.InitializeClassifiers(node, cls: _*) | ||
|
|
@@ -43,19 +43,24 @@ object JointTrainSparseNetwork { | |
| if (idx % 5000 == 0) | ||
| logger.info(s"Training: $idx examples inferred.") | ||
|
|
||
| cls.foreach { | ||
| case classifier: ConstrainedClassifier[_, HEAD] => | ||
| val typedClassifier = classifier.asInstanceOf[ConstrainedClassifier[_, HEAD]] | ||
| val oracle = typedClassifier.onClassifier.getLabeler | ||
| if (lossAugmented) | ||
| cls.foreach { cls_i => | ||
| cls_i.onClassifier.classifier.setLossFlag() | ||
| cls_i.onClassifier.classifier.setCandidates(cls_i.getCandidates(h).size * cls.size) | ||
| } | ||
|
|
||
| typedClassifier.getCandidates(h) foreach { | ||
| cls.foreach { | ||
| currentClassifier: ConstrainedClassifier[_, HEAD] => | ||
| val oracle = currentClassifier.onClassifier.getLabeler | ||
| val baseClassifier = currentClassifier.onClassifier.classifier.asInstanceOf[SparseNetworkLearner] | ||
| currentClassifier.getCandidates(h) foreach { | ||
| candidate => | ||
| { | ||
| def trainOnce() = { | ||
| val result = typedClassifier.classifier.discreteValue(candidate) | ||
|
|
||
| val result = currentClassifier.classifier.discreteValue(candidate) | ||
| val trueLabel = oracle.discreteValue(candidate) | ||
| val ilearner = typedClassifier.onClassifier.classifier.asInstanceOf[SparseNetworkLearner] | ||
| val lLexicon = typedClassifier.onClassifier.getLabelLexicon | ||
| val lLexicon = currentClassifier.onClassifier.getLabelLexicon | ||
| var LTU_actual: Int = 0 | ||
| var LTU_predicted: Int = 0 | ||
| for (i <- 0 until lLexicon.size()) { | ||
|
|
@@ -69,26 +74,26 @@ object JointTrainSparseNetwork { | |
| // and the LTU of the predicted class should be demoted. | ||
| if (!result.equals(trueLabel)) //equals("true") && trueLabel.equals("false") ) | ||
| { | ||
| val a = typedClassifier.onClassifier.getExampleArray(candidate) | ||
| val a = currentClassifier.onClassifier.getExampleArray(candidate) | ||
| val a0 = a(0).asInstanceOf[Array[Int]] //exampleFeatures | ||
| val a1 = a(1).asInstanceOf[Array[Double]] // exampleValues | ||
| val exampleLabels = a(2).asInstanceOf[Array[Int]] | ||
| val label = exampleLabels(0) | ||
| var N = ilearner.getNetwork.size | ||
| var N = baseClassifier.getNetwork.size | ||
|
|
||
| if (label >= N || ilearner.getNetwork.get(label) == null) { | ||
| val conjugateLabels = ilearner.isUsingConjunctiveLabels | ilearner.getLabelLexicon.lookupKey(label).isConjunctive | ||
| ilearner.setConjunctiveLabels(conjugateLabels) | ||
| if (label >= N || baseClassifier.getNetwork.get(label) == null) { | ||
| val conjugateLabels = baseClassifier.isUsingConjunctiveLabels | baseClassifier.getLabelLexicon.lookupKey(label).isConjunctive | ||
| baseClassifier.setConjunctiveLabels(conjugateLabels) | ||
|
|
||
| val ltu: LinearThresholdUnit = ilearner.getBaseLTU | ||
| ltu.initialize(ilearner.getNumExamples, ilearner.getNumFeatures) | ||
| ilearner.getNetwork.set(label, ltu) | ||
| val ltu: LinearThresholdUnit = baseClassifier.getBaseLTU.clone().asInstanceOf[LinearThresholdUnit] | ||
| ltu.initialize(baseClassifier.getNumExamples, baseClassifier.getNumFeatures) | ||
| baseClassifier.getNetwork.set(label, ltu) | ||
| N = label + 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is not required. Also N can be made a val. |
||
| } | ||
|
|
||
| // test push | ||
| val ltu_actual = ilearner.getLTU(LTU_actual).asInstanceOf[LinearThresholdUnit] | ||
| val ltu_predicted = ilearner.getLTU(LTU_predicted).asInstanceOf[LinearThresholdUnit] | ||
| val ltu_actual = baseClassifier.getLTU(LTU_actual).asInstanceOf[LinearThresholdUnit] | ||
| val ltu_predicted = baseClassifier.getLTU(LTU_predicted).asInstanceOf[LinearThresholdUnit] | ||
|
|
||
| if (ltu_actual != null) | ||
| ltu_actual.promote(a0, a1, 0.1) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are promoting/demoting by a fixed update of 0.1, shouldn't we take into account the learning rate parameter. The update rule inside LinearThresholdUnit's learn function is according to the learning rate and margin thickness.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, this has remained here from my very first trial version. How should I pass the parameters, do you think that I just add it to the list of input parameters? Since we have two apply versions it can not have the default value for both cases as well, I guess. Isn't it a separate issue to have a consistent way for parameter setting in Saul?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The baseLTU already has all parameters to use. We can directly call the learn function to use those parameters. val labelValues = a(3).asInstanceOf[Array[Double]]
if (ltu_actual != null) {
# Learn as Positive Example
ltu_actual.learn(a0, a1, Array(1), labelValues)
}
if (ltu_predicted != null) {
# Learn as a negative example
ltu_predicted.learn(a0, a1, Array(0), labelValues)
}Also it might be better to rename all the variables
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. call
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. learn does not use internal prediction result?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Learn promotes or demotes the LTU's weight vector. The third argument controls if promote should be called or demote should be called.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about the score,
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks fine if we cannot use learn. My only concern was using that having a fixed learning rate might affect performance. We can fix that separately. |
||
|
|
@@ -100,8 +105,13 @@ object JointTrainSparseNetwork { | |
| trainOnce() | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } | ||
| if (lossAugmented) | ||
| cls.foreach { cls_i => | ||
| cls_i.onClassifier.classifier.unsetLossFlag() | ||
| } | ||
| } | ||
| train(node, cls, it - 1, false) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,7 @@ object InitSparseNetwork { | |
| if (label >= N || iLearner.getNetwork.get(label) == null) { | ||
| val isConjunctiveLabels = iLearner.isUsingConjunctiveLabels | iLearner.getLabelLexicon.lookupKey(label).isConjunctive | ||
| iLearner.setConjunctiveLabels(isConjunctiveLabels) | ||
| val ltu: LinearThresholdUnit = iLearner.getBaseLTU | ||
| val ltu: LinearThresholdUnit = iLearner.getBaseLTU.clone().asInstanceOf[LinearThresholdUnit] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the necessity for
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this bug was caught by @bhargav, it needs to create a new instance of linear threshold here each time a new label is met. This was the main bug for the SparseNetwork initialization. |
||
| ltu.initialize(iLearner.getNumExamples, iLearner.getNumFeatures) | ||
| iLearner.getNetwork.set(label, ltu) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /** This software is released under the University of Illinois/Research and Academic Use License. See | ||
| * the LICENSE file in the root folder for details. Copyright (c) 2016 | ||
| * | ||
| * Developed by: The Cognitive Computations Group, University of Illinois at Urbana-Champaign | ||
| * http://cogcomp.cs.illinois.edu/ | ||
| */ | ||
| package edu.illinois.cs.cogcomp.saulexamples.Badge; | ||
|
|
||
| import java.io.BufferedReader; | ||
| import java.io.FileInputStream; | ||
| import java.io.InputStreamReader; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class BadgeReader { | ||
| public List<String> badges; | ||
|
|
||
| public BadgeReader(String dataFile) { | ||
| badges = new ArrayList<String>(); | ||
|
|
||
| try { | ||
| BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(dataFile))); | ||
|
|
||
| String str; | ||
| while ((str = br.readLine()) != null) { | ||
| badges.add(str); | ||
| } | ||
|
|
||
| br.close(); | ||
| }catch (Exception e) {} | ||
| } | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you apply the autoformatter on this file? |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| /** This software is released under the University of Illinois/Research and Academic Use License. See | ||
| * the LICENSE file in the root folder for details. Copyright (c) 2016 | ||
| * | ||
| * Developed by: The Cognitive Computations Group, University of Illinois at Urbana-Champaign | ||
| * http://cogcomp.cs.illinois.edu/ | ||
| */ | ||
| package edu.illinois.cs.cogcomp.saulexamples.Badge | ||
|
|
||
| import edu.illinois.cs.cogcomp.lbjava.learn.{ SparseNetworkLearner, SparsePerceptron } | ||
| import edu.illinois.cs.cogcomp.saul.classifier.Learnable | ||
| import edu.illinois.cs.cogcomp.saulexamples.Badge.BadgeDataModel._ | ||
| /** Created by Parisa on 9/13/16. | ||
| */ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drop the comment? |
||
|
|
||
| object BadgeClassifiers { | ||
|
|
||
| /*a binary classifier that predicts the badge label*/ | ||
| object BadgeClassifier extends Learnable[String](badge) { | ||
| def label = BadgeLabel | ||
| override lazy val classifier = new SparsePerceptron() | ||
| override def feature = using(BadgeFeature1) | ||
| } | ||
| /*a binary classifier that predicts a lable that is exactly the opposite of the badge label of the BadgeClassifier*/ | ||
| object BadgeOppositClassifier extends Learnable[String](badge) { | ||
| def label = BadgeOppositLabel | ||
| override lazy val classifier = new SparsePerceptron() | ||
| override def feature = using(BadgeFeature1) | ||
| } | ||
| /*This is a multi-class classifier version of the above binary BadgeClassifier, | ||
| it uses SparseNetworks instead of SparsePerceptrons*/ | ||
| object BadgeClassifierMulti extends Learnable[String](badge) { | ||
| def label = BadgeLabel | ||
| override lazy val classifier = new SparseNetworkLearner() | ||
| override def feature = using(BadgeFeature1) | ||
| } | ||
| /*This is the opposite multi-class classifier of the BadgeClassifierMulti */ | ||
| object BadgeOppositClassifierMulti extends Learnable[String](badge) { | ||
| def label = BadgeOppositLabel | ||
| override lazy val classifier = new SparseNetworkLearner() | ||
| override def feature = using(BadgeFeature1) | ||
| } | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you add a little comment to each of these classifiers? |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /** This software is released under the University of Illinois/Research and Academic Use License. See | ||
| * the LICENSE file in the root folder for details. Copyright (c) 2016 | ||
| * | ||
| * Developed by: The Cognitive Computations Group, University of Illinois at Urbana-Champaign | ||
| * http://cogcomp.cs.illinois.edu/ | ||
| */ | ||
| package edu.illinois.cs.cogcomp.saulexamples.Badge | ||
|
|
||
| import edu.illinois.cs.cogcomp.infer.ilp.OJalgoHook | ||
| import edu.illinois.cs.cogcomp.saul.classifier.ConstrainedClassifier | ||
| import edu.illinois.cs.cogcomp.saul.constraint.ConstraintTypeConversion._ | ||
| import edu.illinois.cs.cogcomp.saulexamples.Badge.BadgeClassifiers.{ BadgeOppositClassifierMulti, BadgeClassifierMulti, BadgeClassifier, BadgeOppositClassifier } | ||
|
|
||
| /** Created by Parisa on 11/1/16. | ||
| */ | ||
| object BadgeConstraintClassifiers { | ||
|
|
||
| val binaryConstraint = ConstrainedClassifier.constraint[String] { | ||
| x: String => | ||
| (BadgeClassifier on x is "negative") ==> (BadgeOppositClassifier on x is "positive") | ||
| } | ||
|
|
||
| val binaryConstraintOverMultiClassifiers = ConstrainedClassifier.constraint[String] { | ||
| x: String => | ||
| (BadgeClassifierMulti on x is "negative") ==> (BadgeOppositClassifierMulti on x is "positive") | ||
| } | ||
| object badgeConstrainedClassifier extends ConstrainedClassifier[String, String](BadgeClassifier) { | ||
| def subjectTo = binaryConstraint | ||
| override val solver = new OJalgoHook | ||
| } | ||
|
|
||
| object oppositBadgeConstrainedClassifier extends ConstrainedClassifier[String, String](BadgeOppositClassifier) { | ||
| def subjectTo = binaryConstraint | ||
| override val solver = new OJalgoHook | ||
| } | ||
|
|
||
| object badgeConstrainedClassifierMulti extends ConstrainedClassifier[String, String](BadgeClassifierMulti) { | ||
| def subjectTo = binaryConstraintOverMultiClassifiers | ||
| override val solver = new OJalgoHook | ||
| } | ||
|
|
||
| object oppositBadgeConstrainedClassifierMulti extends ConstrainedClassifier[String, String](BadgeOppositClassifierMulti) { | ||
| def subjectTo = binaryConstraintOverMultiClassifiers | ||
| override val solver = new OJalgoHook | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a page title here?
For example