一、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/zh-tw/n/257224.html
微信掃一掃
支付寶掃一掃