HOG2
LinearRegression.cpp
Go to the documentation of this file.
1 /*
2  * LinearRegression.cpp
3  * hog2
4  *
5  * Created by Nathan Sturtevant on 6/1/06.
6  * Copyright 2006 Nathan Sturtevant. All rights reserved.
7  *
8  */
9 
10 
11 #include <math.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <assert.h>
16 #include <string.h>
17 #include "LinearRegression.h"
18 #include "SwapEndian.h"
19 
20 static const float VERSION = 1.1;
21 static const float MINVERSION = 1.0;
22 
23 LinearRegression::LinearRegression(int _inputs, int _outputs, double _rate)
24 {
25  useBinary = false;
27  inputs = _inputs;
28  outputs = _outputs;
29  rate = _rate;
30  weight.resize(0);
31  updates.resize(0);
32  //weight = 0;
34 }
35 
37 {
38  useBinary = perp->useBinary;
39 // inputs = perp->inputs;
40  outputs = perp->outputs;
41  rate = perp->rate;
43  weight.resize(0);
44  updates.resize(0);
45  //weight = 0;
46  //allocateMemory(perp->inputs);
47  load(perp);
48 }
49 
51 {
52  useBinary = false;
53  weight.resize(0);
54  updates.resize(0);
55  //weight = 0;
56  inputs = outputs = -1;
57  load(f);
58 }
59 
61 {
62  LinearRegression *perp = (LinearRegression *)fa;
63  useBinary = perp->useBinary;
64  inputs = perp->inputs;
65  outputs = perp->outputs;
67  rate = perp->rate;
68  weight.resize(0);
69  updates.resize(0);
70  //weight = 0;
71  //allocateMemory();
72  load(perp);
73 }
74 
76 {
77  freeMemory();
78 }
79 
80 void LinearRegression::resizeInputs(int newSize, double newVal)
81 {
82  if (newSize < inputs)
83  {
84  for (int x = 0; x < outputs; x++)
85  {
86  weight[x][newSize] = weight[x][inputs];
87  weight[x].resize(newSize+1);
88  updates[x].resize(newSize);
89  }
90  }
91  else if (newSize == inputs)
92  {
93  return;
94  }
95  else {
96  for (int x = 0; x < outputs; x++)
97  {
98  weight[x].resize(newSize+1);// = new double[inputs+1];
99  weight[x][newSize] = weight[x][inputs];
100  for (int y = inputs; y < newSize; y++)
101  weight[x][y] = newVal;
102 
103  updates[x].resize(newSize);// = new double[inputs+1];
104  }
105  }
106  inputs = newSize;
107 }
108 
110 {
111  if (newSize < inputs)
112  {
113  for (int x = 0; x < outputs; x++)
114  {
115  weight[x][newSize] = weight[x][inputs];
116  weight[x].resize(newSize+1);
117  updates[x].resize(newSize);
118  }
119  }
120  else if (newSize == inputs)
121  {
122  return;
123  }
124  else {
125  for (int x = 0; x < outputs; x++)
126  {
127  weight[x].resize(newSize+1);// = new double[inputs+1];
128  weight[x][newSize] = weight[x][inputs];
129  for (int y = inputs; y < newSize; y++)
130  weight[x][y] = ((double)2*random()/RAND_MAX-1)/(double)newSize;
131 
132  updates[x].resize(newSize);// = new double[inputs+1];
133  }
134  }
135  inputs = newSize;
136 }
137 
139 {
140 // if (weight.size() != 0)
141 // freeMemory();
142  weight.resize(outputs);// = new double*[outputs];
143  updates.resize(outputs);
144  for (int x = 0; x < outputs; x++)
145  {
146  weight[x].resize(inputs+1);// = new double[inputs+1];
147  updates[x].resize(inputs);
148  for (int y = 0; y <= inputs; y++)
149  weight[x][y] = ((double)2*random()/RAND_MAX-1)/(double)inputs;
150  }
151  output.resize(outputs);// = new double[outputs];
152 }
153 
155 {
156 // if (weight != 0)
157 // {
162  weight.resize(0);
163  updates.resize(0);
164  // //weight = 0;
165 // }
166 }
167 
168 void LinearRegression::load(const char *fname)
169 {
170  FILE *f;
171  f = fopen(fname, "r");
172  if (f == 0)
173  {
174  fprintf(stderr, "REGR Error: could not open file '%s' for loading; trying once more.\n", fname);
175  sleep(1);
176  f = fopen(fname, "r");
177  if (f == 0)
178  {
179  fprintf(stderr, "REGR Error: could not open file '%s' for loading.\n", fname);
180  exit(0);
181  return;
182  }
183  }
184  load(f);
185  fclose(f);
186 }
187 
189 {
190  int inputs1, outputs1;
191  float version;
192  int res = fscanf(f, "REGR %f %d %d\n", &version, &inputs1, &outputs1);
193  if (res != 3)
194  {
195  printf("Error: unrecognized LinearRegression file. Expected header 'PERP <version> <inputs> <outputs>'.");
196  exit(0);
197  }
198  if (version > VERSION)
199  {
200  printf("Error: loaded network is %1.2f, but code can only handle %1.2f to %1.2f.",
201  version, MINVERSION, VERSION);
202  exit(0);
203  }
204  if (VERSION >= 1.1)
205  {
206  char text[25];
207  res = fscanf(f, "%s\n", text);
208  assert(res == 1);
209  if (strcmp(text, "binary") == 0)
210  useBinary = true;
211  else //if (strcmp(text, "text") == 0)
212  useBinary = false;
213  }
214 
215  if ((inputs1 != inputs) || (outputs1 != outputs))
216  {
217  freeMemory();
218  inputs = inputs1;
219  outputs = outputs1;
220  allocateMemory();
221  }
222 
223  for (int y = 0; y < outputs; y++)
224  {
225  for (int x = 0; x <= inputs; x++)
226  {
227  if (useBinary)
228  {
229  float shrunk;
230  fread(&shrunk, sizeof(float), 1, f);
231  //fread(&weight[y][x], sizeof(double), 1, f);
232  little2machine(shrunk);
233  weight[y][x] = shrunk;
234  }
235  else
236  fscanf(f, "%le ", &weight[y][x]);
237  }
238  }
239 }
240 
242 {
243  if (p && ((p->inputs != inputs) || (p->outputs != outputs)))
244  {
245  freeMemory();
246  inputs = p->inputs;
247  outputs = p->outputs;
249 
250  allocateMemory();
251  }
252 
253  if (p)
254  {
255  for (int y = 0; y < outputs; y++)
256  {
257  for (int x = 0; x <= inputs; x++)
258  {
259  weight[y][x] = p->weight[y][x];
260  }
261  }
262  }
263 }
264 
266 {
267  FILE *f;
268  f = fopen(fname, "r");
269  if (f == 0)
270  {
271  return false;
272  }
273  int finput, foutput;
274  float version;
275  int res = fscanf(f, "REGR %f %d %d\n", &version, &finput, &foutput);
276  fclose(f);
277  if (res != 3)
278  {
279  return false;
280  }
281  if (version > VERSION)
282  {
283  return false;
284  }
285  return true;
286 }
287 
288 void LinearRegression::save(const char *fname)
289 {
290  FILE *f;
291  f = fopen(fname, "w+");
292  if (f == 0)
293  {
294  fprintf(stderr, "Error: could not open file for saving.\n");
295  return;
296  }
297  save(f);
298  fclose(f);
299 }
300 
302 {
303  fprintf(f, "REGR %1.2f %d %d\n", VERSION, inputs, outputs);
304  if (useBinary)
305  fprintf(f, "binary\n");
306  else
307  fprintf(f, "text\n");
308 
309  for (int y = 0; y < outputs; y++)
310  {
311  for (int x = 0; x <= inputs; x++)
312  {
313  if (useBinary)
314  {
315  float val = weight[y][x];
316  little2machine(val);
317  fwrite(&val, sizeof(float), 1, f);
318  }
319  else {
320  fprintf(f, "%le ", weight[y][x]);
321  }
322  }
323  if (!useBinary)
324  fprintf(f, "\n");
325  }
326 }
327 
328 double LinearRegression::outputerr(std::vector<double> &out, std::vector<double> &expected, int which)
329 {
330  double err = (out[which]-expected[which]);
331  //printf("Output error: %1.2f\n", err);
332  return err;
333 }
334 
335 double LinearRegression::train(std::vector<unsigned int> &input, std::vector<double> &target)
336 {
337  double totalErr = 0;
338  test(input);
339  for (int x = 0; x < outputs; x++)
340  {
341  double err = outputerr(output,target,x);
342  totalErr+=err*err;
343  double rateTimesError = rate*err;
344  for (unsigned int y = 0; y < input.size(); y++)
345  {
346  weight[x][input[y]] -= rateTimesError;
347  updateData &val = updates[x][input[y]];
348  val.n++;
349 // double delta = err-val.mean;
350  double delta = rateTimesError-val.mean;
351  val.mean = val.mean+delta/val.n;
352  val.S += delta*(err-val.mean);
353  val.totErr += rateTimesError*rateTimesError;
354  }
355  weight[x][inputs] -= rateTimesError; // bias
356  }
357  return totalErr;
358 }
359 
360 double LinearRegression::train(std::vector<double> &input, std::vector<double> &target)
361 {
362  double totalErr = 0;
363  test(input);
364  for (int x = 0; x < outputs; x++)
365  {
366  double err = outputerr(output,target,x);
367  totalErr+=err*err;
368  double rateTimesError = rate*err;
369  for (int y = 0; y < inputs; y++)
370  {
371  weight[x][y] -= rateTimesError*input[y];
372 
373  updateData &val = updates[x][y];
374  val.n++;
375 // double delta = err-val.mean;
376  double delta = rateTimesError-val.mean;
377  val.mean = val.mean+delta/val.n;
378  val.S += delta*(err-val.mean);
379  val.totErr += rateTimesError*rateTimesError;
380  }
381  weight[x][inputs] -= rateTimesError*(1); // bias
382  }
383  return totalErr;
384 }
385 
386 double *LinearRegression::test(const std::vector<unsigned int> &input)
387 {
388  for (int y = 0; y < outputs; y++)
389  {
390  output[y] = weight[y][inputs]; // bias
391  for (unsigned int x = 0; x < input.size(); x++)
392  {
393  output[y] += weight[y][input[x]];
394  }
395  }
396  return &output[0];
397 }
398 
399 double *LinearRegression::test(const std::vector<double> &input)
400 {
401  for (int y = 0; y < outputs; y++)
402  {
403  output[y] = weight[y][inputs];
404  for (int x = 0; x < inputs; x++)
405  {
406  output[y] += weight[y][x]*input[x];
407  }
408  }
409  return &output[0];
410 }
411 
412 void LinearRegression::getWeightUpdateVariance(std::vector<double> &var, unsigned int which)
413 {
414  assert(which < weight.size());
415  var.resize(weight[which].size()-1);
416  for (unsigned int x = 0; x < weight[which].size()-1; x++) // ignore bias!
417  {
418  updateData &val = updates[which][x];
419  if (val.n > 1)
420  var[x] = val.S/(val.n-1);
421  else
422  var[x] = 0;
423  }
424 }
425 
426 double LinearRegression::getWeightUpdateVariance(unsigned int weightNum, unsigned int whichOutput)
427 {
428  assert(whichOutput < weight.size());
429  assert(weightNum < weight[whichOutput].size());
430 
431  updateData &val = updates[whichOutput][weightNum];
432  if (val.n > 1)
433  return val.S/(val.n-1);
434  return 0;
435 }
436 
437 void LinearRegression::getWeightUpdateAverage(std::vector<double> &var, unsigned int which)
438 {
439  assert(which < weight.size());
440  var.resize(weight[which].size()-1);
441  for (unsigned int x = 0; x < weight[which].size()-1; x++) // ignore bias!
442  {
443  updateData &val = updates[which][x];
444  if (val.n > 1)
445  var[x] = val.totErr/val.n;
446  else
447  var[x] = 0;
448  }
449 }
450 
451 double LinearRegression::getWeightUpdateAverage(unsigned int weightNum, unsigned int whichOutput)
452 {
453  assert(whichOutput < weight.size());
454  assert(weightNum < weight[whichOutput].size());
455 
456  updateData &val = updates[whichOutput][weightNum];
457  if (val.n > 1)
458  return val.totErr/val.n;
459  return 0;
460 }
461 
462 void LinearRegression::getWeightUpdateSum(std::vector<double> &var, unsigned int which)
463 {
464  assert(which < weight.size());
465  var.resize(weight[which].size()-1);
466  for (unsigned int x = 0; x < weight[which].size()-1; x++) // ignore bias!
467  {
468  var[x] = updates[which][x].totErr;
469  }
470 }
471 
472 double LinearRegression::getWeightUpdateSum(unsigned int weightNum, unsigned int whichOutput)
473 {
474  assert(whichOutput < weight.size());
475  assert(weightNum < weight[whichOutput].size());
476 
477  return updates[whichOutput][weightNum].totErr;
478 }
479 
480 void LinearRegression::resetWeightVariance(unsigned int weightNum, unsigned int whichOutput)
481 {
482  updates[whichOutput][weightNum].reset();
483 }
484 
486 {
487  for (unsigned int y = 0; y < updates.size(); y++)
488  {
489  for (unsigned int x = 0; x < updates[y].size(); x++)
490  {
491  updates[y][x].reset();
492  }
493  }
494 }
495 
496 int LinearRegression::getWeightFrequency(unsigned int weightNum, unsigned int whichOutput)
497 {
498  return updates[whichOutput][weightNum].n;
499 }
500 
501 void LinearRegression::setInputWeight(double value, unsigned int weightNum, unsigned int whichOutput)
502 {
503  updates[whichOutput][weightNum].reset();
504  weight[whichOutput][weightNum] = value;
505 }
506 
508 {
509  for (int y = 0; y < outputs; y++)
510  for (int x = 0; x <= inputs; x++)
511  {
512  printf("%1.3f ", weight[y][x]);
513  }
514  printf("\n");
515 }
little2machine
void little2machine(uint16_t &x)
Definition: SwapEndian.h:37
LinearRegression::setInputWeight
void setInputWeight(double value, unsigned int weightNum, unsigned int whichOutput=0)
Definition: LinearRegression.cpp:501
LinearRegression::getWeightUpdateSum
void getWeightUpdateSum(std::vector< double > &var, unsigned int which=0)
Definition: LinearRegression.cpp:462
LinearRegression::Print
void Print()
Definition: LinearRegression.cpp:507
LinearRegression::validSaveFile
static bool validSaveFile(char *fname)
Definition: LinearRegression.cpp:265
LinearRegression::getWeightUpdateVariance
void getWeightUpdateVariance(std::vector< double > &var, unsigned int which=0)
Definition: LinearRegression.cpp:412
LinearRegression::test
double * test(const std::vector< double > &input)
Definition: LinearRegression.cpp:399
LinearRegression::resetWeightVariance
void resetWeightVariance()
Definition: LinearRegression.cpp:485
MINVERSION
static const float MINVERSION
Definition: LinearRegression.cpp:21
updateData::totErr
double totErr
Definition: LinearRegression.h:23
LinearRegression::useBinary
bool useBinary
Definition: LinearRegression.h:90
updateData::n
int n
Definition: LinearRegression.h:24
LinearRegression::LinearRegression
LinearRegression(int _inputs, int _outputs, double learnrate)
Definition: LinearRegression.cpp:23
LinearRegression::load
void load(const char *)
Definition: LinearRegression.cpp:168
FunctionApproximator::rate
double rate
Definition: FunctionApproximator.h:61
LinearRegression::resizeInputs
void resizeInputs(int newSize, double newVal)
Definition: LinearRegression.cpp:80
FunctionApproximator
Definition: FunctionApproximator.h:25
SwapEndian.h
LinearRegression
Definition: LinearRegression.h:27
LinearRegression::outputs
int outputs
Definition: LinearRegression.h:89
updateData::mean
double mean
Definition: LinearRegression.h:21
LinearRegression::getWeightUpdateAverage
void getWeightUpdateAverage(std::vector< double > &var, unsigned int which=0)
Definition: LinearRegression.cpp:437
LinearRegression::weight
std::vector< std::vector< double > > weight
Definition: LinearRegression.h:83
LinearRegression::allocateMemory
void allocateMemory()
Definition: LinearRegression.cpp:138
LinearRegression.h
LinearRegression::freeMemory
void freeMemory()
Definition: LinearRegression.cpp:154
kLinear
@ kLinear
Definition: FunctionApproximator.h:20
LinearRegression::outputerr
double outputerr(std::vector< double > &output, std::vector< double > &expected, int which)
Definition: LinearRegression.cpp:328
updateData::S
double S
Definition: LinearRegression.h:22
LinearRegression::updates
std::vector< std::vector< updateData > > updates
Definition: LinearRegression.h:84
updateData
Definition: LinearRegression.h:17
LinearRegression::~LinearRegression
~LinearRegression()
Definition: LinearRegression.cpp:75
FunctionApproximator::outputActivation
tActivation outputActivation
Definition: FunctionApproximator.h:62
LinearRegression::output
std::vector< double > output
Definition: LinearRegression.h:86
LinearRegression::train
double train(std::vector< double > &input, std::vector< double > &output2)
Definition: LinearRegression.cpp:360
LinearRegression::inputs
int inputs
Definition: LinearRegression.h:89
LinearRegression::save
void save(const char *)
Definition: LinearRegression.cpp:288
VERSION
static const float VERSION
Definition: LinearRegression.cpp:20
LinearRegression::getWeightFrequency
int getWeightFrequency(unsigned int weightNum, unsigned int whichOutput=0)
Definition: LinearRegression.cpp:496