基于词性标注(POS tagging)筛选介词邻近词
从词元-词性标注列表中筛选介词附近的名词及描述性词汇
嘿,这个需求其实很好实现,咱们一步步来拆解。核心目标很明确:先定位所有介词的位置,再抓取它们前后的名词、形容词、动词(跳过冠词这类无关词)。
先明确数据结构(举个实际例子)
假设你的标注数据是类似这样的结构化列表(以Python为例,你可以根据自己用的工具调整格式):
token_pos = [ ("The", "DT"), ("glistening", "JJ"), ("oranges", "NN"), ("rest", "VB"), ("on", "IN"), ("the", "DT"), ("rectangular", "JJ"), ("angular", "JJ"), ("table", "NN") ]
这里IN是Penn Treebank标注体系里的介词标签,如果你用的是spaCy这类工具,介词标签会是ADP,记得对应调整。
核心实现思路
- 先定义好要抓取的目标词性(名词、形容词、动词)、介词词性,以及要跳过的无关词性(比如冠词
DT) - 遍历整个标注列表,定位到每个介词的位置
- 对每个介词,分别向前、向后扫描,收集符合条件的词汇,遇到非目标/非跳过的词就停止扫描(避免抓取太远的无关内容)
具体代码实现(Python)
# 定义要收集的目标词性:形容词、动词、名词(根据你的标注体系调整标签) target_pos = {"JJ", "JJR", "JJS", "VB", "VBD", "VBG", "VBN", "VBP", "VBZ", "NN", "NNS", "NNP", "NNPS"} # 介词的词性标签(根据你的标注工具调整,比如spaCy用"ADP") prep_pos = {"IN"} # 要跳过的无关词性:比如冠词 skip_pos = {"DT"} # 存储结果:键是介词,值是它附近的目标词汇 nearby_words = {} # 遍历所有词元-词性对 for idx, (token, pos) in enumerate(token_pos): # 找到介词的位置 if pos in prep_pos: current_nearby = [] # 向前扫描,直到遇到非目标/非跳过词 for i in range(idx - 1, -1, -1): t, p = token_pos[i] if p in skip_pos: continue if p in target_pos: current_nearby.append(t) else: break # 遇到无关词性,停止向前扫 # 向后扫描,直到遇到非目标/非跳过词 for i in range(idx + 1, len(token_pos)): t, p = token_pos[i] if p in skip_pos: continue if p in target_pos: current_nearby.append(t) else: break # 遇到无关词性,停止向后扫 # 把结果存起来 nearby_words[token] = current_nearby # 打印结果 print(nearby_words) # 输出:{'on': ['glistening', 'oranges', 'rest', 'rectangular', 'angular', 'table']}
几个关键细节要注意
- 词性标签适配:不同NLP工具的词性标签体系不一样!比如NLTK用Penn Treebank标签(介词
IN),spaCy用Universal Dependencies标签(介词ADP),你得根据自己的数据集调整prep_pos和target_pos里的标签。 - 扫描范围自定义:上面的代码是扫到第一个无关词就停,如果你想固定扫前后N个词,比如前后各扫3个,直接把循环改成固定步数就行,不用判断词性停止。
- 去重需求:如果同一个词多次出现在介词附近,你可以用
current_nearby = list(set(current_nearby))快速去重(不过会打乱顺序,要是在意顺序就用其他方法)。
刚好你的例子里,介词on前后的glistening(形容词)、oranges(名词)、rest(动词)、rectangular(形容词)、angular(形容词)、table(名词)都会被精准抓到,完全符合你的预期~
内容的提问来源于stack exchange,提问作者sparkh2o




