XCSF  1.4.7
XCSF learning classifier system
pred_rls.c
Go to the documentation of this file.
1 /*
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation, either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  */
15 
24 #include "pred_rls.h"
25 #include "blas.h"
26 #include "utils.h"
27 
33 void
34 pred_rls_init(const struct XCSF *xcsf, struct Cl *c)
35 {
36  struct PredRLS *pred = malloc(sizeof(struct PredRLS));
37  c->pred = pred;
38  // set the length of weights per predicted variable
39  if (xcsf->pred->type == PRED_TYPE_RLS_QUADRATIC) {
40  // offset(1) + n linear + n quadratic + n*(n-1)/2 mixed terms
41  pred->n = 1 + 2 * xcsf->x_dim + xcsf->x_dim * (xcsf->x_dim - 1) / 2;
42  } else {
43  pred->n = xcsf->x_dim + 1;
44  }
45  // initialise weights
46  pred->n_weights = pred->n * xcsf->y_dim;
47  pred->weights = calloc(pred->n_weights, sizeof(double));
48  blas_fill(xcsf->y_dim, xcsf->pred->x0, pred->weights, pred->n);
49  // initialise gain matrix
50  const int n_sqrd = pred->n * pred->n;
51  pred->matrix = calloc(n_sqrd, sizeof(double));
52  for (int i = 0; i < pred->n; ++i) {
53  pred->matrix[i * pred->n + i] = xcsf->pred->scale_factor;
54  }
55  // initialise temporary storage for weight updating
56  pred->tmp_input = malloc(sizeof(double) * pred->n);
57  pred->tmp_vec = calloc(pred->n, sizeof(double));
58  pred->tmp_matrix1 = calloc(n_sqrd, sizeof(double));
59  pred->tmp_matrix2 = calloc(n_sqrd, sizeof(double));
60 }
61 
68 void
69 pred_rls_copy(const struct XCSF *xcsf, struct Cl *dest, const struct Cl *src)
70 {
71  pred_rls_init(xcsf, dest);
72  const struct PredRLS *dest_pred = dest->pred;
73  const struct PredRLS *src_pred = src->pred;
74  memcpy(dest_pred->weights, src_pred->weights,
75  sizeof(double) * src_pred->n_weights);
76 }
77 
83 void
84 pred_rls_free(const struct XCSF *xcsf, const struct Cl *c)
85 {
86  (void) xcsf;
87  struct PredRLS *pred = c->pred;
88  free(pred->weights);
89  free(pred->matrix);
90  free(pred->tmp_input);
91  free(pred->tmp_vec);
92  free(pred->tmp_matrix1);
93  free(pred->tmp_matrix2);
94  free(pred);
95 }
96 
105 void
106 pred_rls_update(const struct XCSF *xcsf, const struct Cl *c, const double *x,
107  const double *y)
108 {
109  (void) x;
110  const struct PredRLS *pred = c->pred;
111  const int n = pred->n;
112  // gain vector = matrix * tmp_input (tmp_input set during compute)
113  const double *A = pred->matrix;
114  const double *B = pred->tmp_input;
115  double *C = pred->tmp_vec;
116  blas_gemm(0, 0, n, 1, n, 1, A, n, B, 1, 0, C, 1);
117  // divide gain vector by lambda + gain vector
118  double divisor = blas_dot(n, pred->tmp_input, 1, pred->tmp_vec, 1);
119  divisor = 1 / (divisor + xcsf->pred->lambda);
120  blas_scal(n, divisor, pred->tmp_vec, 1);
121  // update weights using the error
122  for (int i = 0; i < xcsf->y_dim; ++i) {
123  const double error = y[i] - c->prediction[i];
124  blas_axpy(n, error, pred->tmp_vec, 1, &pred->weights[i * n], 1);
125  }
126  // update gain matrix
127  for (int i = 0; i < n; ++i) {
128  for (int j = 0; j < n; ++j) {
129  const double tmp = pred->tmp_vec[i] * pred->tmp_input[j];
130  if (i == j) {
131  pred->tmp_matrix1[i * n + j] = 1 - tmp;
132  } else {
133  pred->tmp_matrix1[i * n + j] = -tmp;
134  }
135  }
136  }
137  // tmp_matrix2 = tmp_matrix1 * pred_matrix
138  A = pred->tmp_matrix1;
139  B = pred->matrix;
140  C = pred->tmp_matrix2;
141  blas_gemm(0, 0, n, n, n, 1, A, n, B, n, 0, C, n);
142  // divide gain matrix entries by lambda
143  const double lambda = xcsf->pred->lambda;
144  for (int i = 0; i < n; ++i) {
145  for (int j = 0; j < n; ++j) {
146  pred->matrix[i * n + j] = pred->tmp_matrix2[i * n + j] / lambda;
147  }
148  }
149 }
150 
157 void
158 pred_rls_compute(const struct XCSF *xcsf, const struct Cl *c, const double *x)
159 {
160  const struct PredRLS *pred = c->pred;
161  const int n = pred->n;
162  pred_transform_input(xcsf, x, xcsf->pred->x0, pred->tmp_input);
163  for (int i = 0; i < xcsf->y_dim; ++i) {
164  c->prediction[i] =
165  blas_dot(n, &pred->weights[i * n], 1, pred->tmp_input, 1);
166  }
167 }
168 
174 void
175 pred_rls_print(const struct XCSF *xcsf, const struct Cl *c)
176 {
177  char *json_str = pred_rls_json_export(xcsf, c);
178  printf("%s\n", json_str);
179  free(json_str);
180 }
181 
189 bool
190 pred_rls_crossover(const struct XCSF *xcsf, const struct Cl *c1,
191  const struct Cl *c2)
192 {
193  (void) xcsf;
194  (void) c1;
195  (void) c2;
196  return false;
197 }
198 
205 bool
206 pred_rls_mutate(const struct XCSF *xcsf, const struct Cl *c)
207 {
208  (void) xcsf;
209  (void) c;
210  return false;
211 }
212 
219 double
220 pred_rls_size(const struct XCSF *xcsf, const struct Cl *c)
221 {
222  (void) xcsf;
223  const struct PredRLS *pred = c->pred;
224  return pred->n_weights;
225 }
226 
234 size_t
235 pred_rls_save(const struct XCSF *xcsf, const struct Cl *c, FILE *fp)
236 {
237  (void) xcsf;
238  const struct PredRLS *pred = c->pred;
239  size_t s = 0;
240  s += fwrite(&pred->n, sizeof(int), 1, fp);
241  s += fwrite(&pred->n_weights, sizeof(int), 1, fp);
242  s += fwrite(pred->weights, sizeof(double), pred->n_weights, fp);
243  const int n_sqrd = pred->n * pred->n;
244  s += fwrite(pred->matrix, sizeof(double), n_sqrd, fp);
245  return s;
246 }
247 
255 size_t
256 pred_rls_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
257 {
258  pred_rls_init(xcsf, c);
259  struct PredRLS *pred = c->pred;
260  size_t s = 0;
261  s += fread(&pred->n, sizeof(int), 1, fp);
262  s += fread(&pred->n_weights, sizeof(int), 1, fp);
263  s += fread(pred->weights, sizeof(double), pred->n_weights, fp);
264  const int n_sqrd = pred->n * pred->n;
265  s += fread(pred->matrix, sizeof(double), n_sqrd, fp);
266  return s;
267 }
268 
275 char *
276 pred_rls_json_export(const struct XCSF *xcsf, const struct Cl *c)
277 {
278  const struct PredRLS *pred = c->pred;
279  cJSON *json = cJSON_CreateObject();
280  if (xcsf->pred->type == PRED_TYPE_RLS_QUADRATIC) {
281  cJSON_AddStringToObject(json, "type", "rls_quadratic");
282  } else {
283  cJSON_AddStringToObject(json, "type", "rls_linear");
284  }
285  cJSON *weights = cJSON_CreateDoubleArray(pred->weights, pred->n_weights);
286  cJSON_AddItemToObject(json, "weights", weights);
287  char *string = cJSON_Print(json);
288  cJSON_Delete(json);
289  return string;
290 }
291 
298 void
299 pred_rls_json_import(const struct XCSF *xcsf, struct Cl *c, const cJSON *json)
300 {
301  (void) xcsf;
302  struct PredRLS *pred = c->pred;
303  const cJSON *item = cJSON_GetObjectItem(json, "weights");
304  if (item != NULL && cJSON_IsArray(item)) {
305  if (cJSON_GetArraySize(item) == pred->n_weights) {
306  for (int i = 0; i < pred->n_weights; ++i) {
307  const cJSON *item_i = cJSON_GetArrayItem(item, i);
308  pred->weights[i] = item_i->valuedouble;
309  }
310  } else {
311  printf("Import error: weight length mismatch\n");
312  exit(EXIT_FAILURE);
313  }
314  }
315 }
316 
322 char *
324 {
325  const struct ArgsPred *pred = xcsf->pred;
326  cJSON *json = cJSON_CreateObject();
327  cJSON_AddNumberToObject(json, "x0", pred->x0);
328  cJSON_AddNumberToObject(json, "lambda", pred->lambda);
329  cJSON_AddNumberToObject(json, "scale_factor", pred->scale_factor);
330  char *string = cJSON_Print(json);
331  cJSON_Delete(json);
332  return string;
333 }
334 
341 char *
342 pred_rls_param_json_import(struct XCSF *xcsf, cJSON *json)
343 {
344  for (cJSON *iter = json; iter != NULL; iter = iter->next) {
345  if (strncmp(iter->string, "x0\0", 3) == 0 && cJSON_IsNumber(iter)) {
346  pred_param_set_x0(xcsf, iter->valuedouble);
347  } else if (strncmp(iter->string, "lambda\0", 7) == 0 &&
348  cJSON_IsNumber(iter)) {
349  pred_param_set_lambda(xcsf, iter->valuedouble);
350  } else if (strncmp(iter->string, "scale_factor\0", 13) == 0 &&
351  cJSON_IsNumber(iter)) {
352  pred_param_set_scale_factor(xcsf, iter->valuedouble);
353  } else {
354  return iter->string;
355  }
356  }
357  return NULL;
358 }
void blas_fill(const int N, const double ALPHA, double *X, const int INCX)
Fills the vector X with the value ALPHA.
Definition: blas.c:181
void blas_scal(const int N, const double ALPHA, double *X, const int INCX)
Scales vector X by the scalar ALPHA and overwrites it with the result.
Definition: blas.c:160
double blas_dot(const int N, const double *X, const int INCX, const double *Y, const int INCY)
Computes the dot product of two vectors.
Definition: blas.c:198
void blas_axpy(const int N, const double ALPHA, const double *X, const int INCX, double *Y, const int INCY)
Multiplies vector X by the scalar ALPHA and adds it to the vector Y.
Definition: blas.c:138
void blas_gemm(const int TA, const int TB, const int M, const int N, const int K, const double ALPHA, const double *A, const int lda, const double *B, const int ldb, const double BETA, double *C, const int ldc)
Performs the matrix-matrix multiplication: .
Definition: blas.c:108
Basic linear algebra functions.
Definition: __init__.py:1
void pred_rls_free(const struct XCSF *xcsf, const struct Cl *c)
Frees the memory used by an RLS prediction.
Definition: pred_rls.c:84
void pred_rls_copy(const struct XCSF *xcsf, struct Cl *dest, const struct Cl *src)
Copies an RLS prediction from one classifier to another.
Definition: pred_rls.c:69
void pred_rls_update(const struct XCSF *xcsf, const struct Cl *c, const double *x, const double *y)
Updates an RLS prediction for a given input and truth sample.
Definition: pred_rls.c:106
double pred_rls_size(const struct XCSF *xcsf, const struct Cl *c)
Returns the size of an RLS prediction.
Definition: pred_rls.c:220
void pred_rls_init(const struct XCSF *xcsf, struct Cl *c)
Initialises an RLS prediction.
Definition: pred_rls.c:34
char * pred_rls_json_export(const struct XCSF *xcsf, const struct Cl *c)
Returns a json formatted string representation of an RLS prediction.
Definition: pred_rls.c:276
size_t pred_rls_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
Reads an RLS prediction from a file.
Definition: pred_rls.c:256
void pred_rls_print(const struct XCSF *xcsf, const struct Cl *c)
Prints an RLS prediction.
Definition: pred_rls.c:175
char * pred_rls_param_json_export(const struct XCSF *xcsf)
Returns a json formatted string of the RLS parameters.
Definition: pred_rls.c:323
void pred_rls_json_import(const struct XCSF *xcsf, struct Cl *c, const cJSON *json)
Creates an RLS prediction from a cJSON object.
Definition: pred_rls.c:299
bool pred_rls_crossover(const struct XCSF *xcsf, const struct Cl *c1, const struct Cl *c2)
Dummy function since RLS predictions do not perform crossover.
Definition: pred_rls.c:190
char * pred_rls_param_json_import(struct XCSF *xcsf, cJSON *json)
Sets the RLS parameters from a cJSON object.
Definition: pred_rls.c:342
void pred_rls_compute(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Computes the current RLS prediction for a provided input.
Definition: pred_rls.c:158
bool pred_rls_mutate(const struct XCSF *xcsf, const struct Cl *c)
Dummy function since RLS predictions do not perform mutation.
Definition: pred_rls.c:206
size_t pred_rls_save(const struct XCSF *xcsf, const struct Cl *c, FILE *fp)
Writes an RLS prediction to a file.
Definition: pred_rls.c:235
Recursive least mean squares prediction functions.
void pred_param_set_x0(struct XCSF *xcsf, const double a)
Definition: prediction.c:331
void pred_param_set_lambda(struct XCSF *xcsf, const double a)
Definition: prediction.c:319
void pred_param_set_scale_factor(struct XCSF *xcsf, const double a)
Definition: prediction.c:325
void pred_transform_input(const struct XCSF *xcsf, const double *x, const double X0, double *tmp_input)
Prepares the input state for least squares computation.
Definition: prediction.c:265
#define PRED_TYPE_RLS_QUADRATIC
Prediction type quadratic rls.
Definition: prediction.h:33
Parameters for initialising and operating predictions.
Definition: prediction.h:50
double scale_factor
Initial values for the RLS gain-matrix.
Definition: prediction.h:56
double x0
Prediction weight vector offset value.
Definition: prediction.h:57
double lambda
RLS forget rate.
Definition: prediction.h:55
Classifier data structure.
Definition: xcsf.h:45
void * pred
Prediction structure.
Definition: xcsf.h:50
double * prediction
Current classifier prediction.
Definition: xcsf.h:59
Recursive least mean squares prediction data structure.
Definition: pred_rls.h:32
double * tmp_vec
Temporary storage for updating weights.
Definition: pred_rls.h:38
double * tmp_input
Temporary storage for updating weights.
Definition: pred_rls.h:37
double * matrix
Gain matrix used to update weights.
Definition: pred_rls.h:36
int n
Number of weights for each predicted variable.
Definition: pred_rls.h:33
double * weights
Weights used to compute prediction.
Definition: pred_rls.h:35
int n_weights
Total number of weights.
Definition: pred_rls.h:34
double * tmp_matrix2
Temporary storage for updating gain matrix.
Definition: pred_rls.h:40
double * tmp_matrix1
Temporary storage for updating gain matrix.
Definition: pred_rls.h:39
XCSF data structure.
Definition: xcsf.h:85
Utility functions for random number handling, etc.