go-ego/gse 中的 TextRank 关键词提取算法解析
2025-07-10 07:57:02作者:董斯意
什么是 TextRank 算法
TextRank 是一种基于图的排序算法,它借鉴了 Google 的 PageRank 算法思想,用于文本中的关键词提取和文本摘要生成。在 go-ego/gse 项目中,TextRank 算法被实现为一个独立的功能模块,专门用于从中文文本中提取重要的关键词。
TextRanker 结构体解析
在 go-ego/gse 中,TextRank 算法的核心实现位于 TextRanker
结构体中:
type TextRanker struct {
seg pos.Segmenter
HMM bool
}
seg
: 分词器,用于对文本进行分词处理HMM
: 布尔值,表示是否使用隐马尔可夫模型进行分词
核心功能实现
1. 图的构建
TextRank 算法首先需要构建一个无向加权图,图中的节点代表词语,边代表词语之间的共现关系:
type undirectWeightedGraph struct {
graph map[string]edges
keys sort.StringSlice
}
graph
: 存储图的邻接表结构keys
: 存储所有节点的有序列表
2. 边的添加
通过 addEdge
方法向图中添加边:
func (u *undirectWeightedGraph) addEdge(start, end string, weight float64) {
// 双向添加边,构建无向图
}
3. 排名计算
核心的排名计算在 rank
方法中实现:
func (u *undirectWeightedGraph) rank() segment.Segments {
// 初始化权重
ws := make(map[string]float64)
outSum := make(map[string]float64)
// 迭代计算权重
for x := 0; x < 10; x++ {
for _, n := range u.keys {
// 计算每个节点的权重
}
}
// 归一化处理
// 返回排序后的结果
}
关键词提取流程
1. 文本分词
使用分词器对输入文本进行分词处理:
pairs = append(pairs, t.seg.Cut(text, true)...)
2. 词性过滤
只保留指定词性的词语(默认包括名词、地名、动词等):
posFilt := make(map[string]int)
for _, pos1 := range allowPOS {
posFilt[pos1] = 1
}
3. 共现矩阵构建
统计词语在一定窗口大小(默认为5)内的共现关系:
for i := range pairs {
if _, ok := posFilt[pairs[i].Pos]; ok {
for j := i + 1; j < i+span && j < len(pairs); j++ {
// 统计共现次数
}
}
}
4. 图构建与排名
将共现关系转化为图的边,然后进行排名计算:
g := newUndirectWeightedGraph()
for startEnd, weight := range cm {
g.addEdge(startEnd[0], startEnd[1], weight)
}
tags := g.rank()
使用示例
基本用法
tr := &TextRanker{}
tr.LoadDict() // 加载词典
keywords := tr.TextRank("这是一段需要提取关键词的文本", 10) // 提取前10个关键词
自定义词性过滤
allowPOS := []string{"n", "ns", "vn"} // 只提取名词、地名和动名词
keywords := tr.TextRankWithPOS(text, 5, allowPOS) // 提取前5个关键词
算法参数调优
- 窗口大小(span): 默认为5,可以调整以改变词语共现的范围
- 阻尼系数(dampingFactor): 默认为0.85,影响权重传递的效果
- 迭代次数: 目前固定为10次,可根据需要调整
- 允许的词性列表: 默认包括名词、地名、动词等
性能优化建议
-
对于大规模文本处理,可以考虑:
- 预处理时过滤停用词
- 调整窗口大小以减少图的规模
- 使用更高效的数据结构存储图
-
对于特定领域文本:
- 加载领域专用词典
- 调整允许的词性列表以适应领域特点
总结
go-ego/gse 中的 TextRank 实现提供了一个高效、可配置的关键词提取工具。通过合理的参数调整和词典配置,可以适应不同领域和场景的关键词提取需求。该实现充分利用了 Go 语言的特性,在性能和易用性之间取得了良好的平衡。