Python 如何在无监督的基于方面的情感分析中进行主题检测

Python 如何在无监督的基于方面的情感分析中进行主题检测,python,nlp,word2vec,sentiment-analysis,Python,Nlp,Word2vec,Sentiment Analysis,我想使用Python制作一个ABSA,从在线评论中分析预定义方面(例如交付、质量、服务)的情绪。我想在无人监督的情况下完成这项工作,因为这样可以避免手动标记评论,并且我可以分析更多的评论数据(查看大约10万篇评论)。因此,我的数据集只包含评论,没有评分。我想有一个模型,可以首先检测方面的类别,然后分配情感极性。例如,当评论说“发货顺利,但产品损坏”时,我希望模型将“发货”一词指定给方面类别“交货”,并且“顺利”与积极情绪相关 我一直在寻找可以采取的方法,我想知道是否有人有这方面的经验,可以引导我

我想使用Python制作一个ABSA,从在线评论中分析预定义方面(例如交付、质量、服务)的情绪。我想在无人监督的情况下完成这项工作,因为这样可以避免手动标记评论,并且我可以分析更多的评论数据(查看大约10万篇评论)。因此,我的数据集只包含评论,没有评分。我想有一个模型,可以首先检测方面的类别,然后分配情感极性。例如,当评论说“发货顺利,但产品损坏”时,我希望模型将“发货”一词指定给方面类别“交货”,并且“顺利”与积极情绪相关

我一直在寻找可以采取的方法,我想知道是否有人有这方面的经验,可以引导我走向一个可以帮助我的方向。非常感谢

基于方面的情绪分析(ABSA),任务首先 提取实体的方面或特征(即方面术语提取 或ATE1)从给定的文本中,然后确定情感 极性(SP),如有,指向该实体的各个方面。这个 ABSA的重要性导致了ABSA任务的创建

B-LSTM和CRF分类器将用于特征提取和方面 监督和非监督ATE的术语检测

#-*-编码:utf-8-*-
#文件:infer.py
#作者:宋有为
#版权所有(C)2019年。版权所有。
进口火炬
导入torch.nn.功能为F
导入argparse
从数据导入构建标记器,构建嵌入矩阵
从模型导入IAN、MemNet、ATAElstm、AOA
类推断器:
“”“一个简单的推理示例”“”
定义初始化(自我,选择):
self.opt=opt
self.tokenizer=build\u tokenizer(
fnames=[opt.dataset_文件['train'],opt.dataset_文件['test']],
max_seq_len=opt.max_seq_len,
dat_fname='{0}_tokenizer.dat'。格式(opt.dataset))
嵌入矩阵=构建嵌入矩阵(
word2idx=self.tokenizer.word2idx,
嵌入尺寸=opt.embed尺寸,
dat_fname='{0}{1}}{u嵌入_matrix.dat'。格式(str(opt.embed_dim),opt.dataset))
self.model=opt.model_类(嵌入矩阵,opt)
打印('正在加载模型{0}…'。格式(opt.model_name))
self.model.load\u state\u dict(torch.load(opt.state\u dict\u path))
self.model=self.model.to(可选设备)
#将模型转换为评估模式
self.model.eval()
手电筒自动加载设置梯度启用(假)
def评估(自我、原始文本):
context_seqs=[self.tokenizer.text_到_序列(raw_text.lower().strip()),用于原始_文本中的原始_文本]
aspect_seqs=[self.tokenizer.text_to_sequence('null')]*len(原始_文本)
上下文索引=torch.tensor(上下文索引,数据类型=torch.int64).to(self.opt.device)
纵横比索引=torch.tensor(纵横比索引,数据类型=torch.int64).to(self.opt.device)
t_输入=[上下文索引,方面索引]
t_输出=自身模型(t_输入)
t_probs=F.softmax(t_输出,dim=-1).cpu().numpy()
返回t_probs
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
模型_类={
“atae_lstm”:atae_lstm,
伊恩:伊恩,
“memnet”:memnet,
“aoa”:aoa,
}
#在这里设置您训练有素的模型
模型\状态\指令\路径={
“atae_lstm”:“州/atae_lstm_餐厅”acc0.7786,
“伊恩”:“州/伊恩餐厅”\u acc0.7911“,
“memnet”:“state_dict/memnet_restaurant_acc0.7911”,
“aoa”:州/aoa餐厅0.8063,
}
类选项(对象):传递
opt=Option()
opt.model_name='ian'
opt.model\u class=model\u class[opt.model\u name]
opt.dataset='restaurant'
opt.dataset_文件={
“train”:“./dataset/semeval14/train.xml.seg”,
“test”:“./datasets/semeval14/Restaurants\u test\u Gold.xml.seg”
}
opt.state_dict_path=模型_state_dict_path[opt.model_name]
opt.embed_dim=300
opt.hidden_dim=300
opt.max_seq_len=80
选择极性尺寸=3
opt.hops=3
opt.device=torch.device('cuda'如果torch.cuda.is_可用(),则为'cpu')
inf=推断器(opt)
t_probs=inf.evaluate(['happy memory'、'服务很糟糕'、'只是普通食物']))
打印(t_probs.argmax(轴=-1)-1)

非常感谢您提供的链接。代码看起来很棒!
# -*- coding: utf-8 -*-
# file: infer.py
# author: songyouwei <youwei0314@gmail.com>
# Copyright (C) 2019. All Rights Reserved.

import torch
import torch.nn.functional as F
import argparse

from data_utils import build_tokenizer, build_embedding_matrix
from models import IAN, MemNet, ATAE_LSTM, AOA


class Inferer:
    """A simple inference example"""
    def __init__(self, opt):
        self.opt = opt
        self.tokenizer = build_tokenizer(
            fnames=[opt.dataset_file['train'], opt.dataset_file['test']],
            max_seq_len=opt.max_seq_len,
            dat_fname='{0}_tokenizer.dat'.format(opt.dataset))
        embedding_matrix = build_embedding_matrix(
            word2idx=self.tokenizer.word2idx,
            embed_dim=opt.embed_dim,
            dat_fname='{0}_{1}_embedding_matrix.dat'.format(str(opt.embed_dim), opt.dataset))
        self.model = opt.model_class(embedding_matrix, opt)
        print('loading model {0} ...'.format(opt.model_name))
        self.model.load_state_dict(torch.load(opt.state_dict_path))
        self.model = self.model.to(opt.device)
        # switch model to evaluation mode
        self.model.eval()
        torch.autograd.set_grad_enabled(False)

    def evaluate(self, raw_texts):
        context_seqs = [self.tokenizer.text_to_sequence(raw_text.lower().strip()) for raw_text in raw_texts]
        aspect_seqs = [self.tokenizer.text_to_sequence('null')] * len(raw_texts)
        context_indices = torch.tensor(context_seqs, dtype=torch.int64).to(self.opt.device)
        aspect_indices = torch.tensor(aspect_seqs, dtype=torch.int64).to(self.opt.device)

        t_inputs = [context_indices, aspect_indices]
        t_outputs = self.model(t_inputs)

        t_probs = F.softmax(t_outputs, dim=-1).cpu().numpy()
        return t_probs


if __name__ == '__main__':
    model_classes = {
        'atae_lstm': ATAE_LSTM,
        'ian': IAN,
        'memnet': MemNet,
        'aoa': AOA,
    }
    # set your trained models here
    model_state_dict_paths = {
        'atae_lstm': 'state_dict/atae_lstm_restaurant_acc0.7786',
        'ian': 'state_dict/ian_restaurant_acc0.7911',
        'memnet': 'state_dict/memnet_restaurant_acc0.7911',
        'aoa': 'state_dict/aoa_restaurant_acc0.8063',
    }
    class Option(object): pass
    opt = Option()
    opt.model_name = 'ian'
    opt.model_class = model_classes[opt.model_name]
    opt.dataset = 'restaurant'
    opt.dataset_file = {
        'train': './datasets/semeval14/Restaurants_Train.xml.seg',
        'test': './datasets/semeval14/Restaurants_Test_Gold.xml.seg'
    }
    opt.state_dict_path = model_state_dict_paths[opt.model_name]
    opt.embed_dim = 300
    opt.hidden_dim = 300
    opt.max_seq_len = 80
    opt.polarities_dim = 3
    opt.hops = 3
    opt.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    inf = Inferer(opt)
    t_probs = inf.evaluate(['happy memory', 'the service is terrible', 'just normal food'])
    print(t_probs.argmax(axis=-1) - 1)