00001
00047
00048
00049
00050 #include <math.h>
00051 #include <SharkDefs.h>
00052 #include <LinAlg/LinAlg.h>
00053 #include <ReClaM/LinearModel.h>
00054
00055
00056 LinearMap::LinearMap(int inputdim, int outputdim)
00057 {
00058 inputDimension = inputdim;
00059 outputDimension = outputdim;
00060
00061 parameter.resize(inputdim * outputdim, false);
00062 parameter = 0.0;
00063 }
00064
00065 LinearMap::~LinearMap()
00066 {
00067 }
00068
00069
00070 void LinearMap::model(const Array<double>& input, Array<double> &output)
00071 {
00072 if (input.ndim() == 1)
00073 {
00074 unsigned int i, o;
00075 double value;
00076 output.resize(outputDimension, false);
00077 int p = 0;
00078 for (o = 0; o < outputDimension; o++)
00079 {
00080 value = 0.0;
00081 for (i = 0; i < inputDimension; i++)
00082 {
00083 value += input(i) * parameter(p);
00084 p++;
00085 }
00086 output(o) = value;
00087 }
00088 }
00089 else if (input.ndim() == 2)
00090 {
00091 unsigned int j, jc = input.dim(0);
00092 unsigned int i, o;
00093 double value;
00094 output.resize(jc, outputDimension, false);
00095 for (j = 0; j < jc; j++)
00096 {
00097 int p = 0;
00098 for (o = 0; o < outputDimension; o++)
00099 {
00100 value = 0.0;
00101 for (i = 0; i < inputDimension; i++)
00102 {
00103 value += input(j, i) * parameter(p);
00104 p++;
00105 }
00106 output(j, o) = value;
00107 }
00108 }
00109 }
00110 else throw SHARKEXCEPTION("[LinearMap::model] invalid number of dimensions.");
00111 }
00112
00113 void LinearMap::modelDerivative(const Array<double>& input, Array<double>& derivative)
00114 {
00115 if (input.ndim() == 1)
00116 {
00117 unsigned int o, p, pc = getParameterDimension();
00118 derivative.resize(outputDimension, pc, false);
00119 for (o = 0; o < outputDimension; o++)
00120 {
00121 for (p = 0; p < pc; p++)
00122 {
00123 derivative(o, p) = input(p);
00124 }
00125 }
00126 }
00127 else throw SHARKEXCEPTION("[LinearMap::modelDerivative] invalid number of dimensions.");
00128 }
00129
00130
00132
00133
00134 AffineLinearMap::AffineLinearMap(int inputdim, int outputdim)
00135 {
00136 inputDimension = inputdim;
00137 outputDimension = outputdim;
00138
00139 parameter.resize(inputdim * outputdim + outputdim, false);
00140 parameter = 0.0;
00141 }
00142
00143 AffineLinearMap::~AffineLinearMap()
00144 {
00145 }
00146
00147
00148 void AffineLinearMap::model(const Array<double>& input, Array<double> &output)
00149 {
00150 int pb = inputDimension * outputDimension;
00151
00152 if (input.ndim() == 1)
00153 {
00154 unsigned int i, o;
00155 double value;
00156 output.resize(outputDimension, false);
00157 int p = 0;
00158 for (o = 0; o < outputDimension; o++)
00159 {
00160 value = parameter(pb + o);
00161 for (i = 0; i < inputDimension; i++)
00162 {
00163 value += input(i) * parameter(p);
00164 p++;
00165 }
00166 output(o) = value;
00167 }
00168 }
00169 else if (input.ndim() == 2)
00170 {
00171 unsigned int j, jc = input.dim(0);
00172 unsigned int i, o;
00173 double value;
00174 output.resize(jc, outputDimension, false);
00175 for (j = 0; j < jc; j++)
00176 {
00177 int p = 0;
00178 for (o = 0; o < outputDimension; o++)
00179 {
00180 value = parameter(pb + o);
00181 for (i = 0; i < inputDimension; i++)
00182 {
00183 value += input(j, i) * parameter(p);
00184 p++;
00185 }
00186 output(j, o) = value;
00187 }
00188 }
00189 }
00190 else throw SHARKEXCEPTION("[AffineLinearMap::model] invalid number of dimensions.");
00191 }
00192
00193 void AffineLinearMap::modelDerivative(const Array<double>& input, Array<double>& derivative)
00194 {
00195 if (input.ndim() == 1)
00196 {
00197 unsigned int o, p, pc = getParameterDimension();
00198 derivative.resize(outputDimension, pc, false);
00199 for (o = 0; o < outputDimension; o++)
00200 {
00201 for (p = 0; p < pc; p++)
00202 {
00203 derivative(o, p) = input(p);
00204 }
00205 }
00206 }
00207 else throw SHARKEXCEPTION("[AffineLinearMap::modelDerivative] invalid number of dimensions.");
00208 }
00209
00210
00212
00213
00214 LinearFunction::LinearFunction(int dimension)
00215 : LinearMap(dimension, 1)
00216 {
00217 }
00218
00219
00221
00222
00223 AffineLinearFunction::AffineLinearFunction(int dimension)
00224 : AffineLinearMap(dimension, 1)
00225 {
00226 }
00227
00228
00230
00231
00232 LinearClassifier::LinearClassifier(int dimension, int classes)
00233 {
00234 inputDimension = dimension;
00235 outputDimension = classes;
00236 numberOfClasses = classes;
00237
00238
00239 mean.resize(classes, dimension, false);
00240 covariance.resize(dimension, dimension, false);
00241 inverse.resize(dimension, dimension, false);
00242 parameter.resize(dimension * classes + dimension * (dimension+1) / 2, false);
00243 mean = 0.0;
00244 covariance = 0.0;
00245 inverse = 0.0;
00246 parameter = 0.0;
00247
00248 bNeedsUpdate = true;
00249 }
00250
00251 LinearClassifier::~LinearClassifier()
00252 {
00253 }
00254
00255
00256 void LinearClassifier::setParameter(unsigned int index, double value)
00257 {
00258 Model::setParameter(index, value);
00259
00260 if (index < numberOfClasses * inputDimension)
00261 {
00262
00263 int cls = index / inputDimension;
00264 int dim = index % inputDimension;
00265 mean(cls, dim) = value;
00266 }
00267 else
00268 {
00269
00270 index -= numberOfClasses * inputDimension;
00271 int y = (int)floor(sqrt(2.0*index + 0.25) - 0.5);
00272 int x = index - y*(y+1)/2;
00273 covariance(x, y) = covariance(y, x) = value;
00274 bNeedsUpdate = true;
00275 }
00276 }
00277
00278 void LinearClassifier::model(const Array<double>& input, Array<double>& output)
00279 {
00280 if (bNeedsUpdate)
00281 {
00282 invertSymm(inverse, covariance);
00283 bNeedsUpdate = false;
00284 }
00285
00286 Array<double> diff(inputDimension);
00287
00288 if (input.ndim() == 1)
00289 {
00290 output.resize(numberOfClasses, false);
00291 output = 0.0;
00292 int c, d;
00293 int best = 0;
00294 double dist2, bestDist = MAXDOUBLE;
00295 for (c=0; c<numberOfClasses; c++)
00296 {
00297 for (d=0; d<(int)inputDimension; d++) diff(d) = input(d) - mean(c, d);
00298 dist2 = vecMatVec(diff, inverse, diff);
00299 if (dist2 < bestDist)
00300 {
00301 bestDist = dist2;
00302 best = c;
00303 }
00304 }
00305 output(best) = 1.0;
00306 }
00307 else if (input.ndim() == 2)
00308 {
00309 int i, ic = input.dim(0);
00310 output.resize(ic, numberOfClasses, false);
00311 output = 0.0;
00312 for (i=0; i<ic; i++)
00313 {
00314 int c, d;
00315 int best = 0;
00316 double dist2, bestDist = MAXDOUBLE;
00317 for (c=0; c<numberOfClasses; c++)
00318 {
00319 for (d=0; d<(int)inputDimension; d++) diff(d) = input(i, d) - mean(c, d);
00320 dist2 = vecMatVec(diff, inverse, diff);
00321 if (dist2 < bestDist)
00322 {
00323 bestDist = dist2;
00324 best = c;
00325 }
00326 }
00327 output(i, best) = 1.0;
00328 }
00329 }
00330 else throw SHARKEXCEPTION("[LinearClassifier::model] invalid number of dimensions.");
00331 }