Advertisement

新闻文本分类项目基于textcnn word2vec 代码+数据

阅读量:

该文本主要描述了一个利用GloVe词向量模型进行文本分类的任务。首先从CSV文件中读取数据并生成词向量矩阵;接着定义了一个自定义的卷积神经网络(textCNN)进行特征提取;通过随机梯度下降优化器对模型进行训练,并使用交叉熵损失函数计算损失;最后通过测试集评估模型性能,并计算F1分数作为性能指标。

当时我的成绩 阿里天池

基础数据经过训练生成的词向量模型代码部分在文档中提供两个版本:一个是完整的版本,另一个是尚不完整的版本。

复制代码
 from gensim.models import KeyedVectors

    
 from gensim.scripts.glove2word2vec import glove2word2vec
    
 import pandas as pd
    
 import numpy as np 
    
 import torch
    
 from torch import nn
    
 import torch.utils.data as data
    
 import torch.nn.functional as F
    
 from torch import tensor
    
 from sklearn.metrics import f1_score
    
 from datetime import datetime 
    
 import time 
    
  
    
 #csv数据量的数目测试  一共有20000条
    
 with open("train_set839.csv", 'r') as f: #计算长度
    
     hang_count=len(f.readlines())
    
 #     print(hang_count)
    
  
    
 #先把csv中一个句子拿出来  然后把每个单词去词训练库里面找对应的向量规定对于每个句子矩阵都构建一个2000,300的矩阵。
    
 def hang_vectoes_label(index): # 要读取csv文本第几行的文章数据 会返回一个 列表里面是文章的词向量矩阵和标签值
    
     row=df.values[index] #读取数据的第几行
    
     row=row[0].split()   #这些数据变成一个列表
    
     label=row[0]
    
     hang_txt=row[1:]
    
     hang_labeltxt_juzhen=[]
    
     meihang_wenben_juzhen=np.zeros((1000,300))#,每一个文本定义一个空的全0的2000,300的矩阵 
    
     t=0
    
     for a in hang_txt:
    
     try:
    
         vec = new_model[a]  #从词库里面取出这些词对应的向量 
    
     except KeyError:        #当在词向量模型中没有这个单词的向量的时候可以设置错误跳过 然后把这个单词的向量设置为全0
    
         vec=np.zeros((1,300))
    
     meihang_wenben_juzhen[int(t)]=vec
    
     if t ==999:
    
         break
    
     t=t+1
    
     hang_labeltxt_juzhen.append(label)
    
     hang_labeltxt_juzhen.append(meihang_wenben_juzhen)
    
     return hang_labeltxt_juzhen
    
 # a=hang_vectoes_label(0)  #返回一个列表 第一个是行文本的分类的label 第二个是行文本 2000*300 的词向量矩阵 
    
 # # 这个原始数据有1730条文本 数据 
    
  
    
  
    
  
    
 #手动对数据分块 并且把数据加载到dataloader 让dataloader分batch
    
 def dataloader_batch(start,end,batch,shuffle):# 把多少行的数据加入到这个data.TensorDataset中 然后在对这个中的这些行数据分batch训练
    
         #     开始     终止 batch大小  是否打乱 True False 
    
     x=[]
    
     y=[]
    
     for i in range(int(start),int(end),1):
    
     a=hang_vectoes_label(i)
    
     x_1=a[1]
    
     y_1=int(a[0])
    
     x.append(x_1)
    
     y.append(y_1)
    
     x=torch.Tensor(x)
    
     y=torch.Tensor(y)
    
     torch_dataset = data.TensorDataset(x, y) #要求这两部分 第一个维度是相同的 
    
     loader = data.DataLoader(
    
     dataset=torch_dataset,
    
     batch_size=batch,             # 每批提取的数量
    
     shuffle=shuffle,             # 要不要打乱数据(打乱比较好)
    
     num_workers=0)            # 多少线程来读取数据
    
     return loader 
    
  
    
  
    
  
    
 #定义模型优化器
    
 #
    
 class textCNN(nn.Module):
    
     def __init__(self,):
    
     super(textCNN, self).__init__()
    
     #Vocab = 忘了 ## 已知词的数量
    
     Dim = 300 ##每个词向量长度
    
     Cla = 14 ##类别数
    
     Ci = 1##输入的channel数 一般都是1 与batch大小无关 
    
     Knum = 50 ## 每种卷积核的数量
    
     Ks =[2,3,4]  ## 卷积核list,形如[2,3,4]
    
     dropout=0.5
    
     self.convs = nn.ModuleList([nn.Conv2d(Ci,Knum,(K,Dim)) for K in Ks]) ## 卷积层
    
     self.dropout = nn.Dropout(dropout) 
    
     self.fc = nn.Linear(len(Ks)*Knum,Cla) ##全连接层
    
     
    
     def forward(self,x):
    
 #         x = self.embed(x) #(N,W,D)
    
     x = x.unsqueeze(1) #(N,Ci,W,D)原本进来的数据是【batch,高,宽】---》【batch,1,高,宽】
    
     x = [F.relu(conv(x)).squeeze(3) for conv in self.convs] # len(Ks)*(N,Knum,W)
    
     x = [F.max_pool1d(line,line.size(2)).squeeze(2) for line in x]  # len(Ks)*(N,Knum)
    
     x = torch.cat(x,1) #(N,Knum*len(Ks))
    
     x = self.dropout(x)
    
     logit = self.fc(x)
    
     return logit
    
     
    
 model = textCNN()
    
 # model.aux_logits=False
    
 criterion = torch.nn.CrossEntropyLoss()  # 损失函数的计算 交叉熵损失函数计算
    
 # optimizer=optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
    
 optimizer = torch.optim.SGD(model.parameters(), lr=0.01)  # 优化器
    
 # momentum是优化梯度的方向自动适应学习率
    
    
    
    
    AI助手
复制代码
 # glove2word2vec("text20wan_glove_vec.txt", "text20wan_vec_wd2.txt") #

    
 #把glove训练好的文件转成Wordvec可以读的 如果转过了这个就注释掉 
    
 new_model = KeyedVectors.load_word2vec_format('train_glove.txt', binary=False)
    
 vectors = new_model.wv.vectors
    
 print(vectors.shape)
    
 vec = new_model['4407']
    
 print(vec.shape)
    
 words = new_model.wv.index2word
    
 print(len(words))
    
 df=pd.read_csv("train_set839.csv")
    
 # with open("train_set.csv", 'r') as f: #计算长度
    
 #     hang_count=len(f.readlines())
    
    
    
    
    AI助手
复制代码
 # MAX_F=0 #初始化

    
 for epoch in range(1,10,1):    # 对整套数据训练多少个世代
    
 #     start=datetime.now()
    
     print('第',epoch,"epoch")
    
     for i in range(10000): #全部是6   是6的时候会出错 1730这个地方
    
     loader=dataloader_batch(i*16,i*16+16,16,True) #原始数据分快加载到dataloader分batch
    
     
    
       #                            多少个数据是一个batch
    
 #       if __name__ == '__main__':
    
     for step, (batch_x, batch_y) in enumerate(loader):  # 每一步loader释放一小批数据用来学习\
    
                 input=batch_x #16 2000 300
    
                 target=batch_y #16
    
                 optimizer.zero_grad() #在开始之前梯度清空
    
                 outputs=model(input)    #经过这个模型输出的是 如果批大小是4 就输出四行 每行是14个分类的 二维tensor ,
    
                 target =target.long()   #转化成长整形张量进行计算 loss
    
                 print(target)
    
                 print(outputs)
    
                 loss = criterion(outputs, target)
    
                 loss.backward()
    
                 optimizer.step()
    
 #         print("第"+str(i)+"个3200条数据内",) 
    
 #     end=datetime.now()
    
 #     print("一个epoch:",(end-start).seconds,"秒")
    
     torch.save(model.state_dict(), 'trainModel'+str(epoch)+'.pth') 
    
    
    
    
    AI助手
复制代码
 #模型加载:

    
 model = textCNN()
    
 model.load_state_dict(torch.load('调参1trainModel2.pth'))
    
 model.eval()   
    
    
    
    
    AI助手
复制代码
 def test():

    
     y_pred=[]
    
     y_true=[]
    
     for i in range(10000,10500,1):
    
     loader=dataloader_batch(i*16,i*16+16,1,True) 
    
     #          加载的数据是初始位置 结束位置  batch大小是
    
     for step, (batch_x, batch_y) in enumerate(loader):  #上边batch大小是1 每次拿一个数据出来
    
         with torch.no_grad(): #使用这句话后的代码就不会再去计算梯度了
    
             input=batch_x
    
     #             print( input)
    
             optimizer.zero_grad()
    
             target=int(batch_y[0].item())
    
             outputs=model(input)#经过这个模型输出的是 如果批大小是4 就输出四行 每行是14个分类的 二维tensor ,
    
             outputs=outputs.view(1,-1)
    
             outputs=np.argmax(outputs)
    
     #             print(outputs.item())
    
             y_pred.append(outputs.item())
    
             y_true.append(target)
    
     return y_true, y_pred
    
 y_true, y_pred=test()
    
 print(len(y_pred))
    
 print(y_true)
    
 Fa=f1_score(y_true, y_pred, average='macro') 
    
 # Faw=f1_score(y_true, y_pred, average='weighted') 
    
 print(Fa)
    
 # print(Faw)
    
    
    
    
    AI助手
复制代码
 def test():

    
     y_pred=[]
    
     y_true=[]
    
     for i in range(10000,10500,1):
    
     loader=dataloader_batch(i*16,i*16+16,1,True) 
    
     #          加载的数据是初始位置 结束位置  batch大小是
    
     for step, (batch_x, batch_y) in enumerate(loader):  #上边batch大小是1 每次拿一个数据出来
    
         with torch.no_grad(): #使用这句话后的代码就不会再去计算梯度了
    
             input=batch_x
    
     #             print( input)
    
             optimizer.zero_grad()
    
             target=int(batch_y[0].item())
    
             outputs=model(input)#经过这个模型输出的是 如果批大小是4 就输出四行 每行是14个分类的 二维tensor ,
    
             outputs=outputs.view(1,-1)
    
             outputs=np.argmax(outputs)
    
     #             print(outputs.item())
    
             y_pred.append(outputs.item())
    
             y_true.append(target)
    
     return y_true, y_pred
    
 y_true, y_pred=test()
    
 print(len(y_pred))
    
 print(y_true)
    
 Fa=f1_score(y_true, y_pred, average='macro') 
    
 # Faw=f1_score(y_true, y_pred, average='weighted') 
    
 print(Fa)
    
 # print(Faw)
    
    
    
    
    AI助手

访问以下链接获取文件:https://pan.baidu.com/s/1I8l-5f0-IlrSPa3aP6nY2A;其中文件提取密码为1111;建议复制文件路径至手机端并粘贴到百度网盘App中以提高操作体验流畅度

连接位置:https://pan.baidu.com/s/1XNaM7fc96aSBi-sML-_vEw
访问密码:1111
建议复制该地址至浏览器打开百度网盘手机App进行操作会更加便捷哦

全部评论 (0)

还没有任何评论哟~