XCSF 1.4.8
XCSF learning classifier system
Loading...
Searching...
No Matches
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
33void
34pred_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
68void
69pred_rls_copy(const struct XCSF *xcsf, struct Cl *dest, const struct Cl *src)
70{
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
83void
84pred_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
105void
106pred_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
157void
158pred_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
174void
175pred_rls_print(const struct XCSF *xcsf, const struct Cl *c)
176{
178 printf("%s\n", json_str);
179 free(json_str);
180}
181
189bool
190pred_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
205bool
206pred_rls_mutate(const struct XCSF *xcsf, const struct Cl *c)
207{
208 (void) xcsf;
209 (void) c;
210 return false;
211}
212
219double
220pred_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
234size_t
235pred_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
255size_t
256pred_rls_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
257{
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
275char *
276pred_rls_json_export(const struct XCSF *xcsf, const struct Cl *c)
277{
278 const struct PredRLS *pred = c->pred;
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 }
287 char *string = cJSON_Print(json);
289 return string;
290}
291
298void
299pred_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");
313 }
314 }
315}
316
322char *
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
341char *
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.
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_param_json_import(struct XCSF *xcsf, cJSON *json)
Sets the RLS parameters from a cJSON object.
Definition pred_rls.c:342
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_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
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
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.