大略先容一下,本项目在GitHub上有开源,我根据上面的源码做了部分修正,使其看起来更大略易懂。
同时,代码的规范更符合新手入门。
好了,不多说,就让我们开始吧。

准备事情:

编程工具IDE:pycharm

python版本: 3.6.0

首先新建一个py文件,命名为:ai_poem.py

不会唐诗三百首然则我会让电脑自己写诗内附完整python源码

PS: 以下七步的代码直接复制到单个py文件里面就可以直接运行。
七步成诗)为了让读者方便写代码,我把代码都贴出来了,但是排版存在问题,我又把在pycharm的代码排版给截图出来。

第一步:导入干系的python包

#encoding:utf-8from gensim.models import Word2Vec # 词向量from random import choicefrom os.path import existsfrom warnings import filterwarningsfilterwarnings('ignore') # 不打印警告import re

老规矩,一步一步来,先先容每个包的浸染。
gensim 包是自然措辞处理的个中一个python包,大略随意马虎利用,是入门NLP算法必用的一个python包。
如果你想往人工智能方向发展,这个包必须学会。
random包用来天生随机数,或者从某个列表随机抽取一个元素。
os包,本项目只用到了对文件的操作功能。
re包是用于正则表达式,做爬虫的朋友常常会用到这个包来对数据进行洗濯。
warning包,是包含了程序运行警告的一些功能。

代码排版

以上这些包,不是关键,学习的时候,如果不懂,可以先跳过。
等理解、跑通全体程序流程后,可以一个一个包有针对性地去学习、去看文档。

第二步:参数设定

class CONF: path = '古诗词.txt' # 语料路径 window = 16 # 滑窗大小 min_count = 60 # 过滤低频字 size = 125 # 词向量维度 topn = 14 # 天生诗词的开放度 model_path = 'gushici.model' # 模型路径

这里是个人编程的习气,我习气把一些配置,例如:文件路径、模型存放路径、模型参数统一放在一个类中。
当然,实际项目开拓的时候,是用config 文本文件存放,不会直接写在代码里,这里为了演示方便,就写在一起,也方便运行。

代码排版

第三步:模型的初始化函数

class Model: def __init__(self, window, topn, model): self.window = window self.topn = topn self.model = model # 词向量模型 self.chr_dict = model.wv.index2word # 字典 """模型初始化""" @classmethod def initialize(cls, config): if exists(config.model_path): # 模型读取 model = Word2Vec.load(config.model_path) else: # 语料读取 with open(config.path, encoding='utf-8') as f: ls_of_ls_of_c = [list(line.strip()) for line in f] # 模型演习和保存 model = Word2Vec(sentences=ls_of_ls_of_c, size=config.size, window=config.window, min_count=config.min_count) model.save(config.model_path) return cls(config.window, config.topn, model)

initialize() 函数和 __init__() 函数 是工具初始化和实例化,个中包括基本参数的赋值、模型的导入、模型的演习、模型的保存、末了返回用户一个工具。
这里作为一个类的基本操作,是属于一个通用模板,在大多数项目中,都可以这么去写。
大家可以翻看我之前写的几篇关于python项目,基本都是这个写法,以是这个模板还是有必要记住的。

代码排版

第四步: 古诗词天生(类里面的函数)

class Model: ...... """古诗词天生""" def poem_generator(self, title, form, author='佚名', type_name=''): # list_of_tuples --> list_of_strings 并过滤标点符号 filter = lambda lst: [t[0] for t in lst if t[0] not in [',', '。
']] # 标题补全 if not title: title += choice(self.chr_dict) tmp_n = 0 for _ in range(4 - len(title)): try: chrs = self.model.similar_by_word(title[-1], self.topn // 2) chrs = filter(chrs) char = choice([c for c in chrs if c not in title]) except: char = title[tmp_n] tmp_n += 1 title += char # 文本天生 seq = list(title) for i in range(form[0]): # 多少行 for _ in range(form[1]): # 每行字数 chrs = self.model.predict_output_word(seq[-self.window:], max(self.topn, len(seq) + 1)) chrs = filter(chrs) char = choice([c for c in chrs if c not in seq[len(title):]]) seq.append(char) seq.append(',' if i % 2 == 0 else '。
') # 返回标题+主体 length = form[0] (form[1] + 1) title = '《%s》' % ''.join(seq[:-length]) poem = ''.join(seq[-length:]) if author != 'undefined': return title + '\n'+ "墨客:" + author + '\n\n' + poem else: return title + '\n'+"--"+ type_name + '\n\n' + poem

作诗模型的最核心的算法,通过NLP算法对标题进行补全,对诗的内容进行预测。
这里的预测指的是根据用户输入的内容,找出古诗中干系性比较强的语料,再按照古诗词的排版顺序,依次预测每句诗的每个字。
这是从五万多首古诗里面,程序自主学习得到的模型。

代码排版

第五步:藏头诗生成规则(类里面的函数)

class Model: ...... """古诗词天生 -- 藏头诗""" def poem_generator_hide_head(self, title, form, author='佚名', type_name=''): # list_of_tuples --> list_of_strings 并过滤标点符号 filter = lambda lst: [t[0] for t in lst if t[0] not in [',', '。
']] # 标题补全 if len(title) < 4: if not title: title += choice(self.chr_dict) tmp_n = 0 for _ in range(4 - len(title)): try: chrs = self.model.similar_by_word(title[-1], self.topn // 2) chrs = filter(chrs) char = choice([c for c in chrs if c not in title]) except: char = title[tmp_n] tmp_n+=1 title += char # 文本天生 seq = list(title) for i in range(form[0]): # 多少行 for _ in range(form[1]): # 每行字数 if _ == 0: char = seq[i] else: chrs = self.model.predict_output_word(seq[-self.window:], max(self.topn, len(seq) + 1)) chrs = filter(chrs) char = choice([c for c in chrs if c not in seq[len(title):]]) seq.append(char) seq.append(',' if i % 2 == 0 else '。
') # 返回标题+主体 length = form[0] (form[1] + 1) title = '《%s》' % ''.join(seq[:-length]) poem = ''.join(seq[-length:]) if author != 'undefined': return title + '\n' + "墨客:" + author + '\n\n' + poem else: return title + '\n' + "--" + type_name + '\n\n' + poem

藏头诗,顾名思义便是把用户输入的内容,作为每句诗第一个字。
源码里没有这个模块,这里是我自己添加的,由于在这个项目发布后,有不少网友哀求能天生藏头诗,以是我就做了这个功能。

代码排版

第六步:一些细节上的处理

def filter_char(word): """ 过滤掉非中笔墨符 """ sub_str = re.sub(u"([^\u4e00-\u9fa5])", "", word) return sub_str

在项目开拓的时候,常常要考虑一些分外的情形,例如用户不按常理出牌,给你输入一堆字母或标点符号之类的怎么办?我这里写了一个正则表达式,可以过滤掉所有的非中笔墨符。
感兴趣的朋友可以去理解一下正则表达式,挺有趣的。

代码排版

第七步: 主流程

def main(config=CONF): form = {'五言绝句': (4, 5), '七言绝句': (4, 7)} m = Model.initialize(config) while True: title = input('输入标题:').strip() try: # 普通诗句 poem = m.poem_generator(title, form['五言绝句']) print('\033[031m%s\033[0m' % poem) # red poem = m.poem_generator(title, form['七言绝句']) print('\033[033m%s\033[0m' % poem) # yellow # 藏头诗 poem = m.poem_generator_hide_head(title, form['五言绝句']) print('\033[031m%s\033[0m' % poem) # red poem = m.poem_generator_hide_head(title, form['七言绝句']) print('\033[033m%s\033[0m' % poem) # yellow except: passif __name__ == '__main__': main()

至此,加上一个main函数去调用,所有程序的入口。
我们终于完成了。

代码排版

好了,让我们把代码跑起来。
输入一个主题:“清明节”,不到一秒就天生一首诗。

微信端显示:

程序后台结果显示:

如果有疑问想获取源码(实在代码都在上面),可以后台私信我,回答:python写诗。
我把源码发你。
末了,感谢大家的阅读,祝大家事情生活愉快!