笔记:自然语言处理

2025-02-24

1. 绪论

自然语言处理

- 能够理解自然语言的意义(NLU)
- 能够生成自然语言(NLG)

符号学派和随机学派

ACL: CCF A

Sequence-to-Sequence 方法

自然语言处理中的S2S(Sequence-to-Sequence)方法是一种用于处理序列数据的深度学习技术,特别适用于自然语言处理任务,如机器翻译、文本摘要和对话生成。

  1. 基本概念
    • S2S方法由两个主要部分组成:编码器(Encoder)和解码器(Decoder)。
    • 编码器将输入序列转换为一个固定长度的上下文向量。
    • 解码器从该上下文向量生成输出序列。
  2. 工作流程
    • 编码阶段:输入序列通过编码器,通常由RNN、LSTM或GRU组成,将信息压缩到上下文向量中。
    • 解码阶段:解码器接收上下文向量,并逐步生成输出序列。
  3. 注意力机制
    • 注意力机制允许解码器在生成每个输出时,动态地关注输入序列的不同部分。
  4. 应用场景
    • 机器翻译文本摘要对话生成等。
  5. 优势与挑战
    • 优势:处理变长输入和输出,适应性强。
    • 挑战:需要大量数据和计算资源,长序列处理具有挑战性。

自然语言处理的主要难点

  • 语音歧义
  • 词语切分歧义
  • 语义歧义
  • 语用歧义
  • 结构歧义
  • 指代歧义
  • 省略歧义

人工反馈式强化学习RLHF

困惑度

困惑度(Perplexity)是衡量语言模型性能的一个重要指标,反映了模型对文本数据的预测能力。困惑度越低,表示模型对数据的预测越准确。

概念

  • 困惑度是语言模型对测试集的平均不确定性的一种度量。
  • 它是测试集上交叉熵的指数形式,表示模型在预测下一个词时的平均选择数。

计算过程

  • 对于一个给定的语言模型,困惑度可以通过计算模型在测试集上的平均对数似然来得到。
  • 公式为: \(\text{Perplexity} = 2^{-\frac{1}{N} \sum_{i=1}^{N} \log_2 P(w_i | w_1, w_2, ..., w_{i-1})}\) 其中,$ N $ 是测试集中词的总数,$ P(w_i | w_1, w_2, …, w_{i-1}) $ 是模型预测词 $ w_i $ 的概率。

检索增强RAG

2. 词汇分析

不在课堂小测和作业的内容不会以计算形式出现

  • 词是形式和意义相结合的单位,也是语言中能够独立运用的最小单位
  • 掌握一个词汇意味着知道其读音和语义
  • 自然语言处理算法中通常是基本单元

    llm中token是基础单位

  • 词通常是由语素构成。
    • 语素是语言中意义的最小单元
    • 简单词、复杂词
    • 实义词(表达具体的意义)、功能词(为了满足语法功能需求,也称闭类词)
  • 词性(POS)也称词类
    • 名词
      • 专有名词是我们自然语言处理中需要特别关注的词汇。
    • 动词
      • 句子这一类分析重点关注的词汇。
    • 形容词
      • 情感分析重点关注的词汇。
    • 副词
      • 阅读理解比较关注。作用不大。
    • 数词
      • 自然语言中最难的一类词。
    • 代词
      • 代词消解->人称代词、物主代词
    • 冠词
      • 语法改错,没人做了,打不过大模型。
    • 介词
      • 句法分析。
    • 连词
      • but
  • 词语规范化:将单词或词形转化为标准形式,针对由多种形式的单词使用一种单一的形式进行表示。

  • 词形(Token)指的是在一个特定文档中的某个能够表达语义含义的字符序列。
  • 词形还原:将一个词的多种形式还原为它们的基本形式。
  • 词形分析:将一个词分解成为语素的过程。
  • 词干提取

中文分词

  • 困难:
    • 分词规范
    • 歧义切分
      • 固有歧义
      • 真歧义
      • 交集歧义
    • 未登录词识别

基于最大匹配的中文分词

  • 前向最大匹配
  • 后向最大匹配

  • 根据给定的字典,利用贪心搜索策略找到分词方案。
def forward_max_match(sentence, dictionary, max_len=5):
    """
    前向最大匹配算法
    Args:
        sentence: 待分词的句子
        dictionary: 词典(set类型)
        max_len: 最大词长
    Returns:
        分词结果列表
    """
    words = []
    start = 0
    while start < len(sentence):
        word_len = min(max_len, len(sentence) - start)
        # 从最大长度开始尝试匹配
        while word_len > 0:
            word = sentence[start:start + word_len]
            if word in dictionary or word_len == 1:
                words.append(word)
                break
            word_len -= 1
        start += word_len
    return words

def backward_max_match(sentence, dictionary, max_len=5):
    """
    后向最大匹配算法
    Args:
        sentence: 待分词的句子
        dictionary: 词典(set类型)
        max_len: 最大词长
    Returns:
        分词结果列表
    """
    words = []
    end = len(sentence)
    while end > 0:
        word_len = min(max_len, end)
        # 从最大长度开始尝试匹配
        while word_len > 0:
            word = sentence[end - word_len:end]
            if word in dictionary or word_len == 1:
                words.insert(0, word)
                break
            word_len -= 1
        end -= word_len
    return words

# 示例使用
if __name__ == "__main__":
    # 示例词典
    dictionary = {"我们", "在", "学习", "自然", "语言", "处理", "自然语言", "自然语言处理"}
    
    # 测试句子
    sentence = "我们在学习自然语言处理"
    
    # 前向最大匹配
    forward_result = forward_max_match(sentence, dictionary)
    print("前向最大匹配结果:", "/".join(forward_result))
    
    # 后向最大匹配
    backward_result = backward_max_match(sentence, dictionary)
    print("后向最大匹配结果:", "/".join(backward_result))

基于线性链条件随机场的中文分词

  • 将分词过程转化为对字分类的问题。
    • 对于输入橘子的每一个字,根据他在分词结果中的位置腹语不同的标签
    • BIES标注法:
      • 开始B,中间I,结尾E和单独成次S

        他是研究生物科学的一位科学家 他|是|研究|生物科学|的|一位|科学家 他/S 是/S 研/B究/E 生/B物/I科/I学/E 的/S 一/B位/E 科/B学/I家/E

    • 条件随机场(不要求掌握)
      • 对于给定的观测序列,概率,势函数,马尔科夫状态转移

        BPE算法(Byte Pair Encoding)

  • 基本原理:迭代地合并最频繁出现的字符对
  • 具体步骤:
    1. 准备语料库,将所有单词拆分为字符序列,在每个单词末尾添加特殊符号
    2. 统计所有相邻字符对的频率
    3. 合并最频繁出现的字符对,形成新的子词
    4. 重复步骤2-3直到达到预设的词表大小或合并次数
  • 优点:
    • 可以处理未登录词
    • 压缩效率高
    • 适应性强
  • 示例:

    “lower” -> “l o w e r </w>” 多次合并后可能变成 “low er </w>”

WordPiece算法

  • 基本原理:基于概率最大化的子词分割算法
  • 与BPE的主要区别:
    • 使用语言模型计算合并的收益
    • 选择合并后能最大化训练数据概率的字符对
  • 具体步骤:
    1. 初始化词表为基本字符集
    2. 对每个可能的合并计算概率增益
    3. 选择增益最大的字符对合并
    4. 重复2-3直到达到预设条件
  • 特点:
    • 常用词保持完整
    • 生僻词会被分解为更小的子词
    • 使用”##”标记词中间的子词
  • 应用:
    • BERT等预训练模型的分词算法

中文分词的评价

  • 评价指标
    • 准确率(Precision):
      • 正确分词的词数 / 系统分词结果的总词数
      • P = 正确分词数 / 系统分词总数
    • 召回率(Recall):
      • 正确分词的词数 / 标准答案的总词数
      • R = 正确分词数 / 标准答案总数
    • F1值:
      • 准确率和召回率的调和平均
      • F1 = 2 × P × R / (P + R)
  • 评价难点
    • 分词标准不统一
    • 歧义切分的判定
    • 未登录词的处理
  • 评价工具
    • SIGHAN分词评测工具
    • NLPIR分词评测系统

词性标注(不要求掌握具体怎么做)

  • 词性标注的主要难点在于歧义性
  • 还没有一个被广泛认可的统一词性划分标准
  • 基于规则的词性标注
    • 利用词典和搭配规则针对词语和上下文进行分析,从而得到句子中每个词语词性
  • 基于隐马尔科夫模型的词性标注
    • 长句子未登录词问题实际应用中需要解决问题
  • 基于卷积神经网络的词性标注

  • 评价指标:宏F1

3. 句法分析

  • 句法:研究自然语言中不同成分组成句子的方式以及支配句子结构决定句子是否成立的规则。
  • 语法:指自然语言中句子、短语以及词等语法单位的语法结构和语法意义的规律。
  • 基于成分关系,基于依存关系

  • 成分语法理论
    • 成分又称短语结构,是指一个句子内部的结构成分。
    • 某一类短语属于一个句法范畴。
      • 句法范畴之间不是完全对等的,而是具有层级关系。
    • 短语结构规则
    • 成分语法就是由语法范畴以及短语结构规则定义的语法。
  • 依存语法理论
    • 句子的每个成分对应语法结构中的唯一一个节点。
    • 投射性原则
    • 两种搜索方式:
      • 自顶向下
      • 自顶向上

CYK算法,基于动态规划思想和自底向上语法分析算法

  • 要求所使用的语法必须符合乔姆斯基范式,期语法规则被限制为**只具有A->BC或A->w这种形式。
  • 步骤:
    • 对于一个长度为n的句子,构造一个(n+1)×(n+1)的二维矩阵T
    • 矩阵主对角线一下全部为0,主对角线上的元素由输入橘子的终结符号(单词)构成。
class CYKParser:
    def __init__(self, grammar):
        """
        初始化CYK解析器
        grammar: 字典形式的CNF文法规则
        """
        self.grammar = grammar

    def parse(self, sentence):
        """
        CYK算法实现
        sentence: 输入句子(词序列)
        """
        n = len(sentence)
        # 初始化表格
        table = [[set() for j in range(n)] for i in range(n)]
        
        # 填充对角线(长度为1的子串)
        for i in range(n):
            word = sentence[i]
            for rule in self.grammar:
                if word in self.grammar[rule]:
                    table[i][i].add(rule)
        
        # 填充其他单元格
        for length in range(2, n + 1):  # 子串长度
            for i in range(n - length + 1):  # 起始位置
                j = i + length - 1  # 结束位置
                for k in range(i, j):  # 分割点
                    for rule in self.grammar:
                        for production in self.grammar[rule]:
                            if isinstance(production, tuple) and len(production) == 2:
                                B, C = production
                                if B in table[i][k] and C in table[k+1][j]:
                                    table[i][j].add(rule)
        
        return table
if __name__ == "__main__":
    # 示例语法规则
    grammar = {
        'S': {('NP', 'VP')},
        'NP': {('DET', 'N'), 'N'},
        'VP': {('V', 'NP')},
        'DET': {'the'},
        'N': {'cat', 'dog'},
        'V': {'chased'}
    }
    
    # 创建解析器
    parser = CYKParser(grammar)
    
    # 测试句子
    sentence = ['the', 'cat', 'chased', 'the', 'dog']
    result = parser.parse(sentence)

实验结果:

开始解析句子: the cat chased the dog
句子长度: 5

步骤1: 初始化解析表格

步骤2: 填充对角线(处理单个词)

处理词: the
  找到规则: DET -> the
  位置[0,0]的非终结符: {'DET'}

处理词: cat
  找到规则: N -> cat
  位置[1,1]的非终结符: {'N'}

处理词: chased
  找到规则: V -> chased
  位置[2,2]的非终结符: {'V'}

处理词: the
  找到规则: DET -> the
  位置[3,3]的非终结符: {'DET'}

处理词: dog
  找到规则: N -> dog
  位置[4,4]的非终结符: {'N'}

步骤3: 填充其他单元格(处理短语)

处理长度为 2 的子串:

  子串: the cat
    分割点 k=0:
    左半部分: the -> {'DET'}
    右半部分: cat -> {'N'}
      应用规则: NP -> DET N
    位置[0,1]的非终结符: {'NP'}

  子串: cat chased
    分割点 k=1:
    左半部分: cat -> {'N'}
    右半部分: chased -> {'V'}
    位置[1,2]的非终结符: set()

  子串: chased the
    分割点 k=2:
    左半部分: chased -> {'V'}
    右半部分: the -> {'DET'}
    位置[2,3]的非终结符: set()

  子串: the dog
    分割点 k=3:
    左半部分: the -> {'DET'}
    右半部分: dog -> {'N'}
      应用规则: NP -> DET N
    位置[3,4]的非终结符: {'NP'}

处理长度为 3 的子串:

  子串: the cat chased
    分割点 k=0:
    左半部分: the -> {'DET'}
    右半部分: cat chased -> set()
    分割点 k=1:
    左半部分: the cat -> {'NP'}
    右半部分: chased -> {'V'}
    位置[0,2]的非终结符: set()

  子串: cat chased the
    分割点 k=1:
    左半部分: cat -> {'N'}
    右半部分: chased the -> set()
    分割点 k=2:
    左半部分: cat chased -> set()
    右半部分: the -> {'DET'}
    位置[1,3]的非终结符: set()

  子串: chased the dog
    分割点 k=2:
    左半部分: chased -> {'V'}
    右半部分: the dog -> {'NP'}
      应用规则: VP -> V NP
    分割点 k=3:
    左半部分: chased the -> set()
    右半部分: dog -> {'N'}
    位置[2,4]的非终结符: {'VP'}

处理长度为 4 的子串:

  子串: the cat chased the
    分割点 k=0:
    左半部分: the -> {'DET'}
    右半部分: cat chased the -> set()
    分割点 k=1:
    左半部分: the cat -> {'NP'}
    右半部分: chased the -> set()
    分割点 k=2:
    左半部分: the cat chased -> set()
    右半部分: the -> {'DET'}
    位置[0,3]的非终结符: set()

  子串: cat chased the dog
    分割点 k=1:
    左半部分: cat -> {'N'}
    右半部分: chased the dog -> {'VP'}
    分割点 k=2:
    左半部分: cat chased -> set()
    右半部分: the dog -> {'NP'}
    分割点 k=3:
    左半部分: cat chased the -> set()
    右半部分: dog -> {'N'}
    位置[1,4]的非终结符: set()

处理长度为 5 的子串:

  子串: the cat chased the dog
    分割点 k=0:
    左半部分: the -> {'DET'}
    右半部分: cat chased the dog -> set()
    分割点 k=1:
    左半部分: the cat -> {'NP'}
    右半部分: chased the dog -> {'VP'}
      应用规则: S -> NP VP
    分割点 k=2:
    左半部分: the cat chased -> set()
    右半部分: the dog -> {'NP'}
    分割点 k=3:
    左半部分: the cat chased the -> set()
    右半部分: dog -> {'N'}
    位置[0,4]的非终结符: {'S'}

解析完成!
句子符合语法规则!

PCFG算法(概率上下文无关文法)

实验课内容

关键字提取

TF-IDF(词频-逆文档频率)

  • 基本原理:结合词频(TF)和逆文档频率(IDF)来评估词语对于文档集合的重要程度
  • 计算公式:
    • TF(词频):词语在文档中出现的频率
      TF = 词语在文档中的出现次数 / 文档的总词数
      
    • IDF(逆文档频率):衡量词语的普遍重要性 \(IDF(t, D) = log(文档总数N / 包含该词t的文档数) + 1\)
    • TF-IDF分数:
      TF-IDF = TF × IDF
      
  • 特点:
    • 词语在文档中出现次数越多,TF值越高
    • 词语在越少的文档中出现,IDF值越高
    • 能够过滤掉常见词,突出重要词语
  • 应用:
    • 文本关键词提取
    • 文本相似度计算
    • 文本分类
    • 搜索引擎结果排序

TextRank 算法

  • TextRank是一种基于图的无监督关键词提取和文本摘要算法
    1. 文本预处理:
    • 分词
    • 去除停用词
    • 词性过滤(可选) 2. 构建共现图
    • 节点:图中的节点代表文本中的词语
    • 变:如果两个词语在一定窗口大小内贡献,则在他们之间建立边。边的权重通常基于共现频率或其他相关度量。 3. 计算节点权重:
    • 使用迭代算法计算每个节点的权重。
    • 初始化每个节点的权重为相同值
    • 迭代更新节点权重,直到收敛或达到最大迭代次数
    • 更新公式类似于PageRank: \(Score(A) = (1-d)+d\times \sum_{B\in In(A)} \dfact{Score(B)}{Out(B)}\) 其中,d是阻尼系数(通常为0.85),In(A)是指向节点A的所有节点,Out(B)是B指向的所有节点

4. 语义分析

语义学概述

  • 研究语言意义的科学成为语义学
  • 语义的形式化结构表示成为语义表示

词汇语义学

  • 词汇语义学:主要研究单个词汇的意义以及词汇之间的相互关系
    1. 词汇语义理论
    • 语义场理论:词汇的意义是相互联系的,构成一个完整的系统和网络,具有某些相同语义特征的一组词聚而成场
    • 语义成分分析:词义可以由最小的语义成分组合而成。最小的语义成分称为语义特征。
    • 义元理论:自然语言中包含非常少部分的词汇,这些词语可以用于解释绝大部分的意义
      • Hownet
    • 框架语义学:词义只能在相应的知识框架背景中才能得到理解。 2. 词汇之间的关系
    • 形体关系:研究词汇的声音形体和拼写之间的关系
    • 意义关系:主要关注词汇意义之间的关联性、相似性、对立性等关系。
    • 实体关系:主要研究词汇之间的客观关系。

句子语义学

  • 真值条件语义学
  • 格语法:
    • 语义格:最小的句子语义成分
  • 句子间关系:
    • 同义关系
    • 反义关系
    • 蕴含关系
    • 预设关系

语义表示

  • 语义表示:将语义信息转化为计算机能够处理的形式
  • 数理逻辑表示法
  • 框架表示法
    • 每个框架由若干槽组成,描述框架所讨论对象的某一方面的属性。
  • 语义网络:
    • 是一种用实体及其语义关系来表达知识和语义的网格图。语义网络由节点和弧组成:节点表示各种事件、事物、概念、属性、动作等,也可以是一个子网络;弧表示节点之间的语义关系,并且有方向。

分布式表示

  • 将文本教师为低维空间下稠密向量,并在低维表示空间中利用表示向量之间的计算关系,体现文本间的语义关联。
  • 向量空间模型(VSM)
  • 独热表示

单词分布式表示

  • 通过将单词表视为定长的低维稠密向量
  • 在向量空间构建单词之间的语义关系。
  • 使含义相近的单词具有相似的向量表示
    • 频繁出现在相同上下文的词语之间赋予较高的表示相似度。
  • 单词向量式表示–基于上下文单词预测词向量模型
    • 共现矩阵
    • 连续词袋模型(CBOW)
    • 跳字模型(SG)
    • 全局向量模型(GloVe)
  • 未登录词 -> 用”[UNK]表示

分布式表示的评价

  • 内部评价、外部评价

句子分布式表示

  • 句子分布式表示:将句子转化为低维稠密向量
  • 句子分布式表示的方法
    • 句子向量表示
      • 句子向量表示的方法:
        • 句子平均词向量

篇章分布式表示

  • TF-IDF

词义消歧

语义角色标注

XLNet

自回归模型与自编码模型

  • 自回归模型(如GPT)通过预测序列中的下一个词来进行训练。
  • 自编码模型(如BERT)通过掩盖输入序列中的某些词并预测这些词来进行训练。

XLNet模型

  • 排序语言模型
  • 通过随机打乱句子中词的顺序,让模型在预测某个词时,能同时看到这个词的“前后”上下文信息。
  • 不改变输入顺序
  • 引入Mask矩阵模拟排列,通过掩码控制每个词能“看到”哪些词。
  • 双流自注意机制
    • 内容流
    • 查询流