2

【深度学习教程】Python 如何用 CNN 做情感分析?小白也能上手!

Hello 大家好,这里是你的深度学习小助手!今天我们聊一个非常热门的话题——如何用卷积神经网络(CNN)来做情感分析!如果你对人工智能感兴趣,或者想在NLP(自然语言处理)领域大显身手,那么今天的内容千万不要错过,妥妥的干货!而且这次教程完全从零开始,就算是新手小白,看完也能轻松上手。

说到情感分析,很多人第一反应可能是 RNN(循环神经网络)或者 LSTM(长短期记忆网络)。但实际上,CNN 在处理文本任务时同样有强大的表现力,尤其是在情感分析这种短文本分类任务中,CNN 的高效性和准确性往往能让你眼前一亮。

接下来,我们就用 PythonKeras 实现一个简单的 CNN 模型,对 IMDB 电影评论数据集进行情感分类。话不多说,让我们直接开整吧!

image.png


1. 什么是 CNN?为什么它适合情感分析?

先补点基础知识!

什么是 CNN?

CNN,卷积神经网络(Convolutional Neural Network),是一种非常强大的深度学习模型。它的本质是通过“卷积操作”提取数据中的局部特征,并结合“池化操作”压缩特征图,从而完成分类、检测等任务。

虽然 CNN 最初是为图像处理设计的,但它在处理文本时同样得心应手!为什么?因为卷积操作能够捕捉到文本中局部的上下文模式(比如“good movie”表示正面情绪),这对于情感分析至关重要。

为什么用 CNN 做情感分析?

CNN 适合情感分析的几个原因:

  1. 局部感知:CNN 可以捕捉短语级别的情感特征,比如“excellent performance”或“terrible plot”。
  2. 高效性:相比 RNN,CNN 的计算效率更高,尤其在处理长文本时更具优势。
  3. 模型简单:CNN 架构相对简单,训练起来也更快。

2. 项目概述

在这个项目中,我们将用 CNN 模型对 IMDB 电影评论数据集进行情感分类。这是一个非常经典的 NLP 数据集,包含 50,000 条标注为正面(1)负面(0)的电影评论。

项目的主要步骤如下:

  1. 数据加载和预处理:将文本数据转换为 CNN 可处理的格式;
  2. 构建 CNN 模型:设计一个简单的卷积神经网络;
  3. 训练与评估:训练模型并测试其效果;
  4. 情感预测:用训练好的模型对新评论进行情感预测。

3. 环境准备

在开始之前,先确认你安装了以下 Python 库:

  • TensorFlow(内含 Keras)
  • numpy
  • matplotlib(可选,用于可视化训练结果)

如果还没安装,可以用以下命令搞定:

pip install tensorflow numpy matplotlib

4. 数据加载与预处理

我们依然使用 Keras 自带的 IMDB 数据集,省去了数据爬取和清理的麻烦。IMDB 数据集中的评论已经被转换为整数序列,每个整数对应一个单词。我们只需要对这些序列进行填充和标准化。

加载数据集

from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences

# 超参数设置
max_words = 10000  # 只保留数据集中最常见的 10,000 个单词
max_len = 200  # 每条评论截断或填充到 200 个单词

# 加载 IMDB 数据集
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_words)

print(f"训练集样本数: {len(x_train)}, 测试集样本数: {len(x_test)}")

数据预处理

CNN 要求输入的序列长度一致,所以我们需要将每条评论填充或截断到相同长度。使用 Keras 提供的 pad_sequences 方法非常方便:

# 填充序列
x_train = pad_sequences(x_train, maxlen=max_len)
x_test = pad_sequences(x_test, maxlen=max_len)

print(f"填充后的训练数据形状: {x_train.shape}")

5. 构建 CNN 模型

接下来是最核心的一步:搭建 CNN 模型。我们的 CNN 模型包括以下几个关键部分:

  1. 嵌入层(Embedding Layer):将单词 ID 映射到稠密向量;
  2. 卷积层(Conv1D):提取局部的情感特征;
  3. 池化层(MaxPooling1D):压缩特征图,保留关键信息;
  4. 全连接层(Dense Layer):输出分类结果。

CNN 模型代码

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Conv1D, MaxPooling1D, Dense, Flatten

# 定义模型
model = Sequential([
    Embedding(input_dim=max_words, output_dim=128, input_length=max_len),  # 嵌入层
    Conv1D(128, 5, activation='relu'),  # 卷积层,128 个过滤器,核大小为 5
    MaxPooling1D(5),  # 池化层,池大小为 5
    Flatten(),  # 将特征图展开成一维向量
    Dense(128, activation='relu'),  # 全连接层
    Dense(1, activation='sigmoid')  # 输出层,sigmoid 激活用于二分类
])

# 编译模型
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

# 打印模型摘要
model.summary()

6. 模型训练

我们用训练集训练模型,同时设置一部分数据作为验证集。每次训练一个小批量(batch)的样本,逐步更新模型参数。

训练代码

# 定义训练参数
batch_size = 64
epochs = 5

# 训练模型
history = model.fit(
    x_train, y_train,
    batch_size=batch_size,
    epochs=epochs,
    validation_split=0.2  # 20% 的训练集作为验证集
)

7. 模型评估

训练完成后,我们可以在测试集上评估模型的效果。

# 测试模型
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
print(f"测试集准确率: {test_acc:.4f}")

如果模型的测试集准确率高于 85%,说明我们的 CNN 模型表现不错!


8. 情感预测

模型训练好之后,我们可以用它对新评论进行情感预测。以下是完整的预测步骤:

情感预测代码

假设我们有一条新的电影评论:“The plot was amazing, and the characters were so well developed!”

from tensorflow.keras.preprocessing.text import Tokenizer

# 定义新的评论
new_review = ["The plot was amazing, and the characters were so well developed!"]

# 创建一个 Tokenizer,将单词转化为整数序列
tokenizer = Tokenizer(num_words=max_words)
tokenizer.fit_on_texts(new_review)
new_review_seq = tokenizer.texts_to_sequences(new_review)

# 填充序列长度
new_review_pad = pad_sequences(new_review_seq, maxlen=max_len)

# 使用训练好的模型预测
prediction = model.predict(new_review_pad)

# 输出预测结果
if prediction[0][0] > 0.5:
    print(f"预测结果: 正面情感,置信度: {prediction[0][0]:.2f}")
else:
    print(f"预测结果: 负面情感,置信度: {1 - prediction[0][0]:.2f}")

模型会输出一个在 [0, 1] 之间的概率值:

  • 接近 1 表示正面情感;
  • 接近 0 表示负面情感。

9. 可视化训练过程

为了更直观地了解模型的训练过程,我们可以用 Matplotlib 绘制训练和验证的损失值及准确率变化曲线。

绘制代码

import matplotlib.pyplot as plt

# 绘制训练和验证的损失值
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Loss Curve')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

# 绘制训练和验证的准确率
plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Accuracy Curve')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

通过这些图表,我们可以清楚地看到模型是否收敛以及是否发生了过拟合。


10. 模型优化建议

虽然我们已经完成了一个简单的 CNN 情感分析项目,但还有许多优化的方向可以提升模型的性能:

1. 调整超参数

  • 卷积核大小:尝试不同的卷积核大小(如 3、5、7)来捕捉不同范围的情感特征。
  • 过滤器数量:增加或减少卷积层的过滤器数量,找到最佳的模型复杂度。
  • Dropout:在卷积层后增加 Dropout 层,防止过拟合。

2. 使用预训练词向量

使用像 GloVe 或 FastText 这样的预训练词向量,可以帮助模型理解单词之间的语义关系,并提升性能。

加载 GloVe 词向量示例
import numpy as np
from tensorflow.keras.layers import Embedding

# 加载 GloVe 词向量
embedding_index = {}
with open('glove.6B.100d.txt', encoding='utf-8') as f:
    for line in f:
        values = line.split()
        word = values[0]
        coef = np.asarray(values[1:], dtype='float32')
        embedding_index[word] = coef

# 创建嵌入矩阵
embedding_matrix = np.zeros((max_words, 100))
for word, i in tokenizer.word_index.items():
    if i < max_words:
        embedding_vector = embedding_index.get(word)
        if embedding_vector is not None:
            embedding_matrix[i] = embedding_vector

# 使用预训练的 GloVe 初始化嵌入层
embedding_layer = Embedding(input_dim=max_words, output_dim=100, weights=[embedding_matrix], input_length=max_len, trainable=False)

3. 数据增强

通过同义词替换、语序扰动等方法扩充训练数据,提升模型的泛化能力。

4. 使用更复杂的模型架构

尝试引入双通道 CNN、注意力机制,或者结合 LSTM 和 CNN 的混合架构。


11. 总结与展望

在这篇文章中,我们从零实现了一个基于 CNN 的情感分析项目。通过 IMDB 数据集,我们学习了数据预处理、CNN 模型的搭建与训练、结果评估以及情感预测的完整流程。CNN 模型虽然最初是为图像设计的,但在处理文本任务上也表现得非常优秀。

优点总结

  • 高效性:训练速度快,适合短文本任务。
  • 结构简单:易于实现和优化。

未来扩展

如果你对 NLP 感兴趣,接下来可以尝试:

  • 在更复杂的数据集上训练模型;
  • 探索 BERT 等预训练模型的应用;
  • 结合 CNN 与其他神经网络(如 LSTM)设计混合架构。

如果这篇教程对你有帮助,别忘了点赞收藏并分享给需要的小伙伴!有任何问题或想法,欢迎评论区交流,我们下期再见啦~ 🎉


程序员徐公
37 声望25 粉丝