ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于TensorFlow与DNN的中文情感分析模型构建实战

2026/9/4 21:49:15 拓冰建站 浏览量
基于TensorFlow与DNN的中文情感分析模型构建实战 简介本资源是一个面向NLP初学者与深度学习实践者的中文文本分类项目基于TensorFlow和Keras构建DNN模型实现豆瓣中文影评的二分类情感分析差评/好评适用于自然语言处理入门、课程设计及小型实战训练。压缩包共4个文件含核心训练脚本main.py、标注数据集douban_comments.csv、项目说明README.md及LICENSE许可文件整体大小3.52MB结构精简便于快速复现与调试。已有261人学习下载覆盖从数据预处理、词嵌入加载、DNN模型搭建含全连接层设计与Sigmoid输出、编译训练到预测评估的完整流程代码注释清晰适配中文分词与序列填充等关键处理环节可直接运行并拓展为多分类或接入BERT等进阶模型。1. 项目概述从零构建一个中文情感分析模型最近在整理旧项目时翻出了一个几年前做的“豆瓣影评情感分析”项目。这个项目的核心目标很简单训练一个神经网络模型让它能像人一样读懂一段中文影评并判断出作者是“好评”还是“差评”。听起来像是NLP自然语言处理的入门“Hello World”但麻雀虽小五脏俱全。它完整地串联了从数据获取、文本预处理、模型构建、训练调优到最终预测的整个机器学习流水线。对于想入门深度学习特别是对自然语言处理感兴趣的朋友来说这是一个绝佳的练手项目。它不涉及复杂的图像或序列结构重点在于理解如何处理非结构化的文本数据并将其转化为神经网络能够“消化”的数字特征。这个项目基于TensorFlow和Keras框架实现。选择它们的原因很直接Keras以其简洁、用户友好的API著称能让我们快速搭建和实验模型原型而TensorFlow作为其后端提供了坚实的计算基础和部署灵活性。模型本身采用了经典的深度前馈神经网络DNN也就是全连接神经网络。虽然现在Transformer和预训练模型大行其道但对于情感分析这种相对“浅层”的语义理解任务一个结构合理的DNN在中等规模数据集上依然能取得非常不错的效果并且其原理直观非常适合初学者理解神经网络如何从词向量中学习到情感特征。整个项目的价值在于“端到端”的实践体验。你不仅会学到如何用jieba分词、用Tokenizer构建词表还会亲手设计网络层、选择激活函数、观察损失曲线并最终得到一个可以对新影评进行情感判别的实用小工具。下面我就把这个项目的完整实现思路、关键步骤以及我踩过的那些“坑”详细拆解一遍。2. 核心思路与技术选型解析2.1 问题定义与任务拆解我们的目标是构建一个二分类模型。输入是一段中文文本影评输出是一个二元标签0代表差评1代表好评。这本质上是一个文本分类任务更具体地说是情感分析Sentiment Analysis中的极性分类。要实现这个目标我们需要解决几个核心子问题文本数值化神经网络只能处理数字而影评是文字。如何将一段可变长度的中文句子转换成一个固定长度的、富含语义信息的数字向量特征学习如何设计一个网络结构让它能从这些数字向量中自动学习到与“情感”相关的特征模式例如哪些词组合在一起通常表达愤怒差评哪些表达赞赏好评。泛化能力如何让模型不仅记住训练数据还能对从未见过的影评做出准确判断这涉及到模型复杂度控制、正则化等技术。2.2 技术栈选型背后的考量TensorFlow Keras这是项目的基石。Keras在TensorFlow 2.x中已成为其官方高级API。它的tf.keras模块提供了极佳的易用性。对于本项目我们主要用到keras.layers来搭建网络keras.preprocessing.text来处理文本keras.models来管理模型生命周期。选择它们而非PyTorch主要是考虑到Keras在快速原型开发和教育场景下的低门槛优势其顺序模型Sequential的写法非常直观。深度前馈神经网络DNN为什么不用更“时髦”的CNN或RNN这里有几个考量。首先在文本分类任务中当我们使用词嵌入Word Embedding将文本转换为稠密向量序列后一个句子可以看作一个“词袋”的升级版保留了部分顺序信息。DNN全连接网络擅长学习这种高维特征之间的复杂非线性关系。其次DNN的结构简单训练速度快对于“好评/差评”这种全局情感判断往往不需要像RNN那样显式建模长距离依赖也不一定需要CNN来捕捉局部短语特征虽然它们有效。我们的策略是先用一个基础的DNN实现一个可靠的基线模型理解整个流程后续可以很容易地将其替换为CNN、LSTM或BERT进行效果对比和提升。辅助工具Jieba必不可少的中文分词工具。英文有天然的空格分隔中文则需要分词。jieba的精度和速度在开源工具中表现均衡支持自定义词典可以加入一些电影领域的专有名词如导演名、片名以提高分词准确性。Pandas NumPy用于数据加载、清洗和转换的黄金搭档。Pandas的DataFrame非常适合处理结构化的表格数据如CSV格式的影评数据集。Scikit-learn虽然模型用Keras但数据划分train_test_split、评估指标如分类报告classification_report等工具scikit-learn提供了更统一和方便的接口。注意在开始之前强烈建议使用虚拟环境如venv或conda来管理项目依赖。因为TensorFlow的版本与Python版本、CUDA如果使用GPU有严格的对应关系。一个独立的虚拟环境可以避免包冲突。例如可以使用conda create -n tf-keras python3.8创建一个环境然后pip install tensorflow安装CPU版本。如果需要GPU支持则需安装tensorflow-gpu并配置对应的CUDA和cuDNN。3. 数据准备与预处理全流程模型的效果七分靠数据三分靠调参。这一步是项目中最繁琐但也最关键的一环。3.1 数据获取与初步观察理想的数据集是包含“影评文本”和“情感标签”两列的CSV文件。标签可以是“1/0”也可以是“positive/negative”。我们假设你已经有了这样一个数据集可以从公开的中文情感分析数据集如ChnSentiCorp或者通过爬虫获取豆瓣影评并手动/半自动标注得到。首先用Pandas加载数据import pandas as pd # 假设数据文件为 reviews.csv列名为 ‘review‘ 和 ‘sentiment‘ df pd.read_csv(‘reviews.csv‘) print(df.head()) # 查看前几行 print(df.info()) # 查看数据概览有无缺失值 print(df[‘sentiment‘].value_counts()) # 查看标签分布检查标签分布是否均衡。如果“好评”和“差评”数量相差悬殊例如9:1模型可能会偏向多数类需要进行重采样或调整类别权重。3.2 中文文本清洗与分词中文文本预处理通常包括以下步骤去除无关字符删除HTML标签、URL、用户名、特殊符号如※★、表情符号等。这些信息对情感判断通常无益甚至有害。分词使用jieba将句子切分成词语序列。去除停用词剔除“的”、“了”、“在”等高频但无实际语义的词语。可以使用哈工大、百度等开源的中文停用词表。可选繁体转简体如果数据集中包含繁体字使用opencc等工具进行转换。import jieba import re def clean_and_cut(text): # 1. 去除非中文字符、数字、英文字母根据需求调整 # 这里保留中文、数字、英文去除其他符号 text re.sub(r‘[^\u4e00-\u9fa5a-zA-Z0-9\s]‘, ‘‘, text) # 2. 分词 words jieba.lcut(text) # 3. 去除停用词 (假设已加载停用词列表 stopwords) global stopwords words [w for w in words if w not in stopwords and w.strip() ! ‘‘] # 4. 用空格连接词语形成标准格式 return ‘ ‘.join(words) # 应用清洗函数到整个评论列 df[‘cleaned_review‘] df[‘review‘].apply(clean_and_cut)实操心得分词和停用词处理需要根据任务灵活调整。例如在影评中“烂片”是一个强负面信号但如果停用词表包含了“片”或者分词错误就会丢失这个关键信息。可以考虑构建一个领域专用的停用词表和用户词典将“烂片”、“演技炸裂”等短语作为一个整体加入分词词典。3.3 文本向量化与序列填充神经网络需要固定长度的输入。我们需要将分词后的文本词语序列转换为数字序列索引序列并将所有序列填充或截断到相同长度。Keras的Tokenizer类可以帮我们自动构建词表词汇到整数的映射并完成转换。from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences # 初始化Tokenizer设置只考虑数据集中出现频率最高的前10000个词 vocab_size 10000 tokenizer Tokenizer(num_wordsvocab_size, oov_token‘OOV‘) # 拟合Tokenizer到我们的文本数据构建词表 tokenizer.fit_on_texts(df[‘cleaned_review‘]) # 将文本转换为数字序列 sequences tokenizer.texts_to_sequences(df[‘cleaned_review‘]) # 确定一个合适的序列最大长度。可以取所有序列长度的某个百分位数如95% max_length 200 # 进行填充在前端补0和截断从后端截断 padded_sequences pad_sequences(sequences, maxlenmax_length, padding‘post‘, truncating‘post‘) # 准备标签 labels df[‘sentiment‘].values # 假设标签已经是0/1num_words10000这是一个超参数。它限制了词表大小只保留最常见的10000个词其他词会被视为OOV未登录词。根据数据集大小调整太小会丢失信息太大会增加模型参数和过拟合风险。oov_token‘OOV‘为未登录词指定一个统一的标记这比直接忽略它们更好让模型知道有未知词存在。max_length200另一个关键超参数。需要分析序列长度的分布来确定。太短会损失长评论信息太长会引入大量无意义的填充浪费计算资源。可以通过import matplotlib.pyplot as plt; plt.hist([len(s) for s in sequences])来可视化长度分布。padding‘post‘在序列末尾填充0。对于某些RNN模型pre填充可能更好但对于DNNpost填充更常见。3.4 数据集划分在开始训练前必须将数据划分为训练集、验证集和测试集。训练集用于模型参数更新。验证集用于在训练过程中监控模型在未见数据上的表现以进行超参数调优和早停Early Stopping防止过拟合。测试集仅在最终评估模型性能时使用一次模拟模型在真实世界新数据上的表现。from sklearn.model_selection import train_test_split # 先分出测试集例如20% X_temp, X_test, y_temp, y_test train_test_split(padded_sequences, labels, test_size0.2, random_state42, stratifylabels) # 再从剩余数据中分出验证集例如剩余部分的25%即总体的20% X_train, X_val, y_train, y_val train_test_split(X_temp, y_temp, test_size0.25, random_state42, stratifyy_temp) # 0.25 * 0.8 0.2 print(f“训练集大小: {X_train.shape}“) print(f“验证集大小: {X_val.shape}“) print(f“测试集大小: {X_test.shape}“)使用stratifylabels可以确保在每个数据子集中好评和差评的比例与原始数据集保持一致这对于不平衡数据集尤为重要。4. DNN模型构建与层析解读有了处理好的数据我们就可以搭建神经网络了。我们将使用Keras的Sequential API以最直观的方式堆叠网络层。4.1 模型架构设计一个用于文本分类的典型DNN模型通常包含以下几层嵌入层Embedding Layer这是将整数索引映射为稠密向量的关键层。你可以把它理解为一个可查询的字典输入一个词的索引如5它就输出一个固定长度的向量如[0.2, -0.1, 0.5, ...]。这个向量会在训练过程中不断更新使得语义相近的词在向量空间中的位置也更接近。展平层Flatten Layer嵌入层的输出是一个3D张量样本数, 序列长度, 嵌入维度。全连接层需要2D输入样本数, 特征数。展平层的作用就是将后两个维度“压平”例如将(None, 200, 128)变成(None, 200*12825600)。全连接层Dense Layer也称为隐藏层。这是模型学习非线性特征组合的地方。我们通常会使用一至多个全连接层每层后面跟一个激活函数如ReLU来引入非线性。输出层Output Layer最后一个全连接层神经元数量为1二分类使用sigmoid激活函数将输出值压缩到0到1之间可以解释为“属于好评的概率”。from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding, Flatten, Dense, Dropout embedding_dim 128 # 词向量的维度超参数 model Sequential([ # 嵌入层输入维度(vocab_size)输出维度(embedding_dim)输入长度(max_length) Embedding(input_dimvocab_size, output_dimembedding_dim, input_lengthmax_length), # 展平层将 (max_length, embedding_dim) 的矩阵展平为一维向量 Flatten(), # 第一个全连接隐藏层128个神经元使用ReLU激活函数 Dense(128, activation‘relu‘), # Dropout层随机丢弃50%的神经元连接防止过拟合 Dropout(0.5), # 第二个全连接隐藏层64个神经元 Dense(64, activation‘relu‘), Dropout(0.3), # 输出层1个神经元sigmoid激活函数 Dense(1, activation‘sigmoid‘) ]) # 查看模型结构摘要 model.summary()4.2 关键层与超参数详解Embedding层参数input_dim词表大小 1因为索引从1开始0通常预留给填充符。我们之前设置num_words10000所以这里应该是100001实际上Tokenizer的num_words会确保索引从1到100000被预留所以input_dim设置为vocab_size10000即可但更安全的做法是len(tokenizer.word_index) 1或者直接vocab_size 1。output_dim词向量的维度。常见值在50-300之间。维度越高表达能力越强但也需要更多数据来训练更容易过拟合。128是一个不错的起点。input_length输入序列的长度即我们之前设定的max_length。Dense层与Dropout隐藏层的神经元数量128, 64是经验性超参数。可以从一个较小的网络开始如64-32如果欠拟合训练集和验证集准确率都低再增加层数或神经元数。Dropout是神经网络中最有效的正则化技术之一。它在训练时随机“关闭”一部分神经元迫使网络不依赖于任何单个神经元从而学习到更鲁棒的特征。Dropout(0.5)意味着每个神经元有50%的概率在本次训练中被临时丢弃。通常在靠近输入和隐藏层使用较高的Dropout率。激活函数选择隐藏层使用ReLU计算简单能有效缓解梯度消失问题是目前最常用的激活函数。输出层使用Sigmoid将输出值映射到(0,1)区间完美适配二分类问题的概率输出。4.3 模型编译配置学习过程模型搭建好后需要指定它的学习机制。model.compile(optimizer‘adam‘, loss‘binary_crossentropy‘, metrics[‘accuracy‘])优化器optimizeradam是自适应学习率优化算法结合了Momentum和RMSProp的优点在大多数情况下表现良好且无需太多调参是默认的首选。损失函数loss对于二分类问题binary_crossentropy二元交叉熵是标准选择。它衡量了模型预测的概率分布与真实标签分布之间的差异。评估指标metrics在训练和评估过程中我们除了看损失值更关心分类准确率accuracy。对于不平衡数据集还可以加入Precision、Recall、F1-score等。5. 模型训练、验证与调优实战5.1 启动训练与回调设置现在我们可以用训练数据来“喂养”模型了。在训练过程中我们会同时在验证集上评估以监控模型是否过拟合。from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint # 定义回调函数 callbacks [ # 早停当验证集损失连续3个epoch不再下降时停止训练并恢复最佳权重 EarlyStopping(monitor‘val_loss‘, patience3, restore_best_weightsTrue), # 模型检查点保存验证集上性能最好的模型 ModelCheckpoint(‘best_model.h5‘, monitor‘val_accuracy‘, save_best_onlyTrue, mode‘max‘) ] history model.fit( X_train, y_train, epochs20, # 训练轮数通常会被早停回调提前终止 batch_size32, # 每次梯度更新使用的样本数。越小梯度更新越频繁训练越慢但可能更稳定。 validation_data(X_val, y_val), callbackscallbacks, verbose1 # 显示训练进度条 )batch_size常见值有32, 64, 128。如果你的GPU内存足够大增大batch_size可以加速训练但可能会影响模型泛化能力。可以从32开始尝试。epochs设置一个较大的值依靠EarlyStopping回调来避免无意义的过拟合训练。EarlyStoppingpatience3表示可以容忍验证集损失连续3轮不下降。restore_best_weightsTrue非常重要它确保训练结束后模型加载的是验证集上表现最好的权重而不是最后一轮的权重。5.2 训练过程可视化与分析训练结束后history对象保存了每个epoch的训练指标。可视化这些指标是诊断模型问题的关键。import matplotlib.pyplot as plt def plot_history(history): fig, (ax1, ax2) plt.subplots(1, 2, figsize(12, 4)) # 绘制准确率曲线 ax1.plot(history.history[‘accuracy‘], label‘Train Accuracy‘) ax1.plot(history.history[‘val_accuracy‘], label‘Val Accuracy‘) ax1.set_title(‘Model Accuracy‘) ax1.set_xlabel(‘Epoch‘) ax1.set_ylabel(‘Accuracy‘) ax1.legend() # 绘制损失曲线 ax2.plot(history.history[‘loss‘], label‘Train Loss‘) ax2.plot(history.history[‘val_loss‘], label‘Val Loss‘) ax2.set_title(‘Model Loss‘) ax2.set_xlabel(‘Epoch‘) ax2.set_ylabel(‘Loss‘) ax2.legend() plt.tight_layout() plt.show() plot_history(history)通过观察曲线我们可以判断模型状态理想情况训练和验证的损失同步下降准确率同步上升最终趋于平稳且两者差距很小。过拟合训练损失持续下降训练准确率持续上升但验证损失在某个点后开始上升验证准确率停滞甚至下降。两条曲线出现明显“分叉”。解决方案增加Dropout率、增加L2正则化、使用更简单的网络结构、获取更多训练数据、进行数据增强。欠拟合训练和验证的损失/准确率都很差且训练损失下降缓慢。解决方案增加模型复杂度更多层、更多神经元、减少正则化、延长训练时间、检查特征工程是否有效。5.3 超参数调优思路如果基线模型效果不理想可以系统性地调整以下超参数词向量维度embedding_dim尝试64, 128, 256。序列最大长度max_length根据数据分布调整尝试100, 200, 300。词表大小vocab_size尝试5000, 10000, 20000。网络结构调整隐藏层的数量和神经元数例如[256, 128],[128, 64, 32]。Dropout率在0.2到0.5之间调整。优化器与学习率可以尝试RMSprop或者为Adam设置一个较小的学习率如optimizertf.keras.optimizers.Adam(learning_rate1e-4)。批大小batch_size尝试16, 32, 64。实操心得调参时务必一次只改变一个变量并记录每次实验的配置和结果可以使用TensorBoard或简单的日志文件。优先调整对模型性能影响最大的参数如embedding_dim、网络结构和Dropout率。使用验证集性能作为调参依据绝对不要根据测试集结果来调参否则测试集就失去了其作为最终性能评估的公正性。6. 模型评估、预测与部署6.1 在测试集上进行最终评估训练和调优完成后使用从未参与过任何训练或验证过程的测试集对保存的最佳模型进行最终评估。# 加载早停回调保存的最佳模型 from tensorflow.keras.models import load_model best_model load_model(‘best_model.h5‘) # 在测试集上评估 test_loss, test_accuracy best_model.evaluate(X_test, y_test, verbose0) print(f“测试集损失: {test_loss:.4f}“) print(f“测试集准确率: {test_accuracy:.4f}“) # 更详细的评估分类报告和混淆矩阵 from sklearn.metrics import classification_report, confusion_matrix import seaborn as sns y_pred_prob best_model.predict(X_test) y_pred (y_pred_prob 0.5).astype(“int32“) # 以0.5为阈值进行二值化 print(“\n分类报告:“) print(classification_report(y_test, y_pred, target_names[‘差评‘, ‘好评‘])) # 绘制混淆矩阵 cm confusion_matrix(y_test, y_pred) sns.heatmap(cm, annotTrue, fmt‘d‘, cmap‘Blues‘, xticklabels[‘差评‘, ‘好评‘], yticklabels[‘差评‘, ‘好评‘]) plt.xlabel(‘预测标签‘) plt.ylabel(‘真实标签‘) plt.title(‘混淆矩阵‘) plt.show()分类报告会给出精确率Precision、召回率Recall和F1分数这对于不平衡数据集尤为重要。混淆矩阵能直观地看出模型在两类上的具体错误情况。6.2 对新影评进行预测构建一个完整的预测管道将新的原始影评文本输入输出情感倾向。def predict_sentiment(review_text): 预测单条影评的情感。 参数: review_text (str): 原始影评文本。 返回: str: ‘好评‘ 或 ‘差评‘以及概率值。 # 1. 清洗和分词使用与训练数据相同的函数 cleaned_text clean_and_cut(review_text) # 2. 文本转序列使用训练时拟合好的tokenizer sequence tokenizer.texts_to_sequences([cleaned_text]) # 3. 序列填充使用训练时相同的max_length padded_sequence pad_sequences(sequence, maxlenmax_length, padding‘post‘, truncating‘post‘) # 4. 模型预测 prediction_prob best_model.predict(padded_sequence, verbose0)[0][0] # 5. 解释结果 sentiment ‘好评‘ if prediction_prob 0.5 else ‘差评‘ confidence prediction_prob if sentiment ‘好评‘ else (1 - prediction_prob) return f“情感: {sentiment} (置信度: {confidence:.2%})“ # 测试一下 new_review “这部电影的剧情太拖沓了看得我昏昏欲睡演员演技也很尴尬。“ print(predict_sentiment(new_review)) # 应输出差评 new_review2 “导演的叙事手法太棒了镜头语言充满诗意结尾让人回味无穷。“ print(predict_sentiment(new_review2)) # 应输出好评6.3 模型保存与部署考虑训练好的模型需要保存下来以供后续使用。Keras提供了多种格式HDF5格式.h5model.save(‘my_model.h5‘)保存完整的模型结构、权重和训练配置。这是我们之前用ModelCheckpoint保存的格式。SavedModel格式tf.keras.models.save_model(model, ‘my_saved_model‘)这是TensorFlow推荐的格式更适合跨平台部署。对于简单的本地应用你可以将模型文件、tokenizer通过pickle保存和预处理函数打包写成一个Python脚本或简单的Flask/FastAPI接口就能提供一个情感分析服务。7. 常见问题排查与性能提升技巧在实际操作中你几乎一定会遇到下面这些问题。这里是我总结的一些排查思路和进阶技巧。7.1 模型性能不佳的排查清单问题现象可能原因排查与解决思路训练准确率低验证准确率也低1. 模型能力不足欠拟合2. 特征信息不足3. 数据质量差/噪声大1. 增加网络层数或神经元数量。2. 增加embedding_dim或max_length。3. 检查数据清洗和分词是否合理标签是否正确。训练准确率高验证准确率低过拟合1. 模型过于复杂2. 训练数据量太少3. 正则化不足1. 简化网络结构减少神经元。2. 增加Dropout率或在Dense层添加kernel_regularizer。3. 尝试获取更多训练数据或进行简单的数据增强如回译、同义词替换。训练过程不稳定损失震荡大1. 学习率过高2. 批大小Batch Size太小1. 降低优化器的学习率如Adam(learning_rate1e-4)。2. 适当增大batch_size如从32调到64。验证准确率在某个值附近波动无法提升1. 模型达到数据上限天花板2. 存在难以学习的特征或噪声1. 尝试更复杂的模型如LSTM、CNN或预训练模型。2. 重新审视特征工程检查是否有重要特征被过滤掉如是否过度使用了停用词。7.2 进阶优化与扩展方向当你的基线DNN模型达到一个稳定水平后可以尝试以下方向进一步提升效果使用预训练词向量我们之前的Embedding层是随机初始化并在任务中从头训练的。可以加载像word2vec、GloVe或中文的Tencent AI Lab Embedding、BERT等预训练词向量来初始化嵌入层。这相当于为模型注入了先验的语言知识通常能显著提升效果尤其是在训练数据不多的情况下。在Keras中你可以构建一个预训练权重矩阵并将其设置为Embedding层的初始权重并选择是否在训练中微调trainableTrue/False。尝试不同的网络结构CNN for Text使用一维卷积层Conv1D和全局池化层GlobalMaxPooling1D来捕捉评论中的关键局部短语特征如“演技炸裂”、“五毛特效”。RNN/LSTM/GRU使用循环神经网络层来处理文本的序列依赖关系更适合建模长距离的语义关联。可以将LSTM层接在Embedding层之后。混合模型结合CNN和RNN的优点例如用CNN提取局部特征后再输入到LSTM中学习序列信息。集成预训练语言模型如BERT这是当前NLP的SOTA方案。使用Hugging Face的Transformers库可以轻松加载中文BERT模型将其作为特征提取器或进行微调。对于情感分析这种句子级分类任务BERT几乎总能带来巨大的性能提升但计算成本也更高。处理类别不平衡如果差评和好评数量差距很大除了在数据层面过采样/欠采样还可以在模型层面解决。在model.compile时通过class_weight参数为少数类赋予更高的权重或者在损失函数中使用tf.keras.losses.BinaryFocalCrossentropy它能够降低易分类样本的权重使模型更关注难分类的样本。这个基于DNN的豆瓣影评情感分析项目就像一座通往深度学习NLP世界的桥梁。它涵盖了从数据到产品的完整链路每一个环节的思考和调整都是宝贵的实战经验。模型本身的准确率可能不会达到工业级应用的水平但这个过程所锻炼出的数据直觉、模型调试能力和问题解决思维是任何教程都无法替代的。当你亲手让这个模型从无到有并看着它逐渐学会分辨喜怒哀乐时那种成就感正是驱动我们不断探索的动力。本文还有配套的精品资源点击获取