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
#include "UnfoldedSumOfVariable.h"
00044
#include <plearn/sys/PLMPI.h>
00045
#include <plearn/display/DisplayUtils.h>
00046
00047
namespace PLearn {
00048
using namespace std;
00049
00052
PLEARN_IMPLEMENT_OBJECT(UnfoldedSumOfVariable,
"Variable that sums the value of a Func evaluated on each row of a matrix.\n",
00053
"However, unlike the SumOfVariable, it does so by unfolding the Func (up to given maximum number\n"
00054
"of times 'max_bag_size'), and it allows that number to be variable. Each of the unfolded Func\n"
00055
"is applied on a different row of the input matrix. The number of rows to sum is specified on the\n"
00056
"fly by another input, the bag_size.\n");
00057
00058 UnfoldedSumOfVariable::UnfoldedSumOfVariable(
Var inputmatrix,
Var bagsize,
Func the_f,
int max_bagsize)
00059 :
inherited(
nonInputParentsOfPath(the_f->inputs,the_f->outputs) & inputmatrix & bagsize,
00060 the_f->outputs[0]->length(),
00061 the_f->outputs[0]->width()),
00062 input_matrix(inputmatrix), bag_size(bagsize),
00063 f(the_f), max_bag_size(max_bagsize)
00064 {
00065
build();
00066 }
00067
00068 void UnfoldedSumOfVariable::build()
00069 {
00070 inherited::build();
00071
build_();
00072 }
00073
00074 void UnfoldedSumOfVariable::build_()
00075 {
00076
if (
f) {
00077
if(
f->outputs.size()!=1)
00078
PLERROR(
"In UnfoldedSumOfVariable: function must have a single variable output (maybe you can vconcat the vars into a single one prior to calling sumOf, if this is really what you want)");
00079
f->inputs.setDontBpropHere(
true);
00080
inputs.
resize(
max_bag_size);
00081
outputs.
resize(
max_bag_size);
00082
f_paths.
resize(
max_bag_size);
00083
for (
int i=0;i<
max_bag_size;i++)
00084 {
00085
inputs[i].
resize(
f->inputs.size());
00086
for (
int j = 0; j <
f->inputs.size(); j++) {
00087
inputs[i][j] =
Var(
f->inputs[j]->length(),
f->inputs[j]->width());
00088 }
00089
outputs[i] =
f(
inputs[i])[0];
00090
f_paths[i] =
propagationPath(
inputs[i],
outputs[i]);
00091 }
00092 }
00093 }
00094
00095 void UnfoldedSumOfVariable::declareOptions(
OptionList& ol)
00096 {
00097
declareOption(ol,
"f", &UnfoldedSumOfVariable::f, OptionBase::buildoption,
00098
" Func that is replicated for each element of the 'bag' taken from the VMat.");
00099
00100
declareOption(ol,
"input_matrix", &UnfoldedSumOfVariable::input_matrix, OptionBase::buildoption,
00101
" Var that contains the data, with multiple consecutive rows forming one bag.\n"
00102
" The last row of a bag has a non-missing target value.\n");
00103
00104
declareOption(ol,
"bag_size", &UnfoldedSumOfVariable::bag_size, OptionBase::buildoption,
00105
" Var that gives the size of the bag (number of rows of input_matrix to consider).\n");
00106
00107
declareOption(ol,
"max_bag_size", &UnfoldedSumOfVariable::max_bag_size, OptionBase::buildoption,
00108
" maximum number of examples in a bag (more than that in input_matrix will trigger a run-time error).\n");
00109
00110 inherited::declareOptions(ol);
00111 }
00112
00113 void UnfoldedSumOfVariable::recomputeSize(
int& l,
int& w)
const
00114
{
00115
if (
f &&
f->outputs.size()) {
00116 l =
f->outputs[0]->length();
00117 w =
f->outputs[0]->width();
00118 }
else
00119 l = w = 0;
00120 }
00121
00123
extern void varDeepCopyField(
Var& field, CopiesMap& copies);
00124
00125 void UnfoldedSumOfVariable::makeDeepCopyFromShallowCopy(map<const void*, void*>& copies)
00126 {
00127 NaryVariable::makeDeepCopyFromShallowCopy(copies);
00128
varDeepCopyField(
input_matrix, copies);
00129
varDeepCopyField(
bag_size, copies);
00130
deepCopyField(
f, copies);
00131
deepCopyField(
inputs, copies);
00132
deepCopyField(
outputs, copies);
00133
deepCopyField(
f_paths, copies);
00134 }
00135
00136
00137 void UnfoldedSumOfVariable::fprop()
00138 {
00139 value.
clear();
00140
int bagsize = (
int)
bag_size->valuedata[0];
00141
if (bagsize>
max_bag_size)
00142
PLERROR(
"UnfoldedSumOfVariable: bag size=%d > expected max. bag size(%d)",
00143 bagsize,
max_bag_size);
00144
for (
int i=0;i<bagsize;i++)
00145 {
00146
inputs[i] <<
input_matrix->matValue(i);
00147
f_paths[i].fprop();
00148 value +=
outputs[i]->value;
00149 }
00150 }
00151
00152
00153 void UnfoldedSumOfVariable::bprop()
00154 {
00155
int bagsize = (
int)
bag_size->valuedata[0];
00156
for (
int i=0;i<bagsize;i++)
00157 {
00158
f_paths[i].clearGradient();
00159
outputs[i]->gradient << gradient;
00160
f_paths[i].bprop();
00161 }
00162 }
00163
00164
00165 void UnfoldedSumOfVariable::printInfo(
bool print_gradient)
00166 {
00167
for (
int i=0;i<
max_bag_size;i++)
00168
f_paths[i].printInfo(print_gradient);
00169 cout <<
info() <<
" : " <<
getName() <<
"[" << (
void*)
this <<
"]"
00170 <<
"(input_matrix=" << (
void*)
input_matrix <<
", bag_size="
00171 << (
void*)
bag_size <<
", ";
00172
for(
int i=0; i<max_bag_size; i++) cout << (
void*)
outputs[i] <<
" ";
00173 cout <<
") = " << value;
00174
if (print_gradient) cout <<
" gradient=" << gradient;
00175 cout <<
endl;
00176 }
00177
00178
00179
00180 }
00181
00182