Python NLP Spacy:改进 bi-gram 从数据帧和命名实体中提取?

Python NLP Spacy : improve bi-gram extraction from a dataframe, and with named entities?

我正在使用 Python 和 spaCy 作为我的 NLP 库,处理包含不同汽车反馈的大数据框,如下所示:

然后我创建了以下函数,它将 Spacy nlp 标记应用于我的数据帧的每一行并提取任何 [名词 + 动词]、[动词 + 名词]、[形容词 + 名词]、[形容词 + 专有名词]组合。

def bi_gram(x):
    doc = nlp_token(x)
    result = []
    text = ''
    for i in range(len(doc)):
        j = i+1
        if j < len(doc):
            if (doc[i].pos_ == "NOUN" and doc[j].pos_ == "VERB") or (doc[i].pos_ == "VERB" and doc[j].pos_ == "NOUN") or (doc[i].pos_ == "ADJ" and doc[j].pos_ == "NOUN") or (doc[i].pos_ == "ADJ" and doc[j].pos_ == "PROPN"):
                text = doc[i].text + " " + doc[j].text
                result.append(text)
        i = i+1
        return result

然后我将此函数应用于 'lemmatized' 列:

df['bi_gram'] = df['lemmatized'].apply(bi_gram)

这是我遇到的问题...

  1. 每行最多只生成 一个二元组。我如何调整代码以便可以提取多个二元组并将其放入一列? (还有我应该尝试的更多语言组合吗?)

  2. 是否有可能找出人们对 'entities' 列中提取的 'CAR_BRAND' 和 'CAR_MODEL' 命名实体的看法?例如 'Cool Porsche' - 一些品牌或型号由两个以上的词组成,因此很难处理。

我是 NLP 的新手。.如果有更有效的方法来解决这个问题,任何建议都会非常有帮助! 非常感谢您的提前帮助。

spaCy 有一个 built-in 模式匹配引擎,非常适合您的应用程序 – 已记录 here and in a more extensive usage guide。它允许您以可读且 easy-to-maintain 的方式定义模式,作为定义要匹配的标记属性的字典列表。

设置模式匹配器

import spacy
from spacy.matcher import Matcher

nlp = spacy.load("en_core_web_sm") # or whatever model you choose

matcher = Matcher(nlp.vocab)

# your patterns
patterns = {
    "noun_verb": [{"POS": "NOUN"}, {"POS": "VERB"}],
    "verb_noun": [{"POS": "VERB"}, {"POS": "NOUN"}],
    "adj_noun": [{"POS": "ADJ"}, {"POS": "NOUN"}],
    "adj_propn": [{"POS": "ADJ"}, {"POS": "PROPN"}],
}

# add the patterns to the matcher
for pattern_name, pattern in patterns.items():
    matcher.add(pattern_name, [pattern])

提取匹配项

doc = nlp("The dog chased cats. Fast cats usually escape dogs.")
matches = matcher(doc)

matches 是包含

的元组列表
  • 匹配ID,
  • 匹配位的起始索引和
  • 结束索引(不包括)。

这是从 spaCy 使用指南中采纳的测试输出:

for match_id, start, end in matches:
    
    # Get string representation
    string_id = nlp.vocab.strings[match_id]

    # The matched span
    span = doc[start:end]
    
    print(repr(span.text))
    print(match_id, string_id, start, end)
    print()

结果

'dog chased'
1211260348777212867 noun_verb 1 3

'chased cats'
8748318984383740835 verb_noun 2 4

'Fast cats'
2526562708749592420 adj_noun 5 7

'escape dogs'
8748318984383740835 verb_noun 8 10

改进的一些想法

  • 命名实体识别应该能够检测 multi-word 表达式,因此如果一切设置正确,由多个标记组成的品牌 and/or 模型名称应该不会成为问题
  • 匹配 dependency patterns 而不是线性模式 可能 稍微改善您的结果

话虽这么说,您正在尝试做的事情 – 某种 情感分析 – 是一项相当困难的任务,通常涉及机器学习方法和大量训练数据。所以不要对简单的启发式方法抱有太大期望。