如何使用pandas应用来替换迭代行?



我正在根据新闻标题计算数据集中每行的情感值。我使用iterrows来实现这一点:

field = 'headline'
dfp = pd.DataFrame(columns=('pos', 'neg', 'neu'))
tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
for index, row in df.iterrows():
text = row[field]
encoded_input = tokenizer(text, return_tensors='pt')
output = model(**encoded_input)
probs = torch.nn.functional.softmax(output[0], dim=-1)
probs_arr = probs.cpu().detach().numpy()
dfp = dfp.append({'pos': probs_arr[0][0],
'neg': probs_arr[0][1],
'neu': probs_arr[0][2]
}, ignore_index=True)

但是,处理时间太长(>30分钟运行时间,而且还没有完成)。我的数据集中有16.6k行。

这是数据集的一小部分:

datetime            headline
0   2020-03-17 16:57:07 12 best noise-cancelling headphones: In-ear an...
1   2020-06-08 14:00:55 5G Stocks To Buy And Watch: Pricing of 5G Smar...
2   2020-06-19 10:00:00 10 best wireless printers that will make your ...
3   2020-08-19 00:00:00 Apple Confirms Solid New iOS 14 Security Move ...
4   2020-08-19 00:00:00 Apple Becomes First U.S. Company Worth More Th...

我读到iterrows在大多数情况下不推荐,除非数据集很小,优化不是一个问题。看起来,它的替代方案是使用apply,因为apply遍历每个pandas行并进行了优化。

我读到的一些SO主题建议创建一个函数并在apply中运行它。这是我尝试的:

def calPred(text):
encoded_input = tokenizer(text, return_tensors='pt')
output = model(**encoded_input)
probs = torch.nn.functional.softmax(output[0], dim=-1)
probs_arr = probs.cpu().detach().numpy()
dfp = dfp.append({'pos': probs_arr[0][0],
'neg': probs_arr[0][1],
'neu': probs_arr[0][2]
}, ignore_index=True)
df['headline'].apply(lambda x: calPred(x))

返回错误UnboundLocalError: local variable 'dfp' referenced before assignment

如果有人能指导我如何优化和正确使用apply,我将不胜感激。提前谢谢。

你的代码的问题是,当你做dfp = dfp.append...,dfp已经被定义为全局,你不能重新分配它(使用另一个变量名),即dfp_temp = dfp.append...

然而,我认为应用不是你想要的。ML中的大多数模型将接受一个类似数组的输入,因此您可以在模型中传递整个列(或至少是其中的一大块),而不是每一行。

像这样

field = 'headline'
tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
texts = df[field].values
encoded_input = tokenizer(texts, return_tensors='pt')
output = model(encoded_input)
probs = torch.nn.functional.softmax(output, dim=-1)
probs = probs.cpu().detach().numpy()
dfp = pd.DataFrame({
'pos': probs[:, 0],
'neg': probs[:, 1],
'neu': probs[:, 2]
})
编辑:Tokenizer不支持数组

你可以尝试像这样向量化标记器

注意:np。矢量化和应用不会给你带来任何显著的提升,因为它们仍然迭代每个元素。但是,最好使用apply和np。向量化到尽可能小的范围

...
tokenizer_func = lambda text: tokenizer(text, return_tensors='pt')
encoded_input = np.vectorize(tokenizer_func)(texts)
...

相关内容

  • 没有找到相关文章

最新更新