多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

自动写诗.rar从解压到调参:马尔可夫链与温度采样实战

自动写诗.rar从解压到调参:马尔可夫链与温度采样实战 简介面向人工智能与自然语言处理学习者的自动写诗实验资源包涵盖从古诗数据集构建、数据预处理、深度学习模型训练到生成效果评估的完整闭环。资源共18个文件以Python源码与编译缓存文件为主辅以实验指导书、实验报告、PPT演示文稿、文本数据及numpy数据文件等压缩包约23.83MB。已有169人学习下载。包内核心Python脚本分别承担模型定义、训练流程与工具函数可直接运行复现自动写诗实验numpy数据文件提供了预处理后的诗歌张量数据降低自行准备数据集的成本。两份Word文档分别讲解实验步骤与结果分析PPT则以可视化方式展示模型架构与实验流程可参考BLEU、ROUGE等指标评估生成质量并能对比RNN、LSTM与Transformer在诗歌风格与韵律模仿上的差异。适合具备一定Python和深度学习基础、希望结合实践理解文本生成技术的读者。1. “自动写诗.rar”不只是压缩包先想清楚你要 demo 还是产品“自动写诗.rar”这个名字乍看像压缩包合集实际上是你在某个技术论坛或网盘里见到的自动写诗项目包。里面可能是训练好的模型权重、生成脚本、古诗语料也可能只是几个没有注释的 Python 文件。我接过不少这类包第一个建议是别急着双击解压先问自己拿到它要干嘛。如果想半天内跑通、给朋友演示“AI 写的诗”那路线是解压、装环境、生成如果想把它沉淀成一个能自动写出工整七律的工具那路线完全不同你得从数据清洗、模型选型和调参开始重做。这篇文章按第一条路给你一个最小闭环再带你把第二条路上的坑标出来适合想动手又不想被黑匣子挡在门外的人。2. 用 7-Zip 解开 .rar文件结构、密码恢复与最小环境搭建2.1 解压前先看清单.rar 包里一般是这几样东西拿到任何 .rar 包我一般不会直接右键解压而是先列出压缩包内容确认里面到底是什么形态的项目。很多自动写诗包并没有统一的目录规范但反复出现的基本就这几类家当文件/目录常见内容在管线里的作用model.bin / weights.pt训练好的网络权重生成的核心没有它只能跑模板vocab.json / char2id.json字符表与索引映射把汉字编码成模型能读的数字generate.py / poem.py生成入口脚本调用模型或统计方法输出诗句corpus/ 或 data/古诗语料重新训练或微调时用requirements.txt依赖列表还原作者当时的运行环境README.md / 说明.txt使用方式与参数含义优先级最高先读它先读说明文件这个动作看似多余其实能省下大量试错时间。有的脚本要求 Python 3.7有的要求在 Windows 下运行且用了 Windows 专有路径这些信息往往只在说明里写了一句。如果解压后连说明文件都没有那就要做好自己当作者的心理准备从一堆命名随意的脚本里推断调用关系。2.2 解压命令与密码恢复7-Zip 的三种打开姿势很多人问 7-Zip 能不能解 .rar答案是可以。7-Zip 默认支持解开 RAR 格式不需要安装 WinRAR但要注意它只负责解压不负责创建 RAR所以别指望用 7-Zip 直接压出 .rar。我常用的命令是这三条# 安装 7-ZipDebian/Ubuntu 系列 sudo apt install p7zip-full # 列出压缩包内容不急着解压 7z l 自动写诗.rar # 解压到指定目录避免在当前目录散落一堆文件 7z x 自动写诗.rar -o./autopoet -y参数说明l是 list先看包内文件数量和路径结构x是解压并保留目录结构-o指定输出目录注意-o后面没有空格-y表示覆盖已存在文件时不再逐个询问。如果包里文件很多且路径很深建议先7z l看一眼确认没有藏着绝对路径或可疑脚本再动手。遇到带密码的压缩包时7-Zip 会直接提示密码错误。网上那些“强制解压”的说法大多数不可靠更加靠谱的做法是先回下载页找密码没找到就按常见密码列表逐个试再不行才考虑用字典工具跑一轮弱密码。如果包是用 WinRAR 较新版本默认的 AES-256 加密字典跑不出来基本就只能放弃把时间花在重新找一个没加密的版本上更划算。与其事后后悔不如下载前先确认发布页有没有标注密码。2.3 环境依赖检查让一段诗先跑起来解压完成后的第一件事不是读代码而是复现运行环境。我会新建一个虚拟环境把依赖全部装进去避免解出来的第三方库污染系统 Python。下面是一套很通用的初始化流程# 1) 创建并激活虚拟环境 python -m venv .venv source .venv/bin/activate # Windows PowerShell 用 .venv\Scripts\Activate.ps1 # 2) 安装依赖 pip install -r requirements.txt # 3) 查看生成入口脚本的帮助信息 python generate.py --help逻辑说明venv把项目的 numpy、torch 等依赖与系统环境隔离不同项目之间不打架。requirements.txt如果缺失或装不上先看报错发生在哪个包PyTorch 系经常遇到版本与 Python 版本不匹配常见做法是按报错信息安装对应的 CPU 版。--help是判断脚本是否支持命令行参数最快的办法不支持的话就直接打开源码看if __name__ __main__部分。跑通一遍最重要。哪怕生成结果很烂只要没有报错就说明模型文件、字符表和脚本三者对得上。很多 .rar 包本身没问题问题出在解压后手动移动了模型文件或改了目录名导致脚本找不到相对路径。保持解压后的目录结构原样不变能少踩一堆坑。3. 自动写诗的最小可运行管线从马尔可夫链到温度采样的生成逻辑3.1 先分清三类做法规则、统计与神经网络自动写诗的项目包拆开来看实现思路大致分三类。第一类是模板填充预置一些句式结构再往空位里填意象词比如“春风又绿江南岸”这类模板简单但几分钟就能被看穿第二类是统计语言模型最常见的就是马尔可夫链通过统计语料里字与字的接续关系来生成新句子第三类是神经网络小到单层 LSTM大到基于 Transformer 的预训练语言模型生成质量上限最高但对数据量和训练资源的要求也最高。如果 .rar 包里只有一个几 KB 的脚本那基本是模板或马尔可夫如果带着几十 MB 到几百 MB 的权重文件那才是真正的神经网络。我建议不管包里是哪一类都先用马尔可夫链跑通一个最小数据流。原因很实际它不需要 GPU不需要装深度学习框架几十行代码就能把“语料进、诗句出”的完整链路打通也能帮你理解后续调参时遇到的所有基本概念。3.2 马尔可夫链生成五言诗一个能跑的数据流马尔可夫链的思路是把一首诗看成字与字的接龙。训练阶段统计“春”后面经常跟哪些字“春风”后面又经常跟哪些字生成阶段从任意起点开始按统计概率挑下一个字。下面这个实现可以直接复制运行import random from collections import defaultdict def build_chain(corpus, order2): 构建字符级 n-gram 转移表。 order2 表示用前 2 个字预测下一个字。 chain defaultdict(list) for line in corpus: chars list(line.replace( , )) for i in range(len(chars) - order): prefix tuple(chars[i:i order]) next_char chars[i order] chain[prefix].append(next_char) return chain def sample_poem(chain, verse_len5, num_lines4, order2, seedNone): 生成一首五言绝句每句单独起头。 if seed is not None: random.seed(seed) lines [] for _ in range(num_lines): line [] start random.choice(list(chain.keys())) line.extend(start) while len(line) verse_len: prefix tuple(line[-order:]) if prefix not in chain: break line.append(random.choice(chain[prefix])) lines.append(.join(line)) return lines逻辑说明build_chain把语料里每行诗拆成字符流用长度为order的前缀做键、下一个字符做值得到一张“接龙表”。sample_poem生成每一行时随机取一个出现在语料里的前缀作为起点这样诗句的开头至少是“合法”的随后不断用当前行末尾order个字查表随机选后继字符。每句独立起头能避免四句共用一条概率链导致的内容趋同。参数上order2是最常用的折中order1生成结果乱飘几乎不成词order3以上句子会越来越像语料里的原句重复率也明显升高。seed固定住随机种子后同一份语料和参数能复现同一首诗这对调试很重要。3.3 关键参数n-gram 阶数、温度与采样策略马尔可夫链生成最大的问题是死板和重复。要缓解它得引入两个采样层面的概念温度和 top-k。温度采样的代码很直观本质是把候选字的概率分布做一次“软化”import math def temperature_sample(candidates, temperature0.8): 从候选字列表里按温度缩放后的概率抽一个。 counts {} for c in candidates: counts[c] counts.get(c, 0) 1 exp_scores {c: math.exp(count / temperature) for c, count in counts.items()} total sum(exp_scores.values()) r random.random() * total cumulative 0 for c, score in exp_scores.items(): cumulative score if r cumulative: return c参数说明temperature越小概率分布越尖锐输出越保守越大分布越平坦越容易跳出高频字的循环。在字符级古诗生成里0.8起步比较稳效果太平淡就往上调重复太严重就往下调。top-k 的常做做法是从概率最高的 k 个字里再采样一般 k 取 8 到 20这样能挡住“之、乎、也、者”这类耐造但没诗意的虚词刷屏。我见过不少人在这步直接把random.choice换成argmax结果生成的诗每句都差不太多还以为是模型训练出了问题。其实问题在于确定性解码天然适合机器翻译却不适合创作类任务。创作类生成要的是每次跑都略有不同采样策略和模型本身同等重要。4. 训练数据与超参调整让输出从押韵到像诗的三个必调参数4.1 语料准备清洗古诗文本的四个细节语料质量直接决定生成结果下限这个环节偷懒后面所有调参都是白费。常见做法是拿公开的古诗数据集但网上流传的版本里往往混着作者名、朝代、注释和现代标点这些东西进语料后模型会把“唐”和“白居易”当作诗句的一部分学进去。我一般先做一轮清洗import re def clean_corpus(raw_text): # 只保留汉字与全角标点 text re.sub(r[^\u4e00-\u9fff。], , raw_text) # 去掉句读转成不换行的字符流适合字符级训练 text re.sub(r[。], , text) return text逻辑说明第一行正则把字母、数字、空格、半角符号全部过滤掉第二行再把句读也去掉。对字符级语言模型来说标点符号是多余的模型只需要学“字接字”的规律。注意两个细节繁体字要不要转简体取决于你希望生成古风还是现代风文本编码必须统一成 UTF-8否则读进来全是乱码这一步出错最隐蔽因为程序不报错只是生成结果莫名其妙。清洗后的语料如果只有几千首生成的诗歌会很窄翻来覆去就是那几千句的影子理想情况是几万首以上的唐诗规模。不需要全部喂给神经网络马尔可夫链模型在几万首语料上就能跑出不错的效果。4.2 五言、七言与绝句约束用格式后处理兜底生成模型天然不保证长度和结构哪怕训练语料都是五言模型输出的句子也可能七零八落。解决这个问题的不是改模型而是在解码后加一层格式约束。我常用的后处理函数如下def to_verse(text, verse_len5, num_lines4): 把任意字符串强制切分成五言或七言绝句。 text clean_corpus(text) lines [] for i in range(0, min(len(text), verse_len * num_lines), verse_len): lines.append(text[i:i verse_len]) while len(lines) num_lines: lines.append(春 * verse_len) # 不足时补位宁可露怯也不报错 return lines[:num_lines]参数说明verse_len5是五言换成 7 就是七言num_lines默认 4 对应绝句。这个函数的思路是从模型输出的字符流里按固定步长切块多余的字符直接丢掉不足的地方用“春”字补位。你要是觉得补位太难看也可以用“花”或“山”替代或者干脆截断整个流重新生成一次。很多项目包会在生成脚本里内置类似的强制切分逻辑但做得不够干净有的忘了去掉标点导致五言句子里混着句号有的没有处理生成流过短的情况直接越界报错。自己写一遍这个后处理能帮你理解那些脚本为什么在个别例子上会翻车。4.3 三个必调参数学习率、批次大小与序列长度如果你拿到的是带训练代码的自动写诗包最终还是要面对训练参数这三件套。我整理过一份自己常用的参考区间参数常用范围调整方向失败迹象学习率1e-3 ~ 1e-4loss 震荡就调小一个量级loss 不降、NaN批次大小32 ~ 128显存不够就减半OOM、训练极慢序列长度64 ~ 128 字符古诗短句可降到 64整句割裂、不连贯学习率是这里最带玄学色彩的一个。同样一份唐诗语料1e-3 能跑但 loss 上下乱跳降到 5e-4 反而平稳再往下到 1e-4训练速度又慢得让人失去耐心。我的经验是先按 1e-3 跑 10 个 epoch 看 loss 曲线如果持续不降直接砍到 1e-4不要浪费时间找其他原因。批次大小的影响相对弱但对于字符级模型过小的批次会让梯度估计充满噪音大批次则要求更多内存。序列长度方面古诗不像长文档那样需要很长的上下文依赖64 个字符足够让模型看到大半个句子。训练过程中最值得盯的指标不是 loss 本身而是“生成的样例诗”。每隔固定轮次抽几首出来看如果连续押韵、句子通顺但意思飘忽那是正常的创作状态如果句子重复、韵脚混乱才需要回头调参。死磕 loss 数值容易误导生成结果才是唯一的判断标准。5. 自动写诗常见翻车点排查五个必踩的坑与恢复手段5.1 现象解压后跑起来就报 ModuleNotFoundError原因requirements.txt 缺失或版本没锁住最常见的是 Python 3.11 以上环境里装不上某些旧版依赖也可能是脚本用了某一台机器上的全局包换个环境就露馅。解决先看报错里缺的是哪个模块。如果是 torch 或 tensorflow直接按官方指引安装当前 Python 版本对应的版本如果缺的是小众工具库先查它是否被维护维护停滞的就改脚本绕过去。建议在虚拟环境里操作不要pip install到系统环境否则下个项目又会踩同一颗雷。5.2 现象生成的每一句都重复同一个字原因马尔可夫链的 order 设得太大前缀一旦进入某个高频路径就出不来了神经网络这边则大概率是解码时用了argmax或者温度设得太低模型陷入自我重复的循环。解决先把 order 降到 2再加温度采样temperature 提到 0.9 以上试一轮如果还重复给生成加重复惩罚常见做法是当某字已经在前一句出现过时降低它的采样权重。你可以先跑 short 的语料测试比如拿 1000 首绝句重复生成 20 次统计重复率比自己肉眼看好使。5.3 现象诗太平淡像在念说明书原因温度太低、语料里混了太多白话文或者语料规模太小。有些公开“古诗数据集”其实包含现代白话翻译清洗那一步没做干净模型学到的就是“这是一首什么样的诗”之类的现代句子结构。解决把 temperature 调到 1.2 左右配合 top-p0.92 试试同时回头统计语料里频率最高的 50 个字如果出现“我、你、这、那、是”这类词说明清洗不到位需要重新过一遍正则。真正干净的古诗语料高频字应该是“风、花、雪、月、人、山、水、春、秋”。5.4 现象输出长度对不上五言/七言原因后处理切分逻辑不对或者生成流里有标点。最常见的是把句读 保留在字符流里就按 5 字符切块结果一句里混进“。”视觉上长短不齐。解决先统一过一遍clean_corpus把所有标点去掉再用定长切块。从那些老牌项目包移植代码时尤其注意它们是否对全角逗号做了处理。有的包写的是text[::6]这种按索引步长切遇到标点也一样翻车。这个坑我自己也踩过代码逻辑看半天没毛病最后发现是语料里混进了换行符。5.5 现象CPU 推理慢到怀疑人生原因如果是神经网络方案CPU 上跑大模型本来就慢加上脚本没有做任何加速处理每生成一句要推理一次四句下来要等几十秒。解决先确认脚本是不是每次生成都重新加载了模型这是最常见的性能 bug。模型加载一次后放内存里复用速度能快一个量级。进一步的做法是把模型转成 ONNX用推理引擎跑PyTorch 环境下一行代码就能导出import torch model.eval() dummy_input torch.randint(0, 1000, (1, 64)) torch.onnx.export(model, dummy_input, poem.onnx, opset_version12)参数说明dummy_input的维度要匹配模型输入形状opset_version是 ONNX 算子版本太旧可能不支持新算子。转完之后用 onnxruntime 加载在 CPU 上的推理速度通常能提升 2 到 5 倍。不过这一步属于优化先把前面几项坑排查完再动手否则可能在错误的方向上加速。6. 进阶用押韵校验与困惑度给生成诗做体检生成结果好不好光靠肉眼判断不够。我常用的两个客观指标是韵脚一致性和困惑度前者检查是否押韵后者评估句子通顺程度。韵脚的检查依赖一份韵部表。中华新韵把汉字分成十八个韵部同一个韵部的字可以互相押韵。先把韵部表整理成集合然后校验每句尾字是否落在目标韵部里def check_rhyme(lines, rhyme_set): 检查绝句偶数句或全诗尾字是否同一个韵部。 tails [line[-1] for line in lines if len(line) 0] if len(tails) 2: return False return all(t in rhyme_set for t in tails[1::2])参数说明rhyme_set是你选定的韵部汉字集合tails[1::2]取出第 2、4 句的尾字。绝句一般要求第 2、4 句押韵第 1 句可押可不押。跑一遍这个函数就能量化“看起来押韵”这个主观判断。困惑度适合用来对比两个模型的生成质量。具体做法是拿一个现成的语言模型对生成的诗句打分困惑度越低说明这句诗在统计意义上是越自然的表达。没有现成模型时可以拿你自己训练的马尔可夫链当打分器计算每个字在给定前缀下的条件概率把整句概率连乘再取负对数得到一个简化版困惑度用于横向对比不同参数下的生成结果。我自己的习惯是每调一轮参数就跑押韵校验和简化困惑度两个分数都变好才进入下一轮。最后悔的经历是早期只顾着让生成结果“看起来像诗”没留任何客观指标后来换语料和调参时根本说不清哪个改动起了作用一切回到了原点。现在每次拿到这类压缩包我都会先建虚拟环境、保留原始 rar 备份、跑通最小生成再开始谈调优。这个顺序能替你省下大量不该踩的坑希望帮到你。本文还有配套的精品资源点击获取
返回列表