00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00047
#include <plearn/var/AbsVariable.h>
00048
#include <plearn/var/ConcatColumnsVariable.h>
00049
#include <plearn/var/ConcatRowsVariable.h>
00050
#include <plearn/var/DeterminantVariable.h>
00051
#include <plearn/var/EqualVariable.h>
00052
#include <plearn/var/ExpVariable.h>
00053
#include <plearn/var/ExtendedVariable.h>
00054
#include <plearn/var/LeftPseudoInverseVariable.h>
00055
#include <plearn/var/LogSumVariable.h>
00056
#include <plearn/var/LogVariable.h>
00057
#include <plearn/var/MatrixSumOfVariable.h>
00058
#include <plearn/var/PowVariable.h>
00059
#include <plearn/var/ProductVariable.h>
00060
#include <plearn/var/RightPseudoInverseVariable.h>
00061
#include <plearn/var/SoftmaxVariable.h>
00062
#include <plearn/var/SumOfVariable.h>
00063
#include <plearn/var/SumVariable.h>
00064
00065
#include <plearn/base/general.h>
00066
#include "RandomVar.h"
00067
00068
00069
#include <plearn/math/plapack.h>
00070
#include <plearn/var/Var_operators.h>
00071
00072
00073
namespace PLearn {
00074
using namespace std;
00075
00076 RandomVar::RandomVar()
00077 :
PP<
RandomVariable>(new
NonRandomVariable(1)) {}
00078 RandomVar::RandomVar(
RandomVariable* v)
00079 :
PP<
RandomVariable>(v) {}
00080 RandomVar::RandomVar(
const RandomVar& other)
00081 :
PP<
RandomVariable>(other) {}
00082 RandomVar::RandomVar(
int length,
int width)
00083 :
PP<
RandomVariable>(new
NonRandomVariable(length,width)) {}
00084
00085 RandomVar::RandomVar(
const Vec& vec)
00086 :
PP<
RandomVariable>(new
NonRandomVariable(
Var(vec))) {}
00087 RandomVar::RandomVar(
const Mat& mat)
00088 :
PP<
RandomVariable>(new
NonRandomVariable(
Var(mat))) {}
00089 RandomVar::RandomVar(
const Var& v)
00090 :
PP<
RandomVariable>(new
NonRandomVariable(v)) {}
00091
00092 RandomVar::RandomVar(
const RVArray& rvars)
00093 :
PP<
RandomVariable>(new
JointRandomVariable(rvars)) {}
00094
00095 RandomVar RandomVar::operator[](
RandomVar index)
00096 {
return new RandomElementOfRandomVariable((*
this),index); }
00097
00098 void RandomVar::operator=(
const RVArray& vars)
00099 { *
this =
RandomVar(vars); }
00100
00101 void RandomVar::operator=(
real f)
00102 {
00103
if (!(*this)->isNonRandom())
00104
PLERROR(
"RandomVar: can't assign values to a truly random RV");
00105 (*this)->value->value.fill(f);
00106 }
00107
00108 void RandomVar::operator=(
const Vec& v)
00109 {
00110
if (!(*this)->isNonRandom())
00111
PLERROR(
"RandomVar: can't assign a values to a truly random RV");
00112 (*this)->value->value << v;
00113 }
00114
00115 void RandomVar::operator=(
const Mat& m)
00116 {
00117
if (!(*this)->isNonRandom())
00118
PLERROR(
"RandomVar: can't assign a Var to a truly random RV");
00119
Var v(m);
00120 (*this)->value = v;
00121 }
00122
00123 void RandomVar::operator=(
const Var& v)
00124 {
00125
if (!(*this)->isNonRandom())
00126
PLERROR(
"RandomVar: can't assign a Var to a truly random RV");
00127 (*this)->value = v;
00128 }
00129
00130 RVInstance RandomVar::operator==(
const Var& v)
const
00131
{
00132
return RVInstance(*
this,v);
00133 }
00134
00135
00136 RVArray RandomVar::operator&(
const RandomVar& v)
const
00137
{
00138
return RVArray(*
this,v,10);
00139 }
00140
00141 ConditionalExpression RandomVar::operator|(
RVArray a)
const
00142
{
00143
RVInstanceArray rvia(a.
size());
00144
for (
int i=0;i<a.
size();i++)
00145 {
00146 rvia[i].V = a[i];
00147 rvia[i].v = a[i]->value;
00148 }
00149
return ConditionalExpression(
RVInstance(*
this,
Var((*this)->length())),rvia);
00150 }
00151
00152 ConditionalExpression RandomVar::operator|(
RVInstanceArray rhs)
const
00153
{
00154
return ConditionalExpression(
RVInstance(*
this,
Var((*this)->length())),rhs);
00155 }
00156
00157
#if 0
00158
00159
RandomVar RandomVar::operator[](
RandomVar index)
00160 {
return matRandomVarElement(*
this,index); }
00161
00162 Vec RandomVar::operator[](
int i)
00163 {
return matRandomVarElement(*
this,i); }
00164
00165 RandomVar RandomVar::operator()(RandomVar i, RandomVar j)
00166 {
00167
return
00168
new RandomElementOfRandomVariable(*
this,i*((
real)((*this)->value->matValue.width()))+j);
00169 }
00170
00171
real& RandomVar::operator()(
int i,
int j)
00172 {
00173
return new RandomVarElement(*
this,i*((
real)((*this)->value->matValue.width()))+j);
00174 }
00175
00176
#endif
00177
00178
00179
00182 int RandomVariable::rv_counter = 0;
00183
00184 RandomVariable::RandomVariable(
int thelength,
int thewidth)
00185 :rv_number(rv_counter++), value(thelength,thewidth),marked(false),
00186 EMmark(false), pmark(false), learn_the_parameters(0)
00187 {
00188 }
00189
00190 RandomVariable::RandomVariable(
const Vec& the_value)
00191 :rv_number(rv_counter++), value(the_value),marked(false), EMmark(false)
00192 , pmark(false), learn_the_parameters(0)
00193 {
00194 }
00195
00196 RandomVariable::RandomVariable(
const Mat& the_value)
00197 :rv_number(rv_counter++), value(the_value),marked(false), EMmark(false),
00198 pmark(false), learn_the_parameters(0)
00199 {
00200 }
00201
00202 RandomVariable::RandomVariable(
const Var& the_value)
00203 :rv_number(rv_counter++), value(the_value),marked(false), EMmark(false),
00204 pmark(false), learn_the_parameters(0)
00205 {
00206 }
00207
00208 RandomVariable::RandomVariable(
const RVArray& the_parents,
int thelength)
00209 :rv_number(rv_counter++),
00210 parents(the_parents), value(thelength), marked(false), EMmark(false),
00211 pmark(false), learn_the_parameters(new
bool[the_parents.size()])
00212 {
00213 }
00214
00215 RandomVariable::RandomVariable(
const RVArray& the_parents,
int thelength,
00216
int thewidth)
00217 : rv_number(rv_counter++),
00218 parents(the_parents), value(thelength,thewidth),marked(false),
00219 EMmark(false), pmark(false),
00220 learn_the_parameters(new
bool[the_parents.size()])
00221 {
00222 }
00223
00224
00225 RandomVar RandomVariable::subVec(
int start,
int length) {
00226
return new SubVecRandomVariable(
this,start,length);
00227 }
00228
00229 real RandomVariable::EM(
const RVArray& parameters_to_learn,
00230
VarArray& prop_path,
VarArray& observedVars,
VMat distr,
int n_samples,
00231
int max_n_iterations,
real relative_improvement_threshold,
00232
bool accept_worsening_likelihood)
00233 {
00234
real avgnegloglik = 0;
00235
real previous_nll=FLT_MAX, nll_change;
00236
bool EMfinished= !(max_n_iterations>0);
00237
int n_epochs=0;
00238
00239
EMTrainingInitialize(parameters_to_learn);
00240
clearEMmarks();
00241
while (!EMfinished) {
00242 avgnegloglik=
epoch(prop_path, observedVars, distr,n_samples);
00243 cout <<
"EM epoch NLL = " << avgnegloglik <<
endl;
00244 nll_change = (previous_nll - avgnegloglik)/fabs(previous_nll);
00245
if (nll_change < -1e-4 && !accept_worsening_likelihood)
00246 printf(
"%s %s from %f to %f\n",
"RandomVariable::EM",
00247
"An EM epoch yielded worse negative log-likelihood,",
00248 previous_nll, avgnegloglik);
00249 n_epochs++;
00250 EMfinished =
canStopEM() &&
00251 ((n_epochs >= max_n_iterations) ||
00252 (fabs(nll_change) <= relative_improvement_threshold) ||
00253 (!accept_worsening_likelihood &&
00254 nll_change <= relative_improvement_threshold));
00255 previous_nll=avgnegloglik;
00256 }
00257
return avgnegloglik;
00258 }
00259
00260 real RandomVariable::epoch(
VarArray& prop_path,
00261
VarArray& observed_vars,
00262
const VMat& distr,
int n_samples,
00263
bool do_EM_learning)
00264 {
00265
real avg_cost = 0;
00266
if (do_EM_learning)
00267 {
00268
EMEpochInitialize();
00269
clearEMmarks();
00270 }
00271
for (
int i=0;i<n_samples;i++)
00272 {
00273
Vec sam(distr->
width());
00274 distr->getRow(i,sam);
00275 observed_vars << sam;
00276 prop_path.
fprop();
00277
Var logp = prop_path.
last();
00278
00279
#if 0
00280
00281 cout <<
"at example i=" << i <<
endl;
00282
VarArray sources = logp->sources();
00283 logp->unmarkAncestors();
00284 sources.
printInfo();
00285 prop_path.
printInfo();
00286
#endif
00287
00288 avg_cost -= logp->value[0];
00289
if (do_EM_learning)
00290
00291
EMBprop(observed_vars.
last()->value,1.0);
00292 }
00293
00294
if (do_EM_learning)
00295 {
00296
EMUpdate();
00297
clearEMmarks();
00298 }
00299
return avg_cost / n_samples;
00300 }
00301
00302 void RandomVariable::unmarkAncestors()
00303 {
00304
if (
pmark)
00305 {
00306
marked=
false;
00307
pmark=
false;
00308
for (
int i=0;i<
parents.
size();i++)
00309
parents[i]->unmarkAncestors();
00310 }
00311 }
00312
00313 void RandomVariable::clearEMmarks()
00314 {
00315
if (
EMmark)
00316 {
00317
EMmark=
false;
00318
for (
int i=0;i<
parents.
size();i++)
00319
parents[i]->clearEMmarks();
00320 }
00321 }
00322
00323 void RandomVariable::setKnownValues()
00324 {
00325
if (!
pmark && !
marked)
00326 {
00327
pmark=
true;
00328
bool all_parents_marked=
true;
00329
for (
int i=0;i<
parents.
size();i++)
00330 {
00331
parents[i]->setKnownValues();
00332 all_parents_marked &=
parents[i]->isMarked();
00333 }
00334
setValueFromParentsValue();
00335
if (all_parents_marked)
00336
marked=
true;
00337 }
00338 }
00339
00340 void RandomVariable::EMUpdate()
00341 {
00342
if (
EMmark)
return;
00343
EMmark=
true;
00344
for (
int i=0;i<
parents.
size();i++)
00345
if (!
parents[i]->isConstant())
parents[i]->EMUpdate();
00346 }
00347
00348 bool RandomVariable::canStopEM()
00349 {
00350
00351
bool can=
true;
00352
for (
int i=0;i<
parents.
size() && !can;i++)
00353 can =
parents[i]->canStopEM();
00354
return can;
00355 }
00356
00357
void RandomVariable::
00358 EMTrainingInitialize(
const RVArray& parameters_to_learn)
00359 {
00360
if (
EMmark)
return;
00361
EMmark=
true;
00362
int n_can_learn=0;
00363
int n_random=0;
00364
for (
int i=0;i<
parents.
size();i++)
00365 {
00366
if (parameters_to_learn.
contains(
parents[i]))
00367 {
00368
if (!
parents[i]->isConstant())
00369
PLERROR(
"Trying to learn a parameter that is not constant!");
00370
learn_the_parameters[i] =
true;
00371 n_can_learn++;
00372 }
00373
else learn_the_parameters[i] =
false;
00374
if (!
parents[i]->isNonRandom())
00375 n_random++;
00376 }
00377
if (n_can_learn>0 && n_random>0)
00378
PLERROR(
"RandomVariable: can't learn some parameter if others are random");
00379
00380
for (
int i=0;i<
parents.
size();i++)
00381
parents[i]->EMTrainingInitialize(parameters_to_learn);
00382 }
00383
00384 void RandomVariable::EMEpochInitialize()
00385 {
00386
if (
EMmark)
return;
00387
EMmark=
true;
00388
for (
int i=0;i<
parents.
size();i++)
00389
parents[i]->EMEpochInitialize();
00390 }
00391
00392 Var RandomVariable::P(
const Var& obs,
const RVInstanceArray& RHS)
00393 {
return exp(
logP(obs,RHS,0)); }
00394
00395
00396 RandomVariable::~RandomVariable()
00397 {
if (
learn_the_parameters)
delete learn_the_parameters; }
00398
00399 Var RandomVariable::ElogP(
const Var& obs,
RVArray& parameters_to_learn,
00400
const RVInstanceArray& RHS)
00401 {
00402
PLERROR(
"ElogP not implemented for this class (%s)",
classname());
00403
return Var(0);
00404 }
00405
00408 RandomVar operator*(
RandomVar a,
RandomVar b)
00409 {
00410
if (a->isScalar() || b->isScalar());
00411
else if (a->isVec() && b->isVec())
00412 {
00413
if (a->length()*a->width() != b->length()*b->width())
00414
PLERROR(
"In RandomVar operator*(RandomVar a, RandomVar b) cannot do a dot product between 2 vecs with different sizes");
00415 }
00416
else if (a->isRowVec())
00417 {
00418
if (a->length() != b->width())
00419
PLERROR(
"In RandomVar operator*(RandomVar a, RandomVar b) in case rowvec times mat: a->length() != b->width()");
00420 }
00421
else if (b->isRowVec())
00422 {
00423
if (b->length() != a->width())
00424
PLERROR(
"In RandomVar operator*(RandomVar a, RandomVar b) in case mat times rowvec: b->length() != a->width()");
00425 }
00426
else
00427
PLERROR(
"In RandomVar operator*(RandomVar a, RandomVar b) This case is not handled (but maybe it should be...)");
00428
00429
return new ProductRandomVariable(a,b);
00430 }
00431
00432 RandomVar operator+(
RandomVar a,
RandomVar b)
00433 {
00434
return new PlusRandomVariable(a,b);
00435 }
00436
00437 RandomVar operator-(
RandomVar a,
RandomVar b)
00438 {
00439
return new MinusRandomVariable(a,b);
00440 }
00441
00442 RandomVar operator/(
RandomVar a,
RandomVar b)
00443 {
00444
return new ElementWiseDivisionRandomVariable(a,b);
00445 }
00446
00447
00448 RandomVar exp(
RandomVar x) {
return new ExpRandomVariable(
x); }
00449
00450
00451 RandomVar log(
RandomVar x) {
return new LogRandomVariable(
x); }
00452
00453 RandomVar extend(
RandomVar v,
real extension_value,
int n_extend)
00454 {
return new ExtendedRandomVariable(v,extension_value,n_extend); }
00455
00456 RandomVar hconcat(
const RVArray& a)
00457 {
return new ConcatColumnsRandomVariable(a); }
00458
00459
00460 real EM(
ConditionalExpression conditional_expression,
00461
RVArray parameters_to_learn,
00462
VMat distr,
int n_samples,
int max_n_iterations,
00463
real relative_improvement_threshold,
00464
bool accept_worsening_likelihood,
00465
bool compute_final_train_NLL)
00466 {
00467
00468
RandomVar& LHS=conditional_expression.
LHS.
V;
00469
Var& lhs_observation=conditional_expression.
LHS.
v;
00470
VarArray prop_input_vars;
00472
00473
00474
00475
00477
VarArray distr_observed_vars =
00478 conditional_expression.
RHS.
instances() & (
VarArray)lhs_observation;
00479
00480
00481
00482
Var logp =
logP(conditional_expression,
false);
00483
VarArray prop_path =
00484
propagationPath(distr_observed_vars & parameters_to_learn.
values(), logp);
00485
00486
real train_NLL =
00487 LHS->EM(parameters_to_learn,prop_path,distr_observed_vars, distr,
00488 n_samples, max_n_iterations, relative_improvement_threshold,
00489 accept_worsening_likelihood);
00490
if (compute_final_train_NLL)
00491 train_NLL = LHS->epoch(prop_path,distr_observed_vars,distr,
00492 n_samples,
false);
00493 LHS->unmarkAncestors();
00494
return train_NLL;
00495 }
00496
00497 real EM(
ConditionalExpression conditional_expression,
00498
RVArray parameters_to_learn,
00499
VMat distr,
int n_samples,
int max_n_iterations,
00500
real relative_improvement_threshold,
00501
bool compute_final_train_NLL)
00502 {
00503
00504
RandomVar& LHS=conditional_expression.
LHS.
V;
00505
Var& lhs_observation=conditional_expression.
LHS.
v;
00506
VarArray prop_input_vars;
00508
00509
00510
00511
00513
VarArray distr_observed_vars =
00514 conditional_expression.
RHS.
instances() & (
VarArray)lhs_observation;
00515
00516
00517
00518
RVInstanceArray params_to_learn(parameters_to_learn.
size());
00519
for (
int i=0;i<parameters_to_learn.
size();i++)
00520 {
00521 params_to_learn[i].V=parameters_to_learn[i];
00522
00523 params_to_learn[i].v=
Var(parameters_to_learn[i]->length());
00524
00525 params_to_learn[i].v->value << params_to_learn[i].V->value->value;
00526 }
00527
Var elogp =
ElogP(conditional_expression,params_to_learn,
false);
00528
VarArray new_params = params_to_learn.
instances();
00529
VarArray current_params = parameters_to_learn.
values();
00530
VarArray prop_path =
00531
propagationPath(distr_observed_vars & current_params & new_params, elogp);
00532
00533
00534
00535
00536
00537
int n_free_params = new_params.nelems();
00538
int max_n_Q_iterations = 1 + (
int)(n_free_params*1.5);
00539
Vec params(n_free_params);
00540
00541
Var totalElogP =
meanOf(elogp,distr_observed_vars,
00542 distr,n_samples,new_params);
00543
PLERROR(
"In EM (RandomVar.cc), code using ConjugateGradientOptimizer is now commented out");
00544 max_n_Q_iterations = max_n_Q_iterations;
00545
00546
00547
00548
00549
00550
00551
00552
real avgnegloglik = 0;
00553
real previous_nll=FLT_MAX, nll_change;
00554
bool EMfinished= !(max_n_iterations>0);
00555
int n_epochs=0;
00556
00557
while (!EMfinished) {
00558
00559
PLERROR(
"In EM (RandomVar.cc), code using ConjugateGradientOptimizer is now commented out");
00560
00561 avgnegloglik = - totalElogP->value[0];
00562 cout <<
"EM epoch -Q = " << avgnegloglik <<
endl;
00563 nll_change = (previous_nll - avgnegloglik)/fabs(previous_nll);
00564
if (nll_change < -1e-4)
00565 printf(
"%s %s from %f to %f\n",
"RandomVariable::EM",
00566
"An EM epoch yielded worse negative log-likelihood,",
00567 previous_nll, avgnegloglik);
00568 n_epochs++;
00569 EMfinished =
00570 ((n_epochs >= max_n_iterations) ||
00571 (fabs(nll_change) <= relative_improvement_threshold) ||
00572 nll_change <= relative_improvement_threshold);
00573 previous_nll=avgnegloglik;
00574
00575
00576 new_params >> params;
00577 current_params << params;
00578 }
00579
00580
if (compute_final_train_NLL)
00581 {
00582
Var logp =
logP(conditional_expression,
false);
00583
Var totalLogP =
meanOf(logp,distr_observed_vars,
00584 distr,n_samples,current_params);
00585 totalLogP->fprop();
00586 avgnegloglik = - totalLogP->value[0];
00587 }
00588
00589 LHS->unmarkAncestors();
00590
return avgnegloglik;
00591 }
00592
00593 Var P(
ConditionalExpression conditional_expression,
00594
bool clearMarksUponReturn)
00595 {
00596
RandomVar& LHS = conditional_expression.
LHS.
V;
00597
RVInstanceArray& RHS = conditional_expression.
RHS;
00598
00599
00600
00601
00602 LHS->markRHSandSetKnownValues(RHS);
00603
00604
Var p = LHS->P(conditional_expression.
LHS.
v,RHS);
00605
00606
if (clearMarksUponReturn)
00607
00608 LHS->unmarkAncestors();
00609
00610
00611
00612 p->fprop_from_all_sources();
00613
return p;
00614 }
00615
00616 Var logP(
ConditionalExpression conditional_expression,
bool clearMarksUponReturn,
00617
RVInstanceArray* parameters_to_learn)
00618 {
00619
RandomVar& LHS = conditional_expression.
LHS.
V;
00620
RVInstanceArray& RHS = conditional_expression.
RHS;
00621
00622
00623
00624
00625 LHS->markRHSandSetKnownValues(RHS);
00626
00627
Var logp = LHS->logP(conditional_expression.
LHS.
v,RHS,parameters_to_learn);
00628
00629
if (clearMarksUponReturn)
00630 {
00631
00632 LHS->unmarkAncestors();
00633
for (
int i=0;i<RHS.
size();i++) RHS[i].V->unmark();
00634 }
00635
00636
00637
00638 logp->fprop_from_all_sources();
00639
return logp;
00640 }
00641
00642 Var ElogP(
ConditionalExpression conditional_expression,
00643
RVInstanceArray& parameters_to_learn,
00644
bool clearMarksUponReturn)
00645 {
00646
return logP(conditional_expression,clearMarksUponReturn,¶meters_to_learn);
00647 }
00648
00649
00650
00651
00652
00653 RandomVar marginalize(
const RandomVar& RV,
const RandomVar& hiddenRV)
00654 {
00655
PLERROR(
"marginalize not implemented yet...");
00656
return RandomVar();
00657 }
00658
00659
00660
00661
00662
00663
00664 Vec sample(
ConditionalExpression conditional_expression)
00665 {
00666
Var instance =
Sample(conditional_expression);
00667 instance->fprop_from_all_sources();
00668
return instance->value;
00669 }
00670
00671
00672
00673
00674
00675
00676
00677 void sample(
ConditionalExpression conditional_expression,
Mat& samples)
00678 {
00679
if (samples.
length()==0)
return;
00680
Var instance =
Sample(conditional_expression);
00681 instance->fprop_from_all_sources();
00682 samples(0) << instance->value;
00683
if (samples.
length()>0)
00684 {
00685
VarArray path;
00686 instance->random_sources().setMark();
00687 instance->markPath();
00688 instance->buildPath(path);
00689
00690
for (
int i=1;i<samples.
length();i++)
00691 {
00692 path.
fprop();
00693 samples(i) << instance->value;
00694 }
00695 }
00696 }
00697
00698
00699
00700
00701 Var Sample(
ConditionalExpression conditional_expression)
00702 {
00703
RVInstanceArray& RHS = conditional_expression.
RHS;
00704
RandomVar& LHS = conditional_expression.
LHS.
V;
00705 LHS->markRHSandSetKnownValues(RHS);
00706 LHS->unmarkAncestors();
00707
return LHS->value;
00708 }
00709
00710
00711
00712 RandomVar normal(
real mean,
real standard_dev,
int d,
00713
real minimum_standard_deviation)
00714 {
00715
RandomVar means(d);
00716 means->value->value.fill(
mean);
00717
RandomVar logvar(d);
00718
real variance = standard_dev*standard_dev-
00719 minimum_standard_deviation*minimum_standard_deviation;
00720
if (
variance<=0)
00721
PLERROR(
"normal: variance should be positive");
00722 logvar->value->value.fill((
real)
log((
double)
variance));
00723
return new DiagonalNormalRandomVariable(means,logvar,
00724 minimum_standard_deviation);
00725 }
00726
00727
00728
00729 RandomVar normal(
RandomVar mean,
RandomVar log_variance,
00730
real minimum_standard_deviation)
00731 {
00732
return new DiagonalNormalRandomVariable(
mean,log_variance,
00733 minimum_standard_deviation);
00734 }
00735
00736 RandomVar mixture(
RVArray components,
RandomVar log_weights)
00737 {
00738
return new MixtureRandomVariable(components,log_weights);
00739 }
00740
00741 RandomVar multinomial(
RandomVar log_probabilities)
00742 {
00743
return new MultinomialRandomVariable(log_probabilities);
00744 }
00745
00748 ConditionalExpression::
00749 ConditionalExpression(
RVInstance lhs,
RVInstanceArray rhs)
00750 :LHS(lhs), RHS(rhs) {}
00751
00752 ConditionalExpression::
00753 ConditionalExpression(
RVInstance lhs)
00754 :LHS(lhs), RHS() {}
00755
00756 ConditionalExpression::
00757 ConditionalExpression(
RandomVar lhs)
00758 :LHS(lhs,
Var(lhs->length())), RHS() {}
00759
00760
00761
00762 ConditionalExpression::ConditionalExpression(
RVInstanceArray lhs)
00763 :LHS(lhs.random_variables(),
vconcat(lhs.instances())), RHS() {}
00764
00767 RVInstance::RVInstance(
const RandomVar& VV,
const Var& vv) :V(VV), v(vv)
00768 {
00769
if (VV->length()!=vv->
length())
00770
PLERROR(
"Associating a RandomVar of length %d to a Var of length %d",
00771 VV->length(),vv->
length());
00772 }
00773
00774 RVInstance::RVInstance() {}
00775
00776 RVInstanceArray RVInstance::operator&&(
RVInstance rvi)
00777 {
00778
return RVInstanceArray(*
this,rvi);
00779 }
00780
00781 ConditionalExpression RVInstance::operator|(
RVInstanceArray a)
00782 {
00783
return ConditionalExpression(*
this,a);
00784 }
00785
00786
00787 void RVInstance::swap_v_and_Vvalue()
00788 {
Var tmp =
v; v =
V->value;
V->value = tmp; }
00789
00790
00793 RVInstanceArray::RVInstanceArray()
00794 :
Array<
RVInstance>(0,0)
00795 {}
00796
00797 RVInstanceArray::RVInstanceArray(
int n,
int n_extra)
00798 :
Array<
RVInstance>(n,n_extra)
00799 {}
00800
00801 RVInstanceArray::RVInstanceArray(
const Array<RVInstance>& va)
00802 :
Array<
RVInstance>(va) {}
00803
00804 RVInstanceArray::RVInstanceArray(
const RVInstance& v,
int n_extra)
00805 :
Array<
RVInstance>(1,n_extra)
00806 { (*this)[0] = v; }
00807
00808 RVInstanceArray::RVInstanceArray(
const RVInstance& v1,
const RVInstance& v2,
int n_extra)
00809 :
Array<
RVInstance>(2,n_extra)
00810 {
00811 (*this)[0] = v1;
00812 (*this)[1] = v2;
00813 }
00814
00815 RVInstanceArray::RVInstanceArray(
const RVInstance& v1,
const RVInstance& v2,
00816
const RVInstance& v3,
int n_extra)
00817 :
Array<
RVInstance>(3,n_extra)
00818 {
00819 (*this)[0] = v1;
00820 (*this)[1] = v2;
00821 (*this)[2] = v3;
00822 }
00823
00824 int RVInstanceArray::length()
const {
00825
int l=0;
00826
for (
int i=0;i<
size();i++)
00827 l += (*this)[i].V->length();
00828
return l;
00829 }
00830
00831 VarArray RVInstanceArray::values()
const {
00832
VarArray vals(
size());
00833
for (
int i=0;i<
size();i++)
00834 vals[i]=(*this)[i].V->value;
00835
return vals;
00836 }
00837
00838 VarArray RVInstanceArray::instances()
const {
00839
VarArray vals(
size());
00840
for (
int i=0;i<
size();i++)
00841 vals[i]=(*this)[i].v;
00842
return vals;
00843 }
00844
00845 RVArray RVInstanceArray::random_variables()
const {
00846
RVArray vars(
size());
00847
for (
int i=0;i<
size();i++)
00848 vars[i]=(*this)[i].V;
00849
return vars;
00850 }
00851
00852 RVInstanceArray RVInstanceArray::operator&&(
RVInstance rvi)
00853 {
00854
return PLearn::operator&(*
this,(
RVInstanceArray)rvi);
00855
00856 }
00857
00858 ConditionalExpression RVInstanceArray::operator|(
RVInstanceArray RHS)
00859 {
00860
return ConditionalExpression(
RVInstance(
random_variables(),
00861
vconcat(
instances())),RHS);
00862 }
00863
00864 int RVInstanceArray::compareRVnumbers(
const RVInstance* rvi1,
00865
const RVInstance* rvi2)
00866 {
00867
return rvi1->
V->rv_number - rvi2->
V->rv_number;
00868 }
00869
00870
00871
00872 void RVInstanceArray::sort()
00873 {
00874
RVInstance* array =
data();
00875 qsort(array,
size(),
sizeof(
RVInstance),(
compare_function)
compareRVnumbers);
00876 }
00877
00880 RVArray::RVArray()
00881 :
Array<
RandomVar>(0,0)
00882 {}
00883
00884 RVArray::RVArray(
int n,
int n_extra)
00885 :
Array<
RandomVar>(n,n_extra)
00886 {}
00887
00888 RVArray::RVArray(
const Array<RandomVar>& va)
00889 :
Array<
RandomVar>(va) {}
00890
00891 RVArray::RVArray(
const RandomVar& v,
int n_extra)
00892 :
Array<
RandomVar>(1,n_extra)
00893 { (*this)[0] = v; }
00894
00895 RVArray::RVArray(
const RandomVar& v1,
const RandomVar& v2,
int n_extra)
00896 :
Array<
RandomVar>(2,n_extra)
00897 {
00898 (*this)[0] = v1;
00899 (*this)[1] = v2;
00900 }
00901
00902 RVArray::RVArray(
const RandomVar& v1,
const RandomVar& v2,
const RandomVar& v3,
00903
int n_extra)
00904 :
Array<
RandomVar>(3,n_extra)
00905 {
00906 (*this)[0] = v1;
00907 (*this)[1] = v2;
00908 (*this)[2] = v3;
00909 }
00910
00911 int RVArray::length()
const
00912
{
00913
int l=0;
00914
for (
int i=0;i<
size();i++)
00915 l += (*this)[i]->length();
00916
return l;
00917 }
00918
00919 VarArray RVArray::values()
const
00920
{
00921
VarArray vals(
size());
00922
for (
int i=0;i<
size();i++)
00923 vals[i]=(*this)[i]->value;
00924
return vals;
00925 }
00926
00927 RandomVar RVArray::operator[](
RandomVar index)
00928 {
return new RVArrayRandomElementRandomVariable(*
this, index); }
00929
00930 int RVArray::compareRVnumbers(
const RandomVar* v1,
const RandomVar* v2)
00931 {
00932
return (*v1)->rv_number - (*v2)->rv_number;
00933 }
00934
00935
00936
00937 void RVArray::sort()
00938 {
00939
RandomVar* array =
data();
00940 qsort(array,
size(),
sizeof(
RandomVar),(
compare_function)
compareRVnumbers);
00941 }
00942
00945 StochasticRandomVariable::StochasticRandomVariable(
int length)
00946 :
RandomVariable(length) {}
00947
00948 StochasticRandomVariable::StochasticRandomVariable(
const RVArray& parameters,
00949
int length)
00950 :
RandomVariable(parameters,length)
00951 {}
00952
00953 StochasticRandomVariable::StochasticRandomVariable(
const RVArray& parameters,
00954
int length,
int width)
00955 :
RandomVariable(parameters,length,width)
00956 {
00957 }
00958
00959 void StochasticRandomVariable::setKnownValues()
00960 {
00961
if (!marked && !pmark)
00962 {
00963 pmark=
true;
00964
00965
00966
for (
int i=0;i<parents.
size();i++)
00967 parents[i]->setKnownValues();
00968
setValueFromParentsValue();
00969
if (
isNonRandom()) marked=
true;
00970 }
00971 }
00972
00975
00976 FunctionalRandomVariable::FunctionalRandomVariable(
int thelength)
00977 :
RandomVariable(thelength) {}
00978 FunctionalRandomVariable::FunctionalRandomVariable(
int thelength,
int thewidth)
00979 :
RandomVariable(thelength,thewidth) {}
00980 FunctionalRandomVariable::FunctionalRandomVariable(
const Vec& the_value)
00981 :
RandomVariable(the_value) {}
00982 FunctionalRandomVariable::FunctionalRandomVariable(
const Mat& the_value)
00983 :
RandomVariable(the_value) {}
00984 FunctionalRandomVariable::FunctionalRandomVariable(
const Var& the_value)
00985 :
RandomVariable(the_value) {}
00986
00987
00988 FunctionalRandomVariable::FunctionalRandomVariable(
const RVArray& the_parents,
00989
int length)
00990 :
RandomVariable(the_parents,length) {}
00991
00992 FunctionalRandomVariable::FunctionalRandomVariable(
const RVArray& the_parents,
00993
int length,
int width)
00994 :
RandomVariable(the_parents,length,width) {}
00995
00996 Var FunctionalRandomVariable::logP(
const Var& obs,
const RVInstanceArray& RHS,
00997
RVInstanceArray* parameters_to_learn)
00998 {
00999
01000
int np=parents.
size();
01001
RVInstanceArray unobserved_parents(0,np);
01002
for (
int i=0;i<np;i++)
01003
if (!(parents[i]->isMarked() || parents[i]->isNonRandom()))
01004 unobserved_parents &=
RVInstance(parents[i],
Var(parents[i]->
length()));
01005
01006
int nup = unobserved_parents.
size();
01007
if (nup==0)
01008 {
01009
if (
isDiscrete())
01010
return isequal(value,obs);
01011
01012
return isequal(value,obs)*FLT_MAX;
01013 }
01014
01015
Var *JacobianCorrection=0;
01016
if (
invertible(obs,unobserved_parents,&JacobianCorrection))
01017 {
01018
Var logp(1);
01019
01020 unobserved_parents.
sort();
01021
bool first =
true;
01022
RVInstanceArray RHS(0,RHS.
size()+unobserved_parents.
size());
01023
RVInstanceArray xRHS(RHS);
01024
for (
int i=0;i<nup;i++)
01025 {
01026
01027
if (first)
01028 logp = unobserved_parents[i].V->logP(unobserved_parents[i].v,xRHS,
01029 parameters_to_learn);
01030
else
01031 logp = logp +
01032 unobserved_parents[i].V->logP(unobserved_parents[i].v,xRHS,
01033 parameters_to_learn);
01034 first =
false;
01035
01036
01037
01038 xRHS &= unobserved_parents[i];
01039 }
01040
if (JacobianCorrection)
01041
return logp + *JacobianCorrection;
01042
return logp;
01043 }
01044
01045
return
01046
PLearn::logP(
ConditionalExpression
01047 (RVInstance(
marginalize(
this, unobserved_parents.
random_variables()), obs),
01048 RHS),
true,parameters_to_learn);
01049 }
01050
01051 bool FunctionalRandomVariable::invertible(
const Var& obs,
01052
RVInstanceArray& unobserved_parents,
Var** JacobianCorrection)
01053 {
01054
PLERROR(
"FunctionalRandomVariable::invertible() should not be called\n"
01055
"Either the sub-class should re-implement logP() or re-define\n"
01056
"invertible() appropriately.");
01057
return false;
01058 }
01059
01060
01061
01062
01063
01064
01065
01066 bool FunctionalRandomVariable::isNonRandom()
01067 {
01068
bool non_random=
true;
01069
for (
int i=0;i<parents.
size() && non_random;i++)
01070 non_random = parents[i]->isNonRandom();
01071
return non_random;
01072 }
01073
01074 bool FunctionalRandomVariable::isDiscrete()
01075 {
01076
bool all_discrete =
true;
01077
for (
int i=0;i<parents.
size() && all_discrete;i++)
01078 all_discrete = parents[i]->isDiscrete();
01079
return all_discrete;
01080 }
01081
01082
01085 NonRandomVariable::NonRandomVariable(
int thelength)
01086 :
FunctionalRandomVariable(thelength) {}
01087
01088 NonRandomVariable::NonRandomVariable(
int thelength,
int thewidth)
01089 :
FunctionalRandomVariable(thelength,thewidth) {}
01090
01091 NonRandomVariable::NonRandomVariable(
const Var& v)
01092 :
FunctionalRandomVariable(v) {}
01093
01096 JointRandomVariable::JointRandomVariable(
const RVArray& variables)
01097 :
FunctionalRandomVariable(variables,variables.length())
01098 {
01099
if (variables.
size()==0)
01100
PLERROR(
"JointRandomVariables(RVArray) expects an array with >0 elements");
01101 }
01102
01103 void JointRandomVariable::setValueFromParentsValue()
01104 {
01105
if (marked)
return;
01106
VarArray values(parents.
size());
01107
for (
int i=0;i<parents.
size();i++)
01108 values[i]=parents[i]->value;
01109 value =
vconcat(values);
01110 }
01111
01112 bool JointRandomVariable::invertible(
const Var& obs,
01113
RVInstanceArray& unobserved_parents,
Var** JacobianCorrection)
01114 {
01115
int p=0;
01116
int j=0;
01117
int nun=unobserved_parents.
size();
01118
for (
int i=0;i<parents.
size();i++)
01119 {
01120
if (j==nun)
01121
PLERROR(
"JointRandomVariable::invertible ==> logic error");
01122
int l = parents[i]->
length();
01123
if (unobserved_parents[j].V==parents[i])
01124 unobserved_parents[j++].v = obs->
subVec(p,l);
01125 p+=l;
01126 }
01127
return true;
01128 }
01129
01130 void JointRandomVariable::EMBprop(
const Vec obs,
real posterior)
01131 {
01132
int p=0;
01133
for (
int i=0;i<parents.
size();i++)
01134 {
01135
int l = parents[i]->
length();
01136
01137 parents[i]->EMBprop(obs.
subVec(p,l),posterior);
01138 p+=l;
01139 }
01140 }
01141
01144 RandomElementOfRandomVariable::RandomElementOfRandomVariable(
const RandomVar& v,
01145
const RandomVar& index)
01146 :
FunctionalRandomVariable(v&index,1)
01147 {
01148
if (index->length()!=1)
01149
PLERROR(
"RandomElementOfRandomVariables expects an index RandomVar of length 1");
01150 }
01151
01152 void RandomElementOfRandomVariable::setValueFromParentsValue()
01153 {
01154
if (marked)
return;
01155 value =
v()->value[
index()->value];
01156 }
01157
01158
bool RandomElementOfRandomVariable::
01159 invertible(
const Var& obs,
01160
RVInstanceArray& unobserved_parents,
01161
Var** JacobianCorrection)
01162 {
01163
01164
01165
if (
v()==unobserved_parents[0].V && unobserved_parents.
size()==1)
01166
PLERROR(
"RandomElementOFRandomVariable could compute logP but not implemented");
01167
return false;
01168 }
01169
01170 void RandomElementOfRandomVariable::EMBprop(
const Vec obs,
real posterior)
01171 {
01172 }
01173
01176 RVArrayRandomElementRandomVariable::
01177 RVArrayRandomElementRandomVariable(
const RVArray& table,
const RandomVar& index)
01178 :
FunctionalRandomVariable((
RVArray)(table&index),table[0]->length())
01179 {
01180
int l=table[0]->
length();
01181
for (
int i=1;i<table.size();i++)
01182
if (table[i]->length()!=l)
01183
PLERROR(
"RVArrayRandomElementRandomVariables expect all the elements of table\n"
01184
" to have the same length (%-th has length %d while 0-th has length %d",
01185 i,table[i]->
length(),l);
01186
if (index->length()!=1)
01187
PLERROR(
"RVArrayRandomElementRandomVariables expect an index RandomVar of length 1");
01188 }
01189
01190 void RVArrayRandomElementRandomVariable::setValueFromParentsValue()
01191 {
01192
if (marked)
return;
01193
int n = parents.
size()-1;
01194
VarArray parents_values(n);
01195
for (
int i=0;i<n;i++)
01196 parents_values[i]=parents[i]->value;
01197 value = parents_values[
index()->value];
01198 }
01199
01200
Var RVArrayRandomElementRandomVariable::
01201 logP(
const Var& obs,
const RVInstanceArray& RHS,
01202
RVInstanceArray* parameters_to_learn)
01203 {
01204
int n = parents.
size()-1;
01205
if (
index()->isMarked() ||
index()->isNonRandom())
01206
01207 {
01208
VarArray parents_logp(n);
01209
for (
int i=0;i<n;i++)
01210 parents_logp[i]=parents[i]->logP(obs,RHS,parameters_to_learn);
01211
return parents_logp[
index()->value];
01212 }
01213
01214
VarArray log_weights(n);
01215
RVArray components(n);
01216
for (
int i=0;i<n;i++)
01217 {
01218
Var indx(1);
01219 indx = (
real)i;
01220 log_weights[i] =
index()->logP(indx,RHS,parameters_to_learn);
01221 components[i] = parents[i];
01222 }
01223
RandomVar mixt =
mixture(components,
RandomVar(
vconcat(log_weights)));
01224
return mixt->logP(obs,RHS,parameters_to_learn);
01225 }
01226
01227 void RVArrayRandomElementRandomVariable::EMBprop(
const Vec obs,
real posterior)
01228 {
01229 }
01230
01231
01234 NegRandomVariable::NegRandomVariable(
RandomVariable* input)
01235 :
FunctionalRandomVariable(input->length()) {}
01236
01237 void NegRandomVariable::setValueFromParentsValue()
01238 {
01239
if (marked)
return;
01240 value = -parents[0]->value;
01241 }
01242
01243 bool NegRandomVariable::invertible(
const Var& obs,
01244
RVInstanceArray& unobserved_parents,
01245
Var** JacobianCorrection)
01246 {
01247 unobserved_parents[0].v = -obs;
01248
return true;
01249 }
01250
01251 void NegRandomVariable::EMBprop(
const Vec obs,
real posterior)
01252 {
01253
if (!parents[0]->isConstant())
01254 parents[0]->EMBprop(-obs,posterior);
01255 }
01256
01259 ExpRandomVariable::ExpRandomVariable(
RandomVar& input)
01260 :
FunctionalRandomVariable(input,input->length()) {}
01261
01262 void ExpRandomVariable::setValueFromParentsValue()
01263 {
01264
if (marked)
return;
01265 value =
exp(parents[0]->value);
01266 }
01267
01268 bool ExpRandomVariable::invertible(
const Var& obs,
01269
RVInstanceArray& unobserved_parents,
01270
Var** JacobianCorrection)
01271 {
01272 unobserved_parents[0].v =
log(obs);
01273
return true;
01274 }
01275
01276 void ExpRandomVariable::EMBprop(
const Vec obs,
real posterior)
01277 {
01278
if (!parents[0]->isConstant())
01279 parents[0]->EMBprop(
log(obs),posterior);
01280 }
01281
01284 LogRandomVariable::LogRandomVariable(
RandomVar& input)
01285 :
FunctionalRandomVariable(input,input->length()) {}
01286
01287 void LogRandomVariable::setValueFromParentsValue()
01288 {
01289
if (marked)
return;
01290 value =
log(parents[0]->value);
01291 }
01292
01293 bool LogRandomVariable::invertible(
const Var& obs,
01294
RVInstanceArray& unobserved_parents,
01295
Var** JacobianCorrection)
01296 {
01297 unobserved_parents[0].v =
exp(obs);
01298
return true;
01299 }
01300
01301 void LogRandomVariable::EMBprop(
const Vec obs,
real posterior)
01302 {
01303
if (!parents[0]->isConstant())
01304 parents[0]->EMBprop(
exp(obs),posterior);
01305 }
01306
01309 PlusRandomVariable::PlusRandomVariable(
RandomVar input1,
RandomVar input2)
01310 :
FunctionalRandomVariable(input1 & input2,
01311
MAX(input1->length(),input2->length())),
01312 parent_to_learn(parents[0]), other_parent(parents[0]),
01313 numerator(value->length()),
difference(value->length())
01314 {
01315
if(input1->length() != input2->length() &&
01316 input1->length() !=1 && input2->length()!=1)
01317
PLERROR(
"PlusRandomVariable(RandomVariable* in1, RandomVariable* in2) in1 and"
01318
"in2 must have the same length or one of them must be of length 1");
01319 }
01320
01321 void PlusRandomVariable::setValueFromParentsValue()
01322 {
01323
if (marked)
return;
01324 value =
X0()->value +
X1()->value;
01325 }
01326
01327 bool PlusRandomVariable::invertible(
const Var& obs,
01328
RVInstanceArray& unobserved_parents,
01329
Var** JacobianCorrection)
01330 {
01331
if (unobserved_parents.
size()==2)
01332
return false;
01333
if (unobserved_parents[0].V ==
X0())
01334 unobserved_parents[0].v = obs -
X1()->value;
01335
else
01336 unobserved_parents[0].v = obs -
X0()->value;
01337
return true;
01338
01339 }
01340
01341
void PlusRandomVariable::
01342 EMTrainingInitialize(
const RVArray& parameters_to_learn)
01343 {
01344 RandomVariable::EMTrainingInitialize(parameters_to_learn);
01345
if (
learn_X0() &&
learn_X1())
01346
PLERROR(
"PlusRandomVariable: can't learn both X0 and X1");
01347
if (
learn_X0() ||
learn_X1())
01348 {
01349
learn_something=
true;
01350
if (
learn_X0())
01351 {
01352
parent_to_learn =
X0();
01353
other_parent =
X1();
01354 }
01355
else
01356 {
01357
parent_to_learn =
X1();
01358
other_parent =
X0();
01359 }
01360 }
01361 }
01362
01363 void PlusRandomVariable::EMEpochInitialize()
01364 {
01365
if (EMmark)
return;
01366 RandomVariable::EMEpochInitialize();
01367
if (
learn_something)
01368 {
01369
numerator.
clear();
01370
denom = 0.;
01371 }
01372 }
01373
01374 void PlusRandomVariable::EMBprop(
const Vec obs,
real posterior)
01375 {
01376
if (
learn_something)
01377 {
01378
01379
substract(obs,
other_parent->value->value,
difference);
01380
multiplyAcc(
numerator,
difference,posterior);
01381
denom += posterior;
01382
if (!
other_parent->isConstant())
01383 {
01384
01385
substract(obs,
parent_to_learn->value->value,
difference);
01386
other_parent->EMBprop(
difference,posterior);
01387 }
01388 }
01389
else
01390 {
01391
if (!
X1()->isConstant())
01392 {
01393
substract(obs,
X0()->value->value,
difference);
01394
X1()->EMBprop(
difference,posterior);
01395 }
01396
if (!
X0()->isConstant())
01397 {
01398
substract(obs,
X1()->value->value,
difference);
01399
X0()->EMBprop(
difference,posterior);
01400 }
01401 }
01402 }
01403
01404 void PlusRandomVariable::EMUpdate()
01405 {
01406
if (EMmark)
return;
01407 EMmark=
true;
01408
if (
learn_something &&
denom>0)
01409
01410
multiply(
numerator,
real(1.0/
denom),
parent_to_learn->value->value);
01411
if (!
learn_X0() && !
X0()->isConstant())
01412
X0()->EMUpdate();
01413
if (!
learn_X1() && !
X1()->isConstant())
01414
X1()->EMUpdate();
01415 }
01416
01419 MinusRandomVariable::MinusRandomVariable(
RandomVar input1,
RandomVar input2)
01420 :
FunctionalRandomVariable(input1 & input2,
01421
MAX(input1->length(),input2->length())),
01422 parent_to_learn(parents[0]), other_parent(parents[0]),
01423 numerator(value->length()),
difference(value->length())
01424 {
01425
if(input1->length() != input2->length() &&
01426 input1->length() !=1 && input2->length()!=1)
01427
PLERROR(
"MinusRandomVariable(RandomVariable* in1, RandomVariable* in2) in1 and"
01428
"in2 must have the same length or one of them must be of length 1");
01429 }
01430
01431 void MinusRandomVariable::setValueFromParentsValue()
01432 {
01433
if (marked)
return;
01434 value =
X0()->value -
X1()->value;
01435 }
01436
01437 bool MinusRandomVariable::invertible(
const Var& obs,
01438
RVInstanceArray& unobserved_parents,
01439
Var** JacobianCorrection)
01440 {
01441
if (unobserved_parents.
size()==2)
01442
return false;
01443
if (unobserved_parents[0].V ==
X0())
01444 unobserved_parents[0].v = obs +
X1()->value;
01445
else
01446 unobserved_parents[0].v =
X0()->value - obs;
01447
return true;
01448
01449 }
01450
01451
void MinusRandomVariable::
01452 EMTrainingInitialize(
const RVArray& parameters_to_learn)
01453 {
01454 RandomVariable::EMTrainingInitialize(parameters_to_learn);
01455
if (
learn_X0() &&
learn_X1())
01456
PLERROR(
"MinusRandomVariable: can't learn both X0 and X1");
01457
if (
learn_X0() ||
learn_X1())
01458 {
01459
learn_something=
true;
01460
if (
learn_X0())
01461 {
01462
parent_to_learn =
X0();
01463
other_parent =
X1();
01464 }
01465
else
01466 {
01467
parent_to_learn =
X1();
01468
other_parent =
X0();
01469 }
01470 }
01471 }
01472
01473 void MinusRandomVariable::EMEpochInitialize()
01474 {
01475
if (EMmark)
return;
01476 RandomVariable::EMEpochInitialize();
01477
if (
learn_something)
01478 {
01479
numerator.
clear();
01480
denom = 0.0;
01481 }
01482 }
01483
01484 void MinusRandomVariable::EMBprop(
const Vec obs,
real posterior)
01485 {
01486
if (
learn_something)
01487 {
01488
if (
learn_X0())
01489
01490
add(obs,
other_parent->value->value,
difference);
01491
else
01492
01493
substract(
other_parent->value->value,obs,
difference);
01494
01495
multiplyAcc(
numerator,
difference,posterior);
01496
denom += posterior;
01497
if (!
other_parent->isConstant())
01498 {
01499
01500
if (
learn_X0())
01501
add(obs,
parent_to_learn->value->value,
difference);
01502
else
01503
substract(
parent_to_learn->value->value,obs,
difference);
01504
other_parent->EMBprop(
difference,posterior);
01505 }
01506 }
01507
else
01508 {
01509
if (!
X1()->isConstant())
01510 {
01511
substract(
X0()->value->value,obs,
difference);
01512
X1()->EMBprop(
difference,posterior);
01513 }
01514
if (!
X0()->isConstant())
01515 {
01516
add(obs,
X1()->value->value,
difference);
01517
X0()->EMBprop(
difference,posterior);
01518 }
01519 }
01520 }
01521
01522 void MinusRandomVariable::EMUpdate()
01523 {
01524
if (EMmark)
return;
01525 EMmark=
true;
01526
if (
learn_something &&
denom>0)
01527
01528
multiply(
numerator,
real(1.0/
denom),
parent_to_learn->value->value);
01529
if (!
learn_X0() && !
X0()->isConstant())
01530
X0()->EMUpdate();
01531
if (!
learn_X1() && !
X1()->isConstant())
01532
X1()->EMUpdate();
01533 }
01534
01537 ElementWiseDivisionRandomVariable::
01538 ElementWiseDivisionRandomVariable(
RandomVar input1,
RandomVar input2)
01539 :
FunctionalRandomVariable(input1 & input2,
01540
MAX(input1->length(),input2->length()))
01541 {
01542
if(input1->length() != input2->length() &&
01543 input1->length() !=1 && input2->length()!=1)
01544
PLERROR(
"ElementWiseDivisionRandomVariable(RandomVariable* in1, RandomVariable* in2) in1 and"
01545
"in2 must have the same length or one of them must be of length 1");
01546 }
01547
01548 void ElementWiseDivisionRandomVariable::setValueFromParentsValue()
01549 {
01550
if (marked)
return;
01551 value =
X0()->value /
X1()->value;
01552 }
01553
01554 bool ElementWiseDivisionRandomVariable::invertible(
const Var& obs,
01555
RVInstanceArray& unobserved_parents,
01556
Var** JacobianCorrection)
01557 {
01558
if (unobserved_parents.
size()==2)
01559
return false;
01560
if (unobserved_parents[0].V ==
X0())
01561 unobserved_parents[0].v = obs *
X1()->value;
01562
else
01563 unobserved_parents[0].v =
X0()->value / obs;
01564
return true;
01565 }
01566
01567
void ElementWiseDivisionRandomVariable::
01568 EMTrainingInitialize(
const RVArray& parameters_to_learn)
01569 {
01570 }
01571
01572 void ElementWiseDivisionRandomVariable::EMEpochInitialize()
01573 {
01574 }
01575
01576 void ElementWiseDivisionRandomVariable::EMBprop(
const Vec obs,
real posterior)
01577 {
01578 }
01579
01580 void ElementWiseDivisionRandomVariable::EMUpdate()
01581 {
01582
PLERROR(
"ElementWiseDivisionRandomVariable::EMUpdate() not implemented");
01583 }
01584
01587 ProductRandomVariable::ProductRandomVariable(
RandomVar input1,
01588
RandomVar input2)
01589 :
FunctionalRandomVariable(input1 & input2, input1->value->matValue.length(),
01590 input2->value->matValue.width()),
01591 m(input1->value->matValue.length()), n(input1->value->matValue.width()),
01592 l(input2->value->matValue.width()), learn_something(false)
01593 {
01594
if (n != input2->value->matValue.length())
01595
PLERROR(
"ProductRandomVariable(X0,X1): X0(%d,%d)'s width (%d) must match"
01596
"X1(%d,%d)'s length (%d)", input1->value->matValue.length(),
01597 input1->value->matValue.width(), input1->value->matValue.width(),
01598 input2->value->matValue.length(), input2->value->matValue.width(),
01599 input2->value->matValue.length());
01600 scalars = (m==1 && n==1 && l==1);
01601 }
01602
01603 void ProductRandomVariable::setValueFromParentsValue()
01604 {
01605
if (marked)
return;
01606 value =
Var(
new ProductVariable(
X0()->value,
01607
X1()->value));
01608 }
01609
01610 bool ProductRandomVariable::invertible(
const Var& obs,
01611
RVInstanceArray& unobserved_parents,
01612
Var** JacobianCorrection)
01613 {
01614
if (unobserved_parents.
size()==2)
01615
return false;
01616
if (unobserved_parents[0].V ==
X0())
01617 {
01618 unobserved_parents[0].v =
01619
product(obs,
rightPseudoInverse(
X1()->value));
01620 **JacobianCorrection =
log(
abs(
det(
X1()->value)));
01621 }
01622
else
01623 {
01624 unobserved_parents[0].v =
01625
product(
leftPseudoInverse(
X0()->value), obs);
01626 **JacobianCorrection =
log(
abs(
det(
X0()->value)));
01627 }
01628
return true;
01629
01630 }
01631
01632
void ProductRandomVariable::
01633 EMTrainingInitialize(
const RVArray& parameters_to_learn)
01634 {
01635 RandomVariable::EMTrainingInitialize(parameters_to_learn);
01636
if (
learn_X0() &&
learn_X1())
01637
PLERROR(
"ProductRandomVariable: can't learn both X0 and X1");
01638
if (
learn_X0() ||
learn_X1())
01639 {
01640
denom.
resize(
n,
n);
01641
tmp2.
resize(
n,
n);
01642
tmp4.
resize(
n);
01643
learn_something=
true;
01644
if (
learn_X0())
01645 {
01646
X0numerator.
resize(
m,
n);
01647
tmp1.
resize(
m,
n);
01648
if (!
X1()->isNonRandom())
01649 {
01650
tmp3.
resize(
m,
l);
01651
vtmp3 =
tmp3.
toVec();
01652 }
01653 }
01654
else
01655 {
01656
X1numerator.
resize(
n,
l);
01657
tmp1.
resize(
n,
l);
01658
if (!
X0()->isNonRandom())
01659 {
01660
tmp3.
resize(
n,
m);
01661
vtmp3 =
tmp3.
toVec();
01662 }
01663 }
01664 }
01665
else
01666
learn_something=
false;
01667 }
01668
01669 void ProductRandomVariable::EMEpochInitialize()
01670 {
01671
if (EMmark)
return;
01672 RandomVariable::EMEpochInitialize();
01673
if (
learn_something)
01674 {
01675
denom.
clear();
01676
if (
learn_X0())
01677
X0numerator.
clear();
01678
else
01679
X1numerator.
clear();
01680 }
01681 }
01682
01683 void ProductRandomVariable::EMBprop(
const Vec obs,
real posterior)
01684 {
01685
if (
learn_something)
01686 {
01687
if (
learn_X0())
01688 {
01689
if (
scalars)
01690 {
01691
01692
real x1 = *(
X1()->value->value.data());
01693
real y = *obs.
data();
01694 *
X0numerator.
data() += posterior * y * x1;
01695 *
denom.
data() += posterior * x1 * x1;
01696
01697
if (!
X1()->isNonRandom())
01698 {
01699
real x0 = *(
X0()->value->value.data());
01700
if (x0==0.0)
01701
PLERROR(
"ProductRandomVariable: can't divide by X0==0");
01702 *
tmp3.
data() = y / x0;
01703
X1()->EMBprop(
vtmp3,posterior);
01704 }
01705 }
01706
else
01707 {
01708
Mat matObs = obs.
toMat(
m,
l);
01709
Mat& x1 =
X1()->value->matValue;
01710
01711
productTranspose(
tmp1, matObs,x1);
01712
multiplyAcc(
X0numerator,
tmp1,posterior);
01713
01714
productTranspose(
tmp2, x1,x1);
01715
multiplyAcc(
denom,
tmp2,posterior);
01716
01717
if (!
X1()->isNonRandom())
01718 {
01719
Mat& x0 =
X0()->value->matValue;
01720
01721
solveLinearSystem(x0,matObs,
tmp3);
01722
X1()->EMBprop(
vtmp3,posterior);
01723 }
01724 }
01725 }
01726
else
01727 {
01728
if (
scalars)
01729 {
01730
01731
real x0 = *(
X0()->value->value.data());
01732 *
X1numerator.
data() += posterior * *obs.
data() * x0;
01733 *
denom.
data() += posterior * x0 * x0;
01734
01735
if (!
X0()->isNonRandom())
01736 {
01737
real x1 = *(
X1()->value->value.data());
01738
if (x1==0.0)
01739
PLERROR(
"ProductRandomVariable: can't divide by X1==0");
01740 *
tmp3.
data() = obs[0] / x1;
01741
X0()->EMBprop(
vtmp3,posterior);
01742 }
01743 }
01744
else
01745 {
01746
Mat matObs = obs.
toMat(
m,
l);
01747
Mat& x0 =
X0()->value->matValue;
01748
01749
transposeProduct(
tmp1, x0,matObs);
01750
multiplyAcc(
X1numerator,
tmp1,posterior);
01751
01752
transposeProduct(
tmp2, x0,x0);
01753
multiplyAcc(
denom,
tmp2,posterior);
01754
01755
if (!
X0()->isNonRandom())
01756 {
01757
Mat& x1 =
X1()->value->matValue;
01758
01759
solveTransposeLinearSystem(x1,matObs,
tmp3);
01760
X1()->EMBprop(
vtmp3,posterior);
01761 }
01762 }
01763 }
01764 }
01765
else
01766 {
01767
if (
scalars)
01768 {
01769
if (!
X1()->isNonRandom())
01770 {
01771
real x0 = *(
X0()->value->value.data());
01772
if (x0==0.0)
01773
PLERROR(
"ProductRandomVariable: can't divide by X0==0");
01774 *
tmp3.
data() = obs[0] / x0;
01775
X1()->EMBprop(
vtmp3,posterior);
01776 }
01777
if (!
X0()->isNonRandom())
01778 {
01779
real x1 = *(
X1()->value->value.data());
01780
if (x1==0.0)
01781
PLERROR(
"ProductRandomVariable: can't divide by X1==0");
01782 *
tmp3.
data() = obs[0] / x1;
01783
X0()->EMBprop(
vtmp3,posterior);
01784 }
01785 }
01786
else
01787 {
01788
if (!
X1()->isConstant())
01789 {
01790
Mat matObs = obs.
toMat(
m,
l);
01791
Mat& x0 =
X0()->value->matValue;
01792
solveLinearSystem(x0,matObs,
tmp3);
01793
X1()->EMBprop(
vtmp3,posterior);
01794 }
01795
if (!
X0()->isConstant())
01796 {
01797
Mat matObs = obs.
toMat(
m,
l);
01798
Mat& x1 =
X1()->value->matValue;
01799
01800
solveTransposeLinearSystem(x1,matObs,
tmp3);
01801
X1()->EMBprop(
vtmp3,posterior);
01802 }
01803 }
01804 }
01805 }
01806
01807 void ProductRandomVariable::EMUpdate()
01808 {
01809
if (EMmark)
return;
01810 EMmark=
true;
01811
if (
learn_something)
01812 {
01813
if (
learn_X0())
01814 {
01815
if (
scalars)
01816 {
01817
if (
denom(0,0)>0)
01818
X0()->value->value[0] =
X0numerator(0,0)/
denom(0,0);
01819 }
01820
else
01821
solveTransposeLinearSystemByCholesky(
denom,
X0numerator,
01822
X0()->value->matValue,
01823 &
tmp2,&
tmp4);
01824
if (!
X1()->isConstant())
01825
X1()->EMUpdate();
01826 }
01827
else
01828 {
01829
if (
scalars)
01830 {
01831
if (
denom(0,0)>0)
01832
X1()->value->value[0] =
X1numerator(0,0)/
denom(0,0);
01833 }
01834
else
01835
solveLinearSystemByCholesky(
denom,
X1numerator,
01836
X1()->value->matValue,
01837 &
tmp2,&
tmp4);
01838
if (!
X0()->isConstant())
01839
X0()->EMUpdate();
01840 }
01841 }
01842
else
01843 {
01844
if (!
X0()->isConstant())
01845
X0()->EMUpdate();
01846
if (!
X1()->isConstant())
01847
X1()->EMUpdate();
01848 }
01849 }
01850
01851
01854 DiagonalNormalRandomVariable::DiagonalNormalRandomVariable
01855 (
const RandomVar&
mean,
const RandomVar& log_var,
01856
real minimum_standard_deviation)
01857 :
StochasticRandomVariable(mean & log_var,
mean->length()),
01858 minimum_variance(minimum_standard_deviation*minimum_standard_deviation),
01859 normfactor(
mean->length()*
Log2Pi), shared_variance(log_var->length()==1),
01860 mu_num(
mean->length()), sigma_num(log_var->length())
01861 {
01862 }
01863
01864 Var DiagonalNormalRandomVariable::logP(
const Var& obs,
01865
const RVInstanceArray& RHS,
RVInstanceArray* parameters_to_learn)
01866 {
01867
if (
mean()->isMarked() &&
log_variance()->isMarked())
01868 {
01869
if (
log_variance()->value->getName()[0]==
'#')
01870
log_variance()->value->setName(
"log_variance");
01871
if (
mean()->value->getName()[0]==
'#')
01872
mean()->value->setName(
"mean");
01873
Var variance =
minimum_variance+
exp(
log_variance()->value);
01874
variance->setName(
"variance");
01875
if (
shared_variance)
01876
return (-0.5)*(
sum(
square(obs-
mean()->value))/
variance+
01877 (
mean()->length())*
log(
variance) +
normfactor);
01878
else
01879
return (-0.5)*(
sum(
square(obs-
mean()->value)/
variance)+
01880
sum(
log(
variance))+
normfactor);
01881 }
01882
01883
01884
if (
mean()->isMarked())
01885
return
01886
PLearn::logP(
ConditionalExpression(
RVInstance(
marginalize(
this,
01887
log_variance()),
01888 obs),RHS),
true,parameters_to_learn);
01889
else
01890
return PLearn::logP(
ConditionalExpression(
RVInstance(
marginalize(
this,
mean()),
01891 obs),RHS),
true,parameters_to_learn);
01892 }
01893
01894 void DiagonalNormalRandomVariable::setValueFromParentsValue()
01895 {
01896 value =
01897
Var(
new DiagonalNormalSampleVariable(
mean()->value,
01898
sqrt(
minimum_variance+
01899
exp(
log_variance()->value))));
01900 }
01901
01902 void DiagonalNormalRandomVariable::EMEpochInitialize()
01903 {
01904
if (EMmark)
return;
01905 RandomVariable::EMEpochInitialize();
01906
if (
learn_the_mean())
01907
mu_num.
clear();
01908
if (
learn_the_variance())
01909
sigma_num.
clear();
01910
denom = 0.0;
01911 }
01912
01913 void DiagonalNormalRandomVariable::EMBprop(
const Vec obs,
real posterior)
01914 {
01915
if (
learn_the_mean())
01916
multiplyAcc(
mu_num, obs,posterior);
01917
else if (!
mean()->isConstant())
01918 {
01919
if (!
shared_variance)
01920
PLERROR(
"DiagonalNormalRandomVariable: don't know how to EMBprop "
01921
"into mean if variance is not shared");
01922
mean()->EMBprop(obs,posterior/
01923 (
minimum_variance+
exp(
log_variance()->value->value[0])));
01924 }
01925
if (
learn_the_variance())
01926 {
01927
if (
learn_the_mean())
01928 {
01929
01930
if (
shared_variance)
01931
sigma_num[0] += posterior*
pownorm(obs)/
mean()->length();
01932
else
01933
squareMultiplyAcc(
sigma_num, obs,posterior);
01934 }
01935
else
01936 {
01937
01938
if (
shared_variance)
01939
sigma_num[0] += posterior*
powdistance(obs,
mean()->value->value)
01940 /
mean()->length();
01941
else
01942
diffSquareMultiplyAcc(
sigma_num, obs,
01943
mean()->value->value,
01944 posterior);
01945 }
01946 }
01947
else if (!
log_variance()->isConstant())
01948 {
01949
01950
if (
shared_variance)
01951
log_variance()->EMBprop(
Vec(1,
powdistance(obs,
mean()->value->value)
01952 /
mean()->
length()),
01953 posterior);
01954
else
01955 {
01956
substract(obs,
mean()->value->value,
sigma_num);
01957
apply(
sigma_num,
sigma_num,
square_f);
01958
log_variance()->EMBprop(
sigma_num,posterior);
01959 }
01960 }
01961
if (
learn_the_mean() ||
learn_the_variance())
denom += posterior;
01962 }
01963
01964 void DiagonalNormalRandomVariable::EMUpdate()
01965 {
01966
if (EMmark)
return;
01967 EMmark=
true;
01968
01969
01970
01971
01972
if (
denom>0 && (
learn_the_mean() ||
learn_the_variance()))
01973 {
01974
Vec lv =
log_variance()->value->value;
01975
Vec mv =
mean()->value->value;
01976
if (
learn_the_mean())
01977
multiply(
mu_num,
real(1.0/
denom),
mv);
01978
if (
learn_the_variance())
01979 {
01980
if (
learn_the_mean())
01981 {
01982
01983
sigma_num /=
denom;
01984
multiply(
mv,
mv,
mu_num);
01985
if (
shared_variance)
01986 lv[0] =
sigma_num[0] -
PLearn::mean(
mu_num);
01987
else
01988
substract(sigma_num,
mu_num,lv);
01989
01990
01991
01992
substract(lv,
minimum_variance,lv);
01993
max(lv,
real(0.),lv);
01994
apply(lv,lv,
safeflog);
01995 }
01996
else
01997 {
01998
multiply(
sigma_num,1/
denom,lv);
01999
02000
02001
02002
substract(lv,
minimum_variance,lv);
02003
max(lv,
real(0.),lv);
02004
apply(lv,lv,
safeflog);
02005 }
02006 }
02007 }
02008
if (!
learn_the_mean() && !
mean()->isConstant())
02009
mean()->EMUpdate();
02010
if (!
learn_the_variance() && !
log_variance()->isConstant())
02011
log_variance()->EMUpdate();
02012 }
02013
02014
02017 MixtureRandomVariable::MixtureRandomVariable
02018 (
const RVArray& the_components,
const RandomVar& logweights)
02019 :
StochasticRandomVariable(logweights,the_components[0]->length()),
02020 components(the_components), posteriors(logweights->length()),
02021 sum_posteriors(logweights->length()),
02022 componentsLogP(logweights->length()),
02023 lw(logweights->length())
02024 {
02025 }
02026
02027 Var MixtureRandomVariable::logP(
const Var& obs,
const RVInstanceArray& RHS,
02028
RVInstanceArray* parameters_to_learn)
02029 {
02030
if (parameters_to_learn!=0)
return ElogP(obs,*parameters_to_learn,RHS);
02031
if (
log_weights()->isMarked())
02032 {
02033
int n=
posteriors.
length();
02034
if (
log_weights()->value->getName()[0]==
'#')
02035
log_weights()->value->setName(
"log_weights");
02036
Var weights =
softmax(
log_weights()->value);
02037 weights->setName(
"weights");
02038
lw =
log(weights);
02039
for (
int i=0;i<n;i++)
02040
componentsLogP[i] =
components[i]->logP(obs,RHS) +
lw->
subVec(i,1);
02041
logp =
logadd(
vconcat(
componentsLogP));
02042
return logp;
02043 }
02044
02045
02046
return PLearn::logP(
ConditionalExpression
02047 (
RVInstance(
marginalize(
this,
log_weights()),obs),RHS),
true,0);
02048 }
02049
02050
02051
02052
02053
02054
02055
02056
02057 Var MixtureRandomVariable::ElogP(
const Var& obs,
02058
RVInstanceArray& parameters_to_learn,
02059
const RVInstanceArray& RHS)
02060 {
02061
if (
log_weights()->isMarked())
02062 {
02063
int n=
posteriors.
length();
02064
02065
02066
Var weights =
softmax(
log_weights()->value);
02067
lw =
log(weights);
02068
for (
int i=0;i<n;i++)
02069
02070
componentsLogP[i] =
components[i]->logP(obs,RHS) +
lw->
subVec(i,1);
02071
02072
logp =
logadd(
vconcat(
componentsLogP));
02073
02074
for (
int i=0;i<n;i++)
02075
02076
componentsLogP[i] =
componentsLogP[i] -
logp;
02077
02078
02079 parameters_to_learn.
swap_v_and_Vvalue();
02080
02081
unmarkAncestors();
02082 markRHSandSetKnownValues(RHS);
02083
02084
02085 weights =
softmax(
log_weights()->value);
02086
for (
int i=0;i<n;i++)
02087 componentsLogP[i] =
exp(components[i]->
logP(obs,RHS,¶meters_to_learn)
02088 + componentsLogP[i]);
02089 logp =
sum(
vconcat(componentsLogP));
02090
02091
02092 parameters_to_learn.
swap_v_and_Vvalue();
02093
02094
unmarkAncestors();
02095 markRHSandSetKnownValues(RHS);
02096
02097
return logp;
02098 }
02099
02100
02101
return PLearn::logP(
ConditionalExpression
02102 (
RVInstance(
marginalize(
this,
log_weights()),obs),
02103 RHS),
true,¶meters_to_learn);
02104 }
02105
02106 void MixtureRandomVariable::setValueFromParentsValue()
02107 {
02108
Var index =
new MultinomialSampleVariable(
softmax(
log_weights()->value));
02109 value =
components.
values()[index];
02110 }
02111
02112
void MixtureRandomVariable::
02113 EMTrainingInitialize(
const RVArray& parameters_to_learn)
02114 {
02115
if (EMmark)
return;
02116 EMmark=
true;
02117
learn_the_weights() = parameters_to_learn.
contains(
log_weights())
02118 &&
log_weights()->isConstant();
02119
for (
int i=0;i<
components.
size();i++)
02120
components[i]->EMTrainingInitialize(parameters_to_learn);
02121 }
02122
02123 void MixtureRandomVariable::EMEpochInitialize()
02124 {
02125
if (EMmark)
return;
02126 RandomVariable::EMEpochInitialize();
02127
if (
learn_the_weights())
02128
sum_posteriors.
clear();
02129
for (
int i=0;i<
components.
size();i++)
02130
components[i]->EMEpochInitialize();
02131 }
02132
02133 void MixtureRandomVariable::EMBprop(
const Vec obs,
real posterior)
02134 {
02135
02136
02137
02138
02139
02140
real log_p =
logp->value[0];
02141
real *p =
posteriors.
data();
02142
int n =
lw->value.
length();
02143
for (
int i=0;i<n;i++)
02144 p[i] =
componentsLogP[i]->value[0] - log_p;
02145
#ifdef _MSC_VER
02146
apply(
posteriors,
posteriors,(
tRealFunc)
exp);
02147
#else
02148
apply(
posteriors,
posteriors,
safeexp);
02149
#endif
02150
if (fabs(
sum(
posteriors)-1)>1e-5)
02151 {
02152 cout <<
"sum(posteriors) = " <<
sum(
posteriors) <<
"!" <<
endl;
02153 }
02154
posteriors *= posterior;
02155
02156
if (
learn_the_weights())
02157
sum_posteriors+=
posteriors;
02158
02159
02160
for (
int i=0;i<n;i++)
02161
components[i]->EMBprop(obs,posteriors[i]);
02162 }
02163
02164 void MixtureRandomVariable::EMUpdate()
02165 {
02166
if (EMmark)
return;
02167 EMmark=
true;
02168
02169
if (
learn_the_weights())
02170 {
02171
real denom =
sum(
sum_posteriors);
02172
if (denom>0)
02173 {
02174
multiply(
sum_posteriors,
real(1.0/denom),
posteriors);
02175
apply(
posteriors,
log_weights()->value->value,
safeflog);
02176 }
02177 }
02178
02179
for (
int i=0;i<
components.
size();i++)
02180
components[i]->EMUpdate();
02181 }
02182
02183 bool MixtureRandomVariable::canStopEM()
02184 {
02185
02186
bool can=
log_weights()->canStopEM();
02187
for (
int i=0;i<
components.
size() && !can;i++)
02188 can =
components[i]->canStopEM();
02189
return can;
02190 }
02191
02192 bool MixtureRandomVariable::isDiscrete()
02193 {
02194
return components[0]->isDiscrete();
02195 }
02196
02197 void MixtureRandomVariable::setKnownValues()
02198 {
02199
if (!pmark && !marked)
02200 {
02201 pmark =
true;
02202
log_weights()->setKnownValues();
02203
for (
int i=0;i<
components.
size();i++)
02204
components[i]->setKnownValues();
02205
setValueFromParentsValue();
02206 }
02207 }
02208
02209 void MixtureRandomVariable::unmarkAncestors()
02210 {
02211
if (pmark)
02212 {
02213 marked=
false;
02214 pmark=
false;
02215
log_weights()->unmarkAncestors();
02216
for (
int i=0;i<
components.
size();i++)
02217
components[i]->unmarkAncestors();
02218 }
02219 }
02220
02221 void MixtureRandomVariable::clearEMmarks()
02222 {
02223
if (EMmark)
02224 {
02225 EMmark=
false;
02226
log_weights()->clearEMmarks();
02227
for (
int i=0;i<
components.
size();i++)
02228
components[i]->clearEMmarks();
02229 }
02230 }
02231
02234 MultinomialRandomVariable::
02235 MultinomialRandomVariable(
const RandomVar& log_probabilities)
02236 :
StochasticRandomVariable(log_probabilities,1),
02237 sum_posteriors(log_probabilities->length())
02238 {
02239 }
02240
02241 Var MultinomialRandomVariable::logP(
const Var& obs,
const RVInstanceArray& RHS,
02242
RVInstanceArray* parameters_to_learn)
02243 {
02244
if (
log_probabilities()->isMarked())
02245
return log(
softmax(
log_probabilities()->value))[obs];
02246
02247
02248
return PLearn::logP(
ConditionalExpression
02249 (
RVInstance(
marginalize(
this,
log_probabilities()),obs),
02250 RHS),
true,parameters_to_learn);
02251 }
02252
02253 void MultinomialRandomVariable::EMEpochInitialize()
02254 {
02255
if (EMmark)
return;
02256 RandomVariable::EMEpochInitialize();
02257
if (
learn_the_probabilities())
02258
sum_posteriors.
clear();
02259 }
02260
02261 void MultinomialRandomVariable::EMBprop(
const Vec obs,
real posterior)
02262 {
02263
if (
learn_the_probabilities())
02264 {
02265
real *p =
sum_posteriors.
data();
02266 p[(
int)obs[0]] += posterior;
02267 }
02268 }
02269
02270 void MultinomialRandomVariable::EMUpdate()
02271 {
02272
if (EMmark)
return;
02273 EMmark=
true;
02274
if (
learn_the_probabilities())
02275 {
02276
real denom =
sum(
sum_posteriors);
02277
if (denom>0)
02278
02279 {
02280
multiply(
sum_posteriors,
real(1.0/denom),
sum_posteriors);
02281
apply(
sum_posteriors,
log_probabilities()->value->value,
safeflog);
02282 }
02283
02284 }
02285 }
02286
02287 bool MultinomialRandomVariable::isDiscrete()
02288 {
02289
return true;
02290 }
02291
02292 void MultinomialRandomVariable::setValueFromParentsValue()
02293 {
02294 value =
02295
Var(
new MultinomialSampleVariable(
softmax(
log_probabilities()->value)));
02296 }
02297
02300 SubVecRandomVariable::SubVecRandomVariable
02301 (
const RandomVar& v,
int the_start,
int the_len)
02302 :
FunctionalRandomVariable(v, the_len), start(the_start)
02303 {
02304
if (v->length() < the_len)
02305
PLERROR(
"new SubVecRandomVariable: input should have length at least %d, has %d",
02306 the_len, v->length());
02307 }
02308
02309 void SubVecRandomVariable::setValueFromParentsValue()
02310 {
02311
if (marked)
return;
02312 value = parents[0]->value->
subVec(
start,value->
length());
02313 }
02314
02315
bool SubVecRandomVariable::
02316 invertible(
const Var& obs,
RVInstanceArray& unobserved_parents,
02317
Var** JacobianCorrection)
02318 {
02319
if (
length()!=parents[0]->
length())
02320
return false;
02321
02322 unobserved_parents[0].v = obs;
02323
return true;
02324 }
02325
02326 void SubVecRandomVariable::EMBprop(
const Vec obs,
real posterior)
02327 {
02328
if (
length()!=parents[0]->
length())
02329
PLERROR(
"SubVecRandomVariable: can't EMBprop unless length==parent.length()");
02330
02331 parents[0]->EMBprop(obs,posterior);
02332 }
02333
02336 ExtendedRandomVariable::ExtendedRandomVariable
02337 (
const RandomVar& v,
real fillvalue,
int nextend)
02338 :
FunctionalRandomVariable(v, v->length()+nextend),
02339 n_extend(nextend), fill_value(fillvalue)
02340 {
02341 }
02342
02343 void ExtendedRandomVariable::setValueFromParentsValue()
02344 {
02345
if (marked)
return;
02346 value =
extend(parents[0]->value,
fill_value,
n_extend);
02347 }
02348
02349
bool ExtendedRandomVariable::
02350 invertible(
const Var& obs,
RVInstanceArray& unobserved_parents,
02351
Var** JacobianCorrection)
02352 {
02353
int n =
n_extend*parents[0]->width();
02354 unobserved_parents[0].v = obs->
subVec(parents[0]->value->
length(),n);
02355
return true;
02356 }
02357
02358 void ExtendedRandomVariable::EMBprop(
const Vec obs,
real posterior)
02359 {
02360
int n =
n_extend*parents[0]->width();
02361 parents[0]->EMBprop(obs.
subVec(parents[0]->value->length(),n),posterior);
02362 }
02363
02366
02367
02368 ConcatColumnsRandomVariable::ConcatColumnsRandomVariable(
const RVArray& a)
02369 :
FunctionalRandomVariable(a, a.length())
02370 {
02371
setValueFromParentsValue();
02372
02373
02374
02375
02376 }
02377
02378 void ConcatColumnsRandomVariable::setValueFromParentsValue()
02379 {
02380
if (marked)
return;
02381 value =
hconcat(parents.
values());
02382 }
02383
02384
bool ConcatColumnsRandomVariable::
02385 invertible(
const Var& obs,
RVInstanceArray& unobserved_parents,
02386
Var** JacobianCorrection)
02387 {
02388
PLERROR(
"ConcatColumnsRandomVariable::invertible not yet implemented");
02389
return true;
02390 }
02391
02392 void ConcatColumnsRandomVariable::EMBprop(
const Vec obs,
real posterior)
02393 {
02394
PLERROR(
"ConcatColumnsRandomVariable::EMBprop not yet implemented");
02395 }
02396
02397
02398
02399
02400
02401
02402 RandomVarVMatrix::
02403 RandomVarVMatrix(
ConditionalExpression conditional_expression)
02404 :
VMatrix(-1,-1), instance(
Sample(conditional_expression))
02405 {
02406
02407
instance->fprop_from_all_sources();
02408
02409
instance->random_sources().setMark();
02410
instance->markPath();
02411
instance->buildPath(
prop_path);
02412
02413 }
02414
02415
02416
02417
02418
02419
02420
02421
02422 }