一、Skip-gram简介
Skip-gram是一种NLP(自然语言处理)算法,用于将单词表示为向量并在文本数据上进行预测。此算法通常用于文本数据中句子中的单词的词嵌入处理上。Skip-gram算法和CBOW算法一样都是基于神经网络的模型,但运用了一些不同的技术。Skip-gram能够将单词表示为向量,并寻找同义词之间的关系。
Skip-gram算法的核心思想就是根据目标单词周围的上下文环境预测目标单词。在一段文本数据中,Skip-gram算法会将整段文本中的每一个单词都向量化,在这些向量之间应用高维几何学,使得语义上相关的单词在空间中距离越近或越相似。
二、Skip-gram的优点
1、Skip-gram算法可以通过逐渐迭代和优化来自我训练,从而不断提升单词之间的关联。
2、Skip-gram算法适合处理大规模文本,在工业界和学术界被广泛应用于文本处理和语音识别领域。
3、Skip-gram的训练效果比较好,当用于同义词的寻找或者句子的相似性计算时具有较高的精度和效率。
三、Skip-gram的训练流程
Skip-gram算法的训练流程通常包括以下几个步骤:
1、读入文本数据并对其进行预处理(如分词、去停用词等)。
2、将每个单词表示为向量,并为它们分配一个初始值向量。
# 设置初始向量
W = np.random.uniform(-0.8, 0.8, (vocab_size, vector_dim))
W = (W - np.mean(W)) / (np.std(W) * math.sqrt(vocab_size))
3、选取每个单词,并在其周围定义一个窗口(窗口大小通常在两个单词到十个单词之间)。然后根据目标单词周围的上下文环境预测目标单词。
for center_word in range(vocab_size):
# 选择上下文的单词窗口
context_word_indices = np.concatenate([np.arange(0, center_word), np.arange(center_word + 1, vocab_size)])
reduced_window = random.randint(0, window_size - 1)
window_indices = context_word_indices[
max(0, center_word - window_size + reduced_window):min(len(context_word_indices),
center_word + window_size + 1 - reduced_window)]
# 遍历上下文单词并更新
for context_word in window_indices:
z = np.dot(W[context_word], W[center_word])
p_w = sigmoid(z)
g = eta * (1 - p_w)
W[center_word] += g * W[context_word]
W[context_word] += g * W[center_word]
四、Skip-gram的应用
Skip-gram在跨语言自然语言处理、推荐算法、中文分词、情感分析等方面具有广泛应用。下面以中文分词为例,介绍Skip-gram的应用。
在中文分词中,Skip-gram能够通过学习上下文单词的词义,来对汉语中的复合单词进行更好的分词。通过将中文文本进行序列化,然后训练Skip-gram模型,在学习到的向量空间中通过聚类来得到每一个汉字的词向量,然后通过类似HMM(隐马尔可夫模型)的方式来对中文进行分词。
五、Skip-gram的代码实现
# 读入文本数据并预处理
with open('text.txt', 'r') as f:
text = f.read()
corpus = text.split()
# 分词
cut_corpus = []
for c in corpus:
seg_list = jieba.cut(c, cut_all=False)
temp = " ".join(seg_list)
cut_corpus.append(temp.split())
# 构建语料库
word2id = {}
id2word = {}
for word_list in cut_corpus:
for word in word_list:
if word not in word2id.keys():
wid = len(word2id)
word2id[word] = wid
id2word[wid] = word
# 训练Skip-gram算法
vector_dim = 100
window_size = 5
epochs = 50
eta = 0.1
vocab_size = len(word2id.keys())
# 设置初始向量
W = np.random.uniform(-0.8, 0.8, (vocab_size, vector_dim))
W = (W - np.mean(W)) / (np.std(W) * math.sqrt(vocab_size))
# 训练
for i in range(epochs):
np.random.shuffle(cut_corpus)
for word_list in cut_corpus:
for center_word_idx, center_word in enumerate(word_list):
# 选择上下文的单词窗口
context_word_indices = np.concatenate([np.arange(0, center_word_idx), np.arange(center_word_idx + 1, len(word_list))])
reduced_window = random.randint(0, window_size - 1)
window_indices = context_word_indices[
max(0, center_word_idx - window_size + reduced_window):min(len(context_word_indices),
center_word_idx + window_size + 1 - reduced_window)]
# 遍历上下文单词并更新
for context_word_idx in window_indices:
z = np.dot(W[context_word_idx], W[center_word_idx])
p_w = sigmoid(z)
g = eta * (1 - p_w)
W[center_word_idx] += g * W[context_word_idx]
W[context_word_idx] += g * W[center_word_idx]
# 保存词向量
with open('word_vectors.txt', 'w') as f:
f.write('%d %d\n' % (vocab_size, vector_dim))
for i in range(vocab_size):
f.write('%s %s\n' % (id2word[i], ' '.join(map(str, W[i]))))
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/257224.html
微信扫一扫
支付宝扫一扫