5. 使用PaddleNLP加载词向量
PaddleNLP已经内置了多个开源的预训练词向量模型,用户仅需在使用paddlenlp.embeddings.TokenEmbedding时,指定预训练模型的名称,即可加载相对应的预训练模型。以下将介绍TokenEmbeddign详细用法,并列出PaddleNLP所支持的预训练Embedding模型。
参数 | 类型 | 属性 |
embedding_name | String | 预训练embedding名称,可通过paddlenlp.embeddings.list_embedding_name()查询。 |
unknown_token | string | unknown token。 |
unknown_token_vector | list 或者 np.array | 用来初始化unknown token对应的vector。默认为None(以正态分布方式初始化vector) |
extended_vocab_path | string | 扩展词表的文件名路径。词表格式为一行一个词。 |
trainable | bool | 是否可训练。True表示Embedding可以更新参数,False为不可更新。 |
import paddle import paddlenlp from paddlenlp.embeddings import TokenEmbedding, list_embedding_name paddle.set_device("gpu")
Place(gpu:0)
# 查看预训练embedding名称: print(list_embedding_name()) # ['w2v.baidu_encyclopedia.target.word-word.dim300'] # 初始化TokenEmbedding, 预训练embedding没下载时会自动下载并加载数据 token_embedding = TokenEmbedding(embedding_name="w2v.baidu_encyclopedia.target.word-word.dim300") # 查看token_embedding详情 print(token_embedding)
[32m[2023-03-31 01:45:10,299] [ INFO][0m - Loading token embedding...[0m['w2v.baidu_encyclopedia.target.word-word.dim300', 'w2v.baidu_encyclopedia.target.word-character.char1-1.dim300', 'w2v.baidu_encyclopedia.target.word-character.char1-2.dim300', 'w2v.baidu_encyclopedia.target.word-character.char1-4.dim300', 'w2v.baidu_encyclopedia.target.word-ngram.1-2.dim300', 'w2v.baidu_encyclopedia.target.word-ngram.1-3.dim300', 'w2v.baidu_encyclopedia.target.word-ngram.2-2.dim300', 'w2v.baidu_encyclopedia.target.word-wordLR.dim300', 'w2v.baidu_encyclopedia.target.word-wordPosition.dim300', 'w2v.baidu_encyclopedia.target.bigram-char.dim300', 'w2v.baidu_encyclopedia.context.word-word.dim300', 'w2v.baidu_encyclopedia.context.word-character.char1-1.dim300', 'w2v.baidu_encyclopedia.context.word-character.char1-2.dim300', 'w2v.baidu_encyclopedia.context.word-character.char1-4.dim300', 'w2v.baidu_encyclopedia.context.word-ngram.1-2.dim300', 'w2v.baidu_encyclopedia.context.word-ngram.1-3.dim300', 'w2v.baidu_encyclopedia.context.word-ngram.2-2.dim300', 'w2v.baidu_encyclopedia.context.word-wordLR.dim300', 'w2v.baidu_encyclopedia.context.word-wordPosition.dim300', 'w2v.wiki.target.bigram-char.dim300', 'w2v.wiki.target.word-char.dim300', 'w2v.wiki.target.word-word.dim300', 'w2v.wiki.target.word-bigram.dim300', 'w2v.people_daily.target.bigram-char.dim300', 'w2v.people_daily.target.word-char.dim300', 'w2v.people_daily.target.word-word.dim300', 'w2v.people_daily.target.word-bigram.dim300', 'w2v.weibo.target.bigram-char.dim300', 'w2v.weibo.target.word-char.dim300', 'w2v.weibo.target.word-word.dim300', 'w2v.weibo.target.word-bigram.dim300', 'w2v.sogou.target.bigram-char.dim300', 'w2v.sogou.target.word-char.dim300', 'w2v.sogou.target.word-word.dim300', 'w2v.sogou.target.word-bigram.dim300', 'w2v.zhihu.target.bigram-char.dim300', 'w2v.zhihu.target.word-char.dim300', 'w2v.zhihu.target.word-word.dim300', 'w2v.zhihu.target.word-bigram.dim300', 'w2v.financial.target.bigram-char.dim300', 'w2v.financial.target.word-char.dim300', 'w2v.financial.target.word-word.dim300', 'w2v.financial.target.word-bigram.dim300', 'w2v.literature.target.bigram-char.dim300', 'w2v.literature.target.word-char.dim300', 'w2v.literature.target.word-word.dim300', 'w2v.literature.target.word-bigram.dim300', 'w2v.sikuquanshu.target.word-word.dim300', 'w2v.sikuquanshu.target.word-bigram.dim300', 'w2v.mixed-large.target.word-char.dim300', 'w2v.mixed-large.target.word-word.dim300', 'w2v.google_news.target.word-word.dim300.en', 'glove.wiki2014-gigaword.target.word-word.dim50.en', 'glove.wiki2014-gigaword.target.word-word.dim100.en', 'glove.wiki2014-gigaword.target.word-word.dim200.en', 'glove.wiki2014-gigaword.target.word-word.dim300.en', 'glove.twitter.target.word-word.dim25.en', 'glove.twitter.target.word-word.dim50.en', 'glove.twitter.target.word-word.dim100.en', 'glove.twitter.target.word-word.dim200.en', 'fasttext.wiki-news.target.word-word.dim300.en', 'fasttext.crawl.target.word-word.dim300.en'] [32m[2023-03-31 01:45:13,840] [ INFO][0m - Finish loading embedding vector.[0m[32m[2023-03-31 01:45:13,840] [ INFO][0m - Token Embedding info: Unknown index: 635963 Unknown token: [UNK] Padding index: 635964 Padding token: [PAD] Shape :[635965, 300][0mObject type: TokenEmbedding(635965, 300, padding_idx=635964, sparse=False) Unknown index: 635963 Unknown token: [UNK] Padding index: 635964 Padding token: [PAD] Parameter containing: Tensor(shape=[635965, 300], dtype=float32, place=Place(gpu:0), stop_gradient=False, [[-0.24200200, 0.13931701, 0.07378800, ..., 0.14103900, 0.05592300, -0.08004800], [-0.08671700, 0.07770800, 0.09515300, ..., 0.11196400, 0.03082200, -0.12893000], [-0.11436500, 0.12201900, 0.02833000, ..., 0.11068700, 0.03607300, -0.13763499], ..., [ 0.02628800, -0.00008300, -0.00393500, ..., 0.00654000, 0.00024600, -0.00662600], [ 0.02873484, 0.01525094, -0.00830815, ..., 0.03132731, -0.03779032, 0.00509422], [ 0. , 0. , 0. , ..., 0. , 0. , 0. ]])
6.基于词向量进行计算
6.1 检索词向量
在加载好PaddleNLP内置的词向量后, 可以通过如下方法,检索具体单词的词向量。
test_token_embedding = token_embedding.search("中国") print(test_token_embedding)
[[ 0.260801 0.1047 0.129453 -0.257317 -0.16152 0.19567 -0.074868 0.361168 0.245882 -0.219141 -0.388083 0.235189 0.029316 0.154215 -0.354343 0.017746 0.009028 0.01197 -0.121429 0.096542 0.009255 0.039721 0.363704 -0.239497 -0.41168 0.16958 0.261758 0.022383 -0.053248 -0.000994 -0.209913 -0.208296 0.197332 -0.3426 -0.162112 0.134557 -0.250201 0.431298 0.303116 0.517221 0.243843 0.022219 -0.136554 -0.189223 0.148563 -0.042963 -0.456198 0.14546 -0.041207 0.049685 0.20294 0.147355 -0.206953 -0.302796 -0.111834 0.128183 0.289539 -0.298934 -0.096412 0.063079 0.324821 -0.144471 0.052456 0.088761 -0.040925 -0.103281 -0.216065 -0.200878 -0.100664 0.170614 -0.355546 -0.062115 -0.52595 -0.235442 0.300866 -0.521523 -0.070713 -0.331768 0.023021 0.309111 -0.125696 0.016723 -0.0321 -0.200611 0.057294 -0.128891 -0.392886 0.423002 0.282569 -0.212836 0.450132 0.067604 -0.124928 -0.294086 0.136479 0.091505 -0.061723 -0.577495 0.293856 -0.401198 0.302559 -0.467656 0.021708 -0.088507 0.088322 -0.015567 0.136594 0.112152 0.005394 0.133818 0.071278 -0.198807 0.043538 0.116647 -0.210486 -0.217972 -0.320675 0.293977 0.277564 0.09591 -0.359836 0.473573 0.083847 0.240604 0.441624 0.087959 0.064355 -0.108271 0.055709 0.380487 -0.045262 0.04014 -0.259215 -0.398335 0.52712 -0.181298 0.448978 -0.114245 -0.028225 -0.146037 0.347414 -0.076505 0.461865 -0.105099 0.131892 0.079946 0.32422 -0.258629 0.05225 0.566337 0.348371 0.124111 0.229154 0.075039 -0.139532 -0.08839 -0.026703 -0.222828 -0.106018 0.324477 0.128269 -0.045624 0.071815 -0.135702 0.261474 0.297334 -0.031481 0.18959 0.128716 0.090022 0.037609 -0.049669 0.092909 0.0564 -0.347994 -0.367187 -0.292187 0.021649 -0.102004 -0.398568 -0.278248 -0.082361 -0.161823 0.044846 0.212597 -0.013164 0.005527 -0.004024 0.176243 0.237274 -0.174856 -0.197214 0.150825 -0.164427 -0.244255 -0.14897 0.098907 -0.295891 -0.013408 -0.146875 -0.126049 0.033235 -0.133444 -0.003258 0.082053 -0.162569 0.283657 0.315608 -0.171281 -0.276051 0.258458 0.214045 -0.129798 -0.511728 0.198481 -0.35632 -0.186253 -0.203719 0.22004 -0.016474 0.080321 -0.463004 0.290794 -0.003445 0.061247 -0.069157 -0.022525 0.13514 0.001354 0.011079 0.014223 -0.079145 -0.41402 -0.404242 -0.301509 0.036712 0.037076 -0.061683 -0.202429 0.130216 0.054355 0.140883 -0.030627 -0.281293 -0.28059 -0.214048 -0.467033 0.203632 -0.541544 0.183898 -0.129535 -0.286422 -0.162222 0.262487 0.450505 0.11551 -0.247965 -0.15837 0.060613 -0.285358 0.498203 0.025008 -0.256397 0.207582 0.166383 0.669677 -0.067961 -0.049835 -0.444369 0.369306 0.134493 -0.080478 -0.304565 -0.091756 0.053657 0.114497 -0.076645 -0.123933 0.168645 0.018987 -0.260592 -0.019668 -0.063312 -0.094939 0.657352 0.247547 -0.161621 0.289043 -0.284084 0.205076 0.059885 0.055871 0.159309 0.062181 0.123634 0.282932 0.140399 -0.076253 -0.087103 0.07262 ]]
也可以向search API中传入一批单词,同时获取这些单词的词向量:
words = ['飞桨', '是', '优秀', '的', '深度', '学习', '平台'] test_token_embedding = token_embedding.search(words) # 输出词向量的维度 print(test_token_embedding.shape)
(7, 300)
6.2 计算词向量cosine相似度
使用token_embedding.cosine_sim API 可以轻松地计算两个词汇之间的cosine相似度,代码展示如下。
score = token_embedding.cosine_sim("中国", "美国") print(score)
0.49586025
问问一言:
余弦相似度是通过测量两个向量之间夹角的余弦值来度量它们之间的相似度的,余弦相似度的计算公式为:cosine相似度=cosine(A|B),其中,A和B分别为两个向量。
余弦相似度是一种非常常用的相似度度量方法,尤其在机器学习和计算机视觉领域。它的优点是计算简单,不受向量长度的限制,而且能够比较准确地度量非线性相似度。
cosine相似度是指两个向量的点积,即两个向量在数量上的投影的点积之和。cosine相似度的计算公式为:cosine相似度=向量AB×向量AC/向量AB×向量BC,其中AB和AC分别表示两个向量的向量值,BC和AB分别表示两个向量的模长。
cosine相似度可以用于比较两个向量之间的相似度,尤其适用于计算余弦相似度。余弦相似度是通过测量两个向量之间夹角的余弦值来度量它们之间的相似度的,而cosine相似度是将两个向量在数量上的投影进行点积,从而得到它们之间的相似度。因此,cosine相似度比较适用于比较同类型的向量,例如两个数值向量或两个单位向量。
6.3 计算词向量内积
使用token_embedding.dot API 可以轻松地计算两个词汇向量之间的内积,代码展示如下。
score = token_embedding.dot("中国", "美国") print(score)
8.611071
7 词向量可视化
一般两个单词的语义越相似,其词向量之间的距离越近,否则就越远。 我们可以获取前1000个词向量,然后使用深度学习可视化工具VisualDL的High Dimensional组件对embedding结果进行可视化展示。相关代码如下:
# 引入VisualDL的LogWriter记录日志 from visualdl import LogWriter # 获取词表中前1000个单词 labels = token_embedding.vocab.to_tokens(list(range(0,1000))) test_token_embedding = token_embedding.search(labels) with LogWriter(logdir='./visualize') as writer: writer.add_embeddings(tag='test', mat=test_token_embedding, metadata=labels)
!dir
驱动器 D 中的卷是 program 卷的序列号是 9CBB-0FEE D:\pythonproject\CifarPytorch 的目录 2023/03/31 01:37 <DIR> . 2023/03/31 01:37 <DIR> .. 2023/03/31 01:30 <DIR> .idea 2023/03/28 00:50 <DIR> .ipynb_checkpoints 2023/03/08 20:38 <DIR> housing 2023/03/08 20:42 16,669 housing.zip 2023/03/31 01:37 58,556 my_nlp.ipynb 2019/06/22 03:27 22,752 oh-my-tuna.py 2023/03/27 23:28 259 ppnlp_test.py 2023/03/17 21:48 2,066 qq.py 2023/03/15 19:08 718 test.py 2023/03/15 19:13 578 test2.py 2023/03/27 23:41 100,000,000 text8.txt 2023/03/31 01:37 <DIR> visualize 2023/03/12 21:47 171 截图.py 9 个文件 100,101,769 字节 6 个目录 1,034,063,921,152 可用字节
命令行:!visualdl --logdir ./visualize
启动
(p2) PS D:\pythonproject\CifarPytorch> visualdl --logdir ./visualize VisualDL 2.4.2 Running VisualDL at http://localhost:8040/ (Press CTRL+C to quit) Serving VisualDL on localhost; to expose to the network, use a proxy or pass --host 0.0.0.0
8.基于PaddleNLP内置词向量计算句子间的相似度
前边讲了如何使用PaddleNLP内置的词向量进行词向量级的计算,那么我们应该如何使用这些词向量计算两个句子之间的相似度呢。
计算句子间的相似度的一般做法是先获取句子的句向量表示,然后根据句向量进行相似度计算,如cosine相似度。
8.1 句向量表示
对于给定的一句话,应该如何获取一个向量对这句话进行表示呢。一种简单的做法是首先对给定的语句进行分词,然后将每个词的词向量进行相加,然后将向量平均作为这句话的句向量。
例如, 给定语句:"飞桨是优秀的深度学习平台",可以通过执行如下操作获取句向量:
- 语句分词:['飞桨', '是', '优秀', '的', '深度', '学习', '平台']
- 获取每个单词的词向量V=[v1,v2,v3,v4,v5,v6,v7]V = [v_1, v_2, v_3, v_4, v_5, v_6, v_7]V=[v1,v2,v3,v4,v5,v6,v7]
- 将词向量进行相加 v=∑17viv = \sum_1^7 v_iv=∑17vi
- 将获取的向量vvv进行平均得到句向量: v=v/7v = v/7v=v/7
那么如何对一句话进行分词呢,这里可以使用PaddleNLP内置的分词组件JiebaTokenizer,需要注意的是,这里需要将加载的词向量的词表传给JiebaTokenizer,以帮助JiebaTokenizer进行分词,相关代码如下。
from paddlenlp.data import JiebaTokenizer tokenizer = JiebaTokenizer(vocab=token_embedding.vocab) tokenizer.cut('飞桨是优秀的深度学习平台')
['飞桨', '是', '优秀', '的', '深度', '学习', '平台']
计算句向量
import numpy as np def get_sentence_embedding(text): # 分词 words = tokenizer.cut(text) # 获取词向量 word_embeddings = token_embedding.search(words) # 计算句向量 sentence_embedding = np.sum(word_embeddings, axis=0) / len(words) return sentence_embedding text = "飞桨是优秀的深度学习平台" get_sentence_embedding(text)
array([ 0.19510296, 0.14526556, 0.04353356, -0.16447619, -0.1075983 , 0.08096863, 0.1481626 , -0.03525841, 0.2249497 , 0.05422473, 0.11847366, -0.01143642, 0.210533 , 0.0843911 , -0.16275321, -0.10304531, 0.19928083, 0.11151335, -0.12122246, 0.00717824, 0.06869072, -0.03304985, 0.04737366, -0.04903984, -0.09276368, 0.14815307, 0.11764908, 0.2552487 , 0.03553759, 0.03874803, 0.105869 , 0.03826809, 0.0797499 , 0.07331947, 0.10963003, 0.21121207, 0.07187022, 0.17372386, 0.12214603, 0.05558241, 0.10364453, -0.17042236, -0.09388094, -0.1555377 , 0.16121595, -0.03804519, -0.1271353 , 0.1200745 , 0.09653176, -0.11388861, 0.2205997 , 0.06574674, -0.16068812, -0.04405523, 0.06008752, -0.04770489, 0.12485068, 0.00172876, -0.08036572, -0.05364478, 0.17366108, -0.01403545, 0.06025671, 0.17320652, 0.00298378, -0.08387151, -0.12139515, 0.02183055, 0.12812339, 0.09309892, -0.18843007, -0.04106401, -0.03254778, -0.00939816, -0.08094205, -0.11777003, 0.03482722, 0.12889662, -0.0968136 , -0.15507528, -0.04917407, -0.01044378, 0.16297366, 0.04029513, -0.15563586, 0.01817669, -0.13585247, 0.16801369, -0.02363774, -0.09774144, 0.02816139, 0.08402318, -0.25165498, -0.3721746 , -0.3258135 , -0.01050641, -0.2854829 , -0.19157323, 0.17983662, -0.080662 , 0.2561453 , 0.00350661, -0.0218973 , -0.2753825 , 0.20115063, -0.03554387, 0.14786346, 0.04339342, 0.03214925, 0.29164118, -0.04517195, 0.17884906, -0.01143381, -0.00437825, 0.02973457, -0.10793801, -0.22647807, 0.04565798, 0.19542898, -0.07065425, -0.0730268 , -0.00360838, 0.13907829, 0.12134735, 0.0180327 , 0.21166492, -0.08392329, 0.10567037, 0.14781544, 0.12400176, 0.09055509, 0.0870823 , -0.08237507, -0.19812812, 0.00682083, 0.17064144, -0.06190273, -0.0492782 , 0.04808774, 0.1066234 , 0.04016919, -0.06844995, -0.15411854, -0.12282725, -0.20697036, 0.07054169, 0.24928331, -0.08029113, -0.00948207, 0.11647059, 0.13251722, 0.19403414, -0.10056756, 0.08963453, 0.00443176, -0.00690608, 0.08421244, -0.13469203, 0.00825951, -0.05997926, -0.17951645, -0.09593836, -0.05259605, -0.04120283, -0.12227095, 0.17882767, 0.13015893, 0.17749883, -0.0583581 , -0.01204912, 0.3047711 , -0.0402703 , 0.0539696 , -0.09750988, 0.0837345 , -0.22700866, -0.07904197, -0.06089431, 0.06191074, -0.07821202, -0.10183429, -0.13691941, -0.13274698, -0.3539981 , 0.14334485, 0.06163848, -0.08537608, 0.18528785, -0.05004347, 0.16276717, -0.10791524, -0.11386921, 0.18417777, -0.08590043, -0.07681782, -0.07585763, 0.00686722, -0.06993515, -0.18672559, -0.01409547, -0.07869984, 0.11914798, -0.11347824, 0.03874063, -0.09940962, -0.00482071, 0.06452373, -0.00102185, 0.04440347, -0.15446757, 0.18511854, 0.1290366 , -0.02758869, -0.09910098, 0.21673767, 0.0131802 , -0.12695885, -0.2836155 , 0.17293611, -0.11490408, -0.26381823, -0.13026446, -0.12705307, 0.04711012, 0.08107992, 0.24145982, 0.07222054, -0.01932661, -0.01961996, -0.02205045, -0.00333393, 0.09818899, -0.18834141, -0.12560843, -0.01224316, 0.08893584, 0.08947556, -0.16659333, -0.0621598 , 0.05288253, -0.02581725, -0.01798121, -0.10390489, -0.04412805, -0.18808289, -0.05252216, -0.11618735, 0.00502474, -0.04814149, -0.09425445, 0.06169134, -0.23224752, -0.03472903, -0.13088754, 0.01064928, -0.02322833, -0.18194766, -0.09405632, 0.1139258 , -0.12316331, 0.07132739, 0.03371276, -0.11257417, 0.14023367, 0.04908729, 0.2278197 , 0.03051431, 0.10099815, -0.12568237, -0.00721437, -0.06140849, 0.16141914, -0.19850826, -0.02377282, 0.06997062, 0.11160077, -0.08842317, 0.00937333, 0.12006322, -0.02961009, -0.10157085, 0.16587876, -0.21423234, -0.25040027, 0.27263132, 0.06973907, -0.09058661, 0.06949031, -0.07587279, -0.11172131, -0.05825638, 0.13797857, 0.12154707, 0.14737596, -0.08019464, 0.12680067, -0.11953044, 0.04810719, 0.04678639, -0.06535811], dtype=float32)
8.2 计算语句相似度
下面给出两句话text1和text2,分别获取两句话的句向量,然后计算两句话的cosine相似度,相关代码如下。
import paddle.nn.functional as F text1 = "飞桨是优秀的深度学习平台" text2 = "飞桨是一个深度学习平台" sen_emb1 = get_sentence_embedding(text1) sen_emb2 = get_sentence_embedding(text2) sim = F.cosine_similarity(paddle.to_tensor(sen_emb1).unsqueeze(0), paddle.to_tensor(sen_emb2).unsqueeze(0)) print("Similarity: {:.5f}".format(sim.item()))
Similarity: 0.92739