基于pytorch使用LSTM进行虎年春联生成

news/2024/11/8 20:40:36/

先看看我摘录的一些结果吧

七字春联,开头两个字分别为 虎年、虎气、春节

虎年啸虎春虎虎
虎气伏虎牛龙龙

虎年虎虎展啸风
春节啸春虎风虎

虎年虎啸啸千啸
春节萝啸气风春

虎年啸浩一讯欢
春节回旧鹤绣舞

虎年啸一着有处
春节回一福舞福

虎年啸月翼业来
春节回旧精绣福

我语文水平不太行,乍一眼看感觉还是满高级的。

训练数据 春联.csv

0
龙腾虎啸
腊尽春回
高崖伏虎啸
茅庐卧龙飞
虎啸风声远
龙腾海浪高
龙引千江水
虎越万重山
密林藏伏虎
萝峰染晴云
山月流古雪
风虎浴清泉
事事都如意
虎虎有生气
云中熊虎将
天上凤凰儿
百尺飞泉鸣震谷
一声长啸势惊天
丙部琳琅春馥郁
寅宾璀灿日光华
长白虎啸林中日
江南猿啼岭上风
赤县奔腾如虎跃
神州崛起似龙飞
丑旧寅新宏图展
牛归虎跃春意浓
丑去寅来千里锦
牛奔虎啸九州春
丑去寅来人益健
牛奔虎跃春愈新
春风浩荡神州绿
虎气升腾岳麓雄
春风着意随人愿
虎气生威壮国魂
春光春色源春意
虎将虎年扬虎威
春节乍闻春有喜
虎年乐见虎生风
春雷巨响山河动
月夜旋风草木飞
春晓寅回人起舞
岁祯虎啸物昭苏
电闪金光夸五色
雷鸣巨吼动千山
憨厚忠诚牛品德
高昂奋勇虎精神
虎步奔腾开胜景
春风浩荡展鸿图
虎踞龙盘今胜昔
花得鸟语旧更新
虎踞龙盘今胜昔
莺歌燕舞呈吉祥
虎年赢得春风意
喜讯唤来燕子情
虎气顿生年属虎
春风常驻户迎春
虎气频催翻旧景
春风浩荡著新篇
虎添双翼前程远
国展宏图事业新
虎啸大山山献宝
龙腾祖国国扬威
虎啸密林凤万壑
鹤眠苍松月千岩
虎啸青山千里锦
风拂绿柳万家春
虎啸一声山海动
龙腾三界吉祥来
虎跃龙腾生紫气
风调雨顺兆丰年
虎跃龙腾兴骏业
莺歌燕舞羡鹏程
虎跃神州千业旺
春临盛世万民欢
花事才逢花好日
虎年更有虎威风
黄牛虽去精神在
猛虎初来气象新
江山秀丽春增色
事业辉煌虎更威
江山一统腾龙日
岁月三春入虎年
皆称飞虎一身胆
不负英雄千古名
金牛昂首高歌去
玉虎迎春敛福来
金牛辞岁寒风尽
白虎迎春喜气来
金牛辞岁千仓满
玉虎迎春百业兴
金牛奋蹄奔大道
乳虎添翼舞新春
金牛奋蹄开锦绣
乳虎添翼会风云
金牛送旧千家乐
玉虎迎新万户欢
龙腾虎跃人间景
鸟语花香天地春
绿野春深禾涌碧
神州虎啸青山来
门庭虎踞平安岁
柳浪莺歌锦绣春
门浴春风梅吐艳
户生虎气鸟争鸣
年逢寅虎群情奋
岁别丑牛大地春
牛肥马壮丰收岁
虎跃龙腾大有年
牛肥马壮家家富
虎跃龙腾处处春
牛奋千程荣盛世
虎驮五福贺新春
牛奋四蹄开锦绣
虎添双翼会风云
牛耕绿野千仓满
虎啸青山万木荣
牛耕沃野扬长去
虎啸群山大步来
千载难逢新世纪
万民谱写虎春秋
乾元启运三阳泰
斗丙回寅万户春
人逢盛世精神壮
虎跃奇峰气势雄
人间喜庆康平世
虎岁承欢幸福春
人民气魄如龙虎
祖国江山似画图
人入虎年鼓虎劲
门添春色发春辉
人添志气虎添翼
雪舞丰年燕舞春
人效黄牛心自贵
岁朝寅虎劲更高
山明水秀风光丽
虎跃龙腾日月新
生气联吟欣虎虎
留春伴读奋年年
四海龙腾抒壮志
千山虎啸振雄风
四海三江春气息
千家万户虎精神
四海笙歌迎虎岁
九州英杰跃鹏程
唯大英雄能伏虎
是真俊杰敢擒龙
啸一声惊天动地
睁双眼照耀乾坤
新年捷报虎添翼
大路朝阳马奋蹄
兴伟业仍须牛劲
展宏图更壮虎威
一代英豪生虎气
三春杨柳动莺歌
英雄气概如龙虎
祖国江山似画图
英雄时代英雄业
龙虎精神龙虎年
莺歌燕舞新春日
虎跃龙腾大治年
迎春节莺歌遍地
兴中华虎劲冲天
云喷笔花腾虎豹
雨翻墨浪走蛟龙
宅后青山金虎踞
门前绿水玉龙盘
致富脱贫添虎翼
开山治水展鹏程
丙穴鱼生人间改岁
寅方斗指天下皆春
春风浩荡花香鸟语
岁月峥嵘虎跃龙腾
虎跃龙腾九州焕彩
风调雨顺五谷丰登
牛奔福地普天献瑞
虎卧华堂满院生辉
势如破竹人欢马叫
安若泰山虎踞龙盘
紫气东来江山如画
红旗招展龙虎扬威
祖国富强神龙活虎
人民幸福舞燕飞莺
白虎替青牛招财进宝
黄莺鸣翠柳辞旧迎新
虎跃龙腾创人间奇迹
莺歌燕舞描大地春光
虎跃龙腾有天皆丽日
花香鸟语无地不春风
花团锦簇江山添异彩
虎啸龙吟华夏壮神威
金牛辞旧携凯歌而去
乳虎迎春带捷报新来
瑞雪兆丰年年年大吉
丑牛接寅虎虎虎生威
岁月逢春山河添锦绣
人民思治龙虎振精神
效虎豪吟放怀歌富岁
闻鸡起舞挥笔颂春光
祖国腾飞大鹏振羽翼
宏图再展乳虎显神通
庆虎岁把酒高吟虎跃曲
祝丰年扶犁又唱丰收谣
迎虎年敢逐改革拦路虎
送牛岁勇当奉献老黄牛
迎新春处处呈文明气象
入虎岁人人当改革先锋
虎跃龙腾碧海黄山妆玉宇
莺歌燕舞春风旭日蔚神州
虎跃龙腾华夏人民多俊杰
莺歌燕舞阳春山水尽朝晖
牛耕广野丑年犁出文明路
虎跃深山寅岁图开舜尧天
岁步寅年喜庆团圆同把酒
珠还合浦欢歌一统共迎春
喜庆牛年两制先迎香港还
欢歌兔岁亿民再赞澳门归
栽竹栽松竹隐凤凰松隐鹤
培山培水山藏虎豹水藏龙
丑岁建奇功香港回归昌国运
寅年兴大业宏图展现壮情怀
虎年喜虎劲攻关夺隘皆如虎
春节焕春光绣水描山总是春
牛年虽过去牛劲更增多奉献
虎岁喜临门虎威大振有精神
寅时入虎年十亿人民振虎劲
佳节描春色九州大地荡春潮
忆旧岁牛劲冲霄汉神鞭一指神州巨变
看今朝虎威壮中华众志成城经济腾飞

滑动窗口设置为2,即两个字符预测下一个字符,滑动预测5个字符。
但是还是存在较大问题,因为我是直接将所有的对联都拼接起来然后滑动选取训练数据和标签,而不是每句滑动选取,这样就导致会串,但是懒得切了,就这样吧。

完整代码

# coding: utf-8
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import OneHotEncoder
import torch.nn.functional as Fclass lstm_model(nn.Module):def __init__(self, vocab, hidden_size, num_layers, dropout=0.5):super(lstm_model, self).__init__()self.vocab = vocab  # 字符数据集# 索引,字符self.int_char = {i: char for i, char in enumerate(vocab)}self.char_int = {char: i for i, char in self.int_char.items()}# 对字符进行one-hot encodingself.encoder = OneHotEncoder(sparse=True).fit(vocab.reshape(-1, 1))self.hidden_size = hidden_sizeself.num_layers = num_layers# lstm层self.lstm = nn.LSTM(len(vocab), hidden_size, num_layers, batch_first=True, dropout=dropout)# 全连接层self.linear = nn.Linear(hidden_size, len(vocab))def forward(self, sequence, hs=None):out, hs = self.lstm(sequence, hs)  # lstm的输出格式(batch_size, sequence_length, hidden_size)output = self.linear(out[:, -1])  # linear的输出格式,(batch_size * sequence_length, vocab_size)return output, hsdef onehot_encode(self, data):return self.encoder.transform(data)def onehot_decode(self, data):return self.encoder.inverse_transform(data)def label_encode(self, data):return np.array([self.char_int[ch] for ch in data])def label_decode(self, data):return np.array([self.int_char[ch] for ch in data])def get_batches(data, batch_size, seq_len):''':param data: 源数据,输入格式(num_samples, num_features):param batch_size: batch的大小:param seq_len: 序列的长度(精度):return: (batch_size, seq_len, num_features)'''num_features = data.shape[1]num_chars = batch_size * seq_len  # 一个batch_size的长度num_batches = int(np.floor(data.shape[0] / num_chars))  # 计算出有多少个batchesneed_chars = num_batches * num_chars  # 计算出需要的总字符量targets = np.vstack((data[1:].A, data[0].A))  # 可能版本问题,取成numpy比较好reshapeinputs = data[:need_chars].A.astype("int")  # 从原始数据data中截取所需的字符数量need_wordstrain_data = np.zeros((inputs.shape[0] - seq_len, seq_len, num_features))train_label = np.zeros((inputs.shape[0] - seq_len, num_features))for i in range(0, inputs.shape[0] - seq_len, 1):train_data[i] = inputs[i:i+seq_len]train_label[i] = inputs[i+seq_len-1]for i in range(0, inputs.shape[0] - seq_len,  batch_size):if i + batch_size > inputs.shape[0] - seq_len:breakx = train_data[i:i+batch_size]y = train_label[i:i+batch_size]yield x, ydef train(model, data, batch_size, seq_len, epochs, lr=0.01, valid=None):device = 'cuda' if torch.cuda.is_available() else 'cpu'model = model.to(device)optimizer = torch.optim.Adam(model.parameters(), lr=lr)criterion = nn.CrossEntropyLoss()if valid is not None:data = model.onehot_encode(data.reshape(-1, 1))valid = model.onehot_encode(valid.reshape(-1, 1))else:data = model.onehot_encode(data.reshape(-1, 1))train_loss = []val_loss = []for epoch in range(epochs):model.train()hs = None  # hs等于hidden_size隐藏层节点train_ls = 0.0val_ls = 0.0for x, y in get_batches(data, batch_size, seq_len):optimizer.zero_grad()x = torch.tensor(x).float().to(device)out, hs = model(x, hs)hs = ([h.data for h in hs])y = y.reshape(-1, len(model.vocab))y = model.onehot_decode(y)y = model.label_encode(y.squeeze())y = torch.from_numpy(y).long().to(device)loss = criterion(out, y.squeeze())loss.backward()optimizer.step()train_ls += loss.item()if valid is not None:model.eval()hs = Nonewith torch.no_grad():for x, y in get_batches(valid, batch_size, seq_len):x = torch.tensor(x).float().to(device)  # x为一组测试数据,包含batch_size * seq_len个字out, hs = model(x, hs)# out.shape输出为tensor[batch_size * seq_len, vocab_size]hs = ([h.data for h in hs])  # 更新参数y = y.reshape(-1, len(model.vocab))  # y.shape为(128,100,43),因此需要转成两维,每行就代表一个字了,43为字典大小y = model.onehot_decode(y)  # y标签即为测试数据各个字的下一个字,进行one_hot解码,即变为字符# 但是此时y 是[[..],[..]]形式y = model.label_encode(y.squeeze())  # 因此需要去掉一维才能成功解码# 此时y为[12...]成为一维的数组,每个代表自己字典里对应字符的字典序y = torch.from_numpy(y).long().to(device)# 这里y和y.squeeze()出来的东西一样,可能这里没啥用,不太懂loss = criterion(out, y.squeeze())  # 计算损失值val_ls += loss.item()val_loss.append(np.mean(val_ls))train_loss.append(np.mean(train_ls))print("val_loss", val_ls)print("train_loss:", train_ls)plt.plot(train_loss, label="train_loss")plt.plot(val_loss, label="val loss")plt.title("loop vs epoch")plt.legend()plt.show()model_name = "lstm_model.net"with open(model_name, 'wb') as f:  # 训练完了保存模型torch.save(model.state_dict(), f)def predict(vocab_size, model, char, top_k=None, hidden_size=None):device = 'cuda' if torch.cuda.is_available() else 'cpu'model.to(device)model.eval()  # 固定参数with torch.no_grad():char = np.array([char])  # 输入一个字符,预测下一个字是什么,先转成numpychar = char.reshape(-1, 1)  # 变成二维才符合编码规范char_encoding = model.onehot_encode(char).A  # 对char进行编码,取成numpy比较方便reshapechar_encoding = char_encoding.reshape(1, -1, vocab_size)# 转成模型输入格式 char_tensor = torch.tensor(char_encoding, dtype=torch.float32)  # 转成tensorchar_tensor = char_tensor.to(device)out, hidden_size = model(char_tensor, hidden_size)  # 放入模型进行预测,out为结果probs = F.softmax(out, dim=1).squeeze()  # 计算预测值,即所有字符的概率print(probs.shape)if top_k is None:  # 选择概率最大的top_k个indices = np.arange(vocab_size)else:probs, indices = probs.topk(top_k)indices = indices.cpu().numpy()probs = probs.cpu().numpy()char_index = np.random.choice(indices, p=probs/probs.sum())  # 随机选择一个字符索引作为预测值char = model.int_char[char_index]  # 通过索引找出预测字符return char, hidden_sizedef sample(vocab_size, seq_len, model, length,sentence, top_k=None):hidden_size = Nonenew_sentence = [char for char in sentence]for i in range(length):next_char, hidden_size = predict(vocab_size, model, new_sentence[-seq_len:], top_k=top_k, hidden_size=hidden_size)new_sentence.append(next_char)return "".join(new_sentence)def main():hidden_size = 512num_layers = 4batch_size = 128seq_len = 2epochs = 30lr = 0.0001f = pd.read_csv("春联.csv")f = f["0"]text = list(f)text = ".".join(text).replace(".", "")vocab = np.array(sorted(set(text)))  # 建立字典vocab_size = len(vocab)print("vocab_size", vocab_size)val_len = int(np.floor(0.2 * len(text)))  # 划分训练测试集trainset = np.array(list(text[:-val_len]))validset = np.array(list(text[-val_len:]))model = lstm_model(vocab, hidden_size, num_layers)  # 模型实例化train(model, trainset, batch_size, seq_len, epochs, lr=lr, valid=validset)  # 训练模型model.load_state_dict(torch.load("lstm_model.net"))  # 调用保存的模型new_text1 = sample(vocab_size, seq_len, model, 5, "虎年", top_k=7)  # 预测模型,生成100个字符,预测时选择概率最大的前5个new_text2 = sample(vocab_size, seq_len, model, 5, "春节", top_k=7)  # 预测模型,生成100个字符,预测时选择概率最大的前5个print(new_text1)  # 输出预测文本print(new_text2)if __name__ == "__main__":main()

http://www.ppmy.cn/news/428308.html

相关文章

Mock数据Mustache语法学习记录

简单记录一下Mock数据运行成功。 1.最基础的HTMLjQuery,如何运行Mock数据 新建一个文件夹,用于存放mock.min.js文件和mustache.min.js文件,(压缩文件) 代码自取⬇️ mock.min.js !function(t,e){"object&quo…

python 字典列表,元组列表 列表嵌套字典 列表嵌套元组 字典嵌套列表

列表嵌套字典 l[] for i in alist:kk {}names.append(i.string)a_url.append(i.get(href))kk[章节名]i.stringkk[章节链接]serversi.get(href)l.append(kk) 列表嵌套元组(由字典转化而来) for i in alist:names.append(i.string)a_url.append(i.get(…

前端程序员需要了解的JavaScript之高级部分知识

前言:这一篇文章主要讲解JavaScript高级的知识,涉及到原型,类,继承,模块化,正则匹配,以及promise的使用,还会了解到一些鼠标键盘事件以及关于前端页面内容的知识。学完这些你可以去学…

IDEA+Java+Servlet+JSP+Mysql实现Web停车场管理系统【建议收藏】

目录 一、系统介绍 1.开发环境 2.技术选型 3.系统功能 4.数据库 5.工程截图 二、系统展示 1.登录界面 2.主页面 3.系统信息管理-添加角色信息 4.系统信息管理-管理角色信息 5.系统信息管理-添加用户信息 6.系统信息管理-管理用户信息 7.车位信息管理-添加车位信息…

实时采样与等效采样

实时采样与等效采样 基本的数字化采样方式有两种:实时采样与等效采样 实时采样 实时采样:以等时间间隔的方式,且按时间的顺序,对波形进行A/D转换,并进行存储。如图。 实时采样是最直观的采样方式,其只…

题目记录:

无重复字符的最长子串 class Solution:def lengthOfLongestSubstring(self, s: str) -> int:if not s:return 0 #判断是否为空left 0lookup set() # set() 函数创建一个无序不重复元素集n len(s) # 字符串长度max_len 0 # 最大长度cur_len 0 # 滑动框长度for i in r…

Django3(二)异步编程

目录 一、使用多线程 二、启用ASGI服务 三、异步视图 异步与同步的转换 其他:消息队列(基本概念) 异步编程:使用协程、线程、进程、消息队列等方式实现。 Django支持多线程、内置异步和消息队列方式实现。 多线程:在当前运行的Django服务…

Markdown语法案例

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…