由NER模型发现的实体的匿名化

我试图通过德语文本的NER模型来匿名文件,这些文本有时可能有几个英语单词.如果我采用德语和英语的Spacy NER模型,如de_core_News_sm和en_core_web_sm,它们会找到城镇名称或人,至少英语模型会找到"Dezember 2022",但它没有找到像"15.Dezember 2022"这样的完整日期.

更改实体识别

我不能更改模型的火柴.我认为我可以使用实体标尺来更改NER模型,但NER模型似乎是固定的,我不知道我自己的实体标尺如何才能超过Spacy NER模型,也不知道如何才能让任何实体标尺工作,即使我禁用了NER模型.我在Spacy管道中将实体标尺移到了NER模型之前,但在输出中没有看到任何新的替换项.

简单的例子,主要来自Using the entity ruler岁的主要空格指南:

from spacy.lang.de import German

nlp = German()
ruler = nlp.add_pipe("entity_ruler")

patterns = [
    {"label": "DATE", "pattern": [               
        {"lower": {"regex": "(?:0?[1-9]|[12][0-9]|3[01])[\.\s]{1,2}?(jan(?:uar)?|feb(?:ruar)?|mär(?:z)?|apr(?:il)?|mai|jun(?:i)?|jul(?:i)?|aug(?:ust)?|sep(?:t(?:ember)?)?|okt(?:ober)?|nov(?:ember)?|dez(?:ember)?)\.?\s?['`]?\d{0,4}"}},
        {"shape": {"regex": "(?:0?[1-9]|[12][0-9]|3[01])[\.\s]{1,2}?(0?[1-9]|1[0-2])\.?\s?['`]?\d{0,4}"}},
        {"lower": {"regex": "(?:jan(?:uar)?|feb(?:ruar)?|mär(?:z)?|apr(?:il)?|mai|jun(?:i)?|jul(?:i)?|aug(?:ust)?|sep(?:t(?:ember)?)?|okt(?:ober)?|nov(?:ember)?|dez(?:ember)?)\.?\s?['`]?\d{2,4}"}},
        {"lower": {"regex": "(?:januar|feb(?:ruar)?|mär(?:z)?|apr(?:il)?|mai|jun(?:i)?|jul(?:i)?|aug(?:ust)?|sep(?:t(?:ember)?)?|okt(?:ober)?|nov(?:ember)?|dez(?:ember)?\.?)"}},
        {"shape": "dd"},
        {"TEXT": {"in": ["15"]}}
    ]},
    {"label": "ORG1", "pattern": {"LOWER": "apple"}},
    {"label": "GPE1", "pattern": {"LOWER": "san"}},
    {"label": "DATE1", "pattern": {"TEXT": [{"regex": "^(?:0?[1-9]|[12][0-9]|3[01])$"}]}}
]
ruler.add_patterns(patterns)

# Taking the German Dezember here for the test of the German RegEx
doc = nlp("Apple eröffnet ein Büro in San Francisco am 15. Dezember 2022.")

输出:

[]

问题

我是否可以围绕命名实体识别(NER)空间模型编写代码,以捕获更多的日期模式(也作为日期实体),以便这将超过NER模型的 Select ?

其目的是将完整的"15.Dezember2022"作为一个日期实体找到.


PS

复制?

我找到了spacy how to add patterns to existing Entity ruler?,它告诉我重新训练自定义实体标尺,不要添加模式,因为提问者已经训练了NER模型:

我有一个现有的经过培训的定制NER模型,带有NER和实体标尺 管子.我想更新和重新培训这条现有的管道.

问题是"如何将模式添加到现有的实体统治者?"和我在这里问的差不多.但是由于NER模型是自定义的,答案告诉您使用这些模式重新训练NER模型.这就是为什么这里的问题希望不是重复的:我不能重新训练NER模型,因为它是从spaCy下载的现成的.

灾难性的遗忘?

请注意,这里的答案告诉你,如果你可以重新训练你的NER模型,就不要在NER模型中添加实体统治者,因为它可能会导致已经训练好的NER模型的"灾难性遗忘",请阅读这里了解更多.如果这是正确的,我想知道我在这里做什么,因为这意味着我不能将spaCy NER模型训练的实体识别与另一个实体统治者合并.我非常怀疑这是真的.为什么我不能判断文本中某些实体的某些模式,然后在此基础上运行spaCy NER模型,然后让第一个找到的实体超过第二个?如果我们谈论两个模型,为什么会导致灾难性的遗忘?灾难性遗忘意味着NER模型只在我作为实体统治者的新文本上进行重新训练.我的新输入文本将只是一个带有日期的句子.然后,就很容易发现灾难性遗忘是否发生了.我可以在一个句子上运行管道,这个句子除了日期之外还有更多的实体,看看会发生什么. 然而,我想我的 idea 是错误的,所以我们没有两个模型,而是一个实体识别模型,它是实体统治者和NER模型的合并.这也是我最初对实体统治者的理解.但即使这样,我仍然可以很容易地在灾难性遗忘中测试这一点:如果实体识别在一个大文件中变得更糟,那么我就知道存在灾难性遗忘.如果你问我,这听起来太奇怪了.我怀疑另一个问题的答案是否正确.

推荐答案

Main things

每个匹配项都是一个标签

您必须在标签下列出标签,您不能只将所有正则表达式模式放在一个标签中.请看在Add multiple EntityRuler with spaCy (ValueError: 'entity_ruler' already exists in pipeline)处加下划线的好代码.

图像形式

你必须写ORTHTEXTLOWER(而不是我上面试过的"形状"),然后在嵌套的括号REGEX中.查看完整列表spaCy - Matcher - Patterns

RegEx中没有嵌入空间

而且,您不能将已经标记化的数据与带有空格的单词进行匹配--因为标记器已经通过这些空格将数据拆分成了标记.在标记化的数据中没有任何剩余的空间.匹配它们的唯一方法是将任何嵌入了S+的正则表达式分解为单独的匹配令牌,请访问以下地址查看此问题的无答案:

方括号

spaCy guide on the entity ruler强中,例子不仅是糟糕的编码,而且是必需的:

{'label': 'GPE', 'pattern': [{'lower': 'san'}, {'lower': 'francisco'}]}

有关更多信息,请参阅explosion/spaCy/master/spacy/pipeline/entityruler.py上的完整代码.

令人惊讶的是,您不仅必须为两个或更多的令牌(这意味着它们是相邻的,在一行中)编写这样的方括号,而且如果在开头添加"较低"属性,即使是一个令牌也需要这些方括号!(!)您可能会认为方括号只是列表的开始,事实的确如此,但列表格式似乎也是一个匹配所必需的.我用{'label': 'GPE', 'pattern': [{'LOWER': 'apple'}]}判断了一下,这是可行的,虽然没有方括号就不能工作,但代码没有找到单词"Apple"作为一个实体,只有"Apple".

Code example

有了这些提示,我就能找到上述问题的答案.

from spacy.lang.de import German

nlp = German()
ruler = nlp.add_pipe("entity_ruler")
patterns = [
    {"label": "ORG1", "pattern": {"LOWER": "apple"}},
    {"label": "ORG2", "pattern": [{"LOWER": "apple"}]},
    {"label": "GPE1", "pattern": {"LOWER": "san"}},
    {"label": "GPE2", "pattern": [{"LOWER": "san"}]},
    {"label": "GPE4", "pattern": [{"LOWER": "san"}, {"LOWER": "francisco"}]},
    {"label": "DATE1", "pattern": {"TEXT": [{"regex": "^(?:0?[1-9]|[12][0-9]|3[01])$"}]}},
    {"label": "DATE2", "pattern": [{"TEXT": {"regex": "^(?:0?[1-9]|[12][0-9]|3[01])$"}}]},
    {"label": "DATE3", "pattern": [{"TEXT": {"regex": "(?:0?[1-9]|[12][0-9]|3[01])"}}, {"LOWER": {"regex": "(jan(?:uar)?|feb(?:ruar)?|mär(?:z)?|apr(?:il)?|mai|jun(?:i)?|jul(?:i)?|aug(?:ust)?|sep(?:t(?:ember)?)?|okt(?:ober)?|nov(?:ember)?|dez(?:ember)?)"}}, {"TEXT": {"regex": "['`]?\d{0,4}"}}]},
    {"label": "DATE4", "pattern": [{"TEXT": {"regex": "(?:0?[1-9]|[12][0-9]|3[01])"}}, {"LOWER": {"regex": "(jan(?:uar)?|feb(?:ruar)?|mär(?:z)?|apr(?:il)?|mai|jun(?:i)?|jul(?:i)?|aug(?:ust)?|sep(?:t(?:ember)?)?|okt(?:ober)?|nov(?:ember)?|dez(?:ember)?)"}}]},
    {"label": "DATE5", "pattern": [{"LOWER": {"regex": "(jan(?:uar)?|feb(?:ruar)?|mär(?:z)?|apr(?:il)?|mai|jun(?:i)?|jul(?:i)?|aug(?:ust)?|sep(?:t(?:ember)?)?|okt(?:ober)?|nov(?:ember)?|dez(?:ember)?)"}}, {"TEXT": {"regex": "['`]?\d{0,4}"}}]},
    {"label": "DATE6", "pattern": [{"LOWER": {"regex": "^(januar|feb(?:ruar)?|mär(?:z)?|apr(?:il)?|mai|jun(?:i)?|jul(?:i)?|aug(?:ust)?|sep(?:t(?:ember)?)?|okt(?:ober)?|nov(?:ember)?|dez(?:ember)?)$"}}]}
            ]
ruler.add_patterns(patterns)

# Taking the German Dezember here for the test of the German RegEx
doc = nlp("Apple is opening its first big office in San Francisco on 15. Dezember 2022.")
print([(ent.text, ent.label_) for ent in doc.ents])

好了,我们走吧.

[('Apple', 'ORG2'), ('San Francisco', 'GPE4'), ('15. Dezember 2022', 'DATE3')]

请注意,相同的代码,但与英文型号将只会找到"12月15日2022年":

from spacy.lang.en import English
nlp = English()

只有当你在德国型号上运行它时,它才会找到带圆点的"15.Dezember2022".我猜在英语中,这个点被读作句子的句号.由于句子标记器在单词标记器之前运行,因此不能再将"15"、"Dezember"和"2022"作为一个匹配项一起找到.

上面的代码还证明,您不需要按令牌的数量对模式进行排序,比如"15.Dezember2022"、"15.Dezember"、"Dezember 2022"和"Dezember",因为它默认 Select 具有最多令牌的匹配.否则,它会先捕获标签"DATE2"的编号,然后,就再也找不到完整的日期了.

Python相关问答推荐

如何在vercel中指定Python运行时版本?

如何使用bs 4从元素中提取文本

指示组内的rejected_time是否在creation_timestamp后5分钟内

根据网格和相机参数渲染深度

无法使用equals_html从网址获取全文

理解Python的二分库:澄清bisect_left的使用

Matlab中是否有Python的f-字符串等效物

未删除映射表的行

. str.替换pandas.series的方法未按预期工作

将两只Pandas rame乘以指数

如何让Flask 中的请求标签发挥作用

DataFrames与NaN的条件乘法

我如何根据前一个连续数字改变一串数字?

提取相关行的最快方法—pandas

Python Pandas获取层次路径直到顶层管理

为什么if2/if3会提供两种不同的输出?

使用字典或列表的值组合

递归函数修饰器

GPT python SDK引入了大量开销/错误超时

如何根据一定条件生成段id