• Kmeans文本聚类系列之如何调用Preprocess类


    注意:

    本代码中没有实现“C++工程调用weka”的功能,如果您要找这类的资料,那么您来错地方了。重申一下这份代码的目的:方便广大自然语言处理爱好者,研究者,不必过分究竟于编程的技术细节,而是能在一开始就将注意力集中在文本分类/聚类这个主题上。

    拿我自己做个比方吧,我一直怀疑课本上所讲的各种特征词选择方法是否有效,比如课本上说DF法与IG法,CHI squire法效果差不多,MI法效果最差。我还怀疑课本上所讲的:多重伯努利贝叶斯的分类效果要劣于多项式贝叶斯的分类效果。所以总想实验一下。可是,如果完成这样一项实验,需要花费很大力气,即便是我可以调用weka中的算法,那么繁杂的预处理过程也是十分耗时的。这也是我共享这份代码的初衷。

    另外,比如我想结合自己的专业背景学习下Libsvm.可是发现libsvm网站上所给的数据都是UCI等国外大学提供的,和自己的专业也不太相关。

    在咱们国内可供开源的学习资料太少了。就说进行文本分类的语料库吧,除了搜狗一家之外,没有免费提供的。一些人把这种很底层的资源,奉若神明,当成宝贝一样供起来。所以我们所看到的好的开源的软件库,算法库都是老外搞的,如lucene。

    我想国人把“糟粕”当成宝贝珍藏起来,大概有两个原因:一个是:对自己太不自信了,生怕自己的东西被别人偷师学了去(这也证明 他的水平根本也不咋地,人家一学就会,太低端了),其实拿出来,让别人多指点下岂不是进步更快呢?第二个是:中国的剽窃现象太多了。

    这里上两张图吧。

    QQ截图未命名

    QQ截图未命名2

    “源码下载网”不仅剽窃了我在CSDN上上传的资源,而且还在其中加入了一些成人用品广告,如果在网页挂马,植入病毒就更加大逆不道了。。。。

    好像有点跑题了。

    接着说Preprocess类。

    首先为该类的私有数据成员赋值,这些变量包括文件的储存地址,数据库的链接字符串等等。

    private:
            char *bagofwordsAddress;//存放词袋子模型的位置
            char * featurewordsAddress;//存放特征词文件的位置;
            char *arffFileAddress;//存放ARFF文件的位置
            char *infoFromWekaAddress;//存放调用weka后的实验结果
            char *articleIdsAddress;//存放被聚类的文章的ID号
            char *dbconnection;//数据库的链接字符串
            char *dbselect;//数据库select语句
            char *dbfield;//数据库字段
            int beginIndex;//开始聚类的文章id
            int endIndex;//结束聚类的文章id

    该类提供两个函数。第一个函数完成:建立词袋子模型,特征词选择,建立文档向量模型,并将文档向量模型格式化成arff文件格式。第二个函数完成:从weka聚类信息输出文件获取聚类中心,完成文本聚类,并且输出聚类结果。这两个函数代码见如下:

    第一个函数:

    void Preprocess::WriteTotalArff(char *dbfield,int DFthreshold,bool isbagOfWordsExist,FUNCSEG seg)
    {
    	
    	
    	map<string,vector<pair<int,int>>> mymap;
    	if(!isbagOfWordsExist)
    	{
    		ConstructMap(mymap,dbfield,seg);
    		save(mymap);
    		cout<<"词袋子信息已经保存到硬盘"<<endl;
    	}
    	else
    	{
    		load(mymap);
    	}
    	DFcharicteristicWordSelection(mymap,DFthreshold);
    	WriteHeadArff();
    	VSMFormation(mymap);
    	cout<<"arff文件已经形成"<<endl;
    	
    	
    	string temp(infoFromWekaAddress);
    
    	cout<<"请您将使用weka聚类,并保存为"<<temp<<endl;
    }
     
    第二个函数
    void Preprocess::RetreiveArticleInfoFromDataBase()
    {
    	map<string,vector<pair<int,int>>> mymap;
    	vector<pair<int,string>>resultInfo;
    	map<string,vector<double> >clusters;
    	map<int,vector<double> >vsmMatrix;
    	map<string,vector<int>> articlesInfo;
    	ofstream ofile("F:\\cluster\\ArticlesInPerCluster.txt");
    	//boost::regex_replace(strresult)
    	//ConstructMap(mymap,1,500);
    	//save(mymap);
    	load(mymap);
    	vsmMatrix=VSMConstruction(mymap);
    	clusters=GetClusters();
    	resultInfo=GenerateClusterInfo(vsmMatrix,clusters);
    	articlesInfo=FetchArticlesOFClusters(clusters,resultInfo);
    
    	/*for(map<string,vector<int>>::iterator it=articlesInfo.begin();it!=articlesInfo.end();it++)
    	{
    		ofile<<it->first<<endl;
    		int count=0;
    		ofile<<"(";
    		for(int i=0;i<it->second.size();i++)
    		{
    			ofile<<(it->second)[i];
    
    			if(count<it->second.size()-1)
    			{
    				ofile<<",";
    			}
    			count++;
    		}
    		ofile<<")";
    		ofile<<endl;
    
    
    	}*/
    	for(map<string,vector<int>>::iterator it=articlesInfo.begin();it!=articlesInfo.end();it++)
    	{
    		ostringstream out;
    		string selectassist;
    		char *selectsql=new char[5000];
    		int count=0;
    		CoInitialize(NULL);
    		_ConnectionPtr pConn(__uuidof(Connection));
    		_RecordsetPtr pRst(__uuidof(Recordset));
    		pConn->ConnectionString=dbconnection;
    		pConn->Open("","","",adConnectUnspecified);
    		cout <<it->first<<endl;
    		ofile<<it->first<<endl;
    		out<<"(";
    		count=0;
    		for(int i=0;i<it->second.size();i++)
    		{
    			out<<(it->second)[i];
    			if(count<it->second.size()-1)
    			{
    				out<<",";
    			}
    			count++;
    			
    		
    		}
    		out<<")";
    		selectassist=out.str();
    		sprintf_s(selectsql,5000,"%s %s","Select ArticleTitle,class from News Where ArticleId in ",selectassist.c_str());
    
    		pRst=pConn->Execute(selectsql,NULL,adCmdText);
    		while(!pRst->rsEOF)
    		{	
    		//string keywordstr=(_bstr_t)pRst->GetCollect("CKeyWord");
    			string title=(_bstr_t)pRst->GetCollect("ArticleTitle");
    			//string rawtext=(_bstr_t)pRst->GetCollect("ArticleText");
    			string categorization=(_bstr_t)pRst->GetCollect("class");
    			cout<<"文章标题:"<<title<<"文章所属类别: "<<categorization<<endl;
    			ofile<<"文章标题:"<<title<<"文章所属类别: "<<categorization<<endl;
    
    
    			
    		
    
    
    			pRst->MoveNext();
    			
    		}
    		pRst->Close();
    		pConn->Close();
    		pRst.Release();
    		pConn.Release();
    		CoUninitialize();
    	
    	}
    	
    	
    
    
    ofile.close();	
    	
    	
    }

    在main函数中各种字符串:

     Preprocess::FUNCSEG seg=&Preprocess::goodWordsinPieceArticle;
    	int beginIndex=1;
    	int endIndex=66;
    	const char *bagofwordsAddress="F:\\cluster\\mydict.dat";//存放词袋子模型的位置
    	const char * featurewordsAddress="F:\\cluster\\keywordsinfo.dat";//存放特征词文件的位置;
    	const char *arffFileAddress="F:\\cluster\\tobeClustered.arff";//存放ARFF文件的位置
    	const char *infoFromWekaAddress="F:\\cluster\\InfoFromWeka.dat";//存放调用weka后的实验结果
    	const char * articleidAddress="F:\\cluster\\clusteredArticleId.dat";//存放已经已经被聚类的文章ID
    	const char *conn="Provider=SQLOLEDB.1;Password=xxxx;Persist Security Info=True; User ID=sa;Initial Catalog=MyNews";
        char *firstpart="select ArticleId,ArticleTitle,ArticleText from News where ArticleId between";
    	char *lastpart="order by ArticleId";
    	char selectsql[1000]={'\0'};
    	char *dbfield="ArticleText";
    	sprintf_s(selectsql,1000,"%s %d and %d %s",firstpart,beginIndex,endIndex,lastpart);
    	int string_size=600;
    
    	Preprocess  p(string_size,bagofwordsAddress,featurewordsAddress,arffFileAddress,infoFromWekaAddress,articleidAddress,conn,selectsql,beginIndex,endIndex);
     
     
    调用第一个函数:(注意:由于tobeClustered.arff文件为ios::app格式打开,所以每次开始新的实验之前要TruncateArff()清空下)
    p.TruncateArff();
    	
    p.WriteTotalArff(dbfield,10,false,seg);
    (注意:WrtieTotalArff函数中的false/true表示是否重新建立词袋子模型,如果是false 则表示不再建立词袋子模型了,比如我们想在原来的数据上重新做实验只想改一下DF阈值,从10改成20
    这时候就没有必要再重新建立词袋子模型)
    最后的运行结果:
    QQ截图未命名2 
    此系列已经写完,下一篇博文将上传源代码,和66篇三类新闻的语料资源。
    末了加一句:虽然我的初衷是建立一个开源的预处理框架,但是由于个人水平有限,
    可能整个程序框架会令读者有诸多不满。欢迎大家多提意见。同时也希望我这篇博文能起到
    抛砖引玉的作用。
    最后再次感谢园友嗷嗷 以及Galactica 在我编写C++程序中给予我的帮助,这是我第一个C++
    项目程序,函数命名,变量命名有点乱,希望大家不要学,能够取其精华,去其糟粕。
  • 相关阅读:
    HTML中select标签单选多选详解
    meta name="viewport" content="width=device-width,initial-scale=1.0" 解释
    鼠标点击变色 lvha
    html 标签释义
    百度首页top设置
    html css 笔记
    iOS 遍历控件
    iOS 状态栏更改为白色
    iOS UIModalPresentationFormSheet风格下的键盘隐藏
    iOS Xcode之SVN(remove git)
  • 原文地址:https://www.cnblogs.com/finallyliuyu/p/1817429.html
Copyright © 2020-2023  润新知