通过语言处理进行内容分类/聚类
项目描述
简介
collective.classification旨在提供一套用于自动文档分类的工具。目前它使用自然语言工具包,并具有基于词性标注(POS)的文档分类器,深受topia.termextract的影响。此产品主要用于实验和开发。目前支持英语和荷兰语。
这一切都是关于什么的?
这主要关乎乐趣!该软件包处于非常早期的实验阶段,并热切期待贡献。您可以通过查看测试来了解哪些功能有效或无效。您也可能能够用它做一些有用的事情。
1) 可以执行术语提取,以快速了解文档的内容。2) 在内容丰富、标签众多(或称“主题”在plone语言中)的大型网站上,为新内容分配标签可能很困难。在这种情况下,一个训练有素的分类器可以为负责标记内容的编辑提供有用的建议。3) 可以根据术语相似性找到类似文档。4) 聚类可以帮助您将未分类的内容组织成组。
它是如何工作的?
目前存在以下类型的实用工具
词性标注器,用于将文档中的词语分类为词性。目前提供了两个,一个是Penn TreeBank标注器,另一个是三元组标注器。两者都可以使用除了英语以外的其他语言进行训练,这正是我们在这里所做的工作。
术语提取器,负责从某些文档中提取重要术语。我们这里使用的提取器假设在文档中只有名词是重要的,并使用词性标注器来找到文档中最常用的名词。有关详细信息,请参阅代码和测试。
内容分类器,可以将内容标记为预定义的分类。这里,使用了一个朴素贝叶斯分类器。基本上,分类器查看已经标记的内容,执行术语提取,并使用术语和标签作为输入来训练自己。然后,对于新内容,分类器将根据内容提取的术语提供标签建议。
根据提取的术语找到类似内容的实用工具。
聚类器,可以在没有内容分类先验知识的情况下,根据特征相似性将内容分组。目前使用的是NLTK的k-means聚类器。
安装与设置
在运行buildout之前,请确保已安装yaml及其Python绑定(在OSX上使用macports,或在Linux上使用您的包安装程序)。如果您的操作系统上存在nltk,您也可以安装它,否则它将在运行buildout时被获取。
要开始使用,您只需将包添加到“eggs”部分,并运行buildout,重新启动Plone实例,并使用快速安装程序或通过“站点设置”中的“附加产品”部分安装“collective.classification”包。
警告:首次安装时,将从NLTK的存储库获取语言数据并将其存储在您的文件系统上本地。它并不大(约400kb),但需要plone用户有权访问其“家”。运行测试还将从nltk获取更多数据,总大小约为225Mb,所以不是为磁盘空间小的人准备的。
如何使用它?
对于已解析的文档,您可以调用术语视图来显示已识别的术语(只需将@@terms附加到内容的URL后即可调用视图)。
为了使用分类器并为某些内容获取建议标签,您可以在内容上调用@@suggest-categories。这相当于在浏览器中附加@@suggest-categories到URL。将出现一个表单,提供建议,选择看起来合适的,并应用。您需要有权编辑文档才能调用视图。
您可以根据其术语找到某些内容的类似内容,通过调用@@similar-items视图。
对于聚类,您只需从任何地方调用@@clusterize视图。结果不是确定性的,但希望能有所帮助;)。您需要管理员权限才能进行此操作,以免允许您的用户对您的站点进行DDoS攻击!
集成测试
在这里,我们将使用布朗语料库的样本测试分类器。布朗语料库包含一系列带有词性标注的英语文章,这些文章也被方便地分类。测试包括使用每个类别(新闻、社论和爱好)中的20篇文章来训练分类器。然后我们将要求分类器对每个类别中的5篇文章进行分类,看看会发生什么。
现在我们可以开始添加文档,从布朗语料库中按类别“新闻”分类的前20篇文档开始。
>>> from nltk.corpus import brown >>> for articleid in brown.fileids(categories='news')[:20]: ... text = " ".join(brown.words(articleid)) ... id = self.folder.invokeFactory('Document',articleid, ... title=articleid, ... text=text, ... subject='news')
接着是按类别“社论”分类的20篇文档
>>> for articleid in brown.fileids(categories='editorial')[:20]: ... text = " ".join(brown.words(articleid)) ... id = self.folder.invokeFactory('Document',articleid, ... title=articleid, ... text=text, ... subject='editorial')
最后是按类别“爱好”分类的20篇文档
>>> for articleid in brown.fileids(categories='hobbies')[:20]: ... text = " ".join(brown.words(articleid)) ... id = self.folder.invokeFactory('Document',articleid, ... title=articleid, ... text=text, ... subject='hobbies')
所有这些文档都应该被解析并索引
>>> catalog = self.folder.portal_catalog >>> sr = catalog.searchResults(noun_terms='state') >>> len(sr) > 5 True
让我们看看第一个“社论”内容中我们得到了哪些术语
>>> browser = self.getBrowser() >>> browser.open(self.folder.absolute_url()+'/cb01/@@terms') >>> browser.contents '...state...year...budget...war...danger...nuclear war...united states...'
核战争和美国?令人恐惧的事情……现在是训练分类器的时候了
>>> from zope.component import getUtility >>> from collective.classification.interfaces import IContentClassifier >>> classifier = getUtility(IContentClassifier) >>> classifier.train() >>> classifier.tags() ['editorial', 'hobbies', 'news']
首先,当被询问已分类的文本时,分类器应该相当确信
>>> browser.open(self.folder.absolute_url()+'/ca01/@@suggest-categories') >>> browser.contents '...news 100.0%...editorial 0.0%...hobbies 0.0%...'
所以让我们看看这会带我们到哪儿,通过要求分类器对5篇我们知道类别的更多文档进行分类。我们将直接使用分类器的函数,而不是将文档添加到plone并调用@@suggest-categories视图。首先是“新闻”
>>> classificationResult = [] >>> for articleid in brown.fileids(categories='news')[20:25]: ... text = " ".join(brown.words(articleid)) ... id = self.folder.invokeFactory('Document',articleid, ... text=text) ... uid = self.folder[id].UID() ... classificationResult.append(classifier.classify(uid)) >>> classificationResult ['news', 'news', 'news', 'news', 'news']
让我们看看我们对“社论”的表现如何
>>> classificationResult = [] >>> for articleid in brown.fileids(categories='editorial')[20:25]: ... text = " ".join(brown.words(articleid)) ... id = self.folder.invokeFactory('Document',articleid, ... text=text) ... uid = self.folder[id].UID() ... classificationResult.append(classifier.classify(uid)) >>> classificationResult ['editorial', 'editorial', 'editorial', 'editorial', 'editorial']
太棒了!关于“爱好”呢?
>>> classificationResult = [] >>> for articleid in brown.fileids(categories='hobbies')[20:25]: ... text = " ".join(brown.words(articleid)) ... id = self.folder.invokeFactory('Document',articleid, ... text=text) ... uid = self.folder[id].UID() ... classificationResult.append(classifier.classify(uid)) >>> classificationResult ['hobbies', 'hobbies', 'editorial', 'hobbies', 'hobbies']
还不错!总的来说:我们对了14/15个…
现在让我们再次选择第一个社论项目,并根据我们提取的术语查看哪些文档与它相似
>>> browser.open(self.folder['cb01'].absolute_url()+'/@@similar-items')
最相似的条目(Jaccard指数约为0.2)是cb15
>>> browser.contents '...cb15...0.212121212121...'
让我们看看它们的共同术语是什么
>>> cb01terms = catalog.searchResults( ... UID=self.folder['cb01'].UID())[0].noun_terms[:20] >>> cb15terms = catalog.searchResults( ... UID=self.folder['cb15'].UID())[0].noun_terms[:20] >>> set(cb01terms).intersection(set(cb15terms)) set(['development', 'state', 'planning', 'year', 'area'])
这是可以接受的,因为两篇文档都谈论发展和预算规划…
关于统计信息呢?我们可以调用@@stats视图来找出…
>>> self.setRoles('Manager') >>> browser.open(self.folder.absolute_url()+'/@@classification-stats') >>> browser.contents '...state...True...editorial:hobbies...5.0...'
这基本上告诉我们,如果单词“国家”存在,分类器给出5比1的概率,内容属于“社论”类别而不是“爱好”类别
0.1b2
完全删除了持久的名词存储。现在名词和名词短语术语直接存储在目录中,使用plone.indexer。[ggozad, stefan]
使用BTrees代替PersistentDict。应该会使ZODB的写入更轻量。[ggozad]
名词短语语法和规范化现在成为语言相关标记器的属性。[ggozad]
删除了大量的控制面板功能。不需要混淆。[ggozad]
修复了荷兰语言支持。[ggozad]
0.1b1
通过不再利用PenTreeBank标记器,提高了速度。[ggozad]
添加了多语言支持,从荷兰开始![ggozad]
不再需要下载所有语料库了。[ggozad]
大量重构。东西被移动,并删除了大量不必要的代码。[ggozad]
我们现在使用一个预训练的Brill/Trigram/Affix标记器。这使得collective.classification能够在不包含所有语料库的情况下发货。如果需要,用户仍可以提供不同的标记器。[ggozad]
默认的nltk PenTreeBank标记器不再使用。太慢了。[ggozad]
npextractor不再是一个本地持久性实用程序。选择了全局非持久性对象。[ggozad]
现在使用zope.lifecycle事件。[ggozad]
与plone 4兼容。[ggozad]
0.1a3
引入了IClassifiable接口。ATContentTypes现在适应了它,应该更容易添加其他非AT内容类型或自定义适配器。[ggozad]
处理IObjectRemovedEvent事件。[ggozad]
添加了一个表单,用于从布朗语料库导入样本内容,用于调试和测试。[ggozad]
添加了一些统计信息,通过@@classification-stats。显示了解析的文档数以及最有用的术语。[ggozad]
添加了@@terms视图,允许用户检查某些内容的识别术语。[ggozad]
在训练n-gram标记器时必须指定语料库类别。修复#3 [ggozad]
0.1a2
使控制面板更合理。修复#1。[ggozad]
NP-extractor已成为本地持久性实用程序。[ggozad]
将 @@subjectsuggest 重命名为 @@suggest-categories。修复 #2。[ggozad]
“memoized”术语提取器。[ggozad]
向控制面板添加了友好的类型。[ggozad]
更新了文档和依赖项,以警告关于yaml。[ggozad]
0.1a1
首次公开发布。[ggozad]
项目详情
collective.classification-0.1b2.zip的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | fdbb573fa2ae81b641d96a90744c1f67a41c6500d82f4da16b486f4f1c3d53e8 |
|
MD5 | fdcd6b1ba0ffbb37aff51135eb524c04 |
|
BLAKE2b-256 | e99ad1da0ed1bf2f40220ae5cb7f1446888b5ee09283389e58d556261e4acc2f |