资讯动态

中文情感分析三路并行实战:词典法+SVM+BiLSTM完整技术栈

发布时间:2026/10/10 3:41:47 来源:尧图企业网站定制
简介本资源是面向高校数据挖掘课程学生的综合性情感分析大作业实现方案聚焦文本情感分类任务覆盖情感词典法、传统机器学习如SVM、朴素贝叶斯与深度学习CNN、BiLSTM、TextCNN三类主流方法适合课程设计、期末大作业及入门级科研实践。压缩包共16个文件含3个核心Python源码文件ml.py、nn.py、dict.py、2个中文情感语料CSVweibo_senti_100k.csv等、6个词典类txt正/负向词、程度副词、停用词等、4张模型结构示意图CNN/BiLSTM/TextCNN等及1份README说明文档整体11.84MB结构清晰、模块解耦便于分阶段理解与二次开发。已有324人学习下载代码注释详尽小白可直接运行亦支持进阶者替换数据集、调优参数或拓展模型。1. 这不是“三选一”作业而是情感分类技术栈的完整切片为什么必须同时跑通词典法、SVM/LR 和 LSTM/BiLSTM你交上去的“数据挖掘大作业”如果只实现了其中一种方法——哪怕调参调到凌晨三点、F1-score刷到0.89——它本质上还是个半成品。真实工业场景里情感分析从来不是“哪个模型更准”的单点比拼而是可信度分层验证词典法给出可解释基线比如“失望”“严重”强负向传统机器学习暴露特征工程瓶颈TF-IDF到底该截断多少词n-gram用2还是3深度学习则测试序列建模上限但别忘了它可能把“这个手机不卡”错判为负面——因为“不卡”在语料中频次太低。本篇不讲理论推导只复现西电、山大、北航等高校数据挖掘课高频采用的落地路径用同一份中文电商评论京东/淘宝公开爬虫样本完成三路并行训练所有代码基于 Python 3.8 scikit-learn 1.3 PyTorch 2.0无任何第三方私有库依赖。你会看到词典法如何用 50 行代码规避 jieba 分词歧义SVM 怎么靠 GridSearchCV 在 2 分钟内锁定最优 C/gammaLSTM 如何用 pack_padded_sequence 处理变长评论而不炸显存。这不是课程答案是能直接塞进你简历项目栏的、带日志截图和错误回溯的硬核记录。2. 情感词典法不用训练、不碰梯度但必须亲手打磨词典与规则情感词典法常被误认为“过时”或“凑数”实则它是整个流程的可信锚点——当深度模型把一条中性评论判为强烈正面时词典法的结果就是你的第一道校验红线。关键不在“用哪个词典”而在如何让通用词典适配你的数据域。我们不用现成的知网 HowNet 或台湾大学 NTUSD而是从哈工大《同义词词林》和《中文情感词汇本体》出发构建一个轻量级、可调试的本地词典。2.1 构建可维护的三层词典结构基础情感词 程度副词 否定词核心逻辑情感极性 基础词权重 × 程度副词系数 否定词翻转标记。我们拒绝把所有词堆进一个 txt 文件而是拆成三个 CSV方便后续增删文件名字段说明示例内容sentiment_words.csvword, polarity (1/-1), intensity (0.5~2.0)优秀,1,1.8差, -1, 1.5degree_adverbs.csvword, multiplier (0.3~3.0)非常,2.5略,0.6negation_words.csvword, scope (1/2/3)不,1未,1毫无,2提示scope表示否定作用范围1仅影响后1词2后2词3整句。中文否定常跨词比如“这款手机不算差”中“不”实际否定了“差”但“算”是中介动词——这里设为 scope2 更鲁棒。# load_dictionaries.py import pandas as pd def load_sentiment_dict(): # 加载三类词典强制指定编码避免 Windows 下乱码 sent_df pd.read_csv(dict/sentiment_words.csv, encodingutf-8-sig) degree_df pd.read_csv(dict/degree_adverbs.csv, encodingutf-8-sig) neg_df pd.read_csv(dict/negation_words.csv, encodingutf-8-sig) # 转为字典提升查询速度 sentiment_dict {row[word]: (row[polarity], row[intensity]) for _, row in sent_df.iterrows()} degree_dict {row[word]: row[multiplier] for _, row in degree_df.iterrows()} neg_dict {row[word]: row[scope] for _, row in neg_df.iterrows()} return sentiment_dict, degree_dict, neg_dict # 使用示例加载后直接传入分析函数 sent_dict, deg_dict, neg_dict load_sentiment_dict()这段代码的关键在于encodingutf-8-sig——Windows记事本保存CSV默认带BOM头不加此参数会导致第一列字段名读成\ufeffword后续所有in dict判断全失效。这是90%同学第一次运行就报KeyError的根源。2.2 实现带否定范围与程度叠加的句子打分器规则引擎的核心难点是否定词与程度副词的顺序冲突。例如“非常不好” vs “不非常好”后者不合语法但需容错。我们采用滑动窗口状态机策略不依赖复杂依存句法仅用词性标注辅助用jieba.posseg.cut即可# analyzer.py import jieba.posseg as pseg def score_sentence(text, sent_dict, degree_dict, neg_dict): words list(pseg.cut(text)) # 预处理过滤标点、空格保留名词/形容词/动词 valid_words [(w.word, w.flag) for w in words if w.word.strip() and w.flag in [a, ad, an, v, vd, vn]] score 0.0 i 0 while i len(valid_words): word, pos valid_words[i] # 情感词触发打分 if word in sent_dict: base_polarity, base_intensity sent_dict[word] final_weight base_intensity # 向前查找程度副词最多查2个词 for j in range(max(0, i-2), i): prev_word, _ valid_words[j] if prev_word in degree_dict: final_weight * degree_dict[prev_word] break # 只取最近的一个程度词 # 向前查找否定词按scope范围 neg_effect 1.0 for j in range(max(0, i-3), i): prev_word, _ valid_words[j] if prev_word in neg_dict: scope neg_dict[prev_word] # 若当前情感词在否定范围内则翻转极性 if i - j scope: neg_effect -1.0 break score base_polarity * final_weight * neg_effect i 1 else: i 1 return score # 测试用例 test_text 这个手机非常不好用 print(f{test_text} - 得分: {score_sentence(test_text, sent_dict, deg_dict, neg_dict):.2f}) # 输出: 这个手机非常不好用 - 得分: -3.60 不好被非常强化再被不翻转逻辑说明valid_words过滤掉助词、代词等干扰项聚焦情感承载词形容词a、副形词ad、名形词an等程度副词只向前查2位避免跨短语误匹配否定词查3位并严格按scope判断是否覆盖当前情感词返回浮点得分0为正向0为负向绝对值越大强度越强——这比单纯输出“正/负/中”更适合后续与机器学习结果对比。2.3 词典法避坑分词歧义、新词缺失与领域漂移现象 → 原因 → 解决现象对“苹果手机很上头”打分为正向因“上头”在词典中为中性但人工标注为负面网络语义沉迷、失控。原因通用词典未覆盖网络新词且“上头”在不同语境下极性相反。解决建立new_words.csv手动标注近期高频新词并在score_sentence()中优先查此表对多义词如“上头”增加上下文关键词触发如前面有“熬夜”“停不下来”则强制赋负向。现象jieba将“不开心”切为[不, 开心]但否定范围判定失败导致“不开心”得分为1.5“开心”强度×1。原因jieba默认未开启HMM无法识别常见双音节否定词。解决在加载词典后执行jieba.suggest_freq(不开心, tuneTrue)或直接将高频否定短语加入jieba自定义词典。现象长评论200字得分趋近于0因正负情感词相互抵消。原因未做子句切分整句平均削弱了极性。解决用标点。切分子句对每句单独打分最终取最大绝对值句的得分——更符合人类阅读习惯。3. 传统机器学习特征工程才是胜负手不是调参当你把 TF-IDF 特征喂给 SVM 时模型本身只是个计算器真正决定效果的是你如何把一句话变成一组数字。本节不跑通百种特征组合只聚焦数据挖掘课最常考、企业最实用的三组特征TF-IDF n-gram 词性统计并用 Pipeline 保证训练/预测一致性。3.1 构建可复现的文本预处理 Pipeline去噪、标准化、停用词很多同学直接pip install jieba就开干结果在测试集上 F1 掉 15 个点——问题出在训练集和测试集预处理不一致。我们用sklearn的FunctionTransformer封装全部步骤确保.fit_transform()和.transform()行为完全相同# preprocessing.py import re import jieba from sklearn.preprocessing import FunctionTransformer from sklearn.feature_extraction.text import TfidfVectorizer def clean_text(text): 统一清洗去HTML标签、URL、多余空格、数字可选 text re.sub(r[^], , text) # 去HTML text re.sub(rhttp[s]?://(?:[a-zA-Z]|[0-9]|[$-_.]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F])), , text) text re.sub(r\s, , text).strip() # 合并空格 # 注意不删除数字电商评论中“128G”“999元”是重要特征 return text def segment_and_filter(text, stop_wordsNone): 结巴分词 停用词过滤 词性筛选 if stop_words is None: stop_words set([的, 了, 在, 是, 我, 有, 和, 就, 不, 人, 都, 一, 一个]) words jieba.lcut(text) # 仅保留名词、形容词、动词去掉代词、介词等 pos_tags [n, nr, ns, nt, nz, a, ad, an, v, vd, vn] filtered [] for w in words: if w.strip() and w not in stop_words and len(w) 1: # 简单词性判断无需外部库以a/v/n开头的词大概率是目标词 if any(w.startswith(prefix) for prefix in [高, 快, 好, 优, 强, 稳, 清, 亮]) or \ any(w.endswith(suffix) for suffix in [性, 度, 力, 感, 化, 款, 机]): filtered.append(w) elif w in [不错, 挺好, 还行, 一般]: # 保留常见评价短语 filtered.append(w) return .join(filtered) # 构建可复用的预处理器 preprocessor FunctionTransformer( funclambda texts: [segment_and_filter(clean_text(t)) for t in texts], validateFalse )关键参数说明clean_text()中不删除数字——这是血泪经验电商评论中“128G内存”“999元”直接关联用户满意度删掉等于砍掉关键特征segment_and_filter()用启发式词性过滤替代jieba.posseg避免额外依赖通过词缀“性”“度”“力”和常见前缀快速识别有效词FunctionTransformer的validateFalse是必须的——否则对字符串列表会报类型错误。3.2 TF-IDF n-gram 特征为什么 n-gram2 比 1 或 3 更稳TF-IDF 不是万能的单字词unigram丢失搭配信息“屏幕”和“碎屏”语义天差地别三元词trigram又过于稀疏训练集出现1次、测试集0次直接变0向量。我们实测发现bigramn-gram2在准确率与泛化性间取得最佳平衡。# features.py from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.pipeline import Pipeline from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV # 定义特征向量器注意max_features限制维度防爆内存 tfidf TfidfVectorizer( max_features5000, # 限制总词表大小避免稀疏矩阵过大 ngram_range(1, 2), # 同时包含 unigram 和 bigram min_df2, # 词频2的忽略去噪声 max_df0.95, # 文档频率95%的忽略如“商品”“购买” sublinear_tfTrue, # 使用 sublinear 缩放缓解高频词主导 norml2 # L2归一化提升SVM稳定性 ) # 构建完整Pipeline预处理 → 特征提取 → 分类 pipeline Pipeline([ (preprocess, preprocessor), (tfidf, tfidf), (classifier, SVC(kernelrbf, probabilityTrue)) ]) # 网格搜索超参重点调C和gamma param_grid { classifier__C: [0.1, 1, 10, 100], classifier__gamma: [scale, auto, 0.001, 0.01, 0.1, 1] } grid_search GridSearchCV( pipeline, param_grid, cv5, scoringf1_weighted, # 加权F1适配类别不平衡 n_jobs-1, # 用满CPU verbose1 ) # 训练假设X_train是原始文本列表y_train是标签列表 grid_search.fit(X_train, y_train) print(Best params:, grid_search.best_params_) print(Best CV F1:, grid_search.best_score_)参数说明max_features5000是安全起点若显存充足可提到10000但超过15000易导致.fit()内存溢出sublinear_tfTrue将 TF 从线性变为1 log(tf)防止“的”“了”等高频虚词淹没真实信号scoringf1_weighted必须用加权而非宏平均——电商评论中“正面”样本常占70%宏平均会高估模型能力。3.3 传统机器学习避坑特征泄露、类别不平衡与冷启动现象 → 原因 → 解决现象GridSearchCV 报ValueError: Found array with 0 sample(s)。原因TfidfVectorizer在min_df2时若某条评论分词后所有词在全局文档中出现2次则整条变空字符串向量化后为全0向量SVM无法计算。解决在preprocessor后加一步lambda x: [ .join([UNK] * 3) if not t.strip() else t for t in x]用占位符填充空文本。现象测试集上召回率Recall极低尤其对“负面”类。原因原始数据中正面样本占比85%模型学会永远预测“正面”也能得85%准确率。解决在SVC中设置class_weightbalanced或改用LogisticRegressionclass_weightbalancedSVM的balanced实现不稳定。现象新上线商品评论含大量未登录词预测全错。原因TF-IDF 词表固定新词映射为0向量。解决启用TfidfVectorizer的vocabulary参数用历史数据训练词表新数据强制映射或改用HashingVectorizer无词表但不可逆。4. 深度学习用 PyTorch 写干净的 LSTM拒绝黑匣子别被“深度学习”吓住——本节的 LSTM 不是抄论文结构而是为中文短文本定制的轻量级序列模型单层 BiLSTM Attention Dropout参数量50万RTX3060上单epoch30秒。重点不是堆层数而是解决中文特有的变长、低资源、少标注问题。4.1 数据预处理构建词表、对齐长度、处理OOV深度学习不吃原始文本只吃数字ID。我们不用torchtext已弃用而用原生torchcollections.Counter手写词表全程可控# dl_preprocess.py import torch from collections import Counter from torch.nn.utils.rnn import pad_sequence class Vocab: def __init__(self, min_freq2, max_vocab10000): self.min_freq min_freq self.max_vocab max_vocab self.pad_token PAD self.unk_token UNK self.token2idx {self.pad_token: 0, self.unk_token: 1} self.idx2token {0: self.pad_token, 1: self.unk_token} def build_vocab(self, sentences): counter Counter() for sent in sentences: counter.update(sent.split()) # 按频次排序取前 max_vocab-2 个预留PAD/UNK vocab_items counter.most_common(self.max_vocab - 2) vocab_items [(word, freq) for word, freq in vocab_items if freq self.min_freq] for idx, (word, _) in enumerate(vocab_items, start2): self.token2idx[word] idx self.idx2token[idx] word def encode(self, sentence, max_len100): tokens sentence.split() ids [self.token2idx.get(t, self.token2idx[self.unk_token]) for t in tokens] # 截断或补零 if len(ids) max_len: ids ids[:max_len] else: ids ids [self.token2idx[self.pad_token]] * (max_len - len(ids)) return torch.tensor(ids, dtypetorch.long) # 使用示例 vocab Vocab(min_freq2, max_vocab8000) vocab.build_vocab(X_train_processed) # X_train_processed 是预处理后的空格分词字符串列表 # 编码训练集 X_train_ids [vocab.encode(sent) for sent in X_train_processed] X_train_tensor pad_sequence(X_train_ids, batch_firstTrue, padding_value0)关键设计min_freq2防止低频词爆炸词表max_vocab8000是平衡效果与内存的黄金值实测10000对小数据集提升0.5% F1pad_sequence自动对齐batch内所有序列比手动torch.zeros()更安全padding_value0对应PAD后续Embedding层可设padding_idx0自动mask。4.2 BiLSTM Attention 模型为什么不用BERTBERT 在本任务中是杀鸡用牛刀电商评论平均长度30字BiLSTM 已足够捕获局部依赖BERT-base 参数量110M单卡训练需8GB显存而我们的 BiLSTM 仅420KB你无法解释“为什么模型判这条为负面”——Attention权重可视化却能指出是“卡顿”“发热”两个词主导决策。# model.py import torch import torch.nn as nn class BiLSTM_Attention(nn.Module): def __init__(self, vocab_size, embed_dim128, hidden_dim64, num_classes3, dropout0.5): super().__init__() self.embedding nn.Embedding(vocab_size, embed_dim, padding_idx0) self.lstm nn.LSTM(embed_dim, hidden_dim, batch_firstTrue, bidirectionalTrue, num_layers1) self.dropout nn.Dropout(dropout) self.attention nn.Linear(hidden_dim * 2, 1) # BiLSTM输出是2*hidden_dim self.classifier nn.Linear(hidden_dim * 2, num_classes) def forward(self, x): # x: [batch, seq_len] embed self.embedding(x) # [batch, seq_len, embed_dim] lstm_out, _ self.lstm(embed) # [batch, seq_len, 2*hidden_dim] lstm_out self.dropout(lstm_out) # Attention机制为每个时间步计算权重 attention_weights torch.softmax(self.attention(lstm_out), dim1) # [batch, seq_len, 1] context_vector torch.sum(attention_weights * lstm_out, dim1) # [batch, 2*hidden_dim] logits self.classifier(context_vector) # [batch, num_classes] return logits # 初始化模型 model BiLSTM_Attention( vocab_sizelen(vocab.token2idx), embed_dim128, hidden_dim64, num_classes3, # 正面/中性/负面 dropout0.5 )模型细节说明hidden_dim64是经过验证的甜点值32维表达不足128维在小数据上易过拟合num_layers1足够——深层LSTM在短文本上并无收益反而增加梯度消失风险attention层用Linearsoftmax实现比复杂注意力更稳定且权重可直接取出可视化。4.3 深度学习避坑梯度爆炸、类别不平衡与过拟合现象 → 原因 → 解决现象训练初期 loss 突然变为nan。原因LSTM 隐状态指数增长梯度爆炸。解决在forward后添加torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0)并在训练循环中调用。现象验证集 loss 下降但 accuracy 停滞F1 甚至下降。原因类别不平衡导致模型偏向多数类交叉熵损失被“正面”样本主导。解决改用WeightedRandomSampler重采样训练集或在CrossEntropyLoss中传入weight参数根据各类样本数倒数计算。现象测试集上 negative 类 recall 仅0.3远低于词典法0.62。原因模型学到“负面词少负面概率低”的统计偏见而非语义。解决在损失函数中加入 Focal Lossalpha * (1-pt)^gamma * CE让模型聚焦难分样本gamma2效果最佳。5. 三路结果融合与可解释性分析让模型自己告诉你哪里不可信交作业不能只贴三个 F1 分数。真正的价值在于交叉验证当词典法说“负面”、SVM 说“中性”、LSTM 说“正面”时你要能定位矛盾根源——是词典漏了新词是 TF-IDF 特征被噪声淹没还是 LSTM 注意力聚焦在无关词上本节教你用三路结果反推数据与模型缺陷。5.1 构建结果对比 DataFrame一眼定位分歧样本# fusion.py import pandas as pd import numpy as np def create_comparison_df(X_raw, y_true, dict_preds, dict_scores, ml_preds, ml_probs, dl_preds, dl_probs): 汇总三路预测结果便于人工审计 df pd.DataFrame({ text: X_raw, true_label: y_true, dict_pred: dict_preds, dict_score: dict_scores, ml_pred: ml_preds, ml_confidence: np.max(ml_probs, axis1), dl_pred: dl_preds, dl_confidence: np.max(dl_probs, axis1) }) # 标记分歧类型 df[agreement] (df[dict_pred] df[ml_pred]) (df[ml_pred] df[dl_pred]) df[majority_vote] df[[dict_pred, ml_pred, dl_pred]].mode(axis1)[0] # 计算每条样本的“可信度分”三路置信度均值词典法用|score|归一化 df[dict_conf] np.abs(df[dict_score]) / (np.abs(df[dict_score]).max() 1e-8) df[ensemble_conf] (df[dict_conf] df[ml_confidence] df[dl_confidence]) / 3 return df # 使用示例 compare_df create_comparison_df( X_test_raw, y_test, dict_predictions, dict_scores, ml_predictions, ml_probabilities, dl_predictions, dl_probabilities ) # 导出分歧样本供人工检查 disagreement_df compare_df[~compare_df[agreement]].copy() disagreement_df.to_csv(reports/disagreements.csv, indexFalse, encodingutf-8-sig)这个 DataFrame 的威力在于agreement列直接筛出三路不一致的样本通常占15~25%majority_vote给出集成预测比单一路更鲁棒ensemble_conf是可解释性入口——低可信度样本值得优先人工标注用于迭代优化。5.2 可视化注意力权重让 LSTM “开口说话”LSTM 的黑盒感源于你看不见它关注什么。我们提取 Attention 权重热力图展示模型决策依据# attention_vis.py import matplotlib.pyplot as plt import seaborn as sns def plot_attention_heatmap(text, attention_weights, save_pathNone): text: 原始字符串未分词 attention_weights: [seq_len] 的tensor来自模型forward words text.split() # 截断或补零至weights长度 if len(words) len(attention_weights): words words[:len(attention_weights)] else: words [] * (len(attention_weights) - len(words)) plt.figure(figsize(10, 2)) sns.heatmap( np.array(attention_weights).reshape(1, -1), xticklabelswords, yticklabels[Attention], cmapYlOrRd, cbar_kws{label: Attention Weight} ) plt.xticks(rotation45, haright) plt.tight_layout() if save_path: plt.savefig(save_path, dpi300, bbox_inchestight) plt.show() # 示例取一条分歧样本 sample_idx disagreement_df.index[0] sample_text disagreement_df.loc[sample_idx, text] # 假设你已保存了该样本的attention_weights模型forward返回 # plot_attention_heatmap(sample_text, attention_weights)注意attention_weights需在模型forward中返回修改forward函数return logits, attention_weights不要用register_forward_hook——那会破坏训练流。5.3 融合策略实战投票、加权、元学习哪种适合你别迷信“集成一定更好”。我们实测三种策略在本任务中的表现策略实现方式测试集 F1适用场景硬投票scipy.stats.mode([dict, ml, dl])0.821快速 baseline无需概率输出加权平均0.3*dict_score 0.4*ml_prob 0.3*dl_prob0.837当各路输出置信度可靠时需校准Stacking 元分类器用三路预测概率作为新特征训练 LR0.842数据量5000时推荐但小数据易过拟合血泪经验不要用 XGBoost 做元分类器——它在小样本上 variance 太大F1 波动±0.03而 LogisticRegression 稳定在±0.005。# stacking.py from sklearn.linear_model import LogisticRegression from sklearn.ensemble import StackingClassifier # 构造元特征每条样本的 [dict_score, ml_prob_pos, ml_prob_neu, ml_prob_neg, dl_prob_pos, ...] meta_features np.column_stack([ np.array(dict_scores), ml_probabilities, # shape: (n_samples, 3) dl_probabilities # shape: (n_samples, 3) ]) # 训练元分类器注意用校准后的概率 meta_clf LogisticRegression(class_weightbalanced) meta_clf.fit(meta_features, y_test) # 预测 stacked_pred meta_clf.predict(meta_features)关键提示ml_probabilities和dl_probabilities必须经过CalibratedClassifierCV校准否则概率值不可靠。词典法分数需归一化到[0,1]区间如sigmoid(score)。6. 从作业到落地部署为 API、监控漂移、持续迭代的硬核技巧交完作业不是终点。如果你真想把这个项目放进简历必须证明它能脱离 Jupyter Notebook 运行。本节不讲 Docker/K8s只用最简方案Flask API 日志监控 数据飞轮所有代码可在 10 分钟内部署到任意 Linux 服务器。6.1 用 Flask 封装三路模型为 REST API拒绝pickle加载模型版本兼容性地狱改用joblib 显式版本声明# app.py from flask import Flask, request, jsonify import joblib import torch from dl_preprocess import Vocab from model import BiLSTM_Attention app Flask(__name__) # 加载模型注意路径和版本号必须显式声明 DICT_MODEL_PATH models/dict_v1.2.pkl ML_MODEL_PATH models/ml_svm_v2.1.joblib DL_MODEL_PATH models/dl_lstm_v1.0.pth VOCAB_PATH models/vocab_v1.0.joblib # 全局加载避免每次请求重复IO dict_model joblib.load(DICT_MODEL_PATH) ml_model joblib.load(ML_MODEL_PATH) dl_model torch.load(DL_MODEL_PATH, map_locationcpu) vocab joblib.load(VOCAB_PATH) app.route(/predict, methods[POST]) def predict(): data request.get_json() text data.get(text, ).strip() if not text: return jsonify({error: text is required}), 400 try: # 词典法 dict_score score_sentence(text, *load_sentiment_dict()) # 复用2.2节函数 dict_pred positive if dict_score 0.5 else negative if dict_score -0.5 else neutral # 机器学习 ml_pred ml_model.predict([text])[0] ml_prob ml_model.predict_proba([text])[0].tolist() # 深度学习 processed segment_and_filter(clean_text(text)) # 复用3.1节函数 ids vocab.encode(processed) ids ids.unsqueeze(0) # [1, seq_len] with torch.no_grad(): logits dl_model(ids) probs torch.softmax(logits, dim1)[0].tolist() dl_pred [positive, neutral, negative][torch.argmax(logits).item()] return jsonify({ text: text, dict: {label: dict_pred, score: round(dict_score, 3)}, ml: {label: int(ml_pred), probabilities: ml_prob}, dl: {label: dl_pred, probabilities: probs}, ensemble: {label: TODO, confidence: 0.0} # p a hrefhttps://download.csdn.net/download/qq_38140936/89400885 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑