简介:这份资源面向机器学习与自然语言处理方向的初学者及课程实践者,提供一套古诗自动生成与情感分析的完整项目方案,覆盖从语料爬取、数据清洗到规则作诗与模型写诗的全流程。包内共156个文件,以73个txt语料与说明、43个Python脚本为主,另含模型检查点、词向量文件、png图表及docx文档,压缩包约337MB,便于按模块查阅与复现。项目先通过爬虫采集古诗及作者、朝代、情感标签,再经去重、分词、去停用词等预处理划分训练集、验证集与测试集,并借助统计工具完成词频与关键词分析;规则引擎依据格律韵脚生成诗句,机器学习模型则基于词向量与检查点实现写诗,可作为课程设计或毕业项目的参考。目前已有295人学习下载,适合希望系统掌握文本生成与情感分析实践路径的读者。
1. 从一份 checkpoint 说起:这套古诗生成系统到底能跑出什么
前阵子有个做 NLP 的朋友甩给我一个压缩包,解压完我愣了一下——里面没有 README,没有 requirements.txt,只有一堆checkpoint文件和model.ckpt-4000.data-00000-of-00001、model.ckpt-52000.data-00000-of-00001、model.ckpt-53493.data-00000-of-00001这样的权重分片,外加一个vectors_poem.bin。这就是典型的「模型比代码先到」的现场。这套资源对应的是一个基于机器学习与自然语言处理的古诗自动生成与情感分析系统,覆盖了从语料爬取、数据处理、词频与情感分析,到规则作诗和机器学习写诗两条生成路线的完整链路。它适合两类人:一类是想拿现成语料和权重快速跑通古诗生成 demo 的开发者,另一类是打算把「规则引擎 + 序列模型」这套组合拳拆开研究、迁移到自己文本生成任务上的从业者。下面我按实际拆包顺序,把这份资源怎么用、参数怎么调、坑在哪讲清楚。
2. 语料与数据管道:从爬取到 vectors_poem.bin 的完整链路
2.1 为什么古诗任务的数据处理比模型更费劲
古诗这个场景有个反直觉的地方:模型结构其实不复杂,真正吃掉你时间的是数据管道。原因在于古诗文本短、生僻字多、格律约束强,分词器一不小心就把「萧萧班马鸣」切成「萧萧 / 班 / 马鸣」,训练出来的模型自然写不出像样的句子。所以这套资源里vectors_poem.bin这个文件才是核心资产之一——它是预先训练好的词向量二进制文件,直接决定了后续模型能认识哪些字词、字词之间的语义距离是否合理。
常见做法是先用爬虫把古诗文本连同作者、朝代、情感标签一起抓下来,存成本地文件或数据库。这里要注意,情感标签不是每个语料源都带,没有标签的那部分要么人工标注一批,要么在情感分析环节退化成无监督的词频与主题统计。处理完的语料按训练集、验证集、测试集切分,切分比例我一般用 8:1:1,古诗这种小样本任务不建议留太多验证数据,否则训练集不够模型收敛。
2.2 爬取与清洗的可复现脚本
爬虫部分用 requests + BeautifulSoup 就够,别一上来就上 Scrapy,古诗站点结构通常很简单,重框架反而拖慢调试。下面这段是清洗管道的骨架,重点看去重和停用词处理:
import re import jieba from bs4 import BeautifulSoup # 1. 去 HTML 标签,古诗站点经常把正文包在 <div class="contson"> 里 def clean_html(raw_html): soup = BeautifulSoup(raw_html, "html.parser") return soup.get_text(strip=True) # 2. 古诗专用停用词:除了通用停用词,还要过滤标点与空白 STOPWORDS = set(["的", "了", "在", "是", "我", "有", "和", "就"]) PUNCT = re.compile(r"[,。!?、;:\s]+") def preprocess(poem_text): text = PUNCT.sub("", poem_text) # 去标点,古诗标点对生成无意义 tokens = jieba.lcut(text) # 分词,古诗建议用 jieba 的精确模式 tokens = [t for t in tokens if t not in STOPWORDS and len(t) > 0] return tokens # 3. 去重:按「标题 + 首句」做唯一键,避免同一首诗不同来源重复入库 seen = set() def dedup(poem): key = poem["title"] + poem["content"][:10] if key in seen: return False seen.add(key) return True逻辑说明:clean_html负责剥离标签,preprocess做标点过滤和分词,dedup用标题加首句做去重键。参数上,jieba.lcut默认精确模式,如果你发现生僻字被切碎,可以加载自定义词典把常见古诗词汇加进去。停用词表要按古诗场景裁剪,通用停用词表里很多词在古诗里是有实义的,直接套用会丢信息。
2.3 vectors_poem.bin 的加载与校验
vectors_poem.bin是二进制词向量文件,加载时要注意编码和维度对齐。常见做法是用 gensim 或直接 numpy 读取,加载后先校验词表大小和向量维度是否与模型 embedding 层匹配:
import numpy as np def load_vectors(path): with open(path, "rb") as f: # 假设格式为:词表大小(int) + 维度(int) + 浮点矩阵 vocab_size = int(np.frombuffer(f.read(4), dtype=np.int32)[0]) dim = int(np.frombuffer(f.read(4), dtype=np.int32)[0]) matrix = np.frombuffer(f.read(), dtype=np.float32).reshape(vocab_size, dim) return vocab_size, dim, matrix vocab_size, dim, vecs = load_vectors("vectors_poem.bin") print(f"词表 {vocab_size},维度 {dim}")参数说明:vocab_size和dim必须和模型配置文件里的 embedding 维度一致,不一致会在加载 checkpoint 时报 shape mismatch。如果你拿到的 bin 文件头部没有这两个 int,说明格式不同,需要按实际二进制布局调整读取偏移。这一步是后面所有训练和推理的前提,校验不过就别往下走。
3. 规则作诗与机器学习写诗:两条生成路线的分工与实现
3.1 规则引擎为什么值得先做
很多人一上来就想训模型,结果几千步下来生成的句子平仄全乱。规则作诗不是退而求其次,它是你的基准模型和兜底方案。基于格律和韵脚写一套规则引擎,从已有古诗里抽取常见词语搭配和句式结构作为规则依据,能在模型还没收敛时先产出可读的句子,也能在模型输出跑偏时做后处理校正。
规则引擎的核心是三张表:平仄表、韵脚表、句式模板表。平仄表按普通话声调映射(一声二声为平,三声四声为仄,入声字需要单独维护),韵脚表按《平水韵》或现代韵部分组,句式模板表则是从语料里统计出的高频五言、七言结构。这三张表建好,规则作诗就能跑起来,而且完全可解释。
3.2 规则生成的最小实现
# 简化版五言规则生成:从模板表里选句式,按韵脚表填词 PING_ZE = {"平": ["春", "风", "花", "山"], "仄": ["月", "雪", "夜", "古"]} RHYME_GROUPS = {"a": ["花", "家", "霞"], "ong": ["风", "空", "中"]} def rule_compose(template, rhyme_group): # template 形如 ["平","仄","平","仄","平"] line = [] for tone in template: candidates = PING_ZE[tone] line.append(candidates[0]) # 实际项目里应随机或按搭配概率选 # 末字强制押韵 line[-1] = RHYME_GROUPS[rhyme_group][0] return "".join(line) print(rule_compose(["平","仄","平","仄","平"], "a"))逻辑说明:rule_compose按平仄模板逐位填字,末字从韵脚组里取。参数上,template的长度决定五言还是七言,rhyme_group决定押哪个韵。这套逻辑简单,但它是验证韵脚表和平仄表是否正确的快速手段——如果生成结果读起来别扭,先查表再查模型。
3.3 checkpoint 的加载与推理
资源里的model.ckpt-4000、model.ckpt-52000、model.ckpt-53493是不同训练步数的权重。步数差异直接反映在生成质量上:4000 步通常还在学字词分布,输出可能重复;52000 步和 53493 步接近收敛,句子更通顺但可能过拟合语料。加载时用 TensorFlow 的 checkpoint 机制:
import tensorflow as tf # 加载指定步数的 checkpoint ckpt_path = "model.ckpt-53493" saver = tf.train.import_meta_graph(ckpt_path + ".meta") with tf.Session() as sess: saver.restore(sess, ckpt_path) # 拿到输入输出张量,具体名称取决于模型定义 input_tensor = sess.graph.get_tensor_by_name("input:0") output_tensor = sess.graph.get_tensor_by_name("output:0") # 推理时按模型要求喂入起始词和长度 result = sess.run(output_tensor, feed_dict={input_tensor: [[1, 2, 3]]}) print(result)参数说明:ckpt_path不带后缀,TensorFlow 会自动找.data-00000-of-00001和.index文件。input:0和output:0是占位符名称,实际名称要看模型定义,加载前先用tf.train.list_variables列出所有变量确认。如果报 NotFoundError,多半是 meta graph 和权重步数不匹配,换对应的.meta文件即可。
3.4 情感分析模块的接入方式
情感分析这条线可以独立于生成模块运行。如果语料带情感标签,直接训练一个分类头;如果没有,就用词频统计和关键词提取做无监督分析,探索不同情感下古诗的语言风格。常见做法是把情感分析结果作为生成时的条件输入——比如指定「豪放」风格,模型在解码时偏向高概率的豪放词汇。这一步需要模型本身支持条件输入,如果 checkpoint 是纯语言模型,就只能靠后处理过滤。
4. 避坑与排查:checkpoint 加载、词向量对齐、生成质量三类高频问题
4.1 现象:加载 checkpoint 报 shape mismatch
原因:vectors_poem.bin的词表大小或维度与模型 embedding 层不一致,或者 checkpoint 步数和 meta graph 不匹配。解决:先打印词向量维度,再列出 checkpoint 里的变量形状,逐一对齐。如果词表对不上,要么重新训练 embedding,要么在加载时做映射裁剪。
4.2 现象:生成的诗句全是重复字
原因:模型训练步数太少(比如直接用 4000 步的 checkpoint),解码时陷入重复循环。解决:换用 52000 或 53493 步的权重;如果仍重复,在解码阶段加 repetition penalty,对已生成的 token 降低概率。
4.3 现象:分词后语料里全是单字,模型学不到词搭配
原因:jieba 默认词典对古诗词汇覆盖不足,生僻词被切碎。解决:加载自定义词典,把高频古诗词汇(如「萧萧」「班马」)加进去,重新跑一遍分词和词向量训练。
4.4 现象:规则作诗生成的句子平仄正确但读不通
原因:平仄表和韵脚表只约束了声调和韵脚,没有约束语义搭配。解决:在规则引擎里加入搭配概率表,从语料统计高频二字、三字组合,填词时按概率选,而不是按固定顺序取第一个候选。
4.5 现象:情感分析结果和人工判断偏差大
原因:情感标签缺失或标注质量差,无监督词频统计无法捕捉反讽、借景抒情等复杂表达。解决:人工标注一批种子数据做半监督训练,或者引入预训练情感模型做蒸馏,别指望纯词频能搞定古诗情感。
5. 进阶技巧:用步数插值和条件解码把生成质量再提一档
拆完这套资源后我最大的体会是:checkpoint 不是拿来就用,步数之间可以做文章。model.ckpt-4000、model.ckpt-52000、model.ckpt-53493这三个权重,除了单独加载,还可以做参数插值——把 52000 步和 53493 步的权重按比例融合,往往能得到比单一步数更稳的生成效果。具体做法是读取两组变量的值,按w = alpha * w1 + (1 - alpha) * w2融合后重新保存,alpha 从 0.3 到 0.7 之间调,我一般先用 0.5 试。
条件解码是另一个提质点。如果你想让模型按指定韵脚或情感生成,可以在解码时对 logits 做掩码:把不符合韵脚的字概率压到极低,把符合目标情感的词汇概率抬高。这比重新训练一个条件模型成本低得多,适合快速验证想法。
| 技巧 | 操作对象 | 关键参数 | 适用场景 |
|---|---|---|---|
| 权重插值 | 两个 checkpoint | alpha 0.3~0.7 | 单步数生成不稳定 |
| 韵脚掩码 | 解码 logits | 掩码强度 | 需要强制押韵 |
| 情感偏置 | 解码 logits | 偏置系数 | 指定风格生成 |
| 规则后处理 | 生成结果 | 平仄表 | 校正格律 |
验证方法很简单:固定一组起始词,分别用原始权重和插值权重各生成 20 首,人工打分对比通顺度和格律合规率。别只看 loss,生成任务最终看的是人读起来像不像诗。
从那以后我每次拿到这种「模型比代码先到」的资源包,都强制先跑一遍词向量校验和 checkpoint 变量列表,确认对齐了再动训练脚本。希望帮到你。
本文还有配套的精品资源,点击获取