在pytorch下,以数万首唐诗为素材,训练双层LSTM神经网络,使其能够以唐诗的方式写诗。
代码结构分为四部分,分别为
1.model.py,定义了双层LSTM模型
2.data.py,定义了从网上得到的唐诗数据的处理方法
3.utlis.py 定义了损失可视化的函数
4.main.py定义了模型参数,以及训练、唐诗生成函数。
参考:电子工业出版社的《深度学习框架PyTorch:入门与实践》第九章
main代码及注释如下
import sys, os import torch as t from data import get_data from model import PoetryModel from torch import nn from torch.autograd import Variable from utils import Visualizer import tqdm from torchnet import meter import ipdb class Config(object): data_path = 'data/' pickle_path = 'tang.npz' author = None constrain = None category = 'poet.tang' #or poet.song lr = 1e-3 weight_decay = 1e-4 use_gpu = True epoch = 20 batch_size = 128 maxlen = 125 plot_every = 20 #use_env = True #是否使用visodm env = 'poety' #visdom env max_gen_len = 200 debug_file = '/tmp/debugp' model_path = None prefix_words = '细雨鱼儿出,微风燕子斜。' #不是诗歌组成部分,是意境 start_words = '闲云潭影日悠悠' #诗歌开始 acrostic = False #是否藏头 model_prefix = 'checkpoints/tang' #模型保存路径 opt = Config() def generate(model, start_words, ix2word, word2ix, prefix_words=None): ''' 给定几个词,根据这几个词接着生成一首完整的诗歌 ''' results = list(start_words) start_word_len = len(start_words) # 手动设置第一个词为<START> # 这个地方有问题,最后需要再看一下 input = Variable(t.Tensor([word2ix['<START>']]).view(1,1).long()) if opt.use_gpu:input=input.cuda() hidden = None if prefix_words: for word in prefix_words: output,hidden = model(input,hidden) # 下边这句话是为了把input变成1*1? input = Variable(input.data.new([word2ix[word]])).view(1,1) for i in range(opt.max_gen_len): output,hidden = model(input,hidden) if i<start_word_len: w = results[i] input = Variable(input.data.new([word2ix[w]])).view(1,1) else: top_index = output.data[0].topk(1)[1][0] w = ix2word[top_index] results.append(w) input = Variable(input.data.new([top_index])).view(1,1) if w=='<EOP>': del results[-1] #-1的意思是倒数第一个 break return results def gen_acrostic(model,start_words,ix2word,word2ix, prefix_words = None): ''' 生成藏头诗 start_words : u'深度学习' 生成: 深木通中岳,青苔半日脂。 度山分地险,逆浪到南巴。 学道兵犹毒,当时燕不移。 习根通古岸,开镜出清羸。 ''' results = [] start_word_len = len(start_words) input = Variable(t.Tensor([word2ix['<START>']]).view(1,1).long()) if opt.use_gpu:input=input.cuda() hidden = None index=0 # 用来指示已经生成了多少句藏头诗 # 上一个词 pre_word='<START>' if prefix_words: for word in prefix_words: output,hidden = model(input,hidden) input = Variable(input.data.new([word2ix[word]])).view(1,1) for i in range(opt.max_gen_len): output,hidden = model(input,hidden) top_index = output.data[0].topk(1)[1][0] w = ix2word[top_index] if (pre_word in {u'。',u'!','<START>'} ): # 如果遇到句号,藏头的词送进去生成 if index==start_word_len: # 如果生成的诗歌已经包含全部藏头的词,则结束 break else: # 把藏头的词作为输入送入模型 w = start_words[index] index+=1 input = Variable(input.data.new([word2ix[w]])).view(1,1) else: # 否则的话,把上一次预测是词作为下一个词输入 input = Variable(input.data.new([word2ix[w]])).view(1,1) results.append(w) pre_word = w return results def train(**kwargs): for k,v in kwargs.items(): setattr(opt,k,v) #设置apt里属性的值 vis = Visualizer(env=opt.env) #获取数据 data, word2ix, ix2word = get_data(opt) #get_data是data.py里的函数 data = t.from_numpy(data) #这个地方出错了,是大写的L dataloader = t.utils.data.DataLoader(data, batch_size = opt.batch_size, shuffle = True, num_workers = 1) #在python里,这样写程序可以吗? #模型定义 model = PoetryModel(len(word2ix), 128, 256) optimizer = t.optim.Adam(model.parameters(), lr=opt.lr) criterion = nn.CrossEntropyLoss() if opt.model_path: model.load_state_dict(t.load(opt.model_path)) if opt.use_gpu: model.cuda() criterion.cuda() #The tnt.AverageValueMeter measures and returns the average value #and the standard deviation of any collection of numbers that are #added to it. It is useful, for instance, to measure the average #loss over a collection of examples. #The add() function expects as input a Lua number value, which #is the value that needs to be added to the list of values to #average. It also takes as input an optional parameter n that #assigns a weight to value in the average, in order to facilitate #computing weighted averages (default = 1). #The tnt.AverageValueMeter has no parameters to be set at initialization time. loss_meter = meter.AverageValueMeter() for epoch in range(opt.epoch): loss_meter.reset() for ii,data_ in tqdm.tqdm(enumerate(dataloader)): #tqdm是python中的进度条 #训练 data_ = data_.long().transpose(1,0).contiguous() #上边一句话,把data_变成long类型,把1维和0维转置,把内存调成连续的 if opt.use_gpu: data_ = data_.cuda() optimizer.zero_grad() input_, target = Variable(data_[:-1,:]), Variable(data_[1:,:]) #上边一句,将输入的诗句错开一个字,形成训练和目标 output,_ = model(input_) loss = criterion(output, target.view(-1)) loss.backward() optimizer.step() loss_meter.add(loss.data[0]) #为什么是data[0]? #可视化用到的是utlis.py里的函数 if (1+ii)%opt.plot_every ==0: if os.path.exists(opt.debug_file): ipdb.set_trace() vis.plot('loss',loss_meter.value()[0]) # 下面是对目前模型情况的测试,诗歌原文 poetrys = [[ix2word[_word] for _word in data_[:,_iii]] for _iii in range(data_.size(1))][:16] #上面句子嵌套了两个循环,主要是将诗歌索引的前十六个字变成原文 vis.text('</br>'.join([''.join(poetry) for poetry in poetrys]),win = u'origin_poem') gen_poetries = [] #分别以以下几个字作为诗歌的第一个字,生成8首诗 for word in list(u'春江花月夜凉如水'): gen_poetry = ''.join(generate(model,word,ix2word,word2ix)) gen_poetries.append(gen_poetry) vis.text('</br>'.join([''.join(poetry) for poetry in gen_poetries]), win = u'gen_poem') t.save(model.state_dict(), '%s_%s.pth' %(opt.model_prefix,epoch)) def gen(**kwargs): ''' 提供命令行接口,用以生成相应的诗 ''' for k,v in kwargs.items(): setattr(opt,k,v) data, word2ix, ix2word = get_data(opt) model = PoetryModel(len(word2ix), 128, 256) map_location = lambda s,l:s # 上边句子里的map_location是在load里用的,用以加载到指定的CPU或GPU, # 上边句子的意思是将模型加载到默认的GPU上 state_dict = t.load(opt.model_path, map_location = map_location) model.load_state_dict(state_dict) if opt.use_gpu: model.cuda() if sys.version_info.major == 3: if opt.start_words.insprintable(): start_words = opt.start_words prefix_words = opt.prefix_words if opt.prefix_words else None else: start_words = opt.start_words.encode('ascii', 'surrogateescape').decode('utf8') prefix_words = opt.prefix_words.encode('ascii', 'surrogateescape').decode('utf8') if opt.prefix_words else None start_words = start_words.replace(',',u',') .replace('.',u'。') .replace('?',u'?') gen_poetry = gen_acrostic if opt.acrostic else generate result = gen_poetry(model,start_words,ix2word,word2ix,prefix_words) print(''.join(result)) if __name__ == '__main__': import fire fire.Fire()
以上代码给我一些经验,
1. 了解python的编程方式,如空格、换行等;进一步了解python的各个基本模块;
2. 可能出的错误:函数名写错,大小写,变量名写错,括号不全。
3. 对cuda()的用法有了进一步认识;
4. 学会了调试程序(fire);
5. 学会了训练结果的可视化(visdom);
6. 进一步的了解了LSTM,对深度学习的架构、实现有了宏观把控。
这篇pytorch下使用LSTM神经网络写诗实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 明达年度发烧碟MasterSuperiorAudiophile2021[DSF]
- 英文DJ 《致命的温柔》24K德国HD金碟DTS 2CD[WAV+分轨][1.7G]
- 张学友1997《不老的传说》宝丽金首版 [WAV+CUE][971M]
- 张韶涵2024 《不负韶华》开盘母带[低速原抓WAV+CUE][1.1G]
- lol全球总决赛lcs三号种子是谁 S14全球总决赛lcs三号种子队伍介绍
- lol全球总决赛lck三号种子是谁 S14全球总决赛lck三号种子队伍
- 群星.2005-三里屯音乐之男孩女孩的情人节【太合麦田】【WAV+CUE】
- 崔健.2005-给你一点颜色【东西音乐】【WAV+CUE】
- 南台湾小姑娘.1998-心爱,等一下【大旗】【WAV+CUE】
- 【新世纪】群星-美丽人生(CestLaVie)(6CD)[WAV+CUE]
- ProteanQuartet-Tempusomniavincit(2024)[24-WAV]
- SirEdwardElgarconductsElgar[FLAC+CUE]
- 田震《20世纪中华歌坛名人百集珍藏版》[WAV+CUE][1G]
- BEYOND《大地》24K金蝶限量编号[低速原抓WAV+CUE][986M]
- 陈奕迅《准备中 SACD》[日本限量版] [WAV+CUE][1.2G]