约定一下文中使用的一些词的含义:
- 文章:一般来说,一篇文章具有一个标题、一个或多个段落组成,其他的我们暂时不考虑。
- 段落:一篇文章可以根据缩进(有些可能不存在缩进)或回车换行,将文章分成多个段,而每段是由数个句子组成。
- 片段:片段是由一个或者多个段落组成,但是片段最多不能大于一篇文章的全部段落数,我们限定在一篇文章之内。
对于给定的一篇文章,它到底在围绕哪一个主题(或哪几个主题)进行描述,我们在实际生活中经常会遇到。我们在读小学的时候,老师教我们给文章分段并归纳段落大意,其实,这就是在考虑基于文章段落之间的关系和语义内容对整个文章进行划分,得到的结果是确定某一些连续的段落属于某一个主题。如果一篇文章段落很多,而且根据标题可以确定具有一个主题A,那么这篇文章仍然可以在主题A的范畴内,继续提炼出多个子主题集合{A1, A2, ..., An},也就是说文章仍然是可分的。
上面讲述的是给定一篇文章,根据文章内容抽取出具有多个主题的段落,你可能很容易想到,这就是数据挖掘中的聚类分析:把具有相同特征(主题)的一些连续的段落聚集成一个类,而不去限定类别是什么,可能你根本也不知道能划分成哪些“基于一定主题”的文章片段,也可能不同的文章片段之间出现重叠的段落。在实际中,可能存在这样的应用场景。
但是,在实际中更多的是,基于给定一个关键字词典,基于词典来对一篇文章进行主题划分:抽取出文章的某些段落作为一个片段,这个片段当当且仅当这一组段落在讲述某一个主题时才成立。一个主题通常可以由一个词向量来表达,例如主题“体育运动”可以由词向量(足球, 篮球, 排球 ,网球 , 跑步, NBA)来表达,文章的某些段落中在讲述词向量中词项描述的内容时,基本可以认为在讲述给定的主题。词向量是否足够丰富地表达主题,这就要看你应用需求和你的词典中词项的分布情况。我们分析一下:存在“主题-词向量”词典,也就是说在分析文章的时候,它的类标签只限定于给定的主题词典,实际上这是分类,基于文章内容对文章的多个片段进行分类,而待分类的文章片段需要基于某些启发式信息(或经过预处理的元数据)进行抽取。
我们讨论下面两个问题:
- 第一个:获取主题信息困难
你在看一篇字数很长的文章的时,如果你是想快速获取到你想知道的某一个主题内容,那你必须读过整篇文章之后,才知道哪些段落在讲述这个主题。很有可能一篇文章有50多段,但是描述你想要的主题的只有其中的2~3段,这是你要花费时间浏览很多不相关的信息。如果这篇文章正是你展现给用户的信息,那么这种信息太没有价值了(虽然某些段落可能是精华,但对用户来说不次于垃圾信息),用户体验相当的差:用户可能在浏览的过程中对主题的关注度已经分散了,可能因此而离开你的提供数据的网站——用户流失。
- 第二个:主题相关信息不连贯
书面表达中句与句之间的组合与衔接问题,保持语言连贯,需要兼顾话题(有共同的话题)、语序(合理的语序)和语言的运用(语言的衔接与呼应)三个方面还要注意语境、句式的协调一致。
1、话题统一
指组成段落的句子间,或是组成复句的分句间,有紧密联系,围绕着一个中心,集中表现一个事实、场景、或思想观点,无关的话不掺杂在一起。
(1)陈述对象一致。
(2)观点和材料的统一。
2、句式前后一致(照应)
能收到形势整齐,音节和谐、气势贯通的修辞效果。
(1)句式要协调一致。指一组句子中几个句子的句式要大体相同,读来才琅琅上口,语气连贯或相互对应。
(2)要有必要的过渡、交待、衔接、呼应。恰当的使用关联词语及比照式的词语。
3、合乎事理、语境
(1)意思表达要合乎客观事例,否则,上下句在事理上出现了“裂痕”,衔接不上。
(2)表达要合乎语境。对于写景的复句和语段,要注意语境因素,要分析景物、情调、写法的特点。景物有远近动静不同;色彩有鲜明、暗淡之分,气氛有热烈凄清;视角有高低俯仰之异;态度或褒或贬。要保持和谐一致。
4、语序合理
(1)时间顺序。按陈述内容的时间先后作为排列顺序。(多用于记叙文)
(2)空间顺序。按照空间的上下、左右、外内等顺序。(多用于描写、说明性文字)
(3)逻辑顺序。一是人们对客观事物的认识顺序,如现象本质、个别一般、浅深、感性理性等;二是客观事物固有的内部逻辑,因果、轻重。
为了简化问题,我们考虑语义连贯性的如下几个要素:
- 兼顾话题: 上面已经说过,通过主题及其主题相关词向量来表达,可以考虑主题相关词向量中的词项的出现频率,对片段的边缘段落加权并向两侧扩展段落;
- 保持语序: 虽然包含主题词片段中某些段落之间不连续,例如段落A和C被抽取出来,但是B中不包含主题词,但是可以根据段落B的一些特征(如长度、包含图片)来选择,将B加入到这个片段的段落组中,使片段中个段落之间语义连贯。
基本思想
我们要实现的基于语义连贯性,对文章的片段进行挖掘(对选择的段落进行组合),主要是基于如下几点:
- 建立自己的领域词典D:用来描述主题的词条(词向量)
- 对文章进行分词,获取一篇文章中存在的且出现在词典中的关键词集合S
- 根据关键词集合S中的每一个词,对整篇文章中的各个段落(有序)进行匹配,不考虑词频(TF)影响
- 设定语义连贯性标准:如果按照文章段落顺序(序号),对序号i和序号j,若j-i<maxParagraphGap,则认为i和j两段连续(maxParagraphGap可以调整)
- 语义连贯性扩展:如果一篇文章段落序号序列{0, 1, 2, ... , x, x+1, x+2, ..., y, y+1, ..., N},如果x-0<maxParagraphGap且N-y<maxParagraphGap,则选择整篇文章作为一个段落,亦即,整篇文章都在描述一个主题
- 基于关键词集合S中的每一个关键词,在一篇文章抽取一组片段F={f1, f2, ... , fn},这组片段的选择标准:对F中的片段对应的每个段落集合{P1, P2, ... , Pm},统计段落数为n,一篇文章总段落数N,计算抽取出来的所有段落的覆盖率,可以设定一个阙值Coverage=n/N
程序实现
package org.shirdrn.ie.travel;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.CharTermAttributeImpl;
import com.chenlb.mmseg4j.Dictionary;
import com.chenlb.mmseg4j.analysis.ComplexAnalyzer;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import org.shirdrn.common.DBConfig;
/**
* Article analysis tool.
*
* @author shirdrn
* @date 2011-12-13
*/
public class ArticleAnalyzeTool {
private static final Logger LOG = Logger.getLogger(ArticleAnalyzeTool.class);
private Analyzer analyzer;
private String dictPath;
private String wordsPath;
/** 自定义关键字词典:通常是根据需要进行定向整理的 */
private Set<String> wordSet = new HashSet<String>();
private DBConfig articleConfig;
private MongodbAccesser accesser;
/** 最小段落内容长度限制 */
private int globalMinParagraphLength = 3;
/** 最大段落间隔