自学内容网 自学内容网

预训练词向量的使用

目录

1.代码实现

2.知识点:


 

两个网站可以下载预训练词向量

1.代码实现

import os
import torch
from torch import nn
import dltools
class TokenEmbedding:    #没写括号,就是继承python默认的Object类
    def __init__(self, file_path):
        self.idx_to_token, self.idx_to_vec= self._load_embedding(file_path)
        self.unknown_idx = 0
        #创建 词与索引 对应的词典
        self.token_to_idx = {token: idx for idx, token in enumerate(self.idx_to_token)}
        
    
    #加载预训练好的词向量
    def _load_embedding(self, file_path):
        #创建列表,分别存放词与词向量对应的索引
        idx_to_token, idx_to_vec = ['<unk>'], []  #在存放词索引的列表中先加一个未知字符<unk>
        with open(file_path, 'r', encoding='utf-8') as f:
            #对于数据量非常大的文件读取,把其当做迭代器,一行行遍历输出,避免一下子把整个文件加载进来
            for line in f:
                #strip()移除字符串头尾指定的字符 ( 默认为空白符 ) 空格 ( ' ' ) 、制表符 ( \t ) 、换行符 (\r\ ) 统称为空白符
                #rstrip()只对右边进行移除空白符操作
                elems = line.rstrip().split(' ')  #输出的elems就是一个列表
                token, elems = elems[0], [float(elem) for elem in elems[1:]]
                #跳过fasttext的第一行    fasttext的第一行只有两个元素(一个token, 一个elem) 
                if len(elems) > 1:
                    idx_to_token.append(token)
                    idx_to_vec.append(elems)
        
        #在idx_to_vec中为<unk>添加一个全是0的词向量   #idx_to_vec是一个二维列表
        idx_to_vec = [[0] * len(idx_to_vec[0])] + idx_to_vec
        return idx_to_token, torch.tensor(idx_to_vec)
    
    def __getitem__(self, tokens):
        """根据输入的tokens返回对应的词向量"""
        #根据tokens获取对应的词索引 
        #dict[token]索引字典中没有的元素会报错, dict.get(token, 0) 索引字典中没有的元素会返回0
        indices = [self.token_to_idx.get(token, self.unknown_idx) for token in tokens]
        #根据索引indices来获取对应的词向量
        vecs = self.idx_to_vec[torch.tensor(indices)]
        return vecs
    
    def __len__(self): 
        """返回tokens的数量长度"""
        return len(self.idx_to_token)
glove_6b50d = TokenEmbedding(r'E:/ALOT/10_deep_learning/data/glove.6B/glove.6B.50d.txt')
len(glove_6b50d)
400001
glove_6b50d.token_to_idx['beautiful']
3367
glove_6b50d.idx_to_token[3367]   #idx_to_token是列表,可以根据索引来获取值

 'beautiful'

#计算余弦相似度来衡量词的相似度
def knn(W, x, k):
    cos = torch.mv(W,x.reshape(-1, )) / (torch.sqrt(torch.sum(W * W, axis=1) + 1e-9) * torch.sqrt((x * x).sum()))
    #筛选cos前10位
    _, topk = torch.topk(cos, k=k)
    return topk, [cos[int(i)] for i in topk] 
def get_similar_tokens(query_token, k, embed):
    #获取topk, cos
    #embed.idx_to_vec 已经做了embed的词向量
    #embed[[query_token]]获取查询词的词向量
    topk, cos = knn(embed.idx_to_vec, embed[[query_token]], k+1)
    for i, c in zip(topk[1:], cos[1:]):   #排除查询词query_token它本身
        print(f'{embed.idx_to_token[int(i)]} : cosine相似度={float(c):.3f}')
#查询“chip芯片”的相似词
get_similar_tokens('chip', 3, glove_6b50d)
chips : cosine相似度=0.856
intel : cosine相似度=0.749
electronics : cosine相似度=0.749
#词类比
#例如: man - woman :  son - daughter
#上面相当于
#-->daughter = woman - man  + son
def get_analogy(token_a, token_b, token_c, embed):
    #分别获取token_a, token_b, token_c的词向量
    vecs = embed[[token_a, token_b, token_c]]
    x = vecs[1] - vecs[0] + vecs[2]
    topk, cos = knn(embed.idx_to_vec, x, 1)
    return embed.idx_to_token[int(topk[0])]
get_analogy('man', 'woman', 'son', glove_6b50d)

'daughter' 

#加载fastText词向量
fasttext_16b300d = TokenEmbedding(r'E:/ALOT/10_deep_learning/data/wiki-news-300d-1M.vec')
len(fasttext_16b300d)
999995
fasttext_16b300d.token_to_idx['boy']

 2033

fasttext_16b300d.idx_to_token[2033]

 'boy'

fasttext_16b300d.idx_to_vec[2033].shape


fasttext_16b300d.idx_to_vec[2033].reshape(-1,).shape

 两个形状输出都是:

torch.Size([300])
get_similar_tokens('boy', 2, fasttext_16b300d)

 

girl : cosine相似度=0.862
boys : cosine相似度=0.772 
get_analogy('man', 'woman', 'son', fasttext_16b300d)  #词类比效果比较差

 'son'

2.知识点:

 

 

 


原文地址:https://blog.csdn.net/Hiweir/article/details/142591702

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!