TextCNN代码解读及实战,【干货

  • 1、创建默认方式的分词对象seg。

  • 2、打开文件,按照行读取文章。

  • 3、去掉收尾的空格,将label和文章分割开。

  • 4、将分词后的文章放到src_data,label放入labels里。

  • 5、返回结果。

  • 我对代码做了注解,如下:

def read_corpus(file_path):

“”"读取语料

:param file_path:

:param type:

:return:

“”"

src_data = []

labels = []

seg = pkuseg.pkuseg() #使用默认分词方式。

with codecs.open(file_path,‘r’,encoding=‘utf-8’) as fout:

for line in tqdm(fout.readlines(),desc=‘reading corpus’):

if line is not None:

line.strip()的意思是去掉每句话句首句尾的空格

.split(‘\t’)的意思是根据’\t’把label和文章内容分开,label和内容是通过‘\t’隔开的。

\t表示空四个字符,也称缩进,相当于按一下Tab键

pair = line.strip().split(‘\t’)

if len(pair) != 2:

print(pair)

continue

src_data.append(seg.cut(pair[1]))# 对文章内容分词。

labels.append(pair[0])

return (src_data, labels) #返回文章内容的分词结果和labels

  • 经过这个步骤得到了labels和分词后的文章。如下代码:

src_sents, labels = read_corpus(‘cnews/cnews.train.txt’)

对labels做映射:

labels = {label: idx for idx, label in enumerate(labels)}

得到labels对应的idx的字典,idx的值是最后一次插入label的值。

第二步 构建词向量

这一步主要用到vocab.py的from_corpus方法

思路:

1、创建vocab_entry对象。

2、对分词后的文章统计词频,生成一个词和词频构成的字典。

3、从字典中取出Top size - 2个元素。

4、获取元素的词。

5、执行add方法将词放入vocab_entry,生成词和id,id就是词对应的向量值。

代码如下:

@staticmethod

def from_corpus(corpus, size, min_feq=3):

“”“从给定语料中创建VocabEntry”“”

vocab_entry = VocabEntry()

chain函数来自于itertools库,itertools库提供了非常有用的基于迭代对象的函数,而chain函数则是可以串联多个迭代对象来形成一个更大的迭代对象

*的作用:返回单个迭代器。

word_freq是个字典,key=词,value=词频

word_freq = Counter(chain(*corpus)) # Counter 是实现的 dict 的一个子类,可以用来方便地计数,统计词频

valid_words = word_freq.most_common(size - 2) # most_common()函数用来实现Top n 功能,在这里选出Top size-2个词

valid_words = [word for word, value in valid_words if value >= min_feq] # 把符合要求的词找出来放到list里面。

print(‘number of word types: {}, number of word types w/ frequency >= {}: {}’

.format(len(word_freq), min_feq, len(valid_words)))

for word in valid_words: # 将词放进VocabEntry里面。

vocab_entry.add(word)

return vocab_entry

创建完成后将词向量保存到json文件中

vocab = Vocab.build(src_sents, labels, 50000, 3)

print(‘generated vocabulary, source %d words’ % (len(vocab.vocab)))

vocab.save(‘./vocab.json’)

训练

=============================================================

训练使用Train_CNN.py,先看分析main方法的参数。

参数


parse = argparse.ArgumentParser()

parse.add_argument(“–train_data_dir”, default=‘./cnews/cnews.train.txt’, type=str, required=False)

parse.add_argument(“–dev_data_dir”, default=‘./cnews/cnews.val.txt’, type=str, required=False)

parse.add_argument(“–test_data_dir”, default=‘./cnews/cnews.test.txt’, type=str, required=False)

parse.add_argument(“–output_file”, default=‘deep_model.log’, type=str, required=False)

parse.add_argument(“–batch_size”, default=8, type=int)

parse.add_argument(“–do_train”, default=True, action=“store_true”, help=“Whether to run training.”)

parse.add_argument(“–do_test”, default=True, action=“store_true”, help=“Whether to run training.”)

parse.add_argument(“–learnning_rate”, default=5e-4, type=float)

parse.add_argument(“–num_epoch”, default=50, type=int)

parse.add_argument(“–max_vocab_size”, default=50000, type=int)

parse.add_argument(“–min_freq”, default=2, type=int)

parse.add_argument(“–embed_size”, default=300, type=int)

parse.add_argument(“–dropout_rate”, default=0.2, type=float)

parse.add_argument(“–warmup_steps”, default=0, type=int, help=“Linear warmup over warmup_steps.”)

parse.add_argument(“–GRAD_CLIP”, default=1, type=float)

parse.add_argument(“–vocab_path”, default=‘vocab.json’, type=str)

parse.add_argument(“–num_filter”, default=100, type=int, help=“CNN模型一个filter的输出channels”)

参数说明:

train_data_dir:训练集路径。

dev_data_dir:验证集路径

test_data_dir:测试集路径

output_file:输出的log路径

batch_size:batchsize的大小。

do_train:是否训练,默认True、

do_test:是否测试,默认True

learnning_rate:学习率

num_epoch:epoch的数量

max_vocab_size:词向量的个数

min_freq:词频,过滤低于这个数值的词

embed_size:Embedding的长度。

dropout_rate:dropout的值。

warmup_steps:设置预热的值。

vocab_path:词向量保存的路径

num_filter:卷积输出的数量。

构建词向量


vocab = build_vocab(args)

label_map = vocab.labels

print(label_map)

build_vocab的方法:

def build_vocab(args):

if not os.path.exists(args.vocab_path):

src_sents, labels = read_corpus(args.train_data_dir)

labels = {label: idx for idx, label in enumerate(labels)}

vocab = Vocab.build(src_sents, labels, args.max_vocab_size, args.min_freq)

vocab.save(args.vocab_path)

else:

vocab = Vocab.load(args.vocab_path)

return vocab

创建模型

创建CNN模型,将模型放到GPU上,调用train方法,训练。

cnn_model = CNN(len(vocab.vocab), args.embed_size, args.num_filter, [2, 3, 4], len(label_map),

dropout=args.dropout_rate)

cnn_model.to(device)

print(cnn_model.parameters)

train(args, cnn_model, train_data, dev_data, vocab, dtype=‘CNN’)

对train方法做了一些注解,如下:

def train(args, model, train_data, dev_data, vocab, dtype=‘CNN’):

LOG_FILE = args.output_file

#记录训练log

with open(LOG_FILE, “a”) as fout:

fout.write(‘\n’)

fout.write(‘==========’ * 6)

fout.write(‘start trainning: {}’.format(dtype))

fout.write(‘\n’)

time_start = time.time()

if not os.path.exists(os.path.join(‘./runs’, dtype)):

os.makedirs(os.path.join(‘./runs’, dtype))

tb_writer = SummaryWriter(os.path.join(‘./runs’, dtype))

计算总的迭代次数

t_total = args.num_epoch * (math.ceil(len(train_data) / args.batch_size))

optimizer = AdamW(model.parameters(), lr=args.learnning_rate, eps=1e-8)#设置优化器

scheduler = get_linear_schedule_with_warmup(optimizer=optimizer, num_warmup_steps=args.warmup_steps,

num_training_steps=t_total) #设置预热。

criterion = nn.CrossEntropyLoss()# 设置loss为交叉熵

global_step = 0

total_loss = 0.

logg_loss = 0.

val_acces = []

train_epoch = trange(args.num_epoch, desc=‘train_epoch’)

for epoch in train_epoch:#训练epoch

model.train()

for src_sents, labels in batch_iter(train_data, args.batch_size, shuffle=True):

src_sents = vocab.vocab.to_input_tensor(src_sents, args.device)

global_step += 1

optimizer.zero_grad()

logits = model(src_sents)

y_labels = torch.tensor(labels, device=args.device)

example_losses = criterion(logits, y_labels)

example_losses.backward()

torch.nn.utils.clip_grad_norm_(model.parameters(), args.GRAD_CLIP)

optimizer.step()

scheduler.step()

total_loss += example_losses.item()

if global_step % 100 == 0:

loss_scalar = (total_loss - logg_loss) / 100

logg_loss = total_loss

with open(LOG_FILE, “a”) as fout:

fout.write(“epoch: {}, iter: {}, loss: {},learn_rate: {}\n”.format(epoch, global_step, loss_scalar,

scheduler.get_lr()[0]))

print(“epoch: {}, iter: {}, loss: {}, learning_rate: {}”.format(epoch, global_step, loss_scalar,

scheduler.get_lr()[0]))

tb_writer.add_scalar(“lr”, scheduler.get_lr()[0], global_step)

tb_writer.add_scalar(“loss”, loss_scalar, global_step)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
img

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值