TF-IDF模型

TF-IDF模型简介

                   整理了网上的一些资料

                   TF-IDF是一种用于资讯检索文本挖掘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。

                  TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF实际上是:TF * IDF,TF词频(Term Frequency),IDF逆向文件频率(Inverse Document Frequency)。TF表示词条在文档d中出现的频率。IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。但是实际上,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别于其它类文档。这就是IDF的不足之处。 在一份给定的文件里,词频(term frequency,TF)指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。)对于在某一特定文件里的词语{\displaystyle t_{i}}t_{​{i}}来说,它的重要性可表示为:

                    

以上式子中{\displaystyle n_{i,j}}n_{​{i,j}}是该词在文件{\displaystyle d_{j}}d_{​{j}}中的出现次数,而分母则是在文件{\displaystyle d_{j}}d_{​{j}}中所有字词的出现次数之和。

逆向文件频率(inverse document frequency,IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到:

                    

其中:    

某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

注:以上摘自维基百科

C++实现:来源于互联网


#include<map>
#include<set>
#include<string>
#include<iostream>
#include<fstream>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;

char Comment[]=",.!\"?;:()";
int TextNum=0;                            //文章数
map<string,float> IDFTable;
map<string,int> WordTable;
struct Words{
	string wd;
	float freq;
	float weight;
};
vector<Words> WordList;
bool cmp(Words &w1,Words &w2)
{
	return w1.weight>w2.weight;
}

//判断是不是纯数字
bool IsNumber(string s)
{
	for(int i=0;i<s.length();i++){
		if(s[i]<'0'||s[i]>'9')
			return false;
	}
	return true;
}

//判空
bool Isblank(string s)
{
	for(int i=0;i<s.length();i++){
		if(s[i]!=' '&&s[i]!='\t')
			return false;
	}
	return true;
}

//把大写改成小写
string &Lower(string &cs)
{
	for(int i=0;i<cs.length();i++)
	{
		if(cs[i]>'A'&&cs[i]<'Z')
			cs[i]+=('a'-'A');
	}
	return cs;
}

void ReadFile(string fname,set<string> &wds)
{
	ifstream fin(fname.c_str());
	string word;
	wds.clear();
	while(!fin.eof())
	{
		fin>>word;
		for(int i=0;Comment[i]!=0;i++)
		{
			int pos;
			//去掉词中最后一个特殊符号
			while((pos=word.find(Comment[i]))!=-1)
				word.replace(pos,1,"");
		}
		//如果不是纯数字和空字符串,则加入到set集合中
		if(!IsNumber(word)&&!Isblank(word))
			wds.insert(Lower(word));
	}
	fin.close();
}

//计算IDF值
void IDF()
{
	TextNum=0;
	string files[5]={"first.txt",
			"second.txt",
			"thrid.txt",
			"fourth.txt",
			"fifth.txt"
	};                                    //用作训练集
	set<string> wds;
	for(int i=0;i<5;i++)
	{
		ReadFile(files[i],wds);
		set<string>::iterator it;
		for(it=wds.begin();it!=wds.end();++i)
		{
			map<string,float>::iterator iter;
			string word=*it;
			if((iter=IDFTable.find(word))!=IDFTable.end())
				iter->second+=1;
			else
				IDFTable[word]=1;
		}
		TextNum++;
	}
	for(map<string,float>::iterator iter=IDFTable.begin();
			iter!=IDFTable.end();++iter)
		iter->second=log((float)TextNum/(iter->second+1.0));
}

int TF()
{
	ifstream fin("Test.txt");                  //测试的数据
	string word;
	int textwords=0;
	while(!fin.eof())
	{
		fin>>word;
		for(int i=0;Comment[i]!=0;i++)
		{
			int pos;
			while((pos=word.find(Comment[i]))!=-1)
				word.replace(pos,1,"");
		}
		if(!IsNumber(word)&&!Isblank(word))
		{
			textwords++;
			map<string,int>::iterator it;
			word=Lower(word);
			if((it=WordTable.find(word))!=WordTable.end())
				it->second++;
			else
				WordTable[word]=1;
		}
	}
	fin.close();
	for(map<string,int>::iterator it=WordTable.begin();
			it!=WordTable.end();++it)
	{
		Words wd;
		wd.wd=it->first;
		wd.freq=(float)(it->second)/textwords;
		float idf=0;
		map<string,float>::iterator iter;
		if((iter=IDFTable.find(wd.wd))!=IDFTable.end())
			idf=iter->second;
		else
			idf=log((float)TextNum);
		wd.weight=wd.freq*idf;
		WordList.push_back(wd);
	}
	return textwords;
}

void Sort()
{
	sort(WordList.begin(),WordList.end(),cmp);
}

int main()
{
	IDF();
	int txtwd=TF();
	Sort();
	int topnum=10;
	cout<<"Total Words: "<<txtwd<<" Top "<<topnum<<":\n";
	cout<<"Wrod\t\tweight\n";
	for(int i=0;i<topnum;i++)
		cout<<WordList[i].wd<<"\t\t"<<WordList[i].weight<<endl;
}

      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TF-IDF(Term Frequency-Inverse Document Frequency)模型结构图可以用来表示该模型的主要组成部分和信息流动。下面是一个简单的TF-IDF模型结构图示例: ``` +------------------+ +------------------------+ | 文档集合 | | 文档向量表示 | +------------------+ +------------------------+ | | | | v v +------------------+ +------------------------+ | 分词预处理 | | 计算词频(TF) | +------------------+ +------------------------+ | | | | v v +------------------+ +------------------------+ | 停用词过滤 | | 计算逆文档频率(IDF) | +------------------+ +------------------------+ | | | | v v +------------------+ +-----------------------+ | 词频向量化 | | TF-IDF权重计算 | +------------------+ +-----------------------+ | | | | v v +------------------+ +-----------------------+ | 向量空间模型 | | TF-IDF文档表示 | +------------------+ +-----------------------+ ``` 上图中,TF-IDF模型的主要组成部分包括文档集合、分词预处理、停用词过滤、词频(TF)计算、逆文档频率(IDF)计算、词频向量化、TF-IDF权重计算和向量空间模型。 在TF-IDF模型中,首先将文档集合进行分词预处理,例如分词、去除标点符号等。然后进行停用词过滤,去除常见无意义的词语。接下来,计算每个文档中每个词语的词频(TF),即该词语在文档中出现的频率。 同时,计算逆文档频率(IDF),衡量了一个词语在整个文档集合中的重要性。然后,将词频向量化,将每个文档表示为一个向量,其中每个维度表示一个词语,并用词频来表示该维度的权重。 最后,通过计算TF-IDF权重,将词频与逆文档频率相乘,得到每个词语在文档中的TF-IDF权重。进一步,可以使用向量空间模型表示文档,其中每个文档用一个向量表示其TF-IDF权重。 这样,TF-IDF模型能够将文档集合转换为高维向量空间中的向量表示,方便进行文本检索、相似度计算等任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值