NLP06:基于TextCNN的中文文本分类

2024-09-01 08:18

本文主要是介绍NLP06:基于TextCNN的中文文本分类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

公众号:数据挖掘与机器学习笔记

1.TextCNN基本原理

主要看第二张图:

  • 第一层为输入层,输入是一个 n × k n \times k n×k的矩阵,图中为 7 × 5 7 \times 5 7×5。其中 n n n为句子中的单词数, k k k为词向量维度。词向量可以是预训练好的,也可以在网络中重新开始训练。第一张图中输入有两个矩阵,其中一个使用的预训练好的向量,另一个则作为训练参数。
  • 第二层为卷积层,可以把矩阵理解为一张channels为1的图像,使用宽度同词向量维度一样的卷积核去做卷积运算,且卷积核只在高度方向(单词方向).因此每次卷积核滑动的位置都是完整的单词,保证了单词作为语言中最小粒度的合理性。假设词向量维度为embedding_dim,卷积核高度为filter_window_size,则卷积核大小为(embedding_dim,filter_window_size),卷积后的大小为(sequence_len-filter_window_size,1)
  • 第三层为卷积层,经过max_pooling后得到一个标量。实际中会使用num_filters卷积核同时卷积,每个卷积核得到的标量拼接在一起形成一个向量。此外,也会使用多个filter_window_size(如图2中3个filter_window_size分别为3、4、5),每个filter_window_size会得到一个向量,最后把所有的向量拼接在一起,然后接一个softmax进行分类。

2. TextCNN实现

import torch
from torch import nn
from torch.nn import functional as F
import math
from torch.utils.data import Dataset,DataLoader
import numpy as np
import random
from sklearn.model_selection import train_test_split
import pandas as pd
import re
from tensorflow.keras.preprocessing import sequencemaxlen=300
batch_size=128

2.1 数据预处理

def textToChars(filePath):"""读取文本文件并进行处理:param filePath:文件路径:return:"""lines = []df=pd.read_excel(filePath,header=None)df.columns=['content']for index, row in df.iterrows():row=row['content']row = re.sub("[^\u4e00-\u9fa5]", "", str(row))  # 只保留中文lines.append(list(row))return linesdef getWordIndex(vocabPath):"""获取word2Index,index2Word:param vocabPath:词汇文件:return:"""word2Index = {}with open(vocabPath, encoding="utf-8") as f:for line in f.readlines():word2Index[line.strip()] = len(word2Index)index2Word = dict(zip(word2Index.values(), word2Index.keys()))return word2Index, index2Worddef lodaData(posFile, negFile, word2Index):"""获取训练数据:param posFile:正样本文件:param negFile:负样本文件:param word2Index::return:"""posLines = textToChars(posFile)negLines = textToChars(negFile)posIndexLines = [[word2Index[word] if word2Index.get(word) else 0 for word in line] for line in posLines]negIndexLines = [[word2Index[word] if word2Index.get(word) else 0 for word in line] for line in negLines]lines = posIndexLines + negIndexLinesprint("训练样本和测试样本共:%d 个"%(len(lines)))# lens = [len(line) for line in lines]labels = [1] * len(posIndexLines) + [0] * len(negIndexLines)padSequences = sequence.pad_sequences(lines, maxlen=maxlen, padding="post", truncating="post")X_train,X_test,y_train,y_test=train_test_split(padSequences,np.array(labels),test_size=0.2,random_state=42)return X_train,X_test,y_train,y_test
vocabPath="/content/drive/My Drive/data/vocab.txt"
negFilePath="/content/drive/My Drive/data/text_classify/sentiment/neg.xls"
posFilePath="/content/drive/My Drive/data/text_classify/sentiment/pos.xls"
word2Index, index2Word=getWordIndex(vocabPath)
X_train,X_test,y_train,y_test=lodaData(posFile=posFilePath,negFile=negFilePath,word2Index=word2Index)
print(X_train.shape,X_test.shape,y_train.shape,y_test.shape)
class MyDataset(Dataset):def __init__(self,features,labels):"""features:文本向量化后的特征labels:标签向量 """self.features=featuresself.labels=labelsdef __len__(self):return self.features.shape[0]def __getitem__(self,index):return self.features[index],self.labels[index]train_dataset=MyDataset(X_train,y_train)
test_dataset=MyDataset(X_test,y_test)
train_dataloader=DataLoader(train_dataset,batch_size=batch_size,shuffle=True)
test_dataloader=DataLoader(test_dataset,batch_size=batch_size,shuffle=False)

2.2 TextCNN实现

class TextCnn(nn.Module):def __init__(self, param: dict):super(TextCnn, self).__init__()input_channel = 1  # input channel sizeoutput_channel = param["output_channel"]  # output channel sizekernel_size = param["kernel_size"]vocab_size = param["vocab_size"]embedding_dim = param["embedding_dim"]dropout = param["dropout"]class_num = param["class_num"]self.param = paramself.embedding = nn.Embedding(vocab_size, embedding_dim,padding_idx=0)self.conv1 = nn.Conv2d(input_channel, output_channel, (kernel_size[0], embedding_dim))self.conv2 = nn.Conv2d(input_channel, output_channel, (kernel_size[1], embedding_dim))self.conv3 = nn.Conv2d(input_channel, output_channel, (kernel_size[2], embedding_dim))self.dropout = nn.Dropout(dropout)self.fc1 = nn.Linear(len(kernel_size) * output_channel, class_num)def init_embedding(self, embedding_matrix):self.embedding.weight = nn.Parameter(torch.Tensor(embedding_matrix))@staticmethoddef conv_pool(x, conv):"""卷积+池化:param x:[batch_size,1,sequence_length,embedding_dim]:param conv::return:"""x = conv(x)  # 卷积, [batch_size,output_channel,h_out,1]x = F.relu((x.squeeze(3)))  # 去掉最后一维,[batch_size,output_channel,h_out]x = F.max_pool1d(x, x.size(2)).squeeze(2)  # [batch_size,output_channel]return xdef forward(self, x):"""前向传播:param x:[batch_size,sequence_length]:return:"""x = self.embedding(x)  # [batch_size,sequence_length,embedding_dim]x = x.unsqueeze(1)  # 增加一个channel维度 [batch_size,1,sequence_length,embedding_dim]x1 = self.conv_pool(x, self.conv1)  # [batch_size,output_channel]x2 = self.conv_pool(x, self.conv2)  # [batch_size,output_channel]x3 = self.conv_pool(x, self.conv3)  # [batch_size,output_channel]x = torch.cat((x1, x2, x3), 1)  # [batch_size,output_channel*3]x = self.dropout(x)logit = F.log_softmax(self.fc1(x), dim=1)return logitdef init_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.data.normal_(0, math.sqrt(2. / n))if m.bias is not None:m.bias.data.zero_()elif isinstance(m, nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()elif isinstance(m, nn.Linear):m.weight.data.normal_(0, 0.01)m.bias.data.zero_()

2.3 模型训练

textCNNParams={"vocab_size":len(word2Index),"embedding_dim":100,"class_num":2,"output_channel":4,"kernel_size":[3,4,5],"dropout":0.2
}
net=TextCnn(textCNNParams)
# net.init_weights()net.cuda()
optimizer=torch.optim.SGD(net.parameters(),lr=0.01)
criterion=nn.NLLLoss()
for epoch in range(10):total_train_loss=[]net.train()for i,(feature,label) in enumerate(train_dataloader):feature=feature.cuda()label=label.cuda()y_pred=net(feature.long()) #前向计算loss=criterion(y_pred,label) #计算损失optimizer.zero_grad() #清除梯度loss.backward() #计算梯度,误差回传optimizer.step() #更新参数total_train_loss.append(loss.data.item())total_valid_loss=[]pred_true_labels=0net.eval()for i,(feature_test,label_test) in enumerate(test_dataloader):feature_test=feature_test.cuda()label_test=label_test.cuda()with torch.no_grad():pred_test=net(feature_test.long())test_loss=criterion(pred_test,label_test)total_valid_loss.append(test_loss.data.item())# accu=torch.sum((torch.argmax(pred_test,dim=1)==label_test)).data.item()/feature_test.shape[0]pred_true_labels+=torch.sum(torch.argmax(pred_test,dim=1)==label_test).data.item()print("epoch:{},train_loss:{},test_loss:{},accuracy:{}".format(epoch,np.mean(total_train_loss),np.mean(total_valid_loss),pred_true_labels/len(test_dataset)))

2.4 模型测试

def predict_one(sentence,net,word2Index):sentence=re.sub("[^\u4e00-\u9fa5]", "", str(sentence))  # 只保留中文print(sentence)sentence=[word2Index[word] if word2Index.get(word) else 0 for word in sentence]sentence=sentence+[0]*(maxlen-len(sentence)) if len(sentence)<maxlen else sentence[0:300]print(sentence)sentence=torch.tensor(np.array(sentence)).view(-1,len(sentence)).cuda()label=torch.argmax(net(sentence),dim=1).data.item()print(label)
sentence="一次很不爽的购物,页面上说是第二天能到货,结果货是从陕西发出的,卖家完全知道第二天根本到不了货。多处提到送货入户还有100%送货入户也没有兑现,与客服联系多日,还是把皮球踢到快递公司。算是一个教训吧。"
predict_one(sentence,net,word2Index)

代码:https://github.com/chongzicbo/nlp-ml-dl-notes/blob/master/code/textclassification/text_cnn.ipynb

在这里插入图片描述

这篇关于NLP06:基于TextCNN的中文文本分类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1126408

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

vscode中文乱码问题,注释,终端,调试乱码一劳永逸版

忘记咋回事突然出现了乱码问题,很多方法都试了,注释乱码解决了,终端又乱码,调试窗口也乱码,最后经过本人不懈努力,终于全部解决了,现在分享给大家我的方法。 乱码的原因是各个地方用的编码格式不统一,所以把他们设成统一的utf8. 1.电脑的编码格式 开始-设置-时间和语言-语言和区域 管理语言设置-更改系统区域设置-勾选Bata版:使用utf8-确定-然后按指示重启 2.vscode

解决Office Word不能切换中文输入

我们在使用WORD的时可能会经常碰到WORD中无法输入中文的情况。因为,虽然我们安装了搜狗输入法,但是到我们在WORD中使用搜狗的输入法的切换中英文的按键的时候会发现根本没有效果,无法将输入法切换成中文的。下面我就介绍一下如何在WORD中把搜狗输入法切换到中文。

Level3 — PART 3 — 自然语言处理与文本分析

目录 自然语言处理概要 分词与词性标注 N-Gram 分词 分词及词性标注的难点 法则式分词法 全切分 FMM和BMM Bi-direction MM 优缺点 统计式分词法 N-Gram概率模型 HMM概率模型 词性标注(Part-of-Speech Tagging) HMM 文本挖掘概要 信息检索(Information Retrieval) 全文扫描 关键词

用Pytho解决分类问题_DBSCAN聚类算法模板

一:DBSCAN聚类算法的介绍 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,DBSCAN算法的核心思想是将具有足够高密度的区域划分为簇,并能够在具有噪声的空间数据库中发现任意形状的簇。 DBSCAN算法的主要特点包括: 1. 基于密度的聚类:DBSCAN算法通过识别被低密

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(

PMP–一、二、三模–分类–14.敏捷–技巧–看板面板与燃尽图燃起图

文章目录 技巧一模14.敏捷--方法--看板(类似卡片)1、 [单选] 根据项目的特点,项目经理建议选择一种敏捷方法,该方法限制团队成员在任何给定时间执行的任务数。此方法还允许团队提高工作过程中问题和瓶颈的可见性。项目经理建议采用以下哪种方法? 易错14.敏捷--精益、敏捷、看板(类似卡片)--敏捷、精益和看板方法共同的重点在于交付价值、尊重人、减少浪费、透明化、适应变更以及持续改善等方面。

【python计算机视觉编程——8.图像内容分类】

python计算机视觉编程——8.图像内容分类 8.图像内容分类8.1 K邻近分类法(KNN)8.1.1 一个简单的二维示例8.1.2 用稠密SIFT作为图像特征8.1.3 图像分类:手势识别 8.2贝叶斯分类器用PCA降维 8.3 支持向量机8.3.2 再论手势识别 8.4 光学字符识别8.4.2 选取特征8.4.3 多类支持向量机8.4.4 提取单元格并识别字符8.4.5 图像校正