[thebeast] r737 committed - refactoring learning interface: now learning is argmaxing, too

1 view
Skip to first unread message

codesite...@google.com

unread,
Mar 25, 2010, 7:42:05 PM3/25/10
to thebeas...@googlegroups.com
Revision: 737
Author: sebastian.riedel
Date: Thu Mar 25 16:41:48 2010
Log: refactoring learning interface: now learning is argmaxing, too
http://code.google.com/p/thebeast/source/detail?r=737

Modified:

/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/env/Term.scala

/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/env/doubles/DoubleTerm.scala

/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/learn/OnlineLearner.scala

/branches/thefuture-modules/thebeast-core/src/test/scala/org/riedelcastro/thebeast/learn/OnlineLearnerSpecification.scala

=======================================
---
/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/env/Term.scala
Wed Mar 24 22:06:14 2010
+++
/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/env/Term.scala
Thu Mar 25 16:41:48 2010
@@ -33,7 +33,7 @@
def simplify: Term[T]

/**
- * Replace the free variables in this term which are set in the
specified environment
+ * Replace the variables in this term with the values/constants they are
bound to in the specified environment
*/
def ground(env: Env): Term[T]

@@ -90,7 +90,10 @@

def members: Seq[M] = Seq(member)

- def variables: Set[EnvVar[Any]] = members.foldLeft(Set[EnvVar[Any]]())
{(a,m)=> a ++ m.variables}
+ def variables: Set[EnvVar[Any]] = members.foldLeft(Set[EnvVar[Any]]())
{(a, m) => a ++ m.variables}
+
+
+ def subterms: Seq[Term[Any]] = members.map(_.asInstanceOf[Term[Any]])
}

trait Composite2[V, T <: Term[V], M <: Term[_], M1 <: M, M2 <: M] extends
Composite[V, T, M] {
@@ -393,21 +396,29 @@
}


-
-case class InEnv[T](term:Term[T],env:Env) extends Term[T] with
Composite1[T,InEnv[T],Term[T]] {
- def eval(env: Env): Option[T] = {
- term.eval(env.overlay(this.env))
+/**
+ * A DependsOn term, when evaluated on a world,
+ * bounds every variable in the inner term to its default value, unless it
is in the hidden
+ * set of variables. Hence the term is guaranteed to yield a Non-None
result
+ * when all of the hidden variables are bound, and this result only
depends on
+ * the hidden variable assignments.
+ */
+case class DependsOn[V, T <: Term[V]](term: T, hidden: Set[EnvVar[_]])
extends Composite1[V, DependsOn[V, T], T] {
+ def values: Values[V] = term.values
+
+ def simplify: Term[V] = DependsOn[V,Term[V]](term.simplify, hidden)
+
+ def eval(env: Env): Option[V] = {
+ val closed = new MutableEnv
+ for (variable <- term.variables; if (!hidden(variable)))
closed.close(variable, true)
+ term.eval(env.overlay(closed))
}

- def values: Values[T] = term.values
-
- def simplify: Term[T] = term.simplify match {case c:Constant[_] => c;
case x => InEnv(x,env)}
-
- def member: Term[T] = term
-
- def build(member: Term[T]): InEnv[T] = InEnv(member,env)
-
- def subterms: Seq[Term[Any]] = Seq(term)
+ override def variables: Set[EnvVar[Any]] = hidden
+
+ def member: T = term
+
+ def build(member: T): DependsOn[V, T] = DependsOn(member, hidden)
}


@@ -415,4 +426,3 @@

-
=======================================
---
/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/env/doubles/DoubleTerm.scala
Wed Mar 24 22:06:14 2010
+++
/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/env/doubles/DoubleTerm.scala
Thu Mar 25 16:41:48 2010
@@ -32,6 +32,14 @@

def flatten: DoubleTerm = this

+ def apply(variables:EnvVar[_]*) = {
+ DoubleDependsOn(Set() ++ variables,this)
+ }
+
+ def ~(variables:EnvVar[_]*) = {
+ DoubleDependsOn(Set() ++ variables,this)
+ }
+
}


@@ -252,6 +260,16 @@


}
+
+case class DoubleDependsOn(override val hidden:Set[EnvVar[_]],override val
term:DoubleTerm)
+ extends DependsOn[Double,DoubleTerm](term,hidden) with DoubleTerm {
+ def upperBound: Double = term.upperBound
+
+
+ override def ground(env: Env) = DoubleDependsOn(hidden,term.ground(env))
+
+ override def simplify = DoubleDependsOn(hidden, term.simplify)
+}

object Add extends (Double => (Double => Double)) {
def apply(arg1: Double): (Double => Double) = (arg2: Double) => arg1 +
arg2
=======================================
---
/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/learn/OnlineLearner.scala
Wed Mar 24 22:06:14 2010
+++
/branches/thefuture-modules/thebeast-core/src/main/scala/org/riedelcastro/thebeast/learn/OnlineLearner.scala
Thu Mar 25 16:41:48 2010
@@ -2,10 +2,10 @@


import org.riedelcastro.thebeast.solve.{ExhaustiveSearch, ArgmaxSolver}
-import org.riedelcastro.thebeast.env.MaskedEnv
import org.riedelcastro.thebeast.env.vectors.{VectorTerm, Vector}
import org.riedelcastro.thebeast.util.Trackable
-import org.riedelcastro.thebeast.env.doubles.{LogLinear, Normalize,
SumOverGroundings, DoubleTerm}
+import org.riedelcastro.thebeast.env.{MutableEnv, DependsOn, MaskedEnv}
+import org.riedelcastro.thebeast.env.doubles._

/**
* @author Sebastian Riedel
@@ -19,8 +19,12 @@

def argmax(term: DoubleTerm): ArgmaxResult = {
term match {
- case SumOverGroundings(Normalize(LogLinear(feature, weights, _)),
data)
- if (Set(weights) == term.variables) => CantSolve
+ case
DoubleDependsOn(theta,SumOverGroundings(Normalize(DoubleDependsOn(hidden,
LogLinear(feature, weights, _))), data))
+ if (Set(weights) == theta) => {
+ val result = new MutableEnv
+ result.set(weights,learn(feature,data.map(new
MaskedEnv(_,hidden))))
+ ArgmaxResult(result, Status.Solved, Math.NEG_INF_DOUBLE)
+ }
case _ => CantSolve
}
}
=======================================
---
/branches/thefuture-modules/thebeast-core/src/test/scala/org/riedelcastro/thebeast/learn/OnlineLearnerSpecification.scala
Sun Mar 14 23:39:26 2010
+++
/branches/thefuture-modules/thebeast-core/src/test/scala/org/riedelcastro/thebeast/learn/OnlineLearnerSpecification.scala
Thu Mar 25 16:41:48 2010
@@ -3,9 +3,10 @@
import org.specs._
import runner.JUnit4
import org.riedelcastro.thebeast.solve.ExhaustiveSearch
-import org.riedelcastro.thebeast.env.vectors.UnitVector
import org.riedelcastro.thebeast.CitationMatchingFixtures
-import org.riedelcastro.thebeast.env.TheBeastEnv
+import org.riedelcastro.thebeast.env.doubles.{SumOverGroundings, LogLinear}
+import org.riedelcastro.thebeast.env.{MutableEnv, Env, TheBeastEnv}
+import org.riedelcastro.thebeast.env.vectors.{Vector, VectorVar,
UnitVector}

/**
* @author Sebastian Riedel
@@ -18,27 +19,42 @@
"separate data if data is separable" in {

//todo: factor out this training set
- var y1 = createWorldWhereABAreSimilarAndSame
- var y2 = createWorldWhereABAreSimilarButABCAreSame
-
- var features =
+ val y1 = createWorldWhereABAreSimilarAndSame
+ val y2 = createWorldWhereABAreSimilarButABCAreSame
+
+ val trainingSet = Seq(y1,y2).map(y => y.mask(Set(same)))
+
+ val features =
vectorSum(Citations,Citations)
{(c1,c2)=>$(similar(c1,c2) ~> same(c1,c2)) *
UnitVector("similar")} +
vectorSum(Citations,Citations,Citations)
{(c1,c2,c3)=>$((same(c1,c2) && same(c2,c3)) ~>
same(c1,c3)) * UnitVector("trans")}
- var trainingSet = Seq(y1,y2).map(y => y.mask(Set(same)))
-
- var learner = new OnlineLearner
-
- learner.maxEpochs = 1
-
- var weights = learner.learn(features,trainingSet)
-
- for (y <- trainingSet){
- var score = (features dot weights).ground(y)
- var guess = ExhaustiveSearch.argmax(score).result
- y.unmasked(same).getSources(Some(true)) must_==
guess(same).getSources(Some(true))
- }
+
+ val theta = new VectorVar("theta")
+ val unnormalized = LogLinear(features, theta, 0.0) ~ same
+ val model = normalize(unnormalized)
+ val ll = SumOverGroundings(model,Seq(y1,y2)) ~ theta
+
+
+ val learner = new OnlineLearner
+
+ learner.maxEpochs = 1
+ val result = learner.argmax(ll)
+
+ for (y:Env <- Seq(y1,y2)){
+ val objective =
unnormalized.ground(y.mask(Set(same)).overlay(result.result))
+ val guess = ExhaustiveSearch.argmax(objective).result
+ y(same).getSources(Some(true)) must_==
guess(same).getSources(Some(true))
+ }
+
+
+// val weights = learner.learn(features,trainingSet)
+
+// for (y <- trainingSet){
+// val score = (features dot weights).ground(y)
+// val guess = ExhaustiveSearch.argmax(score).result
+// y.unmasked(same).getSources(Some(true)) must_==
guess(same).getSources(Some(true))
+// }
}
}
}

Reply all
Reply to author
Forward
0 new messages