2011-06-18 41 views
1

我有一個代碼,我需要創建一個關鍵值爲double的映射(兩個集羣之間的f-測試值,我需要計算這個殘差平方和)以及作爲我創建的類Cluster的對的cluspair的映射值。 Map旨在存儲所有簇之間的F檢驗值,這樣我就不需要在每一步中一次又一次地進行計算。 BTW羣集是一個樹形結構,每個羣集包含兩個子羣集,存儲的值爲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的imlementation:

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));  
    } 
} 

提前很多感謝。我現在真的不知道該怎麼做。下面


是與我用於創建具有鍵爲兩個羣集裝置之間簡單歐幾里得距離的映射的代碼。正如我上面所說的那樣,它非常相似並且使用最少的內存。它僅在f值的計算中有所不同。除了遞歸計算之外,還有計算兩個聚類平均值的簡單距離。希望它可以幫助找出問題

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; 
} 

實施vectorDist()的

double vectorDist(vector<double> vec1, vector<double> vec2) 
{ 

    double sqrsum=0; 
    double tempd=0; 

    int vs = vec1.size(); 

    for (int i=0;i<vs;i++) 
    { 
     tempd = vec1[i] - vec2[i]; 
     sqrsum += tempd*tempd; 
    } 

    return sqrsum; 
} 

編輯:

BTW我已經試過這種替代的實施仍無法得到控制內存使用情況

double Cluster::rss() 
{ 
    list<double> fvals; 
    rss(cnode->mean , fvals); 

    double sum=0; 
    list<double>::iterator tpit; 
    for(tpit=fvals.begin() ; tpit != fvals.end() ; ++tpit) 
    { 
     sum += *tpit; 
    } 
    return sum; 
} 

void Cluster::rss(vector<double> &cmean , list<double> &fvals) 
{ 
    if(cnode->numOfVecs==1) 
    { 
     fvals.push_back(vectorDist(cmean,cnode->mean)); 
    } 
    else 
    { 
     ec1->rss(cmean , fvals); 
     ec2->rss(cmean , fvals);   
    } 
} 
+0

用編程語言標記 – emaillenin

+0

那是while循環合法嗎?此外,請考慮不返回地圖<>的副本,而是將其作爲參考參數 – Andrei

+0

並且Cluster :: rss()如何在每次迭代時減少它的工作負荷?請發佈首先編譯的內容... – Andrei

回答

1

如果內存不足,您的樹會非常深,或者您的Cluster對象很大或者兩者都有。嘗試創建另一個與Cluster樹相同拓撲的雙樹樹數據結構,並將其稱爲RSS樹以保存RSS值。計算底部節點的RSS值,然後遞歸填充RSS樹中的其餘值。這樣,您在進行rss計算時不會在內存中保存集羣對象。

+0

集羣樹既大又深我很害怕:)我明白你的意思了,我沒有想到集羣對象被保存在內存中直到計算結束。我會試一試,但我仍然不確定。我返回了我用對象完成的計算結果。對象本身是否也保存在內存中? – serkank

+0

對rss進行的每次遞歸調用都是在調用堆棧上放置新的Cluster :: rss調用之前,將來自Cluster對象的成員變量存儲在堆棧上。如果您在樹中100層深處,您將要從上層遞歸調用中將多達300個Cluster對象存儲在調用堆棧的內存中(因爲每個Cluster對象都有一對作爲成員的集羣對象)以及任何其他Cluster對象具有的成員數據。當你調用一個函數時,通常你會保存堆棧中的本地數據直到它返回。 –

+0

但是,它不會導致與深度相同的問題來計算底部節點的rss?爲了達到底層節點,我仍然需要存儲以前的集羣對象。 – serkank