Python 用SpaCy从德语句子中提取主句和子句

Python 用SpaCy从德语句子中提取主句和子句,python,nlp,spacy,Python,Nlp,Spacy,在德语中,如何从一个有空格的句子中提取主句和子句(又名“从句”、“从属从句”) 我知道如何使用SpaCy的标记器、词性标记和依存关系解析器,但我不知道如何使用SpaCy可以提取的信息来表示德语的语法规则。这个问题可以分为两个任务:1。将句子分为构成从句和2。确定哪些条款是主条款,哪些是子条款。由于关于分句和主句的结构差异有非常严格的语法规则,我将采用基于规则的方法 分句 子句包含限定动词。在德语中,子条款用逗号(“,”)与它们所依赖的“支配”条款(主条款或另一子条款)分开。主句与其他主句之间可以

在德语中,如何从一个有空格的句子中提取主句和子句(又名“从句”、“从属从句”)


我知道如何使用SpaCy的标记器、词性标记和依存关系解析器,但我不知道如何使用SpaCy可以提取的信息来表示德语的语法规则。

这个问题可以分为两个任务:1。将句子分为构成从句和2。确定哪些条款是主条款,哪些是子条款。由于关于分句和主句的结构差异有非常严格的语法规则,我将采用基于规则的方法

分句 子句包含限定动词。在德语中,子条款用逗号(“,”)与它们所依赖的“支配”条款(主条款或另一子条款)分开。主句与其他主句之间可以用逗号分隔,也可以用其中一个连词“und”、“order”、“aber”和“sondern”分隔(如果两个主句用“und”或“order”连接,则省略逗号)

这就是为什么我们可能想到这个想法,用逗号和“und”/“order”/“aber”/“sondern”将句子分成几块。但这给我们留下了一个问题,例如逗号分隔的部分不存在子句(想想枚举或同位语),以及“und”和“order”并不总是表示新子句的开始(想想枚举)。此外,我们可能会遇到这样的情况,子类开头的逗号被省略了。即使这违反了德语的(规范性)语法规则,我们仍然希望正确识别这些子条款

这就是为什么最好从句子中的有限动词开始,使用spacy的依赖解析器。我们可以假设,每个限定动词都是它自己子类的一部分。所以我们可以从一个限定动词开始,遍历它的“子代”(它的子代和它们的子代,等等)。当它遇到另一个限定动词时,就需要停止行走——因为这将是另一个子句的根

然后,我们只需要将这一步的路径组合成一个短语。这需要考虑到一个子句可以由多个跨度组成——因为一个子句可以被一个子子句分割(考虑与主子句中的对象相关的关系子句)

确定一个子句是主子句还是子子句 从语法上讲,在德语中,子类可以通过限定动词位于最后一个位置来识别,这在主句中是不可能的

因此,我们可以利用spacy的词性标签来解决这个问题。 我们可以区分不同的动词标记,无论动词形式是有限的还是无限的,我们可以很容易地检查子句中的最后一个标记(标点符号之前)是有限的还是无限的动词形式

代码
按需要导入itertools
作为tp导入键入
进口空间
动词_POS={“动词”,“辅助词”}
有限动词标记={“VVFIN”、“VMFIN”、“VAFIN”}
类别条款:
定义初始化(self,Span:tp.Iterable[“spacy.tokens.Span]”):
“”“子句是一个可能划分的跨距序列。
这个类基本上将子句标识为子类和子类
提供不带
逗号源于插入的子类。
一个子句可以由多个未连接的跨距组成,因为
子条款可以划分它们所依赖的子句。这就是
为什么一个子句不能仅仅由一个跨度构成,而是
必须基于可测量的跨度。
"""
self.span=跨度
@财产
定义链(self)->tp.Iterable[“spacy.tokens.Token”]:
return[it.chain(*self.span)中令牌的令牌]
#我们使这个类成为令牌的迭代器,以便
#模仿跨度行为。这就是我们所需要的
#dunder方法的应用。
def uu getitem uu(self,index:int)->“spacy.tokens.Token”:
返回自。\u链[索引]
定义iter(self)->tp.迭代器:
self.n=0
回归自我
定义下一个(自我)->“spacy.tokens.Token”:
self.n+=1
尝试:
返回自我[self.n-1]
除索引器外:
提出停止迭代
定义报告(自我)->str:
返回“.join”([self.internal\u span中span的span.text])
@财产
def是子条款(自身)->bool:
“”“子句是有限动词位于最后位置时的子类。”“”
返回(
self[-2]。有限动词标记中的标记
如果self[-1]。位置==“点”
else self[-1]。在有限动词标记中标记
)
@财产
def子句_类型(自身)->str:
如果self.is\u subcase else“MAIN”,则返回“SUB”
@财产
def internal_Span(self)->tp.List[“spacy.tokens.Span”]:
“”从范围边界删除标点符号的范围。”“”
内部_跨度=[]
对于self.span中的span:
span=span[1:]如果span[0]。位置==“点”否则span
span=span[:-1]如果span[-1]。位置==“点”否则span
内部_span.append(span)
返回内弧段
类别子句句子(spacy.tokens.Span):
“”Span,具有提取的子句结构。
此类用于标识限定动词的位置,以
标识属于每个有限元素周围的子句的所有标记
动词和使每个子句成为宾语。
"""
@财产
定义有限动词索引(self)->tp.List[int]:
return[token.i表示self中的token,如果token.tag uu表示有限动词u标记]
def子代(
自己
索引:int,
停止索引:tp.可选[tp.列表[int]]=None,
)->tp.List[“spacy.tokens.Token”]:
“”“遍历子代树,直到满足停止索引。”“”
如果停止指数为无:
停止指数=[]
MAIN: Angela Merkel, die deutsche Bundeskanzlerin, hat nicht erneut für den Vorsitz ihrer Partei kandidiert, 
SUB: obwohl sie stets der Auffassung war, 
MAIN: Kanzlerschaft und Parteivorsitz würden in eine Hand gehören.