当前位置:首页 > 技术 > 正文内容

基于TensorFlow实现中文文本情感分类系统

访客 技术 2026年7月28日 1

系统架构概述

整体处理流程包括数据预处理、特征工程、模型构建等关键环节:

预训练词向量的集成

利用开源中文词向量库构建语义表示层:https://github.com/Embedding/Chinese-Word-Vectors/

from gensim.models import KeyedVectors
# 加载知乎语料预训练的双元语法词向量
vector_model = KeyedVectors.load_word2vec_format('models/zh_word_vectors.bin', binary=False)

验证词向量维度和语义关系:

# 查询单个词汇的向量表示
sample_vector = vector_model['优秀']
print(f"向量维度: {sample_vector.shape}")

# 计算词汇间语义相似度
similarity = vector_model.similarity('酒店', '宾馆')
print(f"语义相似度: {similarity}")

# 获取最相似词汇列表
similar_words = vector_model.most_similar('服务', topn=5)
print(similar_words)

数据集构建与预处理

采用谭松波酒店评论数据集,包含4000条标注样本(2000正面/2000负面),每条独立存储。

import os
import re
import jieba
import numpy as np
from sklearn.model_selection import train_test_split

def load_dataset(base_path):
    """加载并整合正负样本数据"""
    documents = []
    labels = []
    
    # 加载正面样本
    pos_files = os.listdir(os.path.join(base_path, 'positive'))
    for filename in pos_files:
        with open(os.path.join(base_path, 'positive', filename), 'r', encoding='utf-8') as f:
            content = f.read().strip()
            if content:
                documents.append(content)
                labels.append(1)
    
    # 加载负面样本
    neg_files = os.listdir(os.path.join(base_path, 'negative'))
    for filename in neg_files:
        with open(os.path.join(base_path, 'negative', filename), 'r', encoding='utf-8') as f:
            content = f.read().strip()
            if content:
                documents.append(content)
                labels.append(0)
    
    return documents, np.array(labels)

corpus, sentiment_labels = load_dataset('data/hotel_reviews')

文本数字化处理

执行分词、清洗和序列化操作:

def tokenize_texts(texts, vocab_model):
    """将文本转换为数字索引序列"""
    processed_sequences = []
    
    for text in texts:
        # 清理非文本字符
        cleaned = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9]', '', text)
        
        # 执行中文分词
        segmented = list(jieba.cut(cleaned))
        
        # 词汇索引映射
        indexed_sequence = []
        for word in segmented:
            try:
                idx = vocab_model.key_to_index[word]
                indexed_sequence.append(idx)
            except KeyError:
                indexed_sequence.append(0)  # 未知词标记
        
        processed_sequences.append(indexed_sequence)
    
    return processed_sequences

tokenized_corpus = tokenize_texts(corpus, vector_model)

序列长度标准化策略

分析序列长度分布,确定最优序列长度:

import matplotlib.pyplot as plt

# 统计序列长度分布
seq_lengths = [len(seq) for seq in tokenized_corpus]

plt.figure(figsize=(10, 6))
plt.hist(seq_lengths, bins=50, alpha=0.7)
plt.xlabel('序列长度')
plt.ylabel('样本数量')
plt.title('文本序列长度分布')
plt.grid(True)
plt.show()

# 计算最佳截断长度
mean_length = np.mean(seq_lengths)
std_length = np.std(seq_lengths)
optimal_length = int(mean_length + 2 * std_length)

coverage_ratio = np.sum(np.array(seq_lengths) < optimal_length) / len(seq_lengths)
print(f"建议截断长度: {optimal_length}")
print(f"覆盖率: {coverage_ratio:.2%}")

词向量矩阵初始化

构建符合Keras Embedding层要求的词向量矩阵:

def create_embedding_matrix(vocab_model, vocab_size=50000, embed_dim=300):
    """构建词汇-向量映射矩阵"""
    embedding_weights = np.zeros((vocab_size, embed_dim), dtype=np.float32)
    
    for idx in range(vocab_size):
        word = vocab_model.index_to_key[idx]
        embedding_weights[idx] = vocab_model[word]
    
    return embedding_weights

# 生成词向量矩阵
VOCAB_SIZE = 50000
EMBEDDING_DIM = 300
embedding_weights = create_embedding_matrix(vector_model, VOCAB_SIZE, EMBEDDING_DIM)

# 验证矩阵正确性
verification_word = vector_model.index_to_key[123]
is_valid = np.allclose(vector_model[verification_word], embedding_weights[123])
print(f"词向量矩阵验证: {is_valid}")

序列对齐处理

执行填充和截断操作以统一序列长度:

from tensorflow.keras.preprocessing.sequence import pad_sequences

def normalize_sequences(sequences, max_length):
    """统一序列长度处理"""
    return pad_sequences(
        sequences,
        maxlen=max_length,
        padding='pre',
        truncating='pre',
        dtype='int32'
    )

# 应用序列标准化
padded_sequences = normalize_sequences(tokenized_corpus, optimal_length)
print(f"处理前样本形状: {len(tokenized_corpus)}")
print(f"处理后矩阵形状: {padded_sequences.shape}")

训练集与验证集划分

# 数据集分割
X_train, X_val, y_train, y_val = train_test_split(
    padded_sequences,
    sentiment_labels,
    test_size=0.1,
    random_state=42,
    stratify=sentiment_labels  # 保持类别比例
)

print(f"训练集大小: {X_train.shape[0]}")
print(f"验证集大小: {X_val.shape[0]}")
print(f"正负样本比例 - 训练集: {np.mean(y_train):.2f}")
print(f"正负样本比例 - 验证集: {np.mean(y_val):.2f}")

LSTM情感分析模型构建

设计包含Embedding、LSTM和Dense层的神经网络架构:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping

def build_sentiment_model(vocab_size, embed_dim, embed_matrix, seq_length):
    """构建情感分析模型"""
    model = Sequential([
        # 词嵌入层(使用预训练权重)
        Embedding(
            input_dim=vocab_size,
            output_dim=embed_dim,
            input_length=seq_length,
            weights=[embed_matrix],
            trainable=False  # 冻结预训练权重
        ),
        
        # LSTM特征提取层
        LSTM(128, dropout=0.3, recurrent_dropout=0.3, return_sequences=False),
        
        # 全连接分类层
        Dense(64, activation='relu'),
        Dropout(0.5),
        Dense(1, activation='sigmoid')
    ])
    
    # 编译模型
    model.compile(
        optimizer=Adam(learning_rate=0.001),
        loss='binary_crossentropy',
        metrics=['accuracy']
    )
    
    return model

# 实例化模型
sentiment_classifier = build_sentiment_model(
    VOCAB_SIZE,
    EMBEDDING_DIM,
    embedding_weights,
    optimal_length
)

# 模型结构概览
sentiment_classifier.summary()

模型训练与评估

设置训练参数并启动训练过程:

# 训练配置
callbacks = [
    EarlyStopping(
        monitor='val_loss',
        patience=3,
        restore_best_weights=True
    )
]

# 执行训练
training_history = sentiment_classifier.fit(
    X_train,
    y_train,
    validation_data=(X_val, y_val),
    epochs=20,
    batch_size=64,
    callbacks=callbacks,
    verbose=1
)

# 评估模型性能
loss, accuracy = sentiment_classifier.evaluate(X_val, y_val)
print(f"验证集准确率: {accuracy:.4f}")
标签: TensorFlow

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。