自然语言处理工具hanlp关键词提取图解TextRank算法

发布者:上海IT外包来源:http://www.lanmon.net点击数:761

TextRank是在Google的PageRank算法启发下,针对文本里的句子设计的权重算法,方针是主动择要。它把持投票的事理,让每一个单词给它的邻人(术语称窗口)投同意票,票的权重取决于本身的票数。这是一个“先有鸡仍是先有蛋”的悖论,PageRank接纳矩阵迭代收敛的编制处理了这个悖论。 本博文经由过程 hanlp关头词提取的一个Demo,并经由过程图解的编制来讲解TextRank的算法。

1 //长句子

2 String content = "轨范员(英文Programmer)是处置轨范开发、维护的专业人员。" +

3 "一样平常将轨范员分为轨范设计人员和轨范编码人员," +

4 "但两者的鸿沟并不很是清楚,特别是在中国。" +

5 "软件从业人员分为低级轨范员、高级轨范员、体系" +

6 "分析员和项目司理四大类。";

末了提取的关头词是: [轨范员, 轨范, 分为, 人员, 软件]

下面来分析为什么会提掏出这5个关头词

第一步:分词

把 content 经由过程一个的分词算法停止分词,这里接纳的是Viterbi算法也就是HMM算法 分词后(固然首先应把停用词、标点、副词之类的去除)的成效是:

[轨范员, 英文, Programmer, 处置, 轨范, 开发, 维护, 专业, 人员, 轨范员, 分为, 轨范, 设计, 人员, 轨范, 编码, 人员, 鸿沟, 并不, 很是, 清楚, 特别是在, 中国, 软件, 从业人员, 分为, 轨范员, 高级, 轨范员, 体系分析员, 项目司理, 四大]

第二步:机关窗口

hanlp的实当代码如下:

Map> words = new TreeMap>();

Queue que = new LinkedList();

for (String w : wordList)

{

if (!words.containsKey(w))

{

words.put(w, new TreeSet());

}

// 复杂度O(n-1)

if (que.size() >= 5)

{

que.poll();

}

for (String qWord : que)

{

if (w.equals(qWord))

{

continue;

}

//既然是邻人,那么关系是互相的,遍历一遍即可

words.get(w).add(qWord);

words.get(qWord).add(w);

}

que.offer(w);

}

这个代码的功能是为分个词机关窗口,这个词前后各四个词就是这个词的窗口,如词分词后一个词出现了屡次,像 [轨范员],那就是把每次出现取一次窗口,然后把各次成效合并去重,末了成效是: 轨范员 =[Programmer, 专业, 中国, 人员, 从业人员, 处置, 分为, 四大, 开发, 轨范, 体系分析员, 维护, 英文, 设计, 软件, 项目司理, 高级]。 末了形成的窗口:

1 Map> words =

2

3 {Programmer=[处置, 开发, 轨范, 轨范员, 维护, 英文], 专业=[人员, 处置, 分为, 开发, 轨范, 轨范员, 维护], 中国=[从业人员, 分为, 并不, 清楚, 特别是在, 轨范员, 软件, 很是], 人员=[专业, 分为, 并不, 开发, 清楚, 鸿沟, 轨范, 轨范员, 维护, 编码, 设计, 很是], 从业人员=[中国, 分为, 清楚, 特别是在, 轨范员, 软件, 高级], 处置=[Programmer, 专业, 开发, 轨范, 轨范员, 维护, 英文], 分为=[专业, 中国, 人员, 从业人员, 特别是在, 轨范, 轨范员, 体系分析员, 维护, 设计, 软件, 高级], 四大=[轨范员, 体系分析员, 项目司理, 高级], 并不=[中国, 人员, 清楚, 特别是在, 鸿沟, 轨范, 编码, 很是], 开发=[Programmer, 专业, 人员, 处置, 轨范, 轨范员, 维护, 英文], 清楚=[中国, 人员, 从业人员, 并不, 特别是在, 鸿沟, 软件, 很是], 特别是在=[中国, 从业人员, 分为, 并不, 清楚, 鸿沟, 软件, 很是], 鸿沟=[人员, 并不, 清楚, 特别是在, 轨范, 编码, 很是], 轨范=[Programmer, 专业, 人员, 处置, 分为, 并不, 开发, 鸿沟, 轨范员, 维护, 编码, 英文, 设计], 轨范员=[Programmer, 专业, 中国, 人员, 从业人员, 处置, 分为, 四大, 开发, 轨范, 体系分析员, 维护, 英文, 设计, 软件, 项目司理, 高级], 体系分析员=[分为, 四大, 轨范员, 项目司理, 高级], 维护=[Programmer, 专业, 人员, 处置, 分为, 开发, 轨范, 轨范员], 编码=[人员, 并不, 鸿沟, 轨范, 设计, 很是], 英文=[Programmer, 处置, 开发, 轨范, 轨范员], 设计=[人员, 分为, 轨范, 轨范员, 编码], 软件=[中国, 从业人员, 分为, 清楚, 特别是在, 轨范员, 很是, 高级], 很是=[中国, 人员, 并不, 清楚, 特别是在, 鸿沟, 编码, 软件], 项目司理=[四大, 轨范员, 体系分析员, 高级], 高级=[从业人员, 分为, 四大, 轨范员, 体系分析员, 软件, 项目司理]}

第三步:迭代投票

每个词末了的投票得分由这个词的窗口停止屡次迭代投票抉择,迭代的竣事前提就是大于最大迭代次数这里是 200次,或者两轮之前某个词的权重小于某一值这里是0.001f。看下代码:

Map score = new HashMap();

//按照TF来设置初值

for (Map.Entry> entry : words.entrySet()){

score.put(entry.getKey(),sigMoid(entry.getValue().size()));

}

System.out.println(score);

for (int i = 0; i < max_iter; ++i)

{

Map m = new HashMap();

float max_diff = 0;

for (Map.Entry> entry : words.entrySet())

{

String key = entry.getKey();

Set value = entry.getValue();

m.put(key, 1 - d);

for (String element : value)

{

int size = words.get(element).size();

if (key.equals(element) || size == 0) continue;

m.put(key, m.get(key) + d / size * (score.get(element) == null ? 0 : score.get(element)));

}

max_diff = Math.max(max_diff, Math.abs(m.get(key) - (score.get(key) == null ? 0 : score.get(key))));

}

score = m;

if (max_diff <= min_diff) break;

}

System.out.println(score);

return score;

}

投票的事理拿 Programmer=[处置, 开发, 轨范, 轨范员, 维护, 英文],这个词来声名,Programmer末了的得分是由[处置, 开发, 轨范, 轨范员, 维护, 英文],这6个词依次投票抉择的,每个词投出去的分数是和他本身的权重相干的。

1、投票起头前每个词初始化了一个权重, score.put(entry.getKey(),sigMoid(entry.getValue().size())),这个权重是0到1之间,公式是

1 //value是每个词窗口的巨细

2 public static float sigMoid(float value) {

3 return (float)(1d/(1d+Math.exp(-value)));

4 }

这个函数的公式和图像如下 ,由于value必定是大于0的,所以sigMod值属于(0,1)



初始化后的分词是: {特别是在=0.99966466, 轨范员=0.99999994, 编码=0.99752736, 四大=0.98201376, 英文=0.9933072, 很是=0.99966466, 鸿沟=0.99908894, 体系分析员=0.9933072, 从业人员=0.99908894, 轨范=0.99999774, 专业=0.99908894, 项目司理=0.98201376, 设计=0.9933072, 处置=0.99908894, Programmer=0.99752736, 软件=0.99966466, 人员=0.99999386, 清楚=0.99966466, 中国=0.99966466, 开发=0.99966466, 并不=0.99966466, 高级=0.99908894, 分为=0.99999386, 维护=0.99966466}

停止迭代投票,第一轮投票, [Programmer, 专业, 中国, 人员, 从业人员, 处置, 分为, 四大, 开发, 轨范, 体系分析员, 维护, 英文, 设计, 软件, 项目司理, 高级]依给次*轨范员*投票,得分如下:

[Programmer]给[轨范员]投票后,[]轨范员]的得分:



[专业]给[轨范员]投票



如许 [Programmer, 专业, 中国, 人员, 从业人员, 处置, 分为, 四大, 开发, 轨范, 体系分析员, 维护, 英文, 设计, 软件, 项目司理, 高级]依次给[轨范员]投票,投完票后,再给其它的词停止投票,本轮竣事后,断定是否到达最大迭代次数200或两轮之间分数差值小于0.001,若是满足则竣事,不然继续停止迭代。

末了的投票得分是: {特别是在=1.0015739, 轨范员=2.0620303, 编码=0.78676623, 四大=0.6312981, 英文=0.6835063, 很是=1.0018439, 鸿沟=0.88890904, 体系分析员=0.74232763, 从业人员=0.8993066, 轨范=1.554001, 专业=0.88107216, 项目司理=0.6312981, 设计=0.6702926, 处置=0.9027207, Programmer=0.7930236, 软件=1.0078223, 人员=1.4288887, 清楚=0.9998723, 中国=0.99726284, 开发=1.0065585, 并不=0.9968608, 高级=0.9673803, 分为=1.4548829, 维护=0.9946941},分数最高的关头词就是要提取的关头词

IT外包
>
400-635-8089
立即
咨询
电话咨询
服务热线
400-635-8089
微信咨询
微信咨询
微信咨询
公众号
公众号
公众号
返回顶部