📄 matlvq.cpp
字号:
/*********************************************************************************************
* MatLvq makes the convertion between the matrix paradigm which is employed in the PCA dll,
* and the LVQ paradigm.
*
* Written by Sami Romdhani Jully 1996
*********************************************************************************************/
#include "header.h"
#include "lvq.h"
#include "matlvq.h"
#include "tools.h"
#include "clabel.h"
#include "lvq_pak.h"
#include "lvq_rout.h"
#include <stdlib.h>
#include <malloc.h>
CLabel *plabel = NULL; /*points to the beginning of the label's list*/
/*********************************************************************************************
* MattoEntries copy the values the elements of the CMatrix pmat to the entries pentries
*********************************************************************************************/
int MattoEntries(struct entries **pentries, CMatrix *pmat)
{
long l, max, l2, max2;
struct data_entry *current, *prev;
char str[MAX_NAME];
*pentries = alloc_entries();
if (*pentries == NULL)
return -1;
(*pentries)->dimension = pmat->GetLi();
(*pentries)->num_loaded = pmat->GetCol();
(*pentries)->num_entries = pmat->GetCol();
max = (*pentries)->num_entries;
max2 = (*pentries)->dimension;
pmat->Lock();
for (l = 0; l < max; l++)
{
current = (struct data_entry *)malloc(sizeof(struct data_entry));
if (current == NULL)
{
Msg(0, "not enough memory");
pmat->Unlock();
return -1;
}
if (l > 0)
prev->next = current;
current->next = NULL;
current->fixed = NULL;
current->mask = NULL;
current->lab.label_array = NULL;
current->lab.label = LABEL_EMPTY;
current->num_labs = 0;
current->points = (float*)calloc((*pentries)->dimension, sizeof(float));
if (current->points == NULL)
{
free(current);
Msg(0, "not enough memory");
pmat->Unlock();
return -1;
}
for (l2 = 0; l2 < max2; l2++)
current->points[l2] = pmat->GetAt(l2+1, l+1);
pmat->GetColName(l+1, str, sizeof(str));
plabel->SetLabel(current, str);
current->weight = 0;
if (l == 0)
(*pentries)->entry = current;
prev = current;
}
pmat->Unlock();
(*pentries)->current = (*pentries)->entry;
return 0;
}
/*********************************************************************************************
* EntriestpMat copy the values the elements of the entries pentries to the CMatrix pmat
*********************************************************************************************/
int EntriestoMat(CMatrix **pmat, struct entries *pentries)
{
long row, col, max_row, max_col;
struct data_entry *current;
if (*pmat == NULL)
{
*pmat = new CMatrix(pentries->dimension, pentries->num_entries);
if (*pmat == NULL)
return -1;
}
max_row = (*pmat)->GetLi();
max_col = (*pmat)->GetCol();
if (max_row != pentries->dimension || max_col != pentries->num_entries)
{
Msg(0, "EntriestoMat : not the same dim");
return -1;
}
(*pmat)->Lock();
current = pentries->entry;
for (col = 0; col < max_col; col++)
{
if (current == NULL)
break;
for (row = 0; row < max_row; row++)
{
(*pmat)->SetAt(row+1, col+1, current->points[row]);
}
(*pmat)->SetColName(col+1, plabel->GetLabel(current));
current = current->next;
}
(*pmat)->Unlock();
if (col != max_col)
return -1;
return 0;
}
/*********************************************************************************************
* LVQInit performs the initialization of some varibles needed for the processing of LVQ.
* It Must be called before the processing.
*********************************************************************************************/
int LVQInit(PLVQPARAMS params)
{
plabel = new CLabel();
params->sammon = NULL;
/*Set the initial values*/
params->noc = -1;
params->knn = -1;
params->xdim = -1;
params->ydim = -1;
params->neigh = NEIGH_UNKNOWN;
params->topol = TOPOL_UNKNOWN;
params->alpha_type = ALPHA_UNKNOWN;
params->radius = -1;
params->alpha = -1;
params->length = -1;
params->winlen = -1;
params->epsilon = -1;
return 0;
}
/*********************************************************************************************
* LVQEnd frees the memory allocated in the function LVQInit.
* It must be called at the end of the processing of LVQ.
*********************************************************************************************/
int LVQEnd(PLVQPARAMS params)
{
if (plabel != NULL)
delete plabel;
/*if (params->sammon != NULL)
delete params->sammon;*/
return 0;
}
int NumClass()
{return plabel->NumClass();}
int GetClassInt(int i)
{
return plabel->GetClassInt(i);
}
int GetLabelInt(char *str)
{
return plabel->GetLabelInt(str);
}
char *GetClassStr(int i)
{
return plabel->GetClassStr(i);
}
/*********************************************************************************************
* Delete the memory allowed for pentries.
*********************************************************************************************/
int DeleteEntries(struct entries *pentries)
{
close_entries(pentries);
return 0;
}
/*********************************************************************************************
* Converts PLVQPARAMS params into struct teach_params *tparams
* This function makes the connection between the paradigm used in PCA and the paradigm used in
* LVQ
*********************************************************************************************/
int LVQParamstoTeach(struct teach_params *tparams, PLVQPARAMS params)
{
MattoEntries(&(tparams->codes), params->pcode);
if (tparams->codes == NULL)
return -1;
tparams->codes->xdim = params->xdim;
tparams->codes->ydim = params->ydim;
tparams->codes->topol = params->topol;
tparams->codes->neigh = params->neigh;
MattoEntries(&(tparams->data), params->pdata);
if (tparams->data == NULL)
{
DeleteEntries(tparams->codes);
return -1;
}
tparams->data->xdim = params->xdim;
tparams->data->ydim = params->ydim;
tparams->data->topol = params->topol;
tparams->data->neigh = params->neigh;
tparams->topol = params->topol;
tparams->neigh = params->neigh;
tparams->alpha_type = params->alpha_type;
tparams->radius = params->radius;
tparams->alpha = params->alpha;
tparams->length = params->length;
tparams->knn = params->knn;
tparams->snapshot = NULL;
tparams->start_time = 0;
tparams->end_time = 0;
tparams->mapdist = NULL;
tparams->dist = vector_dist_euc;
tparams->neigh_adapt = NULL;
tparams->vector_adapt = adapt_vector;
if (params->knn > 1)
tparams->winner = find_winner_knn;
else
tparams->winner = find_winner_euc;
switch (tparams->alpha_type)
{
case ALPHA_LINEAR:
tparams->alpha_func = linear_alpha;
break;
case ALPHA_INVERSE_T:
tparams->alpha_func = inverse_t_alpha;
break;
case ALPHA_UNKNOWN:
default:
tparams->alpha_func = NULL;
}
tparams->sammon = params->sammon;
/*Checks*/
if (tparams->alpha < 0.0 || tparams->alpha > 1.0)
tparams->alpha = 0.3;
return 0;
}
/*-------------------------------------- LINK ROUTINES ---------------------------------------*/
/***********************************************************************************************
* lvq1 : original LVQ1 learning algorithm
***********************************************************************************************/
int lvq1(PLVQPARAMS params)
{
int ret;
struct teach_params tparams;
struct entries *pcode;
if (params->radius == -1)
{
params->radius = 90.0;
Msg(0, "Radius is undefined, default value = %f", params->radius);
}
if (params->alpha == -1)
{
params->alpha = 0.3;
Msg(0, "Initial aplha value is undefined, default value = %f", params->alpha);
}
if (params->length == -1)
{
params->length = 10000;
Msg(0, "Learning iteration value is undefined, default value = %l", params->length);
}
LVQParamstoTeach(&tparams, params); /*Initialize the teach_param struct*/
pcode = lvq1_training(&tparams);
if (pcode == NULL)
return -1;
delete params->pcode;
params->pcode = NULL;
ret = EntriestoMat(&(params->pcode), pcode);
return ret;
}
/***********************************************************************************************
* olvq1 : optimized-learning-rate LVQ1 algorithm, recomended for the main learning algorithm
* It must always be preceded by an initialization procedure, either eveninit or propinit,
* and possibly by the program balance, too.
***********************************************************************************************/
int olvq1(PLVQPARAMS params)
{
int ret;
struct teach_params tparams;
struct entries *pcode;
if (params->radius == -1)
{
params->radius = 90.0;
Msg(0, "Radius is undefined, default value = %f", params->radius);
}
if (params->alpha == -1)
{
params->alpha = 0.3;
Msg(0, "Initial aplha value is undefined, default value = %f", params->alpha);
}
if (params->length == -1)
{
params->length = 10000;
Msg(0, "Learning iteration value is undefined, default value = %l", params->length);
}
LVQParamstoTeach(&tparams, params); /*Initialize the teach_param struct*/
pcode = olvq1_training(&tparams, NULL, NULL);
if (pcode == NULL)
return -1;
delete params->pcode;
params->pcode = NULL;
ret = EntriestoMat(&(params->pcode), pcode);
return ret;
}
/***********************************************************************************************
* lvq2 : used for an additional fine tuning stage in learning (low alpha).
* The relative length of the window parameter (winlen field of PLVQPARAMS), into which the
* codebook vector must fall to get an updating, is used.
***********************************************************************************************/
int lvq2(PLVQPARAMS params)
{
int ret;
struct teach_params tparams;
struct entries *pcode;
if (params->radius == -1)
{
params->radius = 90.0;
Msg(0, "Radius is undefined, default value = %f", params->radius);
}
if (params->alpha == -1)
{
params->alpha = 0.3;
Msg(0, "Initial aplha value is undefined, default value = %f", params->alpha);
}
if (params->length == -1)
{
params->length = 10000;
Msg(0, "Learning iteration value is undefined, default value = %l", params->length);
}
if (params->winlen == -1)
{
params->winlen = 0.3;
Msg(0, "Length of window for the LVQ2 or LVQ3 is undefined, default value = %f", params->winlen);
}
LVQParamstoTeach(&tparams, params); /*Initialize the teach_param struct*/
pcode = lvq2_training(&tparams, params->winlen);
if (pcode == NULL)
return -1;
delete params->pcode;
params->pcode = NULL;
ret = EntriestoMat(&(params->pcode), pcode);
return ret;
}
/***********************************************************************************************
* lvq3 : used for an additional fine tuning stage in learning (low alpha).
* The relative length of the window parameter (winlen field of PLVQPARAMS), into which the
* codebook vector must fall to get an updating, is used.
* Here epsilon is used, too. It is the relative learning rate used when both of the nearest
* codebook vectors belong to the same class.
***********************************************************************************************/
int lvq3(PLVQPARAMS params)
{
int ret;
struct teach_params tparams;
struct entries *pcode;
if (params->radius == -1)
{
params->radius = 90.0;
Msg(0, "Radius is undefined, default value = %f", params->radius);
}
if (params->alpha == -1)
{
params->alpha = 0.3;
Msg(0, "Initial aplha value is undefined, default value = %f", params->alpha);
}
if (params->length == -1)
{
params->length = 10000;
Msg(0, "Learning iteration value is undefined, default value = %l", params->length);
}
if (params->winlen == -1)
{
params->winlen = 0.3;
Msg(0, "Length of window for the LVQ2 or LVQ3 is undefined, default value = %f", params->winlen);
}
if (params->epsilon == -1)
{
params->epsilon = 10;
Msg(0, "Epsilon value for the LVQ3 is undefined, default value = %i", params->epsilon);
}
LVQParamstoTeach(&tparams, params); /*Initialize the teach_param struct*/
pcode = lvq3_training(&tparams, params->epsilon, params->winlen);
if (pcode == NULL)
return -1;
delete params->pcode;
params->pcode = NULL;
ret = EntriestoMat(&(params->pcode), pcode);
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -