• fastNLP学习笔记——Vocabulary


    Vocabulary是包含字或词与index的关系的类,用于将文本转化为index。

    教程地址

    构建Vocabulary

    from fastNLP import Vocabulary
    
    vocab = Vocabulary()
    vocab.add_word_lst(['复', '旦', '大', '学'])  # 加入新的字
    vocab.add_word('上海')  # `上海`会作为一个整体
    vocab.to_index('复')  # 应该会为3
    vocab.to_index('我')  # 会输出1,Vocabulary中默认pad的index为0, unk(没有找到的词)的index为1
    
    #  在构建target的Vocabulary时,词表中应该用不上pad和unk,可以通过以下的初始化
    vocab = Vocabulary(unknown=None, padding=None)
    vocab.add_word_lst(['positive', 'negative'])
    vocab.to_index('positive')  # 输出0
    vocab.to_index('neutral')  # 会报错,因为没有unk这种情况
    

    除了直接使用一个列表来构建Vocabulary,还可以使用DataSet的某一个Field来构建,然后还能将field的内容转为index。

    from fastNLP import Vocabulary
    from fastNLP import DataSet
    
    dataset = DataSet({'chars': [
                                    ['今', '天', '天', '气', '很', '好', '。'],
                                    ['被', '这', '部', '电', '影', '浪', '费', '了', '两', '个', '小', '时', '。']
                                ],
                        'target': ['neutral', 'negative']
    })
    
    vocab = Vocabulary()
    #  从该dataset中的chars列建立词表
    vocab.from_dataset(dataset, field_name='chars')
    #  使用vocabulary将chars列转换为index
    vocab.index_dataset(dataset, field_name='chars')
    
    target_vocab = Vocabulary(padding=None, unknown=None)
    target_vocab.from_dataset(dataset, field_name='target')
    target_vocab.index_dataset(dataset, field_name='target')
    print(dataset)
    

    输出:

    +---------------------------------------------------+--------+
    |                       chars                       | target |
    +---------------------------------------------------+--------+
    |               [4, 2, 2, 5, 6, 7, 3]               |   0    |
    | [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3] |   1    |
    +---------------------------------------------------+--------+
    

    一些使用tips

    教程中这一部分主要探讨no_create_entry参数的作用。

    建议使用的dev集和test集可以设这个参数。这个参数的作用是指定某个集合中的词如果没出现在预训练 embedding 中,会随机 embedding 还是设为 <UNK>

    from fastNLP import Vocabulary
    from fastNLP import DataSet
    
    tr_data = DataSet({'chars': [
                                    ['今', '天', '心', '情', '很', '好', '。'],
                                    ['被', '这', '部', '电', '影', '浪', '费', '了', '两', '个', '小', '时', '。']
                                ],
                        'target': ['positive', 'negative']
    })
    dev_data = DataSet({'chars': [
                                    ['住', '宿', '条', '件', '还', '不', '错'],
                                    ['糟', '糕', '的', '天', '气', ',', '无', '法', '出', '行', '。']
                                ],
                        'target': ['positive', 'negative']
    })
    
    vocab = Vocabulary()
    #  将验证集或者测试集在建立词表是放入no_create_entry_dataset这个参数中。
    vocab.from_dataset(tr_data, field_name='chars', no_create_entry_dataset=[dev_data])
    

    上面的这个例子就为dev集的词也使用了embedding。

    这样做的好处在于一些词没有在与训练的 embedding 中,但是在test集中出现,我们通过 finetune 可以提高对这个词的理解。若test集或dev集中有这个词,可以达到更好的训练效果。如果test或dev集有只在这两个集合中出现,且没有在预训练出现的词,则按照<UNK>处理。

    如果一个词出现在了train中,但是没在预训练模型中,embedding会为随机初始化,且它单独的一个vector,如果finetune embedding的话, 这个词在更新之后可能会有更好的表示; 而如果这个词仅出现在了dev或test中,那么就不能为它们单独建立vector,而应该让它指向unk这个vector的 值(当unk的值更新时,这个词也使用的是更新之后的vector)。所以被认为是no_create_entry的token,将首先从预训练的词表中寻找它的表示,如 果找到了,就使用该表示; 如果没有找到,则认为该词的表示应该为unk的表示。

    下面这个例子帮助理解这个参数的作用。

    import torch
    from fastNLP.embeddings import StaticEmbedding
    from fastNLP import Vocabulary
    
    vocab = Vocabulary()
    vocab.add_word('train')
    vocab.add_word('only_in_train')  # 仅在train出现,但肯定在预训练词表中不存在
    vocab.add_word('test', no_create_entry=True)  # 该词只在dev或test中出现
    vocab.add_word('only_in_test', no_create_entry=True)  # 这个词在预训练的词表中找不到
    
    embed = StaticEmbedding(vocab, model_dir_or_name='en-glove-6b-50d')
    print(embed(torch.LongTensor([vocab.to_index('train')])))
    print(embed(torch.LongTensor([vocab.to_index('only_in_train')])))
    print(embed(torch.LongTensor([vocab.to_index('test')])))
    print(embed(torch.LongTensor([vocab.to_index('only_in_test')])))
    print(embed(torch.LongTensor([vocab.unknown_idx])))
    

    输出:

    tensor([[ 0.9497,  0.3433,  0.8450, -0.8852, ...]], grad_fn=<EmbeddingBackward>)  # train,en-glove-6b-50d,找到了该词
    tensor([[ 0.0540, -0.0557, -0.0514, -0.1688, ...]], grad_fn=<EmbeddingBackward>)  # only_in_train,en-glove-6b-50d,使用了随机初始化
    tensor([[ 0.1318, -0.2552, -0.0679,  0.2619, ...]], grad_fn=<EmbeddingBackward>)  # test,在en-glove-6b-50d中找到了这个词
    tensor([[0., 0., 0., 0., 0., ...]], grad_fn=<EmbeddingBackward>)   # only_in_test, en-glove-6b-50d中找不到这个词,使用unk的vector
    tensor([[0., 0., 0., 0., 0., ...]], grad_fn=<EmbeddingBackward>)   # unk,使用zero初始化
    
    一个人没有梦想,和咸鱼有什么区别!
  • 相关阅读:
    Java面试——VUE2&VUE3概览
    Golang 面试笔录
    数据科学完整流程概述
    周志华 机器学习 西瓜书 主要符号表
    数据分析师的发展方向?
    404 GET /nbextensions/jupyter-js-widgets/extension.js
    如何使用Conda源快速安装PyTorch?
    美化React组件之CSS Modules
    react如何全局配置sass
    nuxt api缓存,组件缓存,页面缓存
  • 原文地址:https://www.cnblogs.com/TABball/p/12727326.html
Copyright © 2020-2023  润新知