作者:finallyliuyu 转载使用等请注明出处
上一讲:Kmeans文本聚类之VSM模型 中,给出了如何建立文档向量模型,以及写weka软件所要求的数据格式arff的代码。这里我们将介绍从weka中获取聚类中心,完成聚类的代码。
至于如何用weka聚类,该软件使用说明等之类问题,本系列博客不做介绍,请大家自行google之。
我们找到我们已经写好的arff文件:
点击start,出现结果后,单击鼠标右键出现”sava result buffer”选项,就可以将右侧客户区的信息保存下来,按照上面控制台程序的提示,我们将这份信息保存为F:\cluster\InfoFromWeka.dat
以下代码为从F:\cluster\InfoFromWeka.dat中取出聚类中心,实现文本聚类的模块
************************************************************************/
/* 获得Weka提供的聚类信息 */
/************************************************************************/
map<string,vector<double> > Preprocess::GetClusters()
{
map<string,vector<double> >clusters;
ifstream ifile(infoFromWekaAddress);
string temp;
while(getline(ifile,temp))
{ boost::smatch matchcluster;
boost::regex regcluster("Cluster\\s+\\d+",boost::regex::icase);
if(boost::regex_search(temp,matchcluster,regcluster))
{
string clustertmp=matchcluster[0].str();
string ordinates="";
getline(ifile,ordinates);
boost::regex regordinates("\\d+(\\.\\d{1,4})?");
boost::smatch matchordinates;
std::string::const_iterator it=ordinates.begin();
std::string::const_iterator end=ordinates.end();
while (boost::regex_search(it,end,matchordinates,regordinates))
{
string digitstemp=matchordinates[0].str();
double digitval=0.0;
std::stringstream ss;
ss<<digitstemp;
ss>>digitval;
clusters[clustertmp].push_back(digitval);
it=matchordinates[0].second;
}
}
}
return clusters;
}
建立文档向量模型的代码:注意此处只对整个文档集合建立文档向量模型,而不字符串化,这是该函数与Kmeans文本聚类之VSM模型中 VSMFormation函数的主要区别。此处建立的文档向量模型用于和聚类中心计算余弦相似度,然后将该篇文档划分给与它最相似的聚类中心。
map<int,vector<double> > Preprocess::VSMConstruction(map<string,vector<pair<int,int>>> &mymap)
{
int corpus_N=endIndex-beginIndex+1;
map<int,vector<double>> vsmMatrix;
vector<string> myKeys=GetFinalKeyWords();
vector<pair<int,int> >maxTFandDF=GetfinalKeysMaxTFDF(mymap);
for(int i=beginIndex;i<=endIndex;i++)
{
vector<pair<int,double> >tempVSM;
for(vector<string>::size_type j=0;j<myKeys.size();j++)
{
//vector<pair<int,int> >::iterator findit=find_if(mymap[myKeys[j]].begin(),mymap[myKeys[j]].end(),PredTFclass(i));
double TF=(double)count_if(mymap[myKeys[j]].begin(),mymap[myKeys[j]].end(),PredTFclass(i));
TF=0.5+(double)TF/(maxTFandDF[j].first);
TF*=log((double)corpus_N/maxTFandDF[j].second);
tempVSM.push_back(make_pair(j,TF));
}
if(!tempVSM.empty())
{
tempVSM=NormalizationVSM(tempVSM);
for(vector<pair<int,double> >::iterator it=tempVSM.begin();it!=tempVSM.end();it++)
{
vsmMatrix[i].push_back(it->second);
}
}
tempVSM.clear();
}
return vsmMatrix;
}
/**计算向量内积*/
double Preprocess::CalDotProductOfVectors(const vector<double>&vector1,const vector<double>&vector2)
{
double result = 0.0f;
for (int i = 0; i < vector1.size(); i++)
result += vector1[i] * vector2[i];
return result;
}
/**计算向量余弦相似度*/
double Preprocess::CalCosineofVectors(const vector<double>&vector1,const vector<double>&vector2)
{
double numerator=CalDotProductOfVectors(vector1,vector2);
double denominator=CalDotProductOfVectors(vector1,vector1)*CalDotProductOfVectors(vector2,vector2);
denominator=sqrt(denominator);
return numerator/denominator;
}
聚类,给每一篇文章打上类别标签
vector<pair<int,string> > Preprocess::GenerateClusterInfo(map<int,vector<double> >&vsmMatrix, map<string,vector<double> >&clusters)
{
vector<pair<int,string> >resultInfo;
for(map<int,vector<double> >::iterator it=vsmMatrix.begin();it!=vsmMatrix.end();it++)
{
vector<pair<string,double> >clusterDistanceAist;
for(map<string,vector<double> >::iterator clusterit=clusters.begin();clusterit!=clusters.end();clusterit++)
{
double temp=CalCosineofVectors(it->second,clusterit->second);
clusterDistanceAist.push_back(make_pair(clusterit->first,temp));
}
sort(clusterDistanceAist.begin(),clusterDistanceAist.end(),myCmp);
vector<pair<string,double> >::iterator cDAit=clusterDistanceAist.begin();
resultInfo.push_back(make_pair(it->first,cDAit->first));
clusterDistanceAist.clear();
}
return resultInfo;
}
/************************************************************************/
/* 获取每个类别所包含的文章ID */
/************************************************************************/
map<string,vector<int> > Preprocess::FetchArticlesOFClusters(map<string,vector<double> >&clusters,vector<pair<int,string>>&resultInfo)
{
map<string,vector<int>> articlesInfo;
for(vector<pair<int,string>>::iterator retit=resultInfo.begin();retit!=resultInfo.end();retit++)
{
for(map<string,vector<double> >::iterator it=clusters.begin();it!=clusters.end();it++)
{
if(retit->second==it->first)
{
articlesInfo[it->first].push_back(retit->first);
}
}
}
return articlesInfo;
}