Python PhraseMatcher在尝试标记文档中的多个项目时返回空列表
PhraseMatcher在尝试标记文档中的多个项目时返回空列表。我从csv中的一列传递值来标记文档中的产品名称,但PhraseMatcher只标记带有一个字符串的行。当有多个元素用于标记时,它将返回一个空列表。解决这个问题的办法是什么Python PhraseMatcher在尝试标记文档中的多个项目时返回空列表,python,nlp,spacy,tagging,Python,Nlp,Spacy,Tagging,PhraseMatcher在尝试标记文档中的多个项目时返回空列表。我从csv中的一列传递值来标记文档中的产品名称,但PhraseMatcher只标记带有一个字符串的行。当有多个元素用于标记时,它将返回一个空列表。解决这个问题的办法是什么 import spacy import re import csv from spacy.matcher import PhraseMatcher #Function to convert PhraseMatcher return value to strin
import spacy
import re
import csv
from spacy.matcher import PhraseMatcher
#Function to convert PhraseMatcher return value to string indexes
def str_index_conversion(lbl, doc, matchitem):
o_one = len(str(doc[0:matchitem[1]]))
subdoc = doc[matchitem[1]:matchitem[2]]
o_two = o_one + len(str(subdoc))
return (o_one, o_two, lbl)
#nlp = spacy.blank('en')
nlp = spacy.load('en')
if 'ner' not in nlp.pipe_names:
ner = nlp.create_pipe('ner')
nlp.add_pipe(ner)
else:
ner = nlp.get_pipe('ner')
ner.add_label('PRODUCT')
DIR = 'C:\\Users\\Lenovo\\.spyder-py3\\smoke\\'
matcher = PhraseMatcher(nlp.vocab)
list_str_index = []
to_train_ents = []
with open('qq1.csv', newline='') as myFile:
reader = csv.reader(myFile)
for row in reader:
try:
product = row[0].lower()
filename = row[1]
#print(product)
file = open(DIR+filename, "r", encoding ='utf-8')
filecontents = file.read()
#print(product)
for s in filecontents:
filecontents = re.sub(r'\[[0-9]*\]', ' ', filecontents)
filecontents = re.sub(r'\s+', ' ', filecontents)
#filecontents = filecontents.encode().decode('unicode-escape')
filecontents = ''.join([line.lower() for line in filecontents])
print(product.split())
matcher.add('PRODUCT', None, nlp(product))
doc = nlp(filecontents)
matches = matcher(doc)
#print(matches)
list_str_index = [str_index_conversion('PRODUCT', doc, x) for x in matches]
to_train_ents.append((filecontents, dict(entities=list_str_index)))
break
except Exception as e:
#print(e)
pass`
当文档中有多个元素要标记时,“to_train_ents”列表返回空列表。要标记的元素以csv的形式提供,如下所示:
`示例CSV:
PRODUCT FILES
ABC XXXX
ABC2, ABC3, BCA3 XXXX
BC2 XXXX
因此,在第二行的情况下,它返回一个to_train_ents列表中的空列表。在文档中标记此类案例的解决方案是什么
删除TRY和EXCEPT块后:
这次我只在csv中保存了产品名称和文件名,它们位于包含标记文件的目录中。但是,当我发送一个产品名称进行标记时,它在文档中有两个名称要标记,它返回一个空列表。
示例代码现在:
import spacy
import re
import csv
from spacy.matcher import PhraseMatcher
#Function to convert PhraseMatcher return value to string indexes
def str_index_conversion(lbl, doc, matchitem):
o_one = len(str(doc[0:matchitem[1]]))
subdoc = doc[matchitem[1]:matchitem[2]]
o_two = o_one + len(str(subdoc))
return (o_one, o_two, lbl)
#nlp = spacy.blank('en')
nlp = spacy.load('en')
if 'ner' not in nlp.pipe_names:
ner = nlp.create_pipe('ner')
nlp.add_pipe(ner)
else:
ner = nlp.get_pipe('ner')
ner.add_label('PRODUCT')
DIR = 'C:\\Users\\Lenovo\\.spyder-py3\\sanity\\'
matcher = PhraseMatcher(nlp.vocab)
list_str_index = []
to_train_ents = []
with open('qq2.csv', newline='') as myFile:
reader = csv.reader(myFile)
for row in reader:
product = row[0].lower()
filename = row[1]
#print(product)
file = open(DIR+filename, "r", encoding ='utf-8')
filecontents = file.read()
#print(product)
for s in filecontents:
filecontents = re.sub(r'\[[0-9]*\]', ' ', filecontents)
filecontents = re.sub(r'\s+', ' ', filecontents)
#filecontents = filecontents.encode().decode('unicode-escape')
filecontents = ''.join([line.lower() for line in filecontents])
#print(product.split())
#product_patterns = [nlp(text) for text in product.split()]
matcher.add('PRODUCT', None, nlp(product))
doc = nlp(filecontents)
matches = matcher(doc)
#print(matches)
list_str_index = [str_index_conversion('PRODUCT', doc, x) for x in matches]
to_train_ents.append((filecontents, dict(entities=list_str_index)))
break
您是否能够创建简化的、可复制的示例,仅显示短语匹配器的行为,而不打开文件、字符串转换等。?在尝试之前,我的第一反应是,您的巨大
try
块中有一些错误。除了像这样的之外,裸体的尝试一下
/,通常不是很好的做法。如果try
中的近20行(!)中有一行出错,将触发except
块,列表中不会追加任何内容(因此您将得到一个空列表),您将不知道原因,也不会收到错误消息来帮助您(就像现在的情况)。问题是,将文件名和产品名与标记匹配的csv以及文件所在的目录在数量上不相同。我只是传递目录中的几个文件以进行检查。所以我该如何解决这个问题,因为每当它找不到匹配的文件名时,就会抛出一个错误。这一行matcher.add('PRODUCT',None,nlp(PRODUCT))
很好,还是我需要在这里添加另一个for循环?就像我在尝试类似于matcher.add('PRODUCT',None,*[nlp.tokenizer(item)for item in PRODUCT])
的东西一样,我已经删除了try-except块并更新了上面的代码,但仍然无法标记多个名称。您是否能够创建一个简化的、可重复的示例,仅显示短语匹配器的行为,不打开文件、字符串转换等。?在尝试之前,我的第一反应是,您的巨大try
块中有一些错误。除了像这样的
之外,裸体的尝试一下
/,通常不是很好的做法。如果try
中的近20行(!)中有一行出错,将触发except
块,列表中不会追加任何内容(因此您将得到一个空列表),您将不知道原因,也不会收到错误消息来帮助您(就像现在的情况)。问题是,将文件名和产品名与标记匹配的csv以及文件所在的目录在数量上不相同。我只是传递目录中的几个文件以进行检查。所以我该如何解决这个问题,因为每当它找不到匹配的文件名时,就会抛出一个错误。这一行matcher.add('PRODUCT',None,nlp(PRODUCT))
很好,还是我需要在这里添加另一个for循环?就像我在尝试类似matcher.add('PRODUCT',None,*[nlp.tokenizer(item)for item in PRODUCT])
的东西一样,我已经删除了try-except块并更新了上面的代码,但它仍然无法标记多个名称