运用TF-IDF 提取特征词 k-means 挖掘微博的兴趣特征群体



//分词

#include "TFIDFMeasure.h"
#include <limits>
#include <cmath>
using namespace std;

TFIDFMeasure::~TFIDFMeasure(void)
{
 //销毁分词器
 if (this->_tokenizer!=NULL)
 {
  delete _tokenizer;
  _tokenizer = NULL;
 }
 //清空数据
 _docs.clear();
 _terms.clear();
 _wordsIndex.clear();
}

TFIDFMeasure::TFIDFMeasure(const StrVec& documents,ITokeniser* tokeniser)
{
 _docs=documents;
 _numDocs=documents.size();
 _tokenizer = tokeniser;
 this->Init();
}

void TFIDFMeasure::GenerateTerms(const StrVec& docs,StrVec& terms)
{
 for (int i=0; i < docs.size() ; i++)
 {
  StrVec words;
  _tokenizer->Partition(docs[i],words);//分词  

  for (int j=0; j < words.size(); j++)
  {
   //不在单词表中,则加入
   if (find(terms.begin(),terms.end(),words[j])==terms.end())
   {
    terms.push_back(words[j]);
   }
  }
 }
}

void TFIDFMeasure::Init()
{//初始化
 this->GenerateTerms (_docs,_terms);//分出所有词项
 this->_numTerms=_terms.size() ;//所有文档中的词项数目
 //准备好存储空间
 _maxTermFreq.resize(_numDocs);
 _docFreq.resize(_numTerms);
 _termFreq.resize(_numTerms);
 _termWeight.resize(_numTerms);

 for(int i=0; i < _terms.size() ; i++)   
 {
  _termWeight[i].resize(_numDocs);
  _termFreq[i].resize(_numDocs) ;
  _wordsIndex[_terms[i]] = i;//将单词放入单词映射表中 
 }
 this->GenerateTermFrequency ();//计算单词频率
 this->GenerateTermWeight();//计算单词权重
}

void TFIDFMeasure::GetWordFrequency(string& input,map<string,int>& freq)
{//计算单词频率
 transform(input.begin(),input.end(),input.begin(),tolower);
 StrVec temp;
 this->_tokenizer->Partition(input,temp);//对当前文档分词
 unique(temp.begin(),temp.end());
 StrVec::iterator iter;
 for (iter=temp.begin();iter!=temp.end();++iter)
 {
  int count = CountWords(*iter, temp);//计算单词在文档中出现的次数
  freq[*iter] = count;//保存单词频率
 }

void  TFIDFMeasure::GetTermVector(int doc,DoubleVec& vec)
{
 vec.resize(this->_numTerms);
 for (int i=0; i < this->_numTerms; i++)           
  vec[i]=_termWeight[i][doc];//第i个单词在文档doc中的权重
}

//用于字符串比较的仿函数
class WordComp
{
public:
 WordComp(string& sWord) : word(sWord)
   {

   }
   bool operator() (const string& lhs)
   {
    return lhs.compare(word)==0;
   }      
private:
 string word;       
};

int TFIDFMeasure::CountWords(string& word, const StrVec& words)
{
 int nCount = 0;
 nCount = count_if(words.begin(),words.end(),WordComp(word));
 return nCount;

int TFIDFMeasure::GetTermIndex(const string& term)
{
 map<string,int>::iterator pos = _wordsIndex.find(term);
 if (pos!=_wordsIndex.end())
 {
  return pos->second;
 }
 else
  return -1;
}

void TFIDFMeasure::GenerateTermFrequency()
{//计算每个单词在每份文档出现的频率
 for(int i=0; i < _numDocs  ; i++)
 {        
  string curDoc=_docs[i];//当前待处理的文档
  map<string,int> freq;
  this->GetWordFrequency(curDoc,freq);
  map<string,int>::iterator iter;
  _maxTermFreq[i]=numeric_limits<int>::min();
  for (iter = freq.begin();iter!=freq.end();++iter)
  {
   string word=iter->first;
   int wordFreq=iter->second ;
   int termIndex=GetTermIndex(word);//单词下标
   if(termIndex == -1)
    continue;
   _termFreq [termIndex][i]=wordFreq;//单词在第i份文档中出现的频率
   _docFreq[termIndex]++;//出现第termIndex单词的文档频率加1

   if (wordFreq > _maxTermFreq[i]) _maxTermFreq[i]=wordFreq;//记录第i份文档中的最大词频     
  }
 }
}


void TFIDFMeasure::GenerateTermWeight()
{//计算每个单词在每份文档中的权重   
 for(int i=0; i < _numTerms; i++)
 {
  for(int j=0; j < _numDocs ; j++)
  {
   _termWeight[i][j]=ComputeTermWeight (i, j);  
  }
 }
}

double TFIDFMeasure::GetTermFrequency(int term, int doc)
{   
 int freq=_termFreq [term][doc];//词频
 int maxfreq=_maxTermFreq[doc];   
 return ( (float) freq/(float)maxfreq );
}

double TFIDFMeasure::ComputeTermWeight(int term, int doc)
{//计算单词在文档中的权重
 float tf=GetTermFrequency (term, doc);
 float idf=GetInverseDocumentFrequency(term);
 return tf * idf;
}
double TFIDFMeasure::GetInverseDocumentFrequency(int term)
{
 int df=_docFreq[term];//包含单词term的文档数目
 return log((float) (_numDocs) / (float) df );
}

//k-means

#include "KMeans.h"
#include <time.h>
#include "Cluster.h"
#include "TermVector.h"
#include <limits>

KMeans::KMeans(Double2DVec &data, int K)
{
 int i;
 this->_coordinates.resize(data.size());
 for (i=0;i<data.size();++i)
 {
  copy(data[i].begin(),data[i].end(),back_inserter(_coordinates[i]));
 }
 _coordCount = data.size();
 _k = K;
 _clusters.resize(K);
 _clusterAssignments.resize(_coordCount);
 _nearestCluster.resize(_coordCount);
 _distanceCache.resize(_coordCount);
 for (i=0;i<_coordCount;++i)
 {
  _distanceCache[i].resize(_coordCount);
 }
 InitRandom();
}

void KMeans::InitRandom()
{
 srand(unsigned(time(NULL)));
 for (int i = 0; i < _k; i++)
 {
  int temp =  rand()%(_coordCount);//产生随机数
  _clusterAssignments[temp] = i; //记录第temp个资料属于第i个聚类
  _clusters[i] = new Cluster(temp,_coordinates[temp]);
 }
}
void KMeans::Start()
{
 int iter = 0,i,j;
 while (true)
 {
  
  cout<<"Iteration "<<iter++<< "..."<<endl;
  //1、重新计算每个聚类的均值
  for (i = 0; i < _k; i++)
  {
   _clusters[i]->UpdateMean(_coordinates);
  }

  //2、计算每个数据和每个聚类中心的距离
  for (i = 0; i < _coordCount; i++)
  {
   for (j = 0; j < _k; j++)
   {
    double dist = getDistance(_coordinates[i], _clusters[j]->Mean);
    _distanceCache[i][j] = dist;
   }
  }

  //3、计算每个数据离哪个聚类最近
  for (i = 0; i < _coordCount; i++)
  {
   _nearestCluster[i] = this->NearestCluster(i);
  }

  //4、比较每个数据最近的聚类是否就是它所属的聚类
  //如果全相等表示所有的点已经是最佳距离了,直接返回;
  int k = 0;
  for (i = 0; i < _coordCount; i++)
  {
   if (_nearestCluster[i] == _clusterAssignments[i])
    k++;

  }
  if (k == _coordCount)
   break;

  //5、否则需要重新调整资料点和群聚类的关系,调整完毕后再重新开始循环;
  //需要修改每个聚类的成员和表示某个数据属于哪个聚类的变量
  for (j = 0; j < _k; j++)
  {
   _clusters[j]->CurrentMembership.clear();
  }
  for (i = 0; i < _coordCount; i++)
  {
   _clusters[_nearestCluster[i]]->CurrentMembership.push_back(i);
   _clusterAssignments[i] = _nearestCluster[i];
  }

 }

}

double KMeans::getDistance(const DoubleVec& coord, const DoubleVec& center)
{
 return 1- TermVector::ComputeCosineSimilarity(coord, center);
}
int KMeans::NearestCluster(int ndx)
{
 int nearest = -1;
 double min = numeric_limits<double>::max();
 for (int c = 0; c < _k; c++)
 {
  double d = _distanceCache[ndx][c];
  if (d < min)
  {
   min = d;
   nearest = c;
  }

 }
 return nearest;
}
KMeans::~KMeans(void)
{
 vector<Cluster*>::iterator iter;
 for (iter=this->_clusters.begin();iter!=_clusters.end();++iter)
 {
  delete (*iter);
 }
 _clusters.clear();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值