基于质心的划分方法是研究最多的算法,包括k-mean聚类算法及其各种变体,这些变体依据初始簇的选择,对象的划分、相识度的计算方法、簇中心的计算方法不同而不同。基于质心的划分方法将簇中所有对象的平均值看做簇的质心,根据一个数据对象与簇质心的距离,将该对象赋予最近的簇。在这类方法中,需要给定划分的簇个数k,首先得到k个初始划分的集合,然后采用地带重定位技术,通过将对象从一个簇移到另外一个簇来改进划分的质量。

算法:k-mean

输入:数据集D,划分簇的个数k

输出:k个簇的集合

从数据集合D中任意选择k个对象作为初始簇中心;、

Repeat

For 数据集D中每个对象P do

计算对象P到k个簇中心的距离

将对象P指派到与其最近(距离最短)的簇

End for

计算每个簇中心对象的均值,作为新的簇的中心

Until k个簇的簇中心不再发生变化

(1)本例子的样本集合是选择搜狗语料库中的三类文章,每类10篇,如图

(2)对于文本聚类,使用中科院的分词库ICTCLAS,接口封装在split.h和split.cpp中,在分词时,本例子只选用了动词和名词

(3)特征词选取使用tf-idf方法来提取每篇文章的前100个根据tf-idf大小排序的特征词

词频tf(Term Frequency)是指一个词条在一个文本出现的频数。频数越大,则该词语对文本的贡献度越大。其重要可表示为

tf=n/N (n是指单词w在文本Di中出现的次数,Ni是指文本Di中所有词语出现的总数)

逆文本频度idf(Inverse Document Frequency)表示词语在整个文本集中的分布情况,包含该词语的文本数目越少,则idf越大,数目该词语具有较强的类别区别能力。

idf=log2(N/m) (N是文本集合的总个数,m是包含该词语的文本个数)

最后将两者相乘。

算法实现思路是扫描所有的文章,对于每一篇文章都用一个map<string ,double>来记录单词的频数,扫描完一篇文章,就使用map<string ,double>来记录文档频数

/*
统计单词频数和文档频数
*/
void TFIDFMeasure::Statistics(void){for(vector<Document>::iterator it_document=documents.begin();it_document!=documents.end();it_document++){//读取文档string content=ReadFile(it_document->name);vector<Word> words;map<string,int> tf;//分词words=Split::splitToWord(const_cast<char*>(content.c_str()));vector<Word>::iterator it_word=words.begin();vector<Word>::iterator it_end_word=words.end();//记录频数for(;it_word!=it_end_word;it_word++){pair< map<string,int>::iterator,bool> ret =tf.insert(make_pair((*it_word).word,1));if(!ret.second){(ret.first->second)++;}}map<string,int>::iterator it_tf=tf.begin();map<string,int>::iterator it_end_tf=tf.end();int wordsize=0;for(;it_tf!=it_end_tf;it_tf++){KeyWord keyword;keyword.word=it_tf->first;keyword.fre=it_tf->second;it_document->words.insert(make_pair(it_tf->first,keyword));wordsize+=it_tf->second;//文档数目加1pair< map<string,int>::iterator,bool> ret=DocFre.insert(make_pair(it_tf->first,1));if(!ret.second){(ret.first->second++);}}//记录文章的总单词数目it_document->wordSize=wordsize;}
}
/*
将it-idf的前100个作为文档的特征向量如:(坦克:0.32;团长:0.02;...)
*/
void TFIDFMeasure::CalculTFIDF(void){cout<<documents.size()<<endl;//扫描每一篇文章 for(vector<Document>::iterator it_document=documents.begin();it_document!=documents.end();it_document++){vector<KeyWord> vector_sort;for(map<string,KeyWord>::iterator it_keyWord=it_document->words.begin();it_keyWord!=it_document->words.end();it_keyWord++){KeyWord keyword;keyword.word=it_keyWord->first;keyword.fre=it_keyWord->second.fre;map<string,int>::iterator docfre=DocFre.find(keyword.word);//计算ifXidfkeyword.TF_IDF=((double)keyword.fre/it_document->wordSize)*log((double)documents.size()/docfre->second)*10;vector_sort.push_back(keyword);}//排序sort(vector_sort.begin(),vector_sort.end(),sort_keyword);int size=limited>vector_sort.size()?vector_sort.size():limited;//提取前100个double absolute=0.0;for(int i=0;i<size;i++){featrue.insert(vector_sort[i].word);//特征向量的绝对值absolute+=(vector_sort[i].TF_IDF*vector_sort[i].TF_IDF);it_document->featrue.insert(make_pair(vector_sort[i].word,vector_sort[i].TF_IDF));}it_document->absolute=absolute;}cout<<"------"<<featrue.size()<<endl;//CalculCosim(documents[1],documents[11]);
}

对于文档军事10.txt,其特征向量为100维(坦克:0.02;团:0.32;演练,0.034;。。。),本文使用一个map<string,double>来表示,注意,每一篇文章都有一个100维的特征向量

(4)两篇文章之间的距离,本文使用余弦相似度来计算,将两个向量相乘

//计算其余弦相似度
double KMEAN::CalculCosim(Document &document1,Document &document2){double sum=0.0,absolute1=0.0,absolute2=0.0;for(map<string,double>::iterator it_document1=document1.featrue.begin();it_document1!=document1.featrue.end();it_document1++){//计算向量绝对值absolute1+=(it_document1->second*it_document1->second);}for(map<string,double>::iterator it_document2=document2.featrue.begin();it_document2!=document2.featrue.end();it_document2++){map<string,double>::iterator it_match=document1.featrue.find(it_document2->first);if(it_match!=document1.featrue.end()){sum+=(it_match->second*it_document2->second*10);}//计算向量绝对值absolute2+=(it_document2->second*it_document2->second);}//cout<<sum/(absolute1*absolute2)<<endl;return sum/(sqrt(absolute1*absolute2));
}

(5)计算该簇的质心,思路,统计该簇下所有的单词的tf-idf,对于相同的词语,tf-idf相累计,然后对td-idf排序,同样,取最大的前100个作为该簇的特征词。比较前后两次质心的改变情况,作为递归跳出的点,如果前后两次质心向量不变,就说明聚类结束

/*
重新计算该簇的质心向量
*/
void KMEAN::CalculMean(vector<KmeanClass> &classes){for(int i=0;i<classes.size();i++){// 计算其均值map<string,double> allfeatrue;for(int j=0;j<classes[i].Document.size();j++){for(map<string,double>::iterator it=classes[i].Document[j].featrue.begin();it!=classes[i].Document[j].featrue.end();it++){pair<map<string,double>::iterator,bool> ret=allfeatrue.insert(make_pair(it->first,it->second));if(!ret.second){ret.first->second+=it->second;}}         }vector<pair<string,double> > vector_sort;for(map<string,double>::iterator it=allfeatrue.begin();it!=allfeatrue.end();it++){vector_sort.push_back(make_pair(it->first,it->second));}  //取前面100个sort(vector_sort.begin(),vector_sort.end(),cmp_featrue);int size=limited>vector_sort.size()?vector_sort.size():limited;int same=0;for(int k=0;k<limited;k++){map<string,double>::iterator it_find=classes[i].featrue.find(vector_sort[k].first);if(it_find!=classes[i].featrue.end()){same++;}}cout<<"--------"<<endl;classes[i].featrue.clear();classes[i].Document.clear();for(int k=0;k<limited;k++){classes[i].featrue.insert(make_pair(vector_sort[k].first,vector_sort[k].second));}cout<<classes[i].name<<"the same rate(质心相似率) is "<<(double)same/limited<<endl;}
}

完整算法代码

void KMEAN::CalculKmean(int times){if(times==1){return ;}bool flag=true;double  maxCosValue=0.0;int maxIndex=0;for(int i=0;i<documents.size();i++){maxCosValue=0.0;flag=true;maxIndex=0;//计算文章D分别与各个簇之间的距离for(int j=0;j<myclasses.size();j++){double cosValue;Document document;document.featrue=myclasses[j].featrue;document.name=myclasses[j].name;cosValue=CalculCosim(document,documents[i]);if(cosValue>maxCosValue){maxCosValue=cosValue;maxIndex=j;}     }//将文章放到对于的簇myclasses[maxIndex].Document.push_back(documents[i]);cout<<documents[i].name<<"-----is classified ---"<<myclasses[maxIndex].name<<endl;}//计算准确率Accuracy(myclasses);//计算质心CalculMean(myclasses);//递归调用CalculKmean(--times);
}

结果分析

选取

分别作为3个簇的开始,其中军事使用A表示,汽车使用B表示,财经使用C表示

第一遍递归后的准确率和质心相似率

第二遍递归后

可以看出第二遍后质心相似率达到了90%,准确率也有80%左右,对于该算法还有很多研究的地方,比如初始K的选择,质心的计算方法等,有兴趣的同学可以交流一下。

基本k-mean聚类的文本聚类算法原理和例子相关推荐

  1. 基于K-Means的文本聚类

    何为聚类 "聚类是把相似的对象通过静态分类的方法分成不同的组别或者更多的子集(subset),这样让在同一个子集中的成员对象都有相似的一些属性."                 ...

  2. 机器学习之聚类算法:K均值聚类(一、算法原理)

    目录 一.Kmeans 二.Kmeans的流程 三.距离度量方式 3.1.闵可夫斯基距离 3.2.马哈拉诺比斯距离 3.3.其他 四.Kmeans聚类实例 五.Kmeans存在的问题 5.1.初始点的 ...

  3. 神经网络聚类方法:SOM算法原理

    一个神经网络接收外界输入模式时,将会分为不同的对应区域,各区域对输入模式有不同的响应特征,而这个过程是自动完成的.其特点与人脑的自组织特性类似.SOM的目标是用低维(通常是二维或三维)目标空间的点来表 ...

  4. python文本聚类_python 文本聚类算法

    三体下载 将下载的文件重命名为santi.txt,放在文件的目录下 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ ...

  5. 逻辑回归算法python_逻辑回归算法原理和例子

    本课程讲解现在工业界和学术界流行的机器学习算法的相关知识,以及如何用python去实现这些算法.算法的讲解包括supervised learning(有监督式学习)和unsupervised lear ...

  6. hanlp 词频统计_10.HanLP实现k均值--文本聚类

    AI 人工智能 10.HanLP实现k均值--文本聚类 10. 文本聚类 正所谓物以类聚,人以群分.人们在获取数据时需要整理,将相似的数据归档到一起,自动发现大量样本之间的相似性,这种根据相似性归档的 ...

  7. SinglepassTextCluster项目:基于single-pass算法思想的自动文本聚类组件

    项目的背景 SinglepassTextCluster, an TextCluster tool based on Singlepass cluster algorithm that use tfid ...

  8. 【文智背后的奥秘】系列篇——文本聚类系统

    版权声明:本文由文智原创文章,转载请注明出处:  文章原文链接:https://www.qcloud.com/community/article/131 来源:腾云阁 https://www.qclo ...

  9. Spark中文文本聚类

    Spark文本聚类 Spark文本聚类 Spark mlib简介 中文文本分词 TFIDF特征 word2vec介绍 文本表示 Kmeans LDA聚类 聚类是常见的无监督学习算法,用于找到相似的It ...

最新文章

  1. EIGRP的等价负载均衡
  2. MLIR(Multi-Level Intermediate Representation)概述
  3. mysql服务器的启动方式有哪几种_Mysql启动的方式(四种)
  4. 如何在jasperreport自动生成序号
  5. (五十九)自动存储、静态存储、动态存储
  6. 无法找到脚本文件adsutil.vbs的解决方法
  7. python,制作山东省的地图 热力图
  8. zookeeper平滑升级_zookeeper从3.4.8升级到3.4.14
  9. python安装MySQLdb包遇到的坑:EnvironmentError: mysql_config not found
  10. problem a: 简单的整数排序_什么是基数排序?
  11. uva 11728——Alternate Task
  12. 最大子矩阵问题悬线法 学习小结
  13. 场景,生态之面!——保险科技生态建设
  14. [07.08]密西绿色精品软件每日更新[西空整理]
  15. 学术汇报(academic presentation)/PPT应该怎么做?
  16. ArcGIS Pro地理配准
  17. 揭秘金庸笔下的假面江湖
  18. STM32 利用cubemx配置正点原子4.3寸TFT-LCD 驱动芯片NT35510
  19. android多任务列表高斯模糊
  20. 1074 链表翻转(柳神代码思路)yyds

热门文章

  1. Cyclone IV E GX Cyclone 10 LP Cyclone V SE SX 型号命名规则
  2. 【机器学习】线性回归之预测商品的销售额
  3. Enumerator failed to MoveNextAsync 处理思路
  4. 【华为机试真题 Python实现】树形目录操作【2022 Q1 Q2 |200分】
  5. 医咖会免费SPSS教程学习笔记—多重线性回归
  6. caffe中RGB图像三通道卷积过程学习推导
  7. 达梦数据库-安装配置规范(上)
  8. 规则引擎Ilog Jrules开发基础教程【连载1】-- 概述篇
  9. 基于混合整数线性规划的电力系统机组组合优化研究
  10. 利用信鸽推送实现Android登录后强制退出的功能(单点登录)