У меня есть код, в котором мне нужно создать карту с двойными значениями ключей (значение f-критерия между двумя кластерами. Мне нужно рассчитать для этого остаточную сумму квадратов) и сопоставленное значение clusterpair. которая является парой класса Cluster, который я создал. Карта предназначена для хранения значений F-теста между всеми кластерами, чтобы мне не нужно было делать вычисления снова и снова на каждом шаге. Кстати, кластер - это древовидная структура, в которой каждый кластер содержит два подкластера, а сохраненные значения представляют собой 70-мерные векторы.
Проблема в том, что для вычисления RSS мне нужно реализовать рекурсивный код, в котором мне нужно найти расстояние каждого элемента кластера от среднего значения кластера, и это, кажется, потребляет огромный объем памяти. , Когда я создаю ту же карту со значениями ключей, представляющими собой простое расстояние между средними значениями двух кластеров, программа использует минимальное количество памяти, поэтому я думаю, что увеличение использования памяти вызвано вызовом рекурсивной функции RSS. Что я должен сделать, чтобы управлять использованием памяти в коде ниже? В своей текущей реализации системе не хватает памяти, и Windows закрывает приложение, сообщая, что системе не хватило виртуальной памяти.
Основной код:
map<double,cluspair> createRSSMap( list<Cluster*> cluslist )
{
list<Cluster*>::iterator it1;
list<Cluster*>::iterator it2;
map<double,cluspair> rtrnmap;
for(it1=cluslist.begin(); it1!= --cluslist.end() ;it1++)
{
it2=it1;
++it2;
cout << ".";
list<Cluster*>::iterator itc;
double cFvalue=10000000000000000000;
double rIt1 = (*it1)->rss();
for(int kk=0 ; it2!=cluslist.end(); it2++)
{
Cluster tclustr ((*it1) , (*it2));
double r1 = tclustr.rss();
double r2= rIt1 + (*it2)->rss();
int df2 = tclustr.getNumOfVecs() - 2;
double fvalue = (r1 - r2) / (r2 / df2);
if(fvalue<cFvalue)
{
cFvalue=fvalue;
itc=it2;
}
}
cluspair clp;
clp.c1 = *it1;
clp.c2 = *itc;
bool doesexists = (rtrnmap.find(cFvalue) != rtrnmap.end());
while(rtrnmap)
{
cFvalue+= 0.000000001;
rtrnmap= (rtrnmap.find(cFvalue) != rtrnmap.end());
}
rtrnmap[cFvalue] = clp;
}
return rtrnmap;
}
и реализация функции RSS:
double Cluster::rss()
{
return rss(cnode->mean);
}
double Cluster::rss(vector<double> &cmean)
{
if(cnode->numOfVecs==1)
{
return vectorDist(cmean,cnode->mean);
}
else
{
return ( ec1->rss(cmean) + ec2->rss(cmean) );
}
}
Большое спасибо заранее. Я действительно не знаю, что делать в этот момент.
ниже приведен код, который я использую для создания карты с ключами, представляющими собой простое евклидово расстояние между двумя средними значениями кластера. Как я уже говорил выше, он очень похож и использует минимальное количество памяти. Он отличается только в расчете fvalue. Вместо рекурсивного вычисления есть вычисление простого расстояния средних двух кластеров. Надеюсь, это поможет определить проблему
map<double,cluspair> createDistMap( list<Cluster*> cluslist )
{
list<Cluster*>::iterator it1;
list<Cluster*>::iterator it2;
map<double,cluspair> rtrnmap;
for(it1=cluslist.begin(); it1!= --cluslist.end() ;it1++)
{
it2=it1;
++it2;
cout << ".";
list<Cluster*>::iterator itc;
double cDist=1000000000000000;
for(int kk=0 ; it2!=cluslist.end(); it2++)
{
double nDist = vectorDist( (*it1)->getMean(),(*it2)->getMean());
if (nDist<cDist)
{
cDist = nDist;
itc=it2;
}
}
cluspair clp;
clp.c1 = *it1;
clp.c2 = *itc;
bool doesexists = (rtrnmap.find(cDist) != rtrnmap.end());
while(doesexists)
{
cDist+= 0.000000001;
doesexists = (rtrnmap.find(cDist) != rtrnmap.end());
}
rtrnmap[cDist] = clp;
}
return rtrnmap;
}
Конструктор кластеров
Cluster::Cluster (Cluster *C1, Cluster *C2)
{
ec1=C1;
ec2=C2;
node* cn = new node;
cn->numOfVecs = C1->cnode->numOfVecs + C2->cnode->numOfVecs;
double nov = cn->numOfVecs;
double div = (1 / nov);
cn->mean = scalarMultVect(div,vectAdd(scalarMultVect(C1->cnode->numOfVecs,C1->cnode->mean),scalarMultVect(C2->cnode->numOfVecs,C2->cnode->mean)));
mvect tmv;
tmv.stock="";
cn->v1 = tmv;
cnode = cn;
}