如何用NLTK与spaCy处理单句内双主题的情感分析
解决对比句中多主体的情感区分问题
你的核心问题在于SIA是对整句做情感分析,但对比句里的情感是相对的,没法直接用整句结果对应单个主体。当前代码只是重复跑整句分析,自然区分不开Dogs和Alligators的情感。
下面给你两种可行的改造思路,结合spaCy的语法分析来精准绑定主体和情感:
思路1:针对性拆分对比句
对于含than的对比句,直接根据结构把情感分配给前后主体:
- 前面的主体(Dogs)对应正面情感(因为用了better这类褒义对比词)
- 后面的主体(Alligators)对应负面/相对负面情感
修改后的代码如下:
import nltk import spacy from nltk.sentiment import SentimentIntensityAnalyzer from spacy.matcher import PhraseMatcher sia = SentimentIntensityAnalyzer() nlp = spacy.load("en_core_web_sm") text = """Dogs and cats make great pets. Alligators make poor pets. Dogs make better pets than Alligators.""" phrase_matcher = PhraseMatcher(nlp.vocab) phrases = ['Dogs', 'Alligators'] patterns = [nlp(phrase) for phrase in phrases] phrase_matcher.add('Pets', None, *patterns) doc = nlp(text) for sent in doc.sents: sent_text = sent.text # 先找出句子里的所有目标主体 matches = phrase_matcher(sent) subjects = [sent[start:end].text for match_id, start, end in matches] # 处理对比句(含than) if 'than' in sent_text: # 拆分出前后主体 parts = sent_text.split('than') if len(parts) == 2: # 前半部分的主体对应正面,后半部分对应负面 for subj in subjects: if subj in parts[0]: res = sia.polarity_scores(parts[0]) print(f"{subj} 的情感: {res} (来自对比前半段)") elif subj in parts[1]: # 手动调整:对比句中后者是被否定的,取反向情感 res = sia.polarity_scores(sent_text) adjusted_res = { 'neg': res['neg'] + res['pos'], 'neu': res['neu'], 'pos': 0.0, 'compound': -res['compound'] } print(f"{subj} 的情感: {adjusted_res} (来自对比后半段)") # 处理普通非对比句 else: res = sia.polarity_scores(sent_text) for subj in subjects: print(f"{subj} 的情感: {res}")
思路2:用spaCy依赖分析绑定主体与修饰语
更通用的方法是通过spaCy的依赖关系,找到每个主体对应的谓语、形容词等修饰成分,单独分析这些成分的情感,精准匹配主体的情感倾向:
import nltk import spacy from nltk.sentiment import SentimentIntensityAnalyzer from spacy.matcher import PhraseMatcher sia = SentimentIntensityAnalyzer() nlp = spacy.load("en_core_web_sm") text = """Dogs and cats make great pets. Alligators make poor pets. Dogs make better pets than Alligators.""" phrase_matcher = PhraseMatcher(nlp.vocab) phrases = ['Dogs', 'Alligators'] patterns = [nlp(phrase) for phrase in phrases] phrase_matcher.add('Pets', None, *patterns) doc = nlp(text) for sent in doc.sents: matches = phrase_matcher(sent) for match_id, start, end in matches: subj = sent[start:end] # 找到主体对应的核心动词 head_verb = subj.head # 收集和主体相关的描述性词汇(形容词、副词等) desc_tokens = [] for child in head_verb.children: # 匹配表语、形容词补语、直接宾语等描述性成分 if child.dep_ in ['acomp', 'attr', 'dobj']: desc_tokens.append(child.text) # 追加修饰该成分的副词 desc_tokens.extend([gc.text for gc in child.children if gc.dep_ == 'advmod']) # 用描述词汇做情感分析 if desc_tokens: desc_text = ' '.join(desc_tokens) res = sia.polarity_scores(desc_text) print(f"{subj.text} 的情感: {res} (来自描述: {desc_text})") else: # 无明确描述时 fallback到整句分析 res = sia.polarity_scores(sent.text) print(f"{subj.text} 的情感: {res} (来自整句)")
思路1针对你的特定对比场景快速生效,思路2更通用,能处理更复杂的句子结构。你可以根据需求调整,比如给对比句的情感权重做手动修正,或者扩展依赖分析的规则覆盖更多情况。
内容的提问来源于stack exchange,提问作者McArtler
相关产品推荐
相关产品推荐

