pytorch练习(一)词向量

1. 词向量

  • 学习词向量的概念

  • 用Skip-thought模型训练词向量

  • 学习使用PyTorch datasetdataloader

  • 学习定义PyTorch模型

  • 学习torch.nn中常见的Module

    • Embedding
  • 学习常见的PyTorch operations

    • bmm

    • logsigmoid

  • 保存和读取PyTorch模型

训练数据:

链接:https://pan.baidu.com/s/1tFeK3mXuVXEy3EMarfeWvg 密码:v2z5

在这一份notebook中,我们会(尽可能)尝试复现论文Distributed Representations of Words and Phrases and their Compositionality中训练词向量的方法.

我们会实现Skip-gram模型,并且使用论文中noice contrastive sampling的目标函数。

以下是一些我们没有实现的细节

  • subsampling:参考论文section 2.3

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.data as tud
from torch.nn.parameter import Parameter

from collections import Counter
import numpy as np
import random
import math

import pandas as pd
import scipy
import sklearn
from sklearn.metrics.pairwise import cosine_similarity

USE_CUDA = torch.cuda.is_available()

# 为了保证实验结果可以复现,我们经常会把各种random seed固定在某一个值
random.seed(53113)
np.random.seed(53113)
torch.manual_seed(53113)
if USE_CUDA:
    torch.cuda.manual_seed(53113)
    
# 设定一些超参数
    
K = 100          # number of negative samples
C = 3           # nearby words threshold
NUM_EPOCHS = 2      # The number of epochs of training
MAX_VOCAB_SIZE = 30000  # the vocabulary size
BATCH_SIZE = 128     # the batch size
LEARNING_RATE = 0.2   # the initial learning rate
EMBEDDING_SIZE = 100   # 词向量维度
       
    
LOG_FILE = "word-embedding.log"

# tokenize函数,把一篇文本转化成一个个单词
def word_tokenize(text):
    return text.split()
  • 从文本文件中读取所有的文字,通过这些文本创建一个vocabulary

  • 由于单词数量可能太大,我们只选取最常见的MAX_VOCAB_SIZE个单词

  • 我们添加一个UNK单词表示所有不常见的单词

  • 我们需要记录单词到index的mapping,以及index到单词的mapping,单词的count,单词的(normalized) frequency,以及单词总数。

with open("./text8.train.txt", "r") as fin:
    text = fin.read()

text = [w for w in word_tokenize(text.lower())]
vocab = dict(Counter(text).most_common(MAX_VOCAB_SIZE - 1))  # 29999,单词:词频,降序
vocab['<unk>'] = len(text) - np.sum(list(vocab.values()))   # print(vocab)
idx_to_word = [word for word in vocab.keys()]
word_to_idx = {word:i for i, word in enumerate(idx_to_word)}

word_counts = np.array([count for count in vocab.values()], dtype=np.float32) # 词频统计
word_freqs = word_counts / np.sum(word_counts)
word_freqs = word_freqs ** (3./4.)
word_freqs = word_freqs / np.sum(word_freqs) # 用来做 negative sampling
VOCAB_SIZE = len(idx_to_word)
VOCAB_SIZE      # 3000

1.1 实现Dataloader

一个dataloader需要以下内容:

  • 把所有text编码成数字,然后用subsampling预处理这些文字。

  • 保存vocabulary,单词count,normalized word frequency

  • 每个iteration sample一个中心词

  • 根据当前的中心词,返回context单词

  • 根据中心词sample一些negative单词,返回单词的counts

这里有一个好的tutorial介绍如何使用PyTorch dataloader.

为了使用dataloader,我们需要定义以下两个function:

  • __len__ function需要返回整个数据集中有多少个item
  • __get__ 根据给定的index返回一个item

有了dataloader之后,我们可以轻松随机打乱整个数据集,拿到一个batch的数据等等

class WordEmbeddingDataset(tud.Dataset): # torch.utils.data
    def __init__(self, text, word_to_idx, idx_to_word, word_freqs, word_counts):
        ''' text: a list of words, all text from the training dataset
            word_to_idx: the dictionary from word to idx
            idx_to_word: idx to word mapping
            word_freq: the frequency of each word
            word_counts: the word counts
        '''        
        super(WordEmbeddingDataset, self).__init__()
        self.text_encoded = [word_to_idx.get(t, VOCAB_SIZE-1) for t in text]
        self.text_encoded = torch.Tensor(self.text_encoded).long()
        self.word_to_idx = word_to_idx
        self.idx_to_word = idx_to_word
        self.word_freqs = torch.Tensor(word_freqs)
        self.word_counts = torch.Tensor(word_counts)

    def __len__(self):
        '''
        返回整个数据集(所有单词)的长度
        '''
        return len(self.text_encoded)

    def __getitem__(self, idx):
        '''
        返回以下数据用于训练
        - 中心词
        - 这个单词附近(positive)单词
        - 随机采样的 K个单词作为 negative sample
        '''
        center_word = self.text_encoded[idx]
        # C: nearby words threshold
        pos_indices = list(range(idx-C, idx)) + list(range(idx+1, idx+C+1))
        pos_indices = [i % len(self.text_encoded) for i in pos_indices]
        pos_words = self.text_encoded[pos_indices]
        neg_words = torch.multinomial(self.word_freqs, 
                          K * pos_words.shape[0], True) 
        # print(center_word.size(), pos_words.size(), neg_words.size())
        return center_word, pos_words, neg_words

创建dataset和dataloader

dataset = WordEmbeddingDataset(text, word_to_idx, idx_to_word, 
                  word_freqs, word_counts)

# dataset[5]
dataloader = tud.DataLoader(dataset, batch_size=BATCH_SIZE, 
                shuffle=True, num_workers=4)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch能够通过预训练好的词向量对自然语言处理任务进行有力的支持。而在实际应用过程中,很多时候我们需要使用自己提供的词向量。因此,本文将介绍如何使用PyTorch加载自定义词向量。 首先,需要准备好自定义的词向量文件,一般是以文本文件格式存储。文件的每一行代表一个单词和对应的向量值,中间用空格分隔。词向量文件的格式需要与预训练好的词向量文件一致。 接下来,我们将使用PyTorch中的torchtext库来加载自定义词向量。首先需要安装torchtext库,可以通过pip客户端进行安装。 然后,我们需要创建一个自定义词向量字段,代码如下: ``` import torchtext.vocab as vocab custom_embeddings = vocab.Vectors(name='custom_embeddings.txt', cache='/path/to/custom_embeddings', unk_init=torch.Tensor.normal_) TEXT.build_vocab(train, vectors=custom_embeddings) ``` 其中,name参数为自定义词向量文件的名称,cache参数为自定义词向量文件的路径,unk_init参数为向量初始化方法。 最后,我们可以使用创建好的词向量字段来创建数据集和迭代器。代码如下: ``` train_iter, val_iter, test_iter = data.BucketIterator.splits( datasets=(train, val, test), batch_sizes=(batch_size, batch_size, batch_size), sort_within_batch=True, sort_key=lambda x: len(x.text), device=device) ``` 其中,train、val、test分别表示训练、验证、测试数据集,batch_size表示批次大小,sort_within_batch和sort_key参数用于对数据进行排序。 通过以上步骤,我们就能够使用PyTorch加载自定义词向量了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值