home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.disi.unige.it
/
2015-02-11.ftp.disi.unige.it.tar
/
ftp.disi.unige.it
/
pub
/
.person
/
BarlaA
/
sw
/
OLD
/
Simo
/
SVM_mono
/
solve.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-06-25
|
13KB
|
459 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include "patt_rec.h"
#include "image2d.h"
#include "pnmio.h"
#include "nrutil.h"
#define x(i) vect_training(train, (i))
#define y(i) class_training(train, (i))
#define x_in(i) vect_training(train, index_in[(i)])
#define y_in(i) class_training(train, index_in[(i)])
#define x_out(i) vect_training(train, index_out[(i)])
#define y_out(i) class_training(train, index_out[(i)])
#define alpha_in(i) alpha[index_in[(i)]]
#define alpha_out(i) alpha[index_out[(i)]]
#define svc_in(i) svc[index_in[(i)]]
#define svc_out(i) svc[index_out[(i)]]
#define EPS 10e-6
static int *svc; /* 0=non sv ; 1=margine ; 2=outlier */
static int *index_in; /* Array degli indici dei vett. usati */
static int *index_out; /* Array degli indici dei vett. out */
static double *alpha; /* Array degli alpha */
static training *train; /* Vettori di input usati da solve */
extern int knl;
extern int chunk_size;
extern int ell;
extern int dim;
extern double c_const;
extern double bee;
extern int degree;
extern double sigma, normalization;
extern char *image_ker;
extern int dim_r, dim_c;
double *x0;
double Radius;
double **mat_kernel; /* MATRICE KERNEL PRECALCOLATO */
char **mat2, **mat3;
Image2D *mat_image;
int maximum=-1, minimum=10;
int **mat;
int giro;
FILE *fp, *f_ker;
/* Se la soluzione e` ottimale ritorna 1, altrimenti ritorna 0. Per la verifica
controlla (l - chunk_size) elementi del training set; se qualche
punto viola le condizioni di ottimalita` (Khun-Tucker) aggiorna di
conseguenza index_in ed index_out */
int optimal()
{
register i, j, margin_sv_number, error_sv_number, z, k, s;
int nb = ell - chunk_size, /* nb e` il numero di punti fuori base */
nb_choose; /* n.ro max. di p.ti out da testare */
double gx_i, /* parametro delle equazioni di KT */
k_i, /* altro parametro */
aux, aux2, aux3, max, min;
double *point;
nb_choose = ell - chunk_size;
// fprintf(stderr,"dentro optimal\n");
/* Computing Radius */
aux = 0.;
margin_sv_number = 0;
// calcolo il centro
/* for (i=0; i<dim; i++)
x0[i] = 0.;
for (i = 0; i < ell; i++)
//if (svc_in(i) != 0) //if (alpha[i] > DELTA)
{
point = x(i);
for (j = 0; j < dim; j++){
x0[j]+=alpha[i]*point[j];
}
}
ker_c = kernel(knl,x0,x0);
*/
for (i = chunk_size - 1; i >= 0; i--)
if (svc_in(i) == 1)
{
margin_sv_number++;
aux += mat_kernel[index_in[i]][index_in[i]];
for (j=ell-1;j>=0;j--) {
aux += -2.*alpha[j]*mat_kernel[index_in[i]][j];
for (k=ell-1;k>=0;k--)
aux += alpha[j]*alpha[k]*mat_kernel[j][k];
}
}
//fprintf(stderr,"aux2 %lf\n",aux2);
if (margin_sv_number == 0)
{
error_sv_number = 0;
min = 2000000000.;
for (i = chunk_size - 1; i >= 0; i--)
if (svc_in(i) == 2)
{
aux= mat_kernel[index_in[i]][index_in[i]];
error_sv_number++;
for (j=ell-1;j>=0;j--) {
aux += -2.*alpha[j]*mat_kernel[index_in[i]][j];
for (k=ell-1;k>=0;k--)
aux += alpha[j]*alpha[k]*mat_kernel[j][k];
}
if (aux < min)
min = aux;
}
if (error_sv_number == 0)
{
fprintf(stderr,"Strange: no support vector found!\n");
exit(1);
}
aux=min;
Radius = sqrt(min);
}
else {
// fprintf(stderr,"aux %lf\n",aux);
aux /= margin_sv_number;
Radius = sqrt(aux);
}
// fprintf(stderr,"dentro optimal...radius %lf\n",Radius);
/* inserisco in base i punti che violano le condizioni di Kuhn-Tucker
scegliendo tra nb_choose non utilizzati (ne inserisco al massimo
chunk_size-2) */
srandom((unsigned) time(NULL));
for (z = nb_choose, s = chunk_size-2; z > 0 && s > 0; z--, nb--)
{
/* pesco con probabilita` uniforme i punti fuori base */
i = random() % nb;
gx_i = aux - mat_kernel[index_out[i]][index_out[i]]; //aux raggio al quadrato
for (j=ell-1;j>=0;j--) {
gx_i += 2.*alpha[j]*mat_kernel[index_out[i]][j];
for (k=ell-1;k>=0;k--)
gx_i -= alpha[j]*alpha[k]*mat_kernel[j][k];
}
if (((alpha_out(i) < DELTA) && (gx_i < (-DELTA))) ||
((alpha_out(i) > (c_const-DELTA)) && (gx_i > (+DELTA))) ||
((alpha_out(i) > DELTA) && (alpha_out(i) < c_const-DELTA) &&
((gx_i < -DELTA) || (gx_i > +DELTA))))
{
k = random() % s + 1;
j = index_in[k];
memmove(index_in+k, index_in+k+1, (s-k)*sizeof(int));
index_in[s--] = index_out[i];
}
else
j = index_out[i];
memmove(index_out+i, index_out+i+1, (nb-i-1)*sizeof(int));
index_out[nb-1] = j;
}
//fprintf(stderr, "%d\n", chunk_size-s-2);
if (s == chunk_size-2)
return 1;
else
return 0;
}
void pre_compute(training *tr,int knl,double **mat_kernel)
{
int i,j;
train = tr;
ell = length_training(train);
for(i=0;i<ell;i++){
for(j=i;j<ell;j++){
//printf("%d %d\n",i,j);
mat_kernel[i][j] = kernel(knl, x(i), x(j));
fprintf(stderr,"%lf ",mat_kernel[i][j]);
}
printf("\n");
}
for(i=0;i<ell;i++)
for(j=0;j<i;j++){
mat_kernel[i][j] = mat_kernel[j][i];
}
}
double *solve(training *tr, int knl, double c_const, int sp_dim, char *image_ker, char *f_kernel)
{
register i, j;
int *sp_y, /* Vettore delle classi */
*sp_svc; /* Classificazione dei vettori */
double **sp_D, /* Componenti quadratiche del funz. */
*sp_h, /* Componenti lineari del funz. */
*sp_alpha;
double sp_e, aux, inc, min, max;
double *solution;
train = tr;
// sp_dim *= 2;
ell = length_training(train);
dim = dim_training(train);
// chunk_size = (sp_dim+2 < ell) ? sp_dim+2 : ell;
chunk_size = (sp_dim+1 < ell) ? sp_dim+1 : ell;
fprintf(stderr,"chunksize %d ell %d\n",chunk_size,ell);
/* Allocazione memoria necessaria ai dati */
index_in = (int *)myalloc(NULL, chunk_size*sizeof(int), "solve: index_in\n");
if (ell > chunk_size)
index_out = (int *)myalloc(NULL, (ell-chunk_size)*sizeof(int), "solve: index_out\n");
else
index_out = NULL;
alpha = (double *)myalloc(NULL, ell*sizeof(double), "solve: alpha\n");
//XX x0 (dim)
x0 = (double *)malloc(sizeof(double)*dim);
svc = (int*)myalloc(NULL, ell*sizeof(int), "solve: svc\n");
for (i = ell-1; i >= 0; i--)
alpha[i] = 0.;
sp_alpha = (double *)myalloc(NULL, chunk_size*sizeof(double), "solve: sp_alpha\n");
sp_svc= (int *)myalloc(NULL, chunk_size*sizeof(int), "solve: sp_svc\n");
sp_D = (double **)myalloc(NULL, chunk_size*sizeof(double *), "solve: sp_D\n");
for (i = chunk_size - 1; i >= 0; i--)
sp_D[i] = (double *)myalloc(NULL, chunk_size*sizeof(double), "solve: sp_D[i]\n");
sp_h = (double *)myalloc(NULL, chunk_size*sizeof(double), "solve: sp_h\n");
sp_y = (int *) myalloc(NULL, chunk_size*sizeof(int), "solve: sp_cl\n");
mat_kernel = dmatrix(0,ell-1,0,ell-1);
// calcolo immagine solo se non faccio chunking
/*
if (chunk_size==ell) {
mat = imatrix(0,ell-1,0,ell-1);
mat2 = cmatrix(0,ell-1,0,ell-1);
mat3 = cmatrix(0,ell-1,0,ell-1);
}
*/
pre_compute(tr,knl,mat_kernel);
f_ker = fopen(f_kernel,"w");
fprintf(f_ker,"%d \n",ell);
/*if (knl == NEGATIVE_KERNEL){
for(i=0;i<ell;i++) {
for(j=0;j<ell;j++)
fprintf(f_ker,"%lf ",-mat_kernel[i][j]);
fprintf(f_ker,"\n");
}
}
else{*/
for(i=0;i<ell;i++) {
for(j=0;j<ell;j++)
fprintf(f_ker,"%lf ",mat_kernel[i][j]);
fprintf(f_ker,"\n");
}
// }
fclose(f_ker);
/* Creazione del sottoproblema:
scelta dei primi indici da utilizzare e da non utilizzare */
// modifica: noi abbiamo solo una classe....
for (i = 0, j = 0; i < chunk_size; i++, j++)
index_in[j] = i; /* I primi chunk_size di classe 1 */
for (i = chunk_size, j = 0; i < ell; i++, j++)
index_out[j] = i;
/* Inizio del ciclo di risoluzione del problema */
fprintf(stderr,"prima del do\n");
giro=0;
do
{
giro++;
fprintf(stderr,"giro %d\n",giro);
// debug
// fprintf(stderr,"index_in\n");
// for (i=0;i<chunk_size;i++)
// fprintf(stderr,"%d ",index_in[i]);
//fprintf(stderr,"\n");
//fprintf(stderr,"index_out\n");
//for (i=0;i<ell-chunk_size;i++)
//fprintf(stderr,"%d ",index_out[i]);
//fprintf(stderr,"\n");
/* Preparazione delle variabili da passare al solver */
/* Matrice della parte quadratica della funzione obbiettivo */
for (i = chunk_size-1; i >= 0; i--){
// fprintf(stderr,"%d\n",i);
for (j = chunk_size-1; j >= 0; j--) {
sp_D[i][j] = y_in(i)*y_in(j)*mat_kernel[index_in[i]][index_in[j]];
}
}
/* if (chunk_size == ell) {
minimum = -maximum;
mat_image = ImageAlloc(ell,ell);
for (i = chunk_size-1; i >= 0; i--)
for (j = chunk_size-1; j >= 0; j--) {
mat2[i][j] = ( mat[i][j] - minimum )*255/(maximum - minimum);
mat_image->data[i][j]=mat2[i][j];
}
write_file_pnm(image_ker, mat_image );
}*/
//fprintf(stderr,"prima del calcolo lineare\n");
/* Vettore della parte lineare della funzione obbiettivo */
for (i = chunk_size-1; i >= 0; i--)
{
aux = 0.;
for (j = ell-chunk_size-1; j >= 0; j--)
aux += 2*y_out(j)*alpha_out(j)*mat_kernel[index_in[i]][index_out[j]]; //attenti al 2!
//sp_h[i] = y_in(i) * aux - 1.;
sp_h[i] = y_in(i) * aux - mat_kernel[index_in[i]][index_in[i]];
}
//fprintf(stderr,"prima dei vincoli\n");
/* Costante del primo gruppo di vincoli */
//sp_e = 0.;
sp_e = -1.;
//fprintf(stderr,"alpha fuori\n");
for (i = ell-chunk_size-1; i >= 0; i--) {
sp_e += y_out(i) * alpha_out(i); //mat_kernel[index_out[i]][index_out[i]] * alpha_out(i);
//fprintf(stderr,"%lf ",alpha_out(i));
}
// fprintf(stderr,"\n funzionavano meglio le parolacce. sp_e %lf\n",sp_e);
/* Vettore delle classi dei punti in base */
for (i = chunk_size-1; i >= 0; i--)
//sp_y[i] = mat_kernel[index_in[i]][index_in[i]];
sp_y[i] = y_in(i);
/* Chiamate al solver */
fprintf(stderr,"prima del solver\n");
solver(chunk_size, sp_D, sp_h, c_const, sp_e, sp_y, sp_alpha, sp_svc);
fprintf(stderr,"dopo il solver\n");
/* Aggiornamento del vettore globale delle soluzioni */
// fprintf(stderr,"alpha in\n");
for (i = chunk_size-1; i >= 0; i--)
{
alpha_in(i) = sp_alpha[i];
// fprintf(stderr,"%lf ",alpha_in(i));
svc_in(i) = sp_svc[i];
}
fprintf(stderr,"\n");
} while (!optimal());
solution = alpha;
free(index_in);
free(index_out);
for (i = chunk_size - 1; i >= 0; i--)
free(sp_D[i]);
free(sp_D);
free(sp_alpha);
free(sp_svc);
return solution;
}
void write_solution(FILE *fp, double *sol, int knl, double bee, double c_const)
{
register i, j;
int n,m,temp,sv_number = 0;
double alpha_sum, *point;
double *R,*quad,R_alpha,R_alpha2,R_sum;
alpha_sum=0.;
for (i = 0; i < ell; i++){
if (alpha[i] > DELTA) sv_number++;
alpha_sum+=alpha[i];
}
fprintf(stderr, "sv_number: %d\n", sv_number);
fprintf(fp, "%d ", sv_number);
fprintf(stderr,"dimensione punti: %d\n", dim);
fprintf(fp, "%d ", dim);
fprintf(fp, "%d %d\n",dim_r,dim_c);
//Scrivo gli sv, le labels e gli alpha e x0
for (i = 0; i < ell; i++)
// fprintf(stderr,"i: %d alpha: %lf\n",i,alpha[i]);
if (svc[i]!=0)
{
point = x(i);
//modifica al file dei sv: aggiungiamo gli indici
fprintf(fp,"%d ",i);
for (j = 0; j < dim; j++){
fprintf(fp, "%lf ", point[j]);
}
fprintf(fp, "%d ", y(i));
fprintf(fp, "%lf\n", alpha[i]);
printf("i: %d alpha: %lf\n",i,alpha[i]);
}
fprintf(fp, "%lf\n",Radius);
//Ora la costante C, il tipo di kernel e la normalizzazione
fprintf(fp, "%lf\n", c_const);
fprintf(fp, "%d\n", knl);
if (knl == RBF_KERNEL)
fprintf(fp, "%lf\n", sigma);
else if (knl == POLY_KERNEL)
fprintf(fp, "%lf %d\n", normalization, degree);
else if (knl == HAUS_KERNEL)
fprintf(fp, "%lf\n", normalization);
else
fprintf(fp, "%lf\n", normalization);
}