中文自然语言处理--基于textCNN的股吧数据情感分类

以中美贸易战背景下中兴通讯在股吧解禁前一段时间的评论数据,来进行情感数据人工打标签和CNN分类。其中,把消极 、中性 、积极分别用0、1、2来表示。

import pandas as pd
import numpy as np
import jieba
import random
import keras
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.layers import Embedding
from keras.layers import Conv1D, GlobalMaxPooling1D
from keras.datasets import imdb  # 互联网电影资料库
from keras.models import model_from_json
from keras.utils import np_utils
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer

# 整个文本分类流程主要包括以下6个步骤:
# 中文语料;
# 分词;
# 复杂规则;
# 特征向量;
# 算法建模;
# 情感分析。

# 引入停用词和语料文件
'''
数据分布不均匀一般怎么处理呢?从以下几个方面考虑:
数据采样,包括上采样、下采样和综合采样;
改变分类算法,在传统分类算法的基础上对不同类别采取不同的加权方式,使得模型更看重少数类;
采用合理的性能评价指标;
代价敏感。
'''
dir = "./datas/"
# 不设置quoting,默认会去除英文双引号,只留下英文双引号内的内容,设置quoting = 3,会如实读取内容
stopwords = pd.read_csv(dir +"stopwords.txt", index_col=False, quoting=3, sep="\t", names=['stopword'], encoding='utf-8')
stopwords = stopwords['stopword'].values
data_1 = pd.read_csv(dir+"data.csv",encoding='gbk')
#把内容有缺失值的删除
data_1.dropna(inplace=True)
print(data_1.head())

#抽取文本数据和标签
#把消极  中性  积极分别为0、1、2的语料分别拿出来
data_label_0 = data_1.loc[data_1['label'] ==0,:]
data_label_1 = data_1.loc[data_1['label'] ==1,:]
data_label_2 = data_1.loc[data_1['label'] ==2,:]

#定义分词函数
def preprocess_text(content_lines, sentences, category):
    for line in content_lines:
        try:
            segs=jieba.lcut(line)
            segs = list(filter(lambda x:len(x)>1, segs))
            segs = [v for v in segs if not str(v).isdigit()]  # 去数字
            segs = list(filter(lambda x:x.strip(), segs))  # 去左右空格
            segs = list(filter(lambda x:x not in stopwords, segs))
            temp = " ".join(segs)
            if(len(temp)>1):
                sentences.append((temp, category))
        except Exception:
            print(line)
            continue

# 生成训练的分词数据,并进行打散,使其分布均匀
#获取数据
data_label_0_content = data_label_0['content'].values.tolist()
data_label_1_content = data_label_1['content'].values.tolist()
data_label_2_content = data_label_2['content'].values.tolist()
#生成训练数据
sentences = []
preprocess_text(data_label_0_content, sentences, 0)
preprocess_text(data_label_1_content, sentences, 1)
preprocess_text(data_label_2_content, sentences,2)
#我们打乱一下顺序,生成更可靠的训练集
random.shuffle(sentences)
print(sentences)

# 对数据集进行切分,按照训练集合测试集7:3的比例
#所以把原数据集分成训练集的测试集,咱们用sklearn自带的分割函数。
x, y = zip(*sentences)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1234)

#抽取特征,我们对文本抽取词袋模型特征
'''
CountVectorizer 的作用是将文本文档转换为计数的稀疏矩阵;
'''
# 抽取特征,将文本中的词语转换为词频矩阵
# 将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频
# CountVectorizer是属于常见的特征数值计算类,是一个文本特征提取方法。对于每一个训练文本,它只考虑每种词汇在该训练文本中出现的频率。
# CountVectorizer会将文本中的词语转换为词频矩阵,它通过fit_transform函数计算各个词语出现的次数。
# analyzer    一般使用默认,可设置为string类型,如’word’, ‘char’, ‘char_wb’,还可设置为callable类型,比如函数是一个callable类型
# max_features    默认为None,可设为int,对所有关键词的term frequency进行降序排序,只取前max_features个作为关键词集
vec = CountVectorizer(
    analyzer='word', #tokenise by character ngrams
    max_features=4000,  #keep the most common 1000 ngrams
)
vec.fit(x_train)

# 定义模型参数
# 设置参数
max_features = 1001
maxlen = 100
batch_size = 32
embedding_dims = 50
filters = 250
kernel_size = 3
hidden_dims = 250
epochs = 5
nclasses = 3

# 输入特征转成 Array 和标签处理
x_train = vec.transform(x_train)
x_test = vec.transform(x_test)
x_train = x_train.toarray()
x_test = x_test.toarray()
# 独热编码
y_train = np_utils.to_categorical(y_train, nclasses)
y_test = np_utils.to_categorical(y_test, nclasses)
x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = sequence.pad_sequences(x_test, maxlen=maxlen)
print('x_train shape:', x_train.shape)
print(x_train[:3])
print(y_train[:3])
print('x_test shape:', x_test.shape)

# 定义一个绘制 Loss 曲线的类
class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = {'batch': [], 'epoch': []}
        self.accuracy = {'batch': [], 'epoch': []}
        self.val_loss = {'batch': [], 'epoch': []}
        self.val_acc = {'batch': [], 'epoch': []}

    def on_batch_end(self, batch, logs={}):
        self.losses['batch'].append(logs.get('loss'))
        self.accuracy['batch'].append(logs.get('accuracy'))
        self.val_loss['batch'].append(logs.get('val_loss'))
        self.val_acc['batch'].append(logs.get('val_accuracy'))

    def on_epoch_end(self, epoch, logs={}):
        self.losses['epoch'].append(logs.get('loss'))
        self.accuracy['epoch'].append(logs.get('accuracy'))
        self.val_loss['epoch'].append(logs.get('val_loss'))
        self.val_acc['epoch'].append(logs.get('val_accuracy'))

    def loss_plot(self, loss_type):
        iters = range(len(self.losses[loss_type]))
        plt.figure()
        # acc
        # print(self.accuracy[loss_type])
        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')
        # loss
        # print(self.losses[loss_type])
        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')
        if loss_type == 'epoch':
            # val_acc
            # print(self.val_acc[loss_type])
            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')
            # val_loss
            # print(self.val_loss[loss_type])
            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')
        plt.grid(True)
        plt.xlabel(loss_type)
        plt.ylabel('acc-loss')
        plt.legend(loc="upper right")
        plt.show()

    def on_train_end(self, logs={}):
        self.loss_plot('batch')
        self.loss_plot('epoch')

# 初始化上面类的对象,并作为模型的回调函数输入,训练模型
history = LossHistory()

print('Build model...')
model = Sequential()
model.add(Embedding(max_features,
                    embedding_dims,
                    input_length=maxlen))
model.add(Dropout(0.5))
model.add(Conv1D(filters,
                 kernel_size,
                 padding='valid',
                 activation='relu',
                 strides=1))
model.add(GlobalMaxPooling1D())
model.add(Dense(hidden_dims))
model.add(Dropout(0.5))
model.add(Activation('relu'))
model.add(Dense(nclasses))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])
model.summary()
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          validation_data=(x_test, y_test),
          callbacks=[history])

原文(数据似乎没有,我自己参考原文随机构造的):
https://soyoger.blog.csdn.net/article/details/108729401

<think>好的,用户想了解自然语言处理中关于文本分类的方法、技术和实现。首先,我需要整理已有的引用资料,看看里面提到的内容是否足够覆盖用户的需求。根据提供的引用,内容涉及文本分类文本挖掘的关系、流程、具体模型如TextCNN、RNN-based方法,以及n-gram模型的应用。 首先,用户的问题比较广泛,需要系统性地回答。我应该按照方法分类、技术要点、实现步骤的结构来组织内容,确保涵盖传统机器学习和深度学习方法。引用中提到了基于MLP的方法,比如Paragraph-vec,以及RNN和CNN的应用,这些都需要详细说明。 接下来,要检查引用中的关键点。引用[1]和[2]说明了文本分类的流程和与文本挖掘的联系,可以作为概述部分的基础。引用[3]和[4]分别介绍了TextCNN和RNN-based方法,需要详细展开。引用[5]提到的n-gram模型可能在特征工程部分有用。 需要注意用户可能对具体实现步骤感兴趣,因此需要分步骤讲解,比如数据预处理、特征提取、模型选择等。同时,引用中的流程图和模型例子(如TextCNN)应该结合代码示例,这样用户能更直观地理解。 可能还需要补充一些用户未提及但重要的点,比如评估指标(准确率、F1值等),以及当前流行的预训练模型(如BERT),虽然引用中没有提到,但这是现代文本分类的重要技术,应该简要提及以保持回答的全面性。 最后,确保回答符合系统级指令:使用正确的中文,数学公式用$...$,独立公式用$$...$$,结构清晰,并生成相关问题。需要检查LaTeX语法是否正确,例如特征向量或公式的呈现是否准确。例如,在解释TF-IDF时,公式应该用$$包裹。 现在整理各部分内容,确保逻辑连贯,引用正确。例如,在讲述机器学习流程时,引用[2]的流程图;在讨论TextCNN时,引用[3]和[5]的相关内容。同时,生成的代码示例需要正确无误,比如使用Keras实现TextCNN,并解释关键部分。 可能遇到的疑问:用户是否需要更详细的实现步骤,或者更多实际案例?根据问题描述,用户要求“方法、技术、实现”,因此代码示例和步骤分解是必要的。此外,要确认所有引用都被正确使用,比如在提到文本分类作为文本挖掘的一部分时,引用[1]的说明。 最后生成相关问题,需要基于回答内容,涵盖方法比较、技术细节、应用场景等方面,确保问题具有针对性,帮助用户进一步探索。</think>### 自然语言处理中的文本分类方法、技术与实现 #### 一、文本分类基础 文本分类自然语言处理(NLP)的核心任务之一,旨在将文本自动划分到预定义的类别中。它与文本挖掘紧密相关,常作为文本挖掘流程中的关键步骤[^1]。例如,在新闻分类情感分析中,分类结果可直接用于信息筛选或知识发现。 #### 二、技术方法分类 1. **传统机器学习方法** - **特征工程**:使用词袋模型(Bag-of-Words)、TF-IDF 或 n-gram 提取特征。 $$ \text{TF-IDF}(t,d) = \text{TF}(t,d) \times \log\left(\frac{N}{\text{DF}(t)}\right) $$ 其中,$t$为词项,$d$为文档,$N$为总文档数,$\text{DF}(t)$为包含$t$的文档数[^5]。 - **分类器**:常用朴素贝叶斯、SVM 或随机森林。 2. **深度学习方法** - **TextCNN**:通过卷积核捕捉局部语义特征,适用于短文本分类[^3]。 ```python from keras.layers import Conv1D, GlobalMaxPooling1D model.add(Conv1D(128, 5, activation='relu')) model.add(GlobalMaxPooling1D()) ``` - **RNN-based**:如LSTM/GRU,适合处理序列依赖关系,如长文本分类[^4]。 - **预训练模型**:BERT、RoBERTa 通过微调实现高精度分类。 #### 三、实现流程(以机器学习为例)[^2] 1. **数据预处理** - 分词、去停用词、词干提取 - 构建标签编码(如One-hot) 2. **特征提取** - 使用TF-IDF或词向量(Word2Vec)生成特征矩阵 3. **模型训练与评估** - 划分训练集/测试集 - 通过交叉验证优化参数 - 评估指标:准确率、F1值、混淆矩阵 #### 四、代码示例(基于TextCNN) ```python from keras.models import Sequential from keras.layers import Embedding, Conv1D, GlobalMaxPooling1D, Dense model = Sequential() model.add(Embedding(input_dim=10000, output_dim=128, input_length=200)) model.add(Conv1D(256, 3, activation='relu')) # 3-gram卷积核 model.add(GlobalMaxPooling1D()) model.add(Dense(10, activation='softmax')) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) ``` #### 五、应用场景 - **短文本分类**:如新闻标题分类(适合TextCNN- **长文本分析**:如法律文档分类(适合RNN或Transformer) - **多标签分类**:如论文主题标注(需调整损失函数为二元交叉熵)
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值