基于Python从零实现N-gram文本生成教程

何川
何川
发布时间:2026-10-11| 2人浏览过
原创

本文详细演示如何使用纯Python从零构建N-gram文本生成管线。内容涵盖原始语料的标准化预处理、滑动窗口序列建模、基于上下文的随机拼接算法,以及引入Temperature参数优化输出多样性的完整代码。同时对比了传统N-gram模型的局限性,并给出向深度神经网络迁移的明确路径,适合自然语言处理初学者快速建立概率语言模型认知。

N-gram文本建模原理

N-gram是自然语言处理中用于分析文本概率分布的核心技术。它通过将文本切分为连续的n个词(或字符)单元来建模上下文依赖关系,常用于语言模型训练、文本分类与生成任务。常见的划分方式包括:

  • Unigram(1-gram):以单个词为单位,如 "I", "love", "Python"。
  • Bigram(2-gram):以相邻两个词为单位,如 "I love", "love Python"。
  • Trigram(3-gram):以相邻三个词为单位,如 "I love Python"。

模型通过统计训练语料中各N-gram的出现频次,计算给定前缀条件下下一个词出现的概率。虽然算法直观高效,但仅依赖局部上下文,在处理长距离依赖与复杂语义时存在天然局限。

Python实现N-gram文本生成

第1步:准备并预处理原始文本

加载训练数据后,需统一格式以消除换行符干扰,并将文本转为小写以保证后续匹配的一致性。目的是建立标准输入基准;操作入口为直接修改原始字符串变量;核心参数包括换行符替换规则与大小写转换函数;完成状态为获得连续、无断行且全小写的纯净字符串,可直接喂入分割器。示例代码如下:

text = """
To be or not to be, that is the question;
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles
And by opposing end them. To die—to sleep,
No more; and by a sleep to say we end
The heart-ache and the thousand natural shocks
That flesh is heir to, 'tis a consummation
Devoutly to be wish'd. To die, to sleep;
To sleep, perchance to dream—ay, there's the rub,
For in that sleep of death what dreams may come,
When we have shuffled off this mortal coil,
Must give us pause—there's the respect
That makes calamity of so long life;
The oppressor's wrong, the proud man's contumely,
The pangs of despis'd love, the law's delay,
The insolence of office, and the spurns
That patient merit of the unworthy takes,
When he himself might his quietus make
With a bare bodkin? Who would these fardels bear,
To grunt and sweat under a weary life,
But that the dread of something after death—
The undiscover'd country, from whose bourn
No traveller returns—puzzles the will,
And makes us rather bear those ills we have
Than fly to others that we know not of?
Thus conscience does make cowards of us all;
And thus the native hue of resolution
Is sicklied o'er with the pale cast of thought,
And enterprises of great pith and moment
With this regard their currents turn awry,
And lose the name of action.
"""

# 去掉换行符,并将文本转换为小写
text = text.replace('\n', ' ').lower()

第2步:构建N-gram序列字典

将预处理后的文本按空格拆分为单词列表,随后滑动窗口截取长度为n的子串,收集所有出现的N-gram序列。目的是建立词频映射基础;操作入口为调用自定义建模函数;核心参数为原始文本对象与序列长度n;完成状态为返回包含所有有效N-gram组合的列表,索引即代表其在语料中的出现位置。代码如下:

def create_ngram_model(text, n):
    words = text.split()  # 将文本分割成单词
    ngrams = []  # 用于存储n-grams的列表

    for i in range(len(words) - n + 1):
        ngram = ' '.join(words[i:i + n])  # 创建一个n-gram
        ngrams.append(ngram)

    return ngrams

n = 2  # 选择2-gram模型
ngram_model = create_ngram_model(text, n)

# 打印前10个2-grams
print(ngram_model[:10])

第3步:基于上下文的随机文本生成

生成阶段从模型中随机选取一个初始N-gram作为开头,随后循环查找与该结尾n-1个词匹配的下一组N-gram,直至达到目标长度。目的是还原语言连贯性;操作入口为生成函数迭代循环;核心参数为已建模型、窗口尺寸n与期望总词数length;完成状态为输出一条词数达标且内部接龙符合原始语料分布的新文本。代码如下:

import random

def generate_text(ngram_model, n, length=50):
    generated_text = random.choice(ngram_model)  # 随机选择一个n-gram作为起始点
    words = generated_text.split()

    while len(words) < length:
        possible_next_ngrams = [ngram for ngram in ngram_model if ' '.join(words[-n + 1:]) in ngram]
        if not possible_next_ngrams:
            break
        next_ngram = random.choice(possible_next_ngrams)
        words.extend(next_ngram.split())

    generated_text = ' '.join(words)
    return generated_text

generated_text = generate_text(ngram_model, n, length=100)
print(generated_text)

模型优化与进阶调优

第1步:调整N值与扩展训练集

提升N值(如3或4)可捕捉更长的句式结构,显著增强生成文本的连贯性,但会指数级增加稀疏性问题。解决该瓶颈的有效方式是扩充高质量训练语料,或使用平滑算法(如Kneser-Ney)处理未登录词(OOV),从而在复杂度与覆盖率之间取得平衡。

第2步:引入Temperature参数控制多样性

默认random.choice采用均匀分布,生成的文本风格可能过于固定或跳跃。可通过自定义采样函数引入温度系数,调节候选选项的选择倾向:目的是干预模型确定性;操作入口为加权随机抽样模块;核心参数为temperature数值(较低值强化高频词,较高值鼓励冷门探索);完成状态为对比不同温度下的输出波动,确认是否符合业务对创意或严谨度的要求。代码如下:

def generate_text_with_temperature(ngram_model, n, length=50, temperature=1.0):
    generated_text = random.choice(ngram_model)
    words = generated_text.split()

    while len(words) < length:
        possible_next_ngrams = [ngram for ngram in ngram_model if ' '.join(words[-n + 1:]) in ngram]
        if not possible_next_ngrams:
            break
        # 根据温度参数调整选择下一个n-gram的随机性
        next_ngram = random.choices(possible_next_ngrams, weights=[1.0 / temperature] * len(possible_next_ngrams))[0]
        words.extend(next_ngram.split())

    generated_text = ' '.join(words)
    return generated_text

# 使用温度参数为0.5生成文本
generated_text = generate_text_with_temperature(ngram_model, n, length=100, temperature=0.5)
print(generated_text)

第3步:迁移至神经网络生成架构

当任务涉及长文档创作、逻辑推理或专业领域术语时,传统N-gram难以维持全局语义一致性。建议结合循环神经网络(RNN)、长短期记忆网络(LSTM)或直接采用Transformer架构。这些模型通过注意力机制学习动态词向量,能从根本上突破固定窗口的上下文限制,生成更具语法正确性与语义深度的文本。

总结

基于Python手动实现N-gram文本生成,清晰展示了自然语言处理中概率建模的基本链路。掌握从数据清洗、序列切分到随机采样的完整流程,有助于深入理解现代大语言模型的底层逻辑。在实际工程应用中,建议结合温度参数微调输出风格,并在算力与数据充足时逐步向深度生成模型迁移。以上就是基于Python实现N-gram文本生成的详细内容,更多关于自然语言处理基础算法与模型训练的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。