使用CNN模型(Pytorch)实现文本情感分类

  • 导包
import collections
import os
import time
import torch
from torch import nn
import torchtext.vocab as Vocab
import torch.utils.data as Data
import torch.nn.functional as F
import random
from tqdm import tqdm
  • 基本参数配置
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

DATA_ROOT = "E:\data"
  • 池化
# 池化
class GlobalMaxPool1d(nn.Module):
    def __init__(self):
        super(GlobalMaxPool1d, self).__init__()
    def forward(self, x):
        # x shape: [batch_size, channel, seq_len]
        # return shape: [batch_size, channel, 1]
        return F.max_pool1d(x, kernel_size=x.shape[2])
  • 读取数据集
# 读取数据集
def read_imdb(folder='train', data_root=r'E:\data\aclImdb'):
    data = []
    for label in ['pos', 'neg']:
        folder_name = os.path.join(data_root, folder, label) # 拼接文件路径 如:E:\data\aclImdb\train\pos\
        for file in tqdm(os.listdir(folder_name)): # os.listdir(folder_name) 读取文件路径下的所有文件名,并存入列表中
            with open(os.path.join(folder_name, file), 'rb') as f:
                review = f.read().decode('utf-8').replace('\n', ' ').lower()
                data.append([review, 1 if label == 'pos' else 0]) # 将每个文本读取的内容和对应的标签存入data列表中
    random.shuffle(data) # 打乱data列表中的数据排列顺序
    return data
  • 空格分词
# 空格分词
def get_tokenized_imdb(data):
    '''
    :param data: list of [string, label]
    '''
    def tokenizer(text):
        return [tok.lower() for tok in text.split(' ')]
    return [tokenizer(review) for review,_ in data] # 只从data中读取review(评论)内容而不读取标签(label),对review使用tokenizer方法进行分词

  • 创建词典
# 创建词典
def get_vocab_imdb(data):
    tokenized_data = get_tokenized_imdb(data) # 调用get_tokenized_imdb()空格分词方法获取到分词后的数据tokenized_data
    counter = collections.Counter([tk for st in tokenized_data for tk in st]) # 读取tokenized_data列表中每个句子的每个词,放入列表中。
                                                                              # collections.Counter()方法可计算出列表中所有不重复的词数总和
    return Vocab.Vocab(counter, min_freq=5) # 去掉词频小于5的词
  • 对data列表中的每行数据进行处理,将词转换为索引,并使每行数据等长
def process_imdb(data, vocab):
    max_len = 500 # 每条评论通过截断或者补0,使得长度变成500

    def pad(x):
        return x[:max_len] if len(x) > max_len else x + [0]*(max_len - len(x)) # x[:max_len] 只获取前max_len个词
                                                                               # x + [0]*(max_len - len(x)) 词数小于max_len,用pad=0补长到max_len

    tokenized_data = get_tokenized_imdb(data) # 调用方法获取分词后的数据
    features = torch.tensor([pad([vocab.stoi[word] for word in words]) for words in tokenized_data]) # 将词转换为vocab词典中对应词的索引
    labels = torch.tensor([score for _, score in data])
    return features, labels
  • 迭代数据集
# 迭代数据集
batch_size = 64
train_data = read_imdb('train', data_root=os.path.join(DATA_ROOT, "aclImdb"))
test_data = read_imdb('test', data_root=os.path.join(DATA_ROOT, "aclImdb"))
vocab = get_vocab_imdb(train_data)
train_set = Data.TensorDataset(*process_imdb(train_data, vocab))
test_set = Data.TensorDataset(*process_imdb(test_data, vocab))
train_iter = Data.DataLoader(train_set, batch_size, shuffle=True)
test_iter = Data.DataLoader(test_set, batch_size)
  • 创建TextCNN模型
class TextCNN(nn.Module):
    def __init__(self, vocab, embed_size, kernel_sizes, num_channels):
        super(TextCNN, self).__init__()
        self.embedding = nn.Embedding(len(vocab), embed_size)
        # 不参与训练的嵌入层
        self.constant_embedding = nn.Embedding(len(vocab), embed_size)
        self.dropout = nn.Dropout(0.5)
        self.decoder = nn.Linear(sum(num_channels), 2)
        # 时序最大池化层没有权重,所以可以共用一个实例
        self.pool = GlobalMaxPool1d()
        self.convs = nn.ModuleList()  # 创建多个一维卷积层
        for c, k in zip(num_channels, kernel_sizes):
            self.convs.append(nn.Conv1d(in_channels = 2*embed_size,
                                        out_channels 
  • 2
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值