Embeddings 是现代机器学习和深度学习中的一个核心概念,尤其在自然语言处理(NLP)和推荐系统等领域得到了广泛应用。它通过将高维离散数据映射到低维连续向量空间,从而捕捉数据的语义信息和潜在关系。
什么是 Embeddings?
Embeddings 本质上是将离散的输入数据(例如单词、物品、用户)转化为低维连续向量表示的技术。它的主要目的是简化复杂数据的表示,使得机器学习模型可以更高效地处理和学习数据间的关系。
例如,在 NLP 中,单词可以用独热编码表示。然而,这种表示方式存在高维度和稀疏性问题,无法直接捕捉单词之间的语义关系。通过使用 Word2Vec、GloVe 或 Transformer 模型,单词可以被转化为一个稠密的低维向量(例如 300 维),这些向量可以在几何空间中反映单词间的语义相似性。
在推荐系统中,Embeddings 可以用于将用户和物品映射到同一个向量空间,以便通过计算相似度预测用户的偏好。
Embeddings 的核心属性
- 稠密性:与稀疏的独热编码不同,Embeddings 是稠密的连续向量。
- 维度可控性:Embeddings 的维度通常比原始特征的维度低很多,这有助于减少计算复杂度和内存占用。
- 语义表达:在相同向量空间中的相似数据点具有更小的欧几里得距离或余弦相似度。
- 学习方式:Embeddings 通常是通过模型学习得到的,而不是手工设计的。
Embeddings 的用途
- 自然语言处理:单词、句子、段落甚至文档的向量化。
- 推荐系统:用户和物品的个性化匹配。
- 计算机视觉:图像特征向量化,用于图像分类、搜索等。
- 生物信息学:基因序列、蛋白质结构的向量表示。
编程语言中的 Embeddings 操作
俗话说 talk is cheap, show me the code.
我们通过实际例子,展示如何使用 Java、Python 和 Node.js 实现和操作 Embeddings。
使用 Python 操作 Embeddings
Python 由于其强大的机器学习生态系统,是实现 Embeddings 的首选语言。以下示例展示了如何使用 gensim
库加载预训练的 Word2Vec 模型并操作 Embeddings。
from gensim.models import KeyedVectors
# 加载预训练的 Word2Vec 模型
model = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
# 获取单词的 Embedding
word = 'king'
embedding = model[word]
print(f"`{word}` 的 Embedding: {embedding[:10]}...")
# 计算两个单词的相似度
similarity = model.similarity('king', 'queen')
print(f"`king` 和 `queen` 的相似度: {similarity}")
# 寻找与某单词最相似的单词
similar_words = model.most_similar('king', topn=5)
print("与 `king` 最相似的单词:")
for word, score in similar_words:
print(f" `{word}`: {score}")
运行上述代码,我们可以加载 Google 提供的预训练 Word2Vec 模型,获取单词的向量表示,并执行一些基本的向量操作。
使用 Java 操作 Embeddings
虽然 Java 在机器学习生态系统中不如 Python 流行,但它也有一些优秀的库,例如 Deeplearning4j(DL4J)。以下是一个加载并操作 Embeddings 的示例。
import org.deeplearning4j.models.embeddings.loader.WordVectorSerializer;
import org.deeplearning4j.models.embeddings.wordvectors.WordVectors;
import java.io.File;
import java.util.Collection;
public class EmbeddingExample {
public static void main(String[] args) throws Exception {
// 加载预训练的 Word2Vec 模型
WordVectors wordVectors = WordVectorSerializer.readWord2VecModel(new File("path/to/GoogleNews-vectors-negative300.bin"));
// 获取单词的 Embedding
String word = "king";
double[] embedding = wordVectors.getWordVector(word);
System.out.println("Embedding of `" + word + "`: " + java.util.Arrays.toString(embedding));
// 计算两个单词的相似度
double similarity = wordVectors.similarity("king", "queen");
System.out.println("Similarity between `king` and `queen`: " + similarity);
// 寻找与某单词最相似的单词
Collection<String> similarWords = wordVectors.wordsNearest("king", 5);
System.out.println("Words similar to `king`: " + similarWords);
}
}
在上述代码中,使用 DL4J 加载 Word2Vec 模型,并计算单词间的相似性。
使用 Node.js 操作 Embeddings
在 Node.js 环境中,虽然机器学习工具相对较少,但可以借助 @tensorflow/tfjs
或类似库实现 Embeddings 操作。以下是一个基于 TensorFlow.js 的示例。
const tf = require('@tensorflow/tfjs-node');
const fs = require('fs');
async function loadEmbeddings(filePath) {
const data = fs.readFileSync(filePath, 'utf8');
const lines = data.split('\n');
const embeddings = {};
lines.forEach(line => {
const parts = line.split(' ');
const word = parts[0];
const vector = parts.slice(1).map(Number);
embeddings[word] = vector;
});
return embeddings;
}
(async () => {
const embeddings = await loadEmbeddings('path/to/embeddings.txt');
const word = 'king';
const embedding = embeddings[word];
console.log(`Embedding of \`${word}\`:`, embedding.slice(0, 10));
// 手动计算余弦相似度
const cosineSimilarity = (vec1, vec2) => {
const dotProduct = vec1.reduce((sum, v, i) => sum + v * vec2[i], 0);
const norm1 = Math.sqrt(vec1.reduce((sum, v) => sum + v * v, 0));
const norm2 = Math.sqrt(vec2.reduce((sum, v) => sum + v * v, 0));
return dotProduct / (norm1 * norm2);
};
const queen = embeddings['queen'];
const similarity = cosineSimilarity(embedding, queen);
console.log(`Similarity between \`king\` and \`queen\`:`, similarity);
})();
该示例展示了如何使用 Node.js 加载 Embeddings 并计算单词间的余弦相似度。
真实案例分析:推荐系统中的应用
假设我们构建一个音乐推荐系统,其中每首歌曲都被表示为一个 Embedding。用户的听歌历史可以用这些 Embeddings 的平均值表示。通过计算用户向量与歌曲向量的相似度,我们可以推荐最匹配用户兴趣的歌曲。
Python 实现
import numpy as np
# 假设每首歌的 Embedding
song_embeddings = {
'song1': np.array([0.1, 0.2, 0.3]),
'song2': np.array([0.4, 0.5, 0.6]),
'song3': np.array([0.7, 0.8, 0.9]),
}
# 用户听歌历史
user_history = ['song1', 'song2']
# 计算用户向量
user_vector = np.mean([song_embeddings[song] for song in user_history], axis=0)
# 推荐
recommendations = {}
for song, embedding in song_embeddings.items():
similarity = np.dot(user_vector, embedding) / (np.linalg.norm(user_vector) * np.linalg.norm(embedding))
recommendations[song] = similarity
# 排序
sorted_recommendations = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
print("推荐歌曲:", sorted_recommendations)
此代码通过 Embeddings 和余弦相似度,为用户推荐个性化歌曲。