美文网首页
动手学习深度学习 | 语言模型和循环神经网络笔记

动手学习深度学习 | 语言模型和循环神经网络笔记

作者: yuanCruise | 来源:发表于2020-02-12 16:36 被阅读0次
    0.文本处理整体概况

    step1:对原始数据进行分词
    step2:对分词后的数据进行去重编号,得到[词语to序号]的列表,和[序号to词语]的字典。将这两部分用作后续训练循环神经网络的数据集。
    step3:通过一些采样方法对构建的数据集进行采样,得到训练的批次。常见的采样方法有随机采样和相邻采样。
    step4:利用语言模型对上述的数据集进行训练,得到一个nlp模型。语言模型有n元语法模型,RNN模型,LSTM模型等。

    1.使用spacy可以进行语言分词

    达到很好的直观效果,相较于自己构建的逻辑,更加符合语言本身词意的分词操作,且可以将分词对应的idx对应输出。

    import spacy
    text = "Mr. Chen doesn't agree with my suggestion."
    nlp = spacy.load('en_core_web_sm')
    doc = nlp(text)
    print([token.text for token in doc])
    print([token.idx for token in doc])
    
    #------------------
    ['Mr.', 'Chen', 'does', "n't", 'agree', 'with', 'my', 'suggestion', '.']
    [0, 4, 9, 13, 17, 23, 28, 31, 41]
    
    2.随机采样和相邻采样
    2.1 随机采样

    下面的代码每次从数据里随机采样一个小批量。其中批量大小batch_size是每个小批量的样本数,num_steps是每个样本所包含的时间步数。 在随机采样中,每个样本是原始序列上任意截取的一段序列,相邻的两个随机小批量在原始序列上的位置不一定相毗邻。

    import torch
    import random
    def data_iter_random(corpus_indices, batch_size, num_steps, device=None):
        # 减1是因为对于长度为n的序列,X最多只有包含其中的前n - 1个字符
        num_examples = (len(corpus_indices) - 1) // num_steps  # 下取整,得到不重叠情况下的样本个数
        example_indices = [i * num_steps for i in range(num_examples)]  # 每个样本的第一个字符在corpus_indices中的下标
        random.shuffle(example_indices)
    
        def _data(i):
            # 返回从i开始的长为num_steps的序列
            return corpus_indices[i: i + num_steps]
        if device is None:
            device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        
        for i in range(0, num_examples, batch_size):
            # 每次选出batch_size个随机样本
            batch_indices = example_indices[i: i + batch_size]  # 当前batch的各个样本的首字符的下标
            X = [_data(j) for j in batch_indices]
            Y = [_data(j + 1) for j in batch_indices]
            yield torch.tensor(X, device=device), torch.tensor(Y, device=device)
    
    2.2 相邻采样

    在相邻采样中,相邻的两个随机小批量在原始序列上的位置相毗邻。

    def data_iter_consecutive(corpus_indices, batch_size, num_steps, device=None):
        if device is None:
            device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        corpus_len = len(corpus_indices) // batch_size * batch_size  # 保留下来的序列的长度
        corpus_indices = corpus_indices[: corpus_len]  # 仅保留前corpus_len个字符
        indices = torch.tensor(corpus_indices, device=device)
        indices = indices.view(batch_size, -1)  # resize成(batch_size, )
        batch_num = (indices.shape[1] - 1) // num_steps
        for i in range(batch_num):
            i = i * num_steps
            X = indices[:, i: i + num_steps]
            Y = indices[:, i + 1: i + num_steps + 1]
            yield X, Y
    
    3.语言模型

    语言模型的目标就是给定一个通过分词得到的词序列,并且评估该序列是否合理,即计算该序列的概率。语言模型从最初的n-gram方法受限于模型参数大,参数稀疏,计算效率低等不足,发展到现在的基于深度学习的RNN,LSTM等方法,大大的提高了语言模型的能力。

    3.1 n-gram

    如下描述所示,n-gram语言模型是一种基于统计的方法。该方法通过分词在语料库中的比重以及条件概率构建概率模型。由于条件概率的存在,该方法的最终计算需要基于n阶马尔科夫假设。且该方法由于基于分词在语料库中的比重,从而导致很多分词的出现频次很少甚至为零,导致得到的值的稀疏性太强,计算效率低。

    3.2 RNN递归神经网络模型

    如下描述所示,递归神经网络RNN是一种基于参数学习的语言模型。该类模型通过中间状态位的保留,隐式的实现了上述概率模型中的条件概率模型。而且此种方法学习友好,使用方便。且如下代码所示,RNN模型的参数与输入输出的时间步数无关,因此模型的复用性很强。


    vocab_size = 1027
    num_inputs, num_hiddens, num_outputs = vocab_size, 256, vocab_size
    # num_inputs: d
    # num_hiddens: h, 隐藏单元的个数是超参数
    # num_outputs: q
    
    def get_params():
        def _one(shape):
            param = torch.zeros(shape, device=device, dtype=torch.float32)
            nn.init.normal_(param, 0, 0.01)
            return torch.nn.Parameter(param)
    
        # 隐藏层参数
        W_xh = _one((num_inputs, num_hiddens))
        print(W_xh.shape)
        W_hh = _one((num_hiddens, num_hiddens))
        print(W_hh.shape)
        b_h = torch.nn.Parameter(torch.zeros(num_hiddens, device=device))
        # 输出层参数
        W_hq = _one((num_hiddens, num_outputs))
        print(W_hq.shape)
        b_q = torch.nn.Parameter(torch.zeros(num_outputs, device=device))
        return (W_xh, W_hh, b_h, W_hq, b_q)
    get_params()
    print(num_inputs, num_hiddens, num_outputs)
    
    #--------------------
    
    torch.Size([1027, 256])
    torch.Size([256, 256])
    torch.Size([256, 1027])
    1027 256 1027
    

    相关文章

      网友评论

          本文标题:动手学习深度学习 | 语言模型和循环神经网络笔记

          本文链接:https://www.haomeiwen.com/subject/hofcfhtx.html