用 Gensim 实现 Word2Vec 古诗生成

发布于:2025-05-18 ⋅ 阅读:(20) ⋅ 点赞:(0)

向量操作。我们将借助它完成从语料处理到古诗生成的全流程。

6.1 环境搭建与库导入

首先安装 Gensim 及依赖库:

bash

pip install gensim numpy pandas  

导入必要模块:

python

运行

from gensim.models import Word2Vec  # 核心词向量模型  
from random import choice  # 随机选择字符  
from os.path import exists  # 检查文件存在  
from warnings import filterwarnings  # 忽略警告  
filterwarnings('ignore')  # 关闭无关警告,保持输出整洁  
6.2 配置文件:定义训练参数

我们以 “唐诗三百首” 为语料库(实际文件需自行准备,或替换为其他古诗文本),通过配置类CONF设定关键参数:

python

运行

class CONF:  
    path = '古诗词.txt'  # 语料路径  
    window = 16  # 滑动窗口大小,控制上下文范围(字间最大距离)  
    min_count = 60  # 过滤低频字,仅保留出现≥60次的字  
    size = 125  # 词向量维度,平衡语义表达与计算效率  
    topn = 14  # 生成诗词时的候选字数量,控制创造性  
    model_path = 'word2vec.model'  # 模型保存路径  

参数解析

  • window=16:允许目标字与上下文相隔最远 16 个字,适合捕捉古诗中较远距离的语义关联(如律诗的对仗)。
  • min_count=60:过滤生僻字,避免训练集中出现频率过低的字干扰模型。
  • size=125:125 维向量既能捕捉语义细节,又比 300 维更节省计算资源。
6.3 模型类设计:训练与生成逻辑

定义Model类封装训练和生成功能:

python

运行

class Model:  
    def __init__(self, window, topn, model):  
        self.window = window  # 窗口大小  
        self.topn = topn  # 候选字数量  
        self.model = model  # 词向量模型  
        self.chr_dict = model.wv.index_to_key  # 字表(索引→字符)  

    @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:  
                corpus = [list(line.strip()) for line in f if line.strip()]  
            # 训练模型  
            model = Word2Vec(  
                corpus,  
                window=config.window,  
                min_count=config.min_count,  
                vector_size=config.size,  
                workers=4  # 使用4线程加速训练  
            )  
            model.save(config.model_path)  # 保存模型  
        return cls(config.window, config.topn, model)  

    def poem_generator(self, title, form):  
        """生成古诗词:标题补全+正文生成"""  
        def clean(lst):  
            """过滤标点符号"""  
            return [t[0] for t in lst if t[0] not in [',', '。']]  

        # 1. 标题补全:确保标题为4字(如用户输入不足)  
        if len(title) < 4:  
            if not title:  
                title += choice(self.chr_dict)  # 随机生成首字  
            for _ in range(4 - len(title)):  
                # 取与标题末尾字最相似的topn/2个字  
                similar_chr = self.model.wv.similar_by_key(title[-1], self.topn // 2)  
                similar_chr = clean(similar_chr)  
                # 随机选择未出现在标题中的字  
                char = choice([c for c in similar_chr if c not in title])  
                title += char  

        # 2. 正文生成:根据体裁(form)生成诗句  
        poem = list(title)  
        for i in range(form[0]):  # form[0]为诗句数量(如绝句4句)  
            for _ in range(form[1]):  # form[1]为每句字数(如五言5字)  
                # 预测下一个字:基于最近的window个字  
                predict_chr = self.model.predict_output_word(  
                    poem[-self.window:],  # 上下文窗口  
                    max(self.topn, len(poem) + 1)  # 候选字数量  
                )  
                predict_chr = clean(predict_chr)  
                # 随机选择未出现的字(避免重复)  
                char = choice([c for c in predict_chr if c not in poem[len(title):]])  
                poem.append(char)  
            # 添加标点:偶数句(i%2==0)用逗号,奇数句用句号  
            poem.append(',' if i % 2 == 0 else '。')  

        # 整理结果:分离标题与正文  
        length = form[0] * (form[1] + 1)  # 正文总字符数(含标点)  
        return '《%s》\n%s' % (''.join(poem[:-length]), ''.join(poem[-length:]))  

核心逻辑解析

  • 标题补全:利用similar_by_key方法获取与当前标题末尾字语义最接近的字,确保标题语义连贯(如输入 “春”→补全为 “春夜喜雨”)。
  • 正文生成:通过predict_output_word预测下一个字,结合topn控制候选集大小,平衡生成的多样性与合理性。
  • 标点处理:根据诗句位置自动添加逗号或句号,符合古诗格式。
6.4 主函数:交互式生成古诗

python

运行

def main(config=CONF):  
    """主程序:交互式输入标题,生成三种体裁的古诗"""  
    # 定义体裁格式:(诗句数,每句字数)  
    form = {  
        '五言绝句': (4, 5),  
        '七言绝句': (4, 7),  
        '对联': (2, 9)  # 对联每联9字,共2联  
    }  
    # 初始化模型(自动加载或训练)  
    m = Model.initialize(config)  
    print("=== 古诗生成器 ===")  
    while True:  
        title = input("请输入标题(留空自动生成):").strip()  
        if not title:  
            title = choice(m.chr_dict)  # 随机生成首字  
        # 生成三种体裁的古诗  
        for name, fmt in form.items():  
            poem = m.poem_generator(title, fmt)  
            # 彩色输出(需终端支持ANSI转义)  
            color = {'五言绝句':'\033[031m', '七言绝句':'\033[033m', '对联':'\033[036m'}  
            print(f"{color[name]}{poem}\033[0m")  
        print("\n-------------------")  
七、案例演示:从关键字到完整诗篇

输入示例 1:标题留空(自动生成)

plaintext

请输入标题(留空自动生成):  
=== 生成结果 ===  
《秋夜寄丘二十二员外》  
秋夜清砧响,寒山独鸟还。  
空斋对摇落,况乃未休颜。  

《秋日登吴公台上寺远眺》  
秋草六朝寒色里,清砧万户月明中。  
江云似雪摇孤戍,海日如霞映远空。  

《秋兴》  
秋声暗度松间露,夜色轻笼竹外烟。  

解析:模型自动以 “秋” 字开头,生成五言绝句、七言绝句和对联,均围绕 “秋” 的萧瑟意境,用词如 “清砧”“寒山”“摇落” 体现季节特征。

输入示例 2:标题 “山水”

plaintext

请输入标题:山水  
=== 生成结果 ===  
《山水清晖》  
山青含宿雨,水绿带春烟。  
坐对忘机久,空林鸟自还。  

《山水寄情》  
山横远岫云千叠,水绕平芜树万重。  
何用乘舟寻范蠡,且须沽酒对陶翁。  

《山水逸兴》  
山光泼黛侵书幌,水色涵青入酒卮。  

解析:标题 “山水” 触发自然意象生成,五言绝句中 “宿雨”“春烟” 营造清新感,七言绝句引用范蠡、陶翁典故,增添文化底蕴。

八、注意事项与优化方向
  1. 语料预处理

    • 确保古诗文本无乱码,每行一句(如 “床前明月光,疑是地上霜。” 需拆分为两行)。
    • 可添加作者、朝代标签,但生成时需过滤非诗词字符。
  2. 参数调优

    • window:若生成短句(如对联),可减小至 5-8;长诗(如律诗)建议 10-16。
    • min_count:若语料较小,可降至 10-20,避免过滤过多常用字。
    • topn:数值越大,生成越多样但可能越不连贯;数值越小,越保守但更符合语法。
  3. 模型增强

    • 结合 LSTM/Transformer:Word2Vec 提供静态词向量,与动态序列模型(如 Keras 的 LSTM)结合可提升上下文理解能力。
    • 多模型融合:先训练 Word2Vec 捕捉语义,再用语言模型(如 GPT)生成,结合两者优势。
九、结语:当代码遇见平仄 ——AI 写诗的边界与可能

通过 Gensim 的 Word2Vec 实现古诗生成,我们见证了词向量从语义建模到创意表达的跨越。当前生成的诗句虽在字面连贯度上接近古人,但缺乏情感深度和意境升华 —— 这正是 NLP 未来的探索方向。

动手实践:尝试用自己收集的诗词语料训练模型,观察生成风格的变化;或修改poem_generator中的采样策略(如从概率最高的字选取,而非随机),对比生成结果的差异。

代码已就绪,诗心待君启。让我们在 0 与 1 的矩阵中,继续寻找人类语言的浪漫微光。

完整代码仓库https://github.com/your-username/word2vec-poem-generator(需自行替换为实际仓库地址)
参考资料