词嵌入的实际应用涉及使用 gensim 等库训练模型。一个Word2Vec模型可以利用流行的 gensim 库在一个小型数据集上进行训练,并对生成的词向量进行考察。同时,还会介绍如何加载和利用强大的预训练嵌入模型。此实践有助于巩固对分布语义如何转化为实际向量表示的理解。设置您的环境首先,请确保您已安装必要的库。我们主要使用 gensim 进行Word2Vec,nltk 用于示例数据和基本分词,以及可能使用 sklearn 和 plotly 进行可视化。pip install gensim nltk scikit-learn plotly如果您尚未下载,可能还需要下载特定的 nltk 资源:import nltk try: nltk.data.find('corpora/brown') except nltk.downloader.DownloadError: nltk.download('brown') nltk.download('punkt')准备文本数据Word2Vec从词语序列(句子或文档)中学习。与TF-IDF不同,TF-IDF通常受益于停用词移除和词干提取等积极的预处理,而Word2Vec通常在较少操作的情况下表现更好。基本的清理,如转换为小写和分词,通常就足够了。周围的上下文词语,包括停用词,为学习嵌入提供了有价值的信息。让我们使用 nltk 中的Brown语料库作为我们的示例数据集,并执行最少的预处理:import nltk from nltk.corpus import brown import string # 从Brown语料库加载句子 # 在此语料库中,每个句子已经是一个单词/词元列表 raw_sentences = brown.sents() # 预处理:转换为小写并移除标点符号 processed_sentences = [] for sentence in raw_sentences: processed_sentence = [word.lower() for word in sentence if word not in string.punctuation] # 确保句子在移除标点符号后不为空 if processed_sentence: processed_sentences.append(processed_sentence) print(f"已加载并处理 {len(processed_sentences)} 个句子。") # 已处理句子的示例: print("已处理句子的示例:", processed_sentences[10])这为我们提供了一个列表的列表,其中每个内部列表包含一个句子的词元。这是 gensim 所期望的格式。使用Gensim训练Word2Vec模型现在,让我们使用 gensim 训练一个Word2Vec模型。我们需要指定几个超参数:sentences:输入数据(我们的 processed_sentences)。vector_size:词向量的维度(例如,100,300)。更高的维度可以表示更复杂的关联,但需要更多数据和计算。window:句子中当前词与预测词之间的最大距离。min_count:忽略总频率低于此值的词语。有助于过滤掉不常见的词语或拼写错误。workers:用于训练的CPU核心数量(并行化)。sg:训练算法。0 表示CBOW(连续词袋),1 表示Skip-gram。Skip-gram通常对不常用的词语表现更好,而CBOW速度更快。epochs:语料库上的迭代次数(训练轮数)。from gensim.models import Word2Vec import multiprocessing # 查找核心数量 # 定义模型参数 vector_dim = 100 # 嵌入的维度 window_size = 5 # 上下文窗口大小 min_word_count = 5 # 最小词频 training_algorithm = 1 # 1 表示Skip-gram,0 表示CBOW num_workers = multiprocessing.cpu_count() # 使用所有可用核心 training_epochs = 10 # 训练迭代次数 print("正在训练Word2Vec模型...") # 初始化并训练模型 # 注意:训练时间可能因数据大小和CPU而异,需要几分钟。 model = Word2Vec(sentences=processed_sentences, vector_size=vector_dim, window=window_size, min_count=min_word_count, sg=training_algorithm, workers=num_workers, epochs=training_epochs) print("模型训练完成。") # 您可以保存训练好的模型以备后用 # model.save("brown_word2vec.model") # 加载模型:model = Word2Vec.load("brown_word2vec.model")考察学到的嵌入模型训练完成后,我们可以查看学到的表示。model.wv 属性包含词汇和向量。# 访问特定词语的向量 try: vector_king = model.wv['king'] print(f"'king' 的向量:\n {vector_king[:10]}...") # 打印前10个维度 print(f"'king' 向量的形状: {vector_king.shape}") except KeyError: print("词汇中没有'king'(可能是因为min_count或语料库中不存在)。") # 查找与给定词最相似的词语 try: similar_to_woman = model.wv.most_similar('woman', topn=5) print("\n与 'woman' 最相似的词语:") for word, score in similar_to_woman: print(f"- {word}: {score:.4f}") except KeyError: print("词汇中没有'woman'。") # 考察词语类比:king - man + woman = ? try: analogy_result = model.wv.most_similar(positive=['king', 'woman'], negative=['man'], topn=1) print(f"\n类比 'king' - 'man' + 'woman' ≈ {analogy_result[0][0]} (得分: {analogy_result[0][1]:.4f})") except KeyError as e: print(f"\n无法进行类比:词语 '{e.args[0]}' 不在词汇中。") # 检查词语是否在词汇中 print(f"\n'government' 在词汇中吗? {'government' in model.wv.key_to_index}") print(f"词汇量大小: {len(model.wv.key_to_index)}")结果,特别是类比的结果,很大程度上取决于训练数据的大小和性质以及所选的超参数。我们仅在Brown语料库上训练的模型可能无法像在千兆字节文本上训练的模型那样好地表示类比。使用PCA/t-SNE可视化嵌入词向量存在于高维空间中(在我们的示例中是100维)。为了对其进行可视化,我们需要将其维度降至2D或3D。主成分分析(PCA)和t-分布式随机邻居嵌入(t-SNE)是常用的方法。t-SNE通常更适合可视化局部结构和聚类。让我们使用PCA和Plotly来可视化我们学到向量的一个子集。import numpy as np from sklearn.decomposition import PCA import plotly.graph_objects as go # 选择词语子集进行可视化 words_to_visualize = ['man', 'woman', 'king', 'queen', 'boy', 'girl', 'father', 'mother', 'son', 'daughter', 'uncle', 'aunt', 'dog', 'cat', 'animal', 'pet', 'house', 'home', 'car', 'road', 'city', 'country', 'love', 'hate', 'happy', 'sad'] # 获取词汇表中选中词语的向量 vectors = [] words = [] for word in words_to_visualize: if word in model.wv.key_to_index: vectors.append(model.wv[word]) words.append(word) if not vectors: print("所选用于可视化的词语均不在词汇表中。") else: vectors = np.array(vectors) # 使用PCA降维 pca = PCA(n_components=2) vectors_2d = pca.fit_transform(vectors) # 使用Plotly创建交互式散点图 fig = go.Figure(data=go.Scatter( x=vectors_2d[:, 0], y=vectors_2d[:, 1], mode='markers+text', marker=dict( size=8, color='#228be6' # 蓝色标记颜色 ), text=words, textposition='top center' )) fig.update_layout( title='使用PCA(2D)可视化的词嵌入', xaxis_title='PCA分量1', yaxis_title='PCA分量2', width=700, height=600, template='plotly_white' # 使用简洁模板 ) # 显示图表(在Jupyter等环境中) # fig.show() # 或者生成用于网页嵌入的JSON plotly_json = fig.to_json() print("\nPlotly 可视化JSON(前500字符):") print(plotly_json[:500] + "...") # 打印JSON片段 # 在网页环境中,您将使用Plotly.js嵌入此JSON # 示例: # ```plotly # {"layout": {"title": {"text": "Word Embeddings Visualized using PCA (2D)"}, ...}, "data": [{"x": [...], "y": [...], ...}]} # ```{ "data": [ { "x": [-1.01611066, -0.63843226, 0.5325136, 1.3459572, -1.273785, -0.9712762, 0.08503094, -0.06407633, -0.41735646, -0.40381184, 0.28162795, 0.1939366, 0.9796771, 1.1803932, 1.1139715, 1.0847292, -0.15815337, -0.09363376, -0.23822996, -0.22942254, -0.73567724, -0.43333733, -0.17882924, 0.05811722, -0.46446952, -0.06559316], "y": [0.4892139, 0.3983181, 1.3179333, 1.5159775, 0.5114402, 0.29538316, 0.8561967, 0.8343815, 0.4325446, 0.60650885, 0.6452927, 0.9083193, -1.057401, -1.008875, -0.7273944, -0.72633445, -0.613686, -0.8512656, -1.032218, -0.9064242, -0.5827198, -0.5822094, -0.00944266, 0.13858478, 0.34471238, 0.2827387], "mode": "markers+text", "marker": {"size": 8, "color": "#228be6"}, "text": ["man", "woman", "king", "queen", "boy", "girl", "father", "mother", "son", "daughter", "uncle", "aunt", "dog", "cat", "animal", "pet", "house", "home", "car", "road", "city", "country", "love", "hate", "happy", "sad"], "textposition": "top center", "type": "scatter" } ], "layout": { "title": {"text": "使用PCA(2D)可视化的词嵌入"}, "xaxis": { "title": {"text": "PCA分量1"} }, "yaxis": { "title": {"text": "PCA分量2"} }, "width": 700, "height": 600, "template": "plotly_white" } }在Brown语料库上训练的词向量的PCA投影。观察相关概念(如'man'、'woman'、'boy'、'girl')或('dog'、'cat'、'pet')如何倾向于聚集在一起,这表明嵌入表示了语义关系。使用预训练词嵌入模型训练嵌入需要大量的计算资源和庞大的数据集才能获得高质量的结果。通常,使用研究机构发布的预训练嵌入更为实际。这些模型在网络规模的语料库(如Google新闻或维基百科)上进行训练,并表示丰富的语义关系。gensim 提供了方便的途径访问多种流行的预训练模型。让我们加载一个在维基百科上预训练的较小GloVe模型。其他选项包括更大的GloVe模型或Word2Vec模型,如 word2vec-google-news-300。import gensim.downloader as api # 列出可用模型(可选) # print(list(api.info()['models'].keys())) print("\n正在加载预训练GloVe模型 (glove-wiki-gigaword-100)...") # 如果本地不存在,这将下载模型(可能需要时间和磁盘空间) try: glove_model = api.load("glove-wiki-gigaword-100") # 100维GloVe向量 print("预训练GloVe模型已加载。") # 现在像使用我们自己的模型一样使用它 print("向量形状:", glove_model['computer'].shape) print("\n与 'technology' 相似的词语(GloVe):") similar_tech = glove_model.most_similar('technology', topn=5) for word, score in similar_tech: print(f"- {word}: {score:.4f}") print("\n类比 'king' - 'man' + 'woman' ≈ (GloVe):") analogy_result_glove = glove_model.most_similar(positive=['king', 'woman'], negative=['man'], topn=1) print(f"- {analogy_result_glove[0][0]} (得分: {analogy_result_glove[0][1]:.4f})") except Exception as e: print(f"加载预训练模型失败。错误:{e}") print("请检查您的互联网连接或尝试其他模型。") 您可能会发现,预训练模型提供了更直观的相似性结果,并且在类比任务上表现更好,这归因于其训练所用的大量数据。本次实践展示了如何训练您自己的Word2Vec模型,以及对于许多应用来说可能更重要的一点,如何加载和使用强大的预训练嵌入。这些紧密的向量表示是许多高级自然语言处理任务的基础组成部分,包括我们将在下一章介绍的序列模型。它们提供了一种将语义理解输入到机器学习算法的方式。