3 Hydrological Modeling of Forested Catchments
3.3 Parameter estimation for hydrological models
/*Este evalua_prob se va a diferenciar del evalua en que aquí, si me encuentro con un caso en el que la distancia mínima del ejemplo en estudio a uno de la BD con la que ha entrenado no es cero (es decir, no se encuentra ese ejemplo en la BD), se dará como solución la más probable*/
#include <assert.h> #include "silabica.h" #include <string.h> #include <stdio.h> #include <values.h> #include <math.h> #include <mem.h> #include "portable.h" #include "portimpr.h" #include "flh.h" #include "tildes.h" TEjemplo *ejemplos;
TIndiceEj NumEjemplos; //Nº de ejemplos de la BD de entrenamiento TDistancia *pesos;
TIndiceRasgos NumRasgos = 0; //Variable con el n'umero de rasgos que lee desde el fichero BD de ejemplos
TValorSolucion SolucionEvaluada;
TValorSolucion SolucionMasProbable; //Sol. más probable en el fich. de entren. (para la pal. en estudio)
TFrecuencia frecSolucMasProbable=0; //Guarda la frec. de la soluc + probable para cada vantana evaluada
TDistancia distMin=0; //Guarda la dist. min. de cada ventana de rasgos a los ej de dist mínima char FicheroPruebas[MAXPATH]="fich_ej_prue.dic"; //Fichero con todos las palabras para evaluar (pasado por el traductor)
char FicheroBDEjemplos[MAXPATH]="bd_ej.dic";//Fichero con ejemplos y soluciones char FicheroPesos[MAXPATH]="pesos.dic"; //Fichero con los pesos
char FicheroEvaluacion[MAXPATH]="evaluacion_prob.est"; //Fichero con todas las ventanas evaluadas. /*El formato de evaluacion.est es: nºrasgos, 1er rasgo,...,último rasgo, solución según se
ha leído del texto de pruebas, solucion estimada por el evaluador, frecuencia acumulada de lo/s ejemplo/s de dist. mínima cuya solución se ha tomado como la más probable, distancia mínima a lo/s ejemplo/s de dist. mínima y comentario (palabra leída del texto de pruebas, de la que se ha obtenido la ventana en estudio*/
char FicheroEstadisticasEvaluacion[MAXPATH]="estadis_prob.est"; // Fichero con las estad'isticas char FicheroProbEntren[MAXPATH]="prob_entren.dic"; // Fichero con las prob. de cada solución TDistancia DistanciaRasgos(TValorRasgo a, TValorRasgo b)
{ if (a==b) return 0; else return 1; }
TDistancia distancia(TValorRasgo *ejemp1, TValorRasgo *ejemp2) {
TIndiceRasgos i; TDistancia Distancia;
for (i=0,Distancia=0; i<NumRasgos; i++) {
Distancia+=pesos[i]*DistanciaRasgos(ejemp1[i],ejemp2[i]); }
return Distancia; }
/*Esta funcion busca el primer ejemplo de distancia minima*/ TIndiceEj BuscaMinimo(TValorRasgo *rasgos)
{
TDistancia distMin=MAXFLOAT; TIndiceEj indMin=-MAXLONG; TIndiceEj i;
for (i=0; i<NumEjemplos; i++) { if (distancia(ejemplos[i].rasgos,rasgos)<distMin) { distMin=distancia(ejemplos[i].rasgos,rasgos); indMin=i; } } assert(indMin>=0); return indMin; }
int comparaEjemplos(const void *x, const void *y) {
TEjemplo *ej=(TEjemplo *)y; for (int i=0; i<NumRasgos; i++)
{ if (vent[i]>ej->rasgos[i]) return 1; else if (vent[i]<ej->rasgos[i]) return -1; } return 0; }
/*Esta funcion da los indices de los ejemplos que han dado distancia minima. ConjuntoMinimo contiene los indices de los ejemplos de distancia minima, hasta que haya un -1 (ahi acaba la lista de ejemplos)*/
TIndiceEj *BuscaKMinimos(TValorRasgo *rasgos) {
TEjemplo EjAuxiliar; TIndiceEj PrimerIndMin;
for (TIndiceEj i=0; i<NumRasgos && rasgos[i]!=FINALIZADOR; i++) {
EjAuxiliar.rasgos[i]=rasgos[i]; if (i<NumRasgos-1)
EjAuxiliar.rasgos[i+1]=FINALIZADOR; }
TEjemplo * ej=(TEjemplo * )bsearch((const void*)&EjAuxiliar,(const void*)ejemplos,NumEjemplos,sizeof(ejemplos[0]),comparaEjemplos);
/* TEjemplo * ej=(TEjemplo * )lfind((const void*)&EjAuxiliar,(const void*)ejemplos,(unsigned int*)&NumEjemplos,sizeof(ejemplos[0]),comparaEjemplos);*/ if (ej!=NULL) { PrimerIndMin=((int32)ej-(int32)ejemplos)/(int32)(sizeof(ejemplos[0])); } else { PrimerIndMin=BuscaMinimo(rasgos); } distMin=distancia(ejemplos[PrimerIndMin].rasgos,rasgos); #if defined(__WIN32__)
TIndiceEj *ConjuntoMinimo=new TIndiceEj [NumEjemplos+1]; #else
TIndiceEj *ConjuntoMinimo=(TIndiceEj *)farmalloc (sizeof(TIndiceEj)*(NumEjemplos+1)); #endif
TIndiceEj i;
TIndiceEj j; /* falta k-NN */
for (i=PrimerIndMin, j=0; i<NumEjemplos; i++) { if (distancia(ejemplos[i].rasgos,rasgos)==distMin) { ConjuntoMinimo[j++]=i; } else if (ej!=NULL) break; } if (ej!=NULL) {
for (i=PrimerIndMin-1; i>=0; i--) { if (distancia(ejemplos[i].rasgos,rasgos)==distMin) { ConjuntoMinimo[j++]=i; } else if (ej!=NULL) break; } } if (j<=0) assert(0); else ConjuntoMinimo[j]=FINALIZADOR; return ConjuntoMinimo; }
/*Esta función devuelve los ejemplos que han dado distancia mínima.
Soluciones: lista de ejemplos hasta que haya un finalizador en la solución del último ejemplo*/
TEjemplo *BuscaSoluciones(TValorRasgo *rasgos) {
TEjemplo *soluciones=new TEjemplo[NumEjemplos+1]; TIndiceEj *ConjuntoMinimo=BuscaKMinimos(rasgos); TIndiceEj i;
for (i=0; ConjuntoMinimo[i] != FINALIZADOR; i++) { soluciones[i].solucion=ejemplos[ConjuntoMinimo[i]].solucion; soluciones[i].frecuencia=ejemplos[ConjuntoMinimo[i]].frecuencia; memcpy(soluciones[i].rasgos,ejemplos[ConjuntoMinimo[i]].rasgos, sizeof(soluciones[i].rasgos)); } if (i<=0) assert(0);
else
soluciones[i].solucion=FINALIZADOR; delete []ConjuntoMinimo;
return soluciones; }
/*Estas funciones recorren la variable ejemplos, para dar las soluc. max y min*/ TValorSolucion CalculaMinSoluc()
{
TValorSolucion MinSoluc = ejemplos[0].solucion; TIndiceEj i;
for (i=0; i<NumEjemplos; i++) {
if (ejemplos[i].solucion < MinSoluc) MinSoluc = ejemplos[i].solucion; }
return MinSoluc; }
TValorSolucion CalculaMaxSoluc() {
TValorSolucion MaxSoluc = ejemplos[0].solucion; TIndiceEj i;
for (i=0; i<NumEjemplos; i++) {
if (ejemplos[i].solucion > MaxSoluc) MaxSoluc = ejemplos[i].solucion; }
return MaxSoluc; }
/*A esta funci'on se le pasa un array de contadores, y devuelve el indice del contador m'as alto*/
TValorSolucion BuscaSolMasProbable(TFrecuencia *contador,TIndiceEj rangoSoluc,TIndiceEj minSoluc) {
TIndiceEj i; TIndiceEj indice=0; TIndiceEj maximo=0;
for (i=0; i<rangoSoluc; i++) { if (contador[i] > maximo) { indice = i+minSoluc; maximo=contador[i]; } } return indice; }
/*A esta función se le pasa una ventana de rasgos y devuelve la solución
estimada para el rasgo (letra) central. Utiliza el array de frecuencias Contador: cada posición se corresponde con una solución (de la mín a la máx), y contiene la frecuencia acumulada con que se da esa solución dentro del conjunto de ejemplos que han dado distancia mínima a la ventana en estudio*/
TValorSolucion DecisionSolucion(TValorRasgo *rasgos) { TEjemplo *soluciones=BuscaSoluciones(rasgos); TIndiceEj maxSoluc=CalculaMaxSoluc(); TIndiceEj minSoluc=CalculaMinSoluc(); TIndiceEj rangoSoluc=maxSoluc-minSoluc+1; TValorSolucion resultado;
TFrecuencia *Contador=new TFrecuencia[rangoSoluc];
memset(Contador,0,rangoSoluc*sizeof(TFrecuencia)); //Inicializo el arrray Contador TIndiceEj i;
for (i=0; soluciones[i].solucion!=FINALIZADOR; i++) { Contador[soluciones[i].solucion-minSoluc]+=soluciones[i].frecuencia; } resultado = BuscaSolMasProbable(Contador,rangoSoluc,minSoluc); frecSolucMasProbable=Contador[resultado]; delete [] soluciones; delete [] Contador; return resultado; }
/*Funcion que calcula el número de ejemplos (es decir, el número de líneas del fichero de la base de datos de ejemplos*/
TIndiceEj CalculaNumEjemplos(char *directorio, char *NomFichero) {
TIndiceEj i;
TIndiceEj contador=0; char *linea=new char [1000];
FILE *fichero=flhOpen(directorio,NomFichero,"rt"); if (fichero==NULL)
{
errorPrintf("falta el fichero %s",NomFichero); }
for (i=0; feof(fichero)==0; i++) {
if (fgets(linea,1000,fichero)!=NULL) contador++; else break; } flhClose(fichero); delete [] linea; return contador; }
float LeeFlotante(char *token, int i) {
float float_aux;
if(sscanf(token,"%f",(float*)&float_aux)!=1) {
errorPrintf("error de formato en l'inea %d",(long)i); }
return float_aux; }
int LeeSolucion(char *token, int i) {
int int_aux;
if(sscanf(token,"%d",(int*)&int_aux)!=1) {
errorPrintf("error de formato en l'inea %d",(long)i); }
return int_aux; }
/*Esta funcion carga en la variable ejemplos los datos del fichero diccionario de ejemplos (que contiene en cada linea un ejemplo (una ventana de rasgos), una solucion y la frecuencia de ese ejemplo). Cada linea del fichero de entrada es como sigue: nº de rasgos por ejemplo, blanco, nº de 1er rasgo, blanco,..., solucion, blanco, frecuencia, blanco, comentario*/
TEjemplo* CargaEjemplos(char *directorio, char *NomFichero) {
TIndiceEj i;
char *linea=new char [1000];
NumEjemplos=CalculaNumEjemplos(directorio, NomFichero); if (NumEjemplos<=0)
{
errorPrintf("fichero vac'io: %s",NomFichero); return NULL;
}
ejemplos=new TEjemplo[NumEjemplos];
FILE *fichero=flhOpen(directorio, NomFichero, "rt"); if (fichero==NULL)
{
errorPrintf("falta el fichero %s",NomFichero); }
for (i=0; feof(fichero)==0 && i<NumEjemplos; i++) {
if (i%100==0)
printf("Llevo cargados %ld ejemplos\n",(long)i); if (fgets(linea,1000,fichero)!=NULL)
{
TIndiceRasgos j; char *token=linea; token=strtok(token," ");
NumRasgos = atoi(token); //Aqui queda ya cargada la var. global NumRasgos token = NULL; for (j=0; j<NumRasgos; j++) { token=strtok(token," "); if (token==NULL) {
errorPrintf("error de formato en l'inea %d",(long)i); } float aux=LeeFlotante(token,i); ejemplos[i].rasgos[j] = aux; token=NULL; } token=strtok(NULL," "); if (token==NULL) {
errorPrintf("error de formato en l'inea %d",(long)i); }
ejemplos[i].solucion = LeeSolucion(token,i); token=strtok(NULL," ");
if (token==NULL) {
errorPrintf("error de formato en l'inea %d",(long)i); }
ejemplos[i].frecuencia = LeeFlotante(token,i); if (ejemplos[i].frecuencia<=0)
{
errorPrintf("error de formato en l'inea %ld",(long)i); }
token=strtok(NULL,"\n"); if (token==NULL)
errorPrintf("error de formato en l'inea %d",(long)i); } strcpy(ejemplos[i].comentario,token); } else { break; } } flhClose(fichero); delete [] linea;
qsort(ejemplos, NumEjemplos, sizeof(ejemplos[0]),comparaEjemplos); return ejemplos;
}
/*Esta funci'on devuelve para que se cargue en la variable global pesos los pesos de cada rasgo desde el fichero de pesos generado anterioemente a partir de la BD, para su posterior utilizaci'on en el c'alculo de la distancia entre ventanas de rasgos*/ TDistancia *InicializaPesos(char *directorio, char *NomFichero)
{
TDistancia *pesos=new TDistancia[NumRasgos]; TIndiceRasgos i;
TIndiceRasgos NumRasgosFichPesos; char *linea=new char [1000];
FILE *fichero=flhOpen(directorio, NomFichero, "rt"); if (fichero==NULL)
{
errorPrintf("falta el fichero %s",NomFichero); } if (fgets(linea,1000,fichero)!=NULL) { char *token=linea; token=strtok(token," "); if (token==NULL) {
errorPrintf("error de formato en el fichero de pesos"); }
NumRasgosFichPesos = LeeFlotante(token,1); if (NumRasgos != NumRasgosFichPesos)
{
errorPrintf("error de formato en el fichero de pesos"); }
token = NULL;
for (i=0; i<NumRasgos; i++) {
token=strtok(token," "); if (token==NULL)
{
errorPrintf("error de formato en el fichero de pesos"); } pesos[i] = LeeFlotante(token,i); token=NULL; } } flhClose(fichero); delete [] linea; return pesos; }
/*Esta función calcula cuál de las 2 soluciones (acentuada o no acentuada) es la más probable para la palabra ambigua que se está evaluando, a partir del fichero de probabilidades prob_entren.dic*/
TValorSolucion CalculaSolMasProbEntren(char *directorio, char *NomFichero) {
TValorSolucion solucion; TIndiceEj ContAcen=0; TIndiceEj ContDesacen=0;
char *linea=new char [1000]; char *token;
FILE *fichero=flhOpen(directorio, NomFichero, "rt"); if (fichero==NULL)
{
errorPrintf("falta el fichero %s",NomFichero); } if (fgets(linea,1000,fichero)!=NULL) { token=linea; token=strtok(token," "); if (token==NULL) {
errorPrintf("Error de formato en el fichero de probabilidades"); }
ContAcen = LeeFlotante(token,1); if (ContAcen < 0)
{
errorPrintf("error de formato en el fichero de probabilidades"); }
token = NULL; }
if (fgets(linea,1000,fichero)!=NULL) {
token=linea;
token=strtok(token," "); if (token==NULL)
{
errorPrintf("Error de formato en el fichero de probabilidades"); }
ContDesacen = LeeFlotante(token,1); if (ContDesacen < 0)
{
errorPrintf("error de formato en el fichero de probabilidades"); } } if (ContAcen>ContDesacen) solucion = ES_INTERROG; else if (ContAcen<ContDesacen) solucion = NO_ES_INTERROG; else solucion = INDEFINIDO; flhClose(fichero); delete [] linea; return solucion; }
void main(int argc,char *argv[]) { if (argc==1) { } else if (argc==6) { strcpy(FicheroPruebas,argv[1]); strcpy(FicheroBDEjemplos,argv[2]); strcpy(FicheroPesos,argv[3]); strcpy(FicheroEvaluacion,argv[4]); strcpy(FicheroEstadisticasEvaluacion,argv[5]); } ejemplos=CargaEjemplos(DIRECTORIO, FicheroBDEjemplos); if (ejemplos!=NULL) {
TEjemplo EjemploPrueba; //Contiene el ejemplo que se va leyendo del fichero de pruebas
TIndiceRasgos NumRasgosFichPruebas; //Nº de rasgos que lee del fichero de pruebas char *linea=new char [1000];
TIndiceEj contOK=0; TIndiceEj i; int k;
pesos = InicializaPesos(DIRECTORIO,FicheroPesos);
SolucionMasProbable = CalculaSolMasProbEntren(DIRECTORIO, FicheroProbEntren); FILE *fichero1=flhOpen(DIRECTORIO, FicheroEvaluacion, "wt"); if (fichero1==NULL)
{
errorPrintf("falta el fichero %s",FicheroEvaluacion); }
k=fprintf(fichero1,"%s\n\n","Num_Rasgos Rasgo1 ... RasgoN Soluc_Leida Soluc_Estimada Frec_SolMasProb Dist_Min Pal_leida");
if (k==EOF)
errorPrintf("error en la escritura del fichero %s",FicheroEvaluacion); FILE *fichero2=flhOpen(DIRECTORIO, FicheroPruebas, "rt");
if (fichero2==NULL) {
errorPrintf("falta el fichero %s",FicheroPruebas); }
FILE *fichero3=flhOpen(DIRECTORIO, FicheroEstadisticasEvaluacion, "wt"); if (fichero1==NULL)
{
errorPrintf("falta el fichero %s",FicheroEstadisticasEvaluacion); }
for (i=0; feof(fichero2)==0; i++) {
if (i%100==0)
printf("Llevo evaluados %ld ejemplos\n",(long)i); if (fgets(linea,1000,fichero2)!=NULL) { TIndiceRasgos j; char *token=linea; token=strtok(token," "); NumRasgosFichPruebas = atoi(token); if (NumRasgos != NumRasgosFichPruebas) {
errorPrintf("error de formato en el fichero de pruebas");
} token = NULL; for (j=0; j<NumRasgos; j++) { token=strtok(token," "); if (token==NULL) {
errorPrintf("error de formato en l'inea %d",(long)i);
}
float aux=LeeFlotante(token,i); EjemploPrueba.rasgos[j] = aux;
token=NULL; }
token=strtok(NULL," "); if (token==NULL)
{
errorPrintf("error de formato en l'inea %d",(long)i); }
EjemploPrueba.solucion = LeeSolucion(token,i); token=strtok(NULL," ");
if (token==NULL)
errorPrintf("error de formato en l'inea %d",(long)i); EjemploPrueba.frecuencia = LeeFlotante(token,i);
token=strtok(NULL,"\n"); if (token==NULL)
{
errorPrintf("error de formato en l'inea %d",(long)i); } strcpy(EjemploPrueba.comentario,token); } else { break; } SolucionEvaluada = DecisionSolucion(EjemploPrueba.rasgos); if (distMin>0 && SolucionMasProbable!=INDEFINIDO)
{
SolucionEvaluada = SolucionMasProbable; }
k=fprintf(fichero1,"%d ", (int)NumRasgos); if (k==EOF)
errorPrintf("error en la escritura del fichero %s",FicheroEvaluacion);
for (TIndiceRasgos j=0; j<NumRasgos; j++) {
k=fprintf(fichero1,"%.0f ", (float)EjemploPrueba.rasgos[j]); if (k==EOF)
errorPrintf("error en la escritura del fichero %s",FicheroEvaluacion); } if (SolucionEvaluada == EjemploPrueba.solucion) { contOK++; k=fprintf(fichero1,"%.0f _%.0f %.0f %f %s\n", (float)EjemploPrueba.solucion, (float)SolucionEvaluada, (float)frecSolucMasProbable, (float)distMin, EjemploPrueba.comentario); if (k==EOF)
errorPrintf("error en la escritura del fichero %s",FicheroEvaluacion); } else { k=fprintf(fichero1,"%.0f _%.0f %.0f %f %s_ERROR\n", (float)EjemploPrueba.solucion, (float)SolucionEvaluada, (float)frecSolucMasProbable, (float)distMin, EjemploPrueba.comentario); if (k==EOF)
errorPrintf("error en la escritura del fichero %s",FicheroEvaluacion);
}
}
k=fprintf(fichero3,"%s\n", "Estad'sticas de la evaluaci'on:"); if (k==EOF)
errorPrintf("error en la escritura del fichero %s",FicheroEstadisticasEvaluacion);
k=fprintf(fichero3," Tasa de aciertos (en%%): %f (%ld de %ld)\n",(contOK/(float)i)*100,contOK,(long)i);
if (k==EOF)
errorPrintf("error en la escritura del fichero %s",FicheroEstadisticasEvaluacion); flhClose(fichero1); flhClose(fichero2); flhClose(fichero3); delete [] linea; delete [] pesos; } delete [] ejemplos; }