zoukankan      html  css  js  c++  java
  • Kmeans聚类之特征词选择(DF法)

    写个菜鸟的入门级读物:如何利用weka进行文本聚类(一)(老鸟勿进,因为你会失望的。。。)

    作者:finallyliuyu(转载请注明作者和出处)

    哦,(一)忘记附上了去掉字符串首尾空格的小函数了,现在补上。

    void trim(string  &str,const string val)
    {  
       str.erase(
    0,str.find_first_not_of(val));
       str.erase(str.find_last_not_of(val)
    +val.size());
       
       
    }

    在(一)中,我们已经建立了稳定词袋子模型,这个词袋子模型可是个宝贝家伙,我们一定要小心维护。为什么呢?因为 特征词选择模块,VSM(文档向量模型)的建立模块,我们都要用到它。另外我们也说了这个这个东西很占内存,所以我们不能在特征词选择的时候调用一次这个函数,然后在建立VSM模型的时候再调用一次这个函数,这样会影响程序的运行速度,所以最好的方法就是把这个宝贝家伙保存到硬盘上。序列化。对于序列化这个复杂的map,我问过嗷嗷,也问过同学,有人建议我用boost库,但是我觉得最简单的方法还是自己按某种规则自己序列化到硬盘,然后解序列化到内存。

    至于格式,我是这么定义的。

    首行,词的总个数

    然后

    词1的text

    词1的DF,

    然后是vector<pair<int,int> >

    ...

    以此类推。上个图给大家看看就一目了然了。

    下面给出序列化和反序列化的代码

    save:保存词袋子信息到硬盘
    //将词典信息存到硬盘上
    void save(map<string,vector<pair<int,int> > >&mymap)
    {   ofstream outfile(
    "f:\\mydict.dat",ios::binary);
        outfile
    <<mymap.size()<<endl;
        map
    <string,vector<pair<int,int> > >::iterator it;
        
    for (it=mymap.begin();it!=mymap.end();it++)
        {   outfile
    <<it->first<<endl;
            vector
    <pair<int,int>>::iterator subit;
            outfile
    <<it->second.size()<<endl;
            
    for(subit=(it->second).begin();subit!=(it->second).end();++subit)
            {
                outfile
    <<subit->first<<" "<<subit->second<<" "<<";"<<" ";
            }
            outfile
    <<endl;
        }
        
    //outfile.write((char *)&mymap,sizeof(mymap));

        outfile.close();
    }
    load:重新加载词袋子模型到内存
    void load(map<string,vector<pair<int,int> > >&mymap)
    {   
        
    //设置代码页为简体中文,936是简体中文的代码页。
        std::locale loc1 = std::locale::global(std::locale(".936"));
        {
            
    // 在这里使用std::ifstream 或者 std::fstream
            ifstream infile("F:\\mydict.dat",ios::binary);
            
    int lenMyMap;//保存词典长度
            int lenVector;//保存每个词出现的文章数目
            string key;//保存读出的map的键值
            int articleId;//文章标号
            int count;//在该文章中刚出现的数目
            string comma;
            
    string semicolon;
            infile
    >>lenMyMap;
            
    while(!infile.eof())
            {
                infile
    >>key;
                infile
    >>lenVector;
                vector
    <pair<int,int> >temp;
                
    for (int i=0;i<lenVector;i++)
                {
                    infile
    >>articleId>>count>>semicolon;
                    temp.push_back(make_pair(articleId,count));
                }
                mymap[key]
    =temp;
            
            
            }
        

            infile.close();
        }
        std::locale::
    global(std::locale(loc1));

    }
    打印词典信息到屏幕
    /打印词典信息
    void print(map<string,vector<pair<int,int> > >&mymap)
    {   
        cout
    <<mymap.size()<<endl;
        map
    <string,vector<pair<int,int> > >::iterator it;
        
    for (it=mymap.begin();it!=mymap.end();it++)
        {   cout
    <<it->first<<endl;
            vector
    <pair<int,int>>::iterator subit;
            cout
    <<it->second.size()<<endl;
            
    for(subit=(it->second).begin();subit!=(it->second).end();++subit)
            {
                cout
    <<subit->first<<','<<subit->second<<";";
            }
            cout
    <<endl;
        }
        
    }

     下面开始介绍特征词选择模块:

    首先是几个辅助函数,也就是用到泛型算法中的谓词函数

    some assistant predicate
    bool isLonger(const  pair<string,int> &pair1, const pair<string,int>  &pair2)
    {
        
    return pair1.second>pair2.second;
    }
    bool cntAssist(const  pair<string,int> &pair1)
    {
        
    return pair1.second<=100;
    }

    DF特征词选择方法
    ///关键词统计以及DF法选择特征词        
    void DFcharicteristicWordSelection(map<string,vector<pair<int,int>>> &mymap,int DFthreshold)
    {        
    int finalKeyWordsCount=0;//计算共取了多少个关键词
            vector<pair<string,int> >tempvector;
            
    for(map<string,vector<pair<int,int>>>::iterator it=mymap.begin();it!=mymap.end();++it)
            {
                tempvector.push_back(make_pair(it
    ->first,(it->second).size()));
            }
        
            stable_sort(tempvector.begin(),tempvector.end(),isLonger);
            ofstream outfile(
    "F:\\keywordsinfo.txt");
            
    for(vector<pair<string,int> >::iterator it=tempvector.begin();it!=tempvector.end();it++)
            {   
                
    if(it->second>=DFthreshold)
                {
                        
    //outfile<<it->first<<" "<<it->second<<endl;
                    outfile<<it->first<<endl;
                    finalKeyWordsCount
    ++;
                    
                }
             
            }
            outfile.close();
            cout
    <<"最后共选择特征词"<<finalKeyWordsCount<<endl;
            cout
    <<"by the way,DFthreshold equals"<<DFthreshold<<endl;
                
    }

     下面给出特征词文件的部分截图

    有一点要提醒大家哈,特征词选择模块执行之前,要load  词袋子模型到内存哈。

    下面我们开始给出建立VSM模型的代码。

    建立VSM模型需要两个数据,词袋子就是前面所说的那个map,以及刚刚选出的特征词。load map的函数已经给出,下面给出load特征词集合的函数

    将特征词信息加载到内存
    //获取最终选取的特征词
    vector<string> GetFinalKeyWords()
    {
        vector
    <string>myKeys;
        ifstream infile(
    "F:\\keywordsinfo.txt");
        
    while(!infile.eof())
        {
            
    string temp;
            infile
    >>temp;
            
    if(temp!="")
            {
                myKeys.push_back(temp);
            }
            
            
        }
        
    return myKeys;

    }

    方法就是:对于每一篇文章,检查我们选出的特征词集合,对于每个特征词,查map,看看里面有没有该篇文章的id出现过,以及该特征词在该篇文章中出现过几次。

     未完待续。。。

  • 相关阅读:
    Python模块之logging
    Python模块之configparser
    python序列化模块 json&&pickle&&shelve
    Python模块之hashlib
    最短路之Floyd(多源)HDU 1874
    Python类知识学习时的部分问题
    第9章 Python文件操作目录
    第8章 Python类中常用的特殊变量和方法目录
    第7章 Python类型、类、协议目录
    第6章 Python中的动态可执行方法目录
  • 原文地址:https://www.cnblogs.com/finallyliuyu/p/1812086.html
Copyright © 2011-2022 走看看