Python NLP Spacy:改进 bi-gram 从数据帧和命名实体中提取?
Python NLP Spacy : improve bi-gram extraction from a dataframe, and with named entities?
我正在使用 Python 和 spaCy 作为我的 NLP 库,处理包含不同汽车反馈的大数据框,如下所示:
- 'feedback' 列包含要处理的自然语言文本,
- 'lemmatized' 列包含反馈文本的词形还原版本,
- 'entities' 列包含从反馈文本中提取的命名实体(我已经训练了管道,以便它能够识别汽车型号和品牌,并将它们标记为 'CAR_BRAND' 和 'CAR_MODEL' )
然后我创建了以下函数,它将 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)
这是我遇到的问题...
每行最多只生成 一个二元组。我如何调整代码以便可以提取多个二元组并将其放入一列? (还有我应该尝试的更多语言组合吗?)
是否有可能找出人们对 '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 而不是线性模式 可能 稍微改善您的结果
话虽这么说,您正在尝试做的事情 – 某种 情感分析 – 是一项相当困难的任务,通常涉及机器学习方法和大量训练数据。所以不要对简单的启发式方法抱有太大期望。
我正在使用 Python 和 spaCy 作为我的 NLP 库,处理包含不同汽车反馈的大数据框,如下所示:
- 'feedback' 列包含要处理的自然语言文本,
- 'lemmatized' 列包含反馈文本的词形还原版本,
- 'entities' 列包含从反馈文本中提取的命名实体(我已经训练了管道,以便它能够识别汽车型号和品牌,并将它们标记为 'CAR_BRAND' 和 'CAR_MODEL' )
然后我创建了以下函数,它将 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)
这是我遇到的问题...
每行最多只生成 一个二元组。我如何调整代码以便可以提取多个二元组并将其放入一列? (还有我应该尝试的更多语言组合吗?)
是否有可能找出人们对 '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 而不是线性模式 可能 稍微改善您的结果
话虽这么说,您正在尝试做的事情 – 某种 情感分析 – 是一项相当困难的任务,通常涉及机器学习方法和大量训练数据。所以不要对简单的启发式方法抱有太大期望。