import sys,random,math
from collections import Counter
import numpy as np
np.random.seed(1)
random.seed(1)
f = open('reviews.txt')
raw_reviews = f.readlines()
f.close()
tokens = list(map(lambda x:(x.split(" ")),raw_reviews))
#wordcnt = Counter() 这行代码的作用是创建一个 Counter 对象,
# 并将其赋值给变量 wordcnt。Counter 是 Python 标准库 collections 模块中的一个类,
# 它是一种特殊的字典,用于对可哈希对象进行计数。
wordcnt = Counter()
for sent in tokens:
for word in sent:
wordcnt[word] -= 1
vocab = list(set(map(lambda x:x[0],wordcnt.most_common())))
#print(vocab)
word2index = {}
for i,word in enumerate(vocab):
word2index[word]=i
concatenated = list()
input_dataset = list()
for sent in tokens:
sent_indices = list()
for word in sent:
try:
sent_indices.append(word2index[word])
concatenated.append(word2index[word])
except:
""
input_dataset.append(sent_indices)
'''
concatenated = np.array(concatenated) 这行代码的主要功能是将 concatenated 对象转换为 NumPy 数组。
NumPy 是 Python 中用于科学计算的一个重要库,np.array() 是 NumPy 提供的一个函数,
它可以将多种类型的对象(如列表、元组等)转换为 NumPy 数组,以便进行高效的数值计算和操作。
'''
concatenated = np.array(concatenated)
'''
random.shuffle(input_dataset) 这行代码的主要功能是对 input_dataset 列表中的元素进行随机打乱顺序的操作。
random 是 Python 的标准库,shuffle 是 random 模块中的一个函数,它会直接修改传入的列表,使其元素顺序随机化。
'''
random.shuffle(input_dataset)
alpha, iterations = (0.05, 2)
hidden_size,window,negative = (50,2,5)
weights_0_1 = (np.random.rand(len(vocab),hidden_size) - 0.5) * 0.2
weights_1_2 = np.random.rand(len(vocab),hidden_size)*0
layer_2_target = np.zeros(negative+1)
layer_2_target[0] = 1
'''
下面的这个程序要表现的东西会很多,请大家慢慢听我描述
程序功能是:
这段 Python 代码定义了一个名为 similar 的函数,其主要目的是找出与给定目标单词(默认是 'beautiful')
在词向量空间中最相似的 10 个单词。它基于词向量之间的欧几里得距离来衡量单词间的相似度。
然后我们怎么找到词向量,然后什么又是欧几里得距离:
先说:词向量。我们都知道当我们对一个神经网络训练完成以后,我们就会得到一组权重。这组权重一般是如果输入层是n个值,隐藏层是m个点。
那么这个权重就是(n,m)的一个numpy矩阵。
对应的权重矩阵的第一行第一列就是我们说的第一个输入元素的词向量。
然后我们说一下什么是欧几里得距离,计算公式我知道:
raw_difference = weights_0_1[index] - (weights_0_1[target_index])
squared_difference = raw_difference * raw_difference
scores[word] = -math.sqrt(sum(squared_difference))
使用全部词的词向量值和 beautiful这个词的词向量值进行相减。
然后在把相减后的结果进行平方
然后再把所有的平方的数据相加然后求平方根。
然后
'''
def similar(target='beautiful'):
target_index = word2index[target]
scores = Counter()
'''
for word, index in word2index.items()::遍历 word2index 字典中的每个键值对,word 是单词,
index 是该单词在词向量矩阵中的索引。
'''
for word,index in word2index.items():
'''
raw_difference = weights_0_1[index] - (weights_0_1[target_index]):
计算当前单词的词向量与目标单词的词向量之间的差值。weights_0_1 是一个二维的 NumPy 数组,
存储着所有单词的词向量,每一行对应一个单词的词向量。
'''
raw_difference = weights_0_1[index] - (weights_0_1[target_index])
'''
squared_difference = raw_difference * raw_difference:对差值向量的每个元素进行平方操作。
'''
squared_difference = raw_difference * raw_difference
'''
scores[word] = -math.sqrt(sum(squared_difference)):计算平方和的平方根,得到欧几里得距离,
并取其负值作为相似度得分。之所以取负值,是因为 Counter 的 most_common 方法会返回得分最高的元素,
而我们希望距离最近(相似度最高)的单词排在前面。
'''
scores[word] = -math.sqrt(sum(squared_difference))
'''most_common(10) 方法会返回 scores 中得分最高的 10 个元素及其得分,
以列表形式呈现,列表中的每个元素是一个包含单词和得分的元组。
'''
return scores.most_common(10)
def sigmoid(x):
return 1/(1 + np.exp(-x))
#input_dataset = 1
#iterations = 1
for rev_i, review in enumerate(input_dataset * iterations):
#for rev_i, review in enumerate(1 * 1):
for target_i in range(len(review)):
#for target_i in range(1):
# since it's really expensive to predict every vocabulary
# we're only going to predict a random subset
target_samples = [review[target_i]] + list(concatenated \
[(np.random.rand(negative) * len(concatenated)).astype(
'int').tolist()])
print("target_samples")
print(target_samples)
left_context = review[max(0, target_i - window):target_i]
right_context = review[target_i + 1:min(len(review), target_i + window)]
layer_1 = np.mean(weights_0_1[left_context + right_context], axis=0)
layer_2 = sigmoid(layer_1.dot(weights_1_2[target_samples].T))
layer_2_delta = layer_2 - layer_2_target
layer_1_delta = layer_2_delta.dot(weights_1_2[target_samples])
weights_0_1[left_context + right_context] -= layer_1_delta * alpha
weights_1_2[target_samples] -= np.outer(layer_2_delta, layer_1) * alpha
if (rev_i % 250 == 0):
sys.stdout.write('\rProgress:' + str(rev_i / float(len(input_dataset)
* iterations)) + " " + str(similar('terrible')))
sys.stdout.write('\rProgress:' + str(rev_i / float(len(input_dataset)
* iterations)))
print(similar('terrible'))
#运行结果
'''
Progress:0.99998
[('terrible', -0.0), #可怕的
('horrible', -2.7898821106802045), #令人恐惧的
('brilliant', -3.470232426351145), #明亮的,恒成功的
('pathetic', -3.8372465135492355), #可怜的
('phenomenal', -3.928297271813787), #非凡的
('mediocre', -3.9289917580116294), #平庸的
('superb', -3.9764853704721492), #棒 极 了
('masterful', -4.022889507518986), #有驾驭能力的
('marvelous', -4.0699092654045375), #了不起的
('bad', -4.220448952264187)] #坏的
'''