analistica/ex-7/main.c

111 lines
3.1 KiB
C

#include <stdio.h>
#include <string.h>
#include "fisher.h"
#include "percep.h"
/* Options for the program */
struct options {
char *mode;
size_t nsig;
size_t nnoise;
int iter;
};
int main(int argc, char **argv) {
/* Set default options */
struct options opts;
opts.mode = "fisher";
opts.nsig = 800;
opts.nnoise = 1000;
opts.iter = 5;
/* Process CLI arguments */
for (size_t i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-m")) opts.mode = argv[++i];
else if (!strcmp(argv[i], "-s")) opts.nsig = atol(argv[++i]);
else if (!strcmp(argv[i], "-n")) opts.nnoise = atol(argv[++i]);
else if (!strcmp(argv[i], "-i")) opts.nnoise = atoi(argv[++i]);
else {
fprintf(stderr, "Usage: %s -[hiIntp]\n", argv[0]);
fprintf(stderr, "\t-h\tShow this message.\n");
fprintf(stderr, "\t-m MODE\tThe disciminant to use: 'fisher' for "
"Fisher linear discriminant, 'percep' for perceptron.\n");
fprintf(stderr, "\t-i N\tThe number of training iterations (for perceptron).\n");
fprintf(stderr, "\t-n N\tThe number of events in noise class.\n");
return EXIT_FAILURE;
}
}
// initialize RNG
gsl_rng_env_setup();
gsl_rng *r = gsl_rng_alloc(gsl_rng_default);
/* Generate two classes of normally
* distributed 2D points with different
* paramters: signal and noise.
*/
struct par par_sig = { 0, 0, 0.3, 0.3, 0.5 };
struct par par_noise = { 4, 4, 1.0, 1.0, 0.4 };
sample_t *signal = generate_normal(r, opts.nsig, &par_sig);
sample_t *noise = generate_normal(r, opts.nnoise, &par_noise);
gsl_vector *w;
double t_cut;
if (!strcmp(opts.mode, "fisher")) {
/* Fisher linear discriminant
*
* First calculate the direction w onto
* which project the data points. Then the
* cut which determines the class for each
* projected point.
*/
fputs("# Linear Fisher discriminant\n\n", stderr);
double ratio = opts.nsig / (double)opts.nnoise;
w = fisher_proj(signal, noise);
t_cut = fisher_cut(ratio, w, signal, noise);
}
else if (!strcmp(opts.mode, "percep")) {
/* Perceptron
*
* Train a single perceptron on the
* dataset to get an approximate
* solution in `iter` iterations.
*/
fputs("# Perceptron \n\n", stderr);
w = percep_train(signal, noise, opts.iter, &t_cut);
}
else {
fputs("\n\nerror: invalid mode. select either"
" 'fisher' or 'percep'\n", stderr);
return EXIT_FAILURE;
}
/* Print the results of the method
* selected: weights and threshold.
*/
fprintf(stderr, "* w: [%.3f, %.3f]\n",
gsl_vector_get(w, 0),
gsl_vector_get(w, 1));
fprintf(stderr, "* t_cut: %.3f\n", t_cut);
gsl_vector_fprintf(stdout, w, "%g");
printf("%f\n", t_cut);
/* Print data to stdout for plotting.
* Note: we print the sizes to be able
* to set apart the two matrices.
*/
printf("%ld %ld %d\n", opts.nsig, opts.nnoise, 2);
gsl_matrix_fprintf(stdout, signal->data, "%g");
gsl_matrix_fprintf(stdout, noise->data, "%g");
// free memory
gsl_rng_free(r);
sample_t_free(signal);
sample_t_free(noise);
return EXIT_SUCCESS;
}