使用Python学习深度学习,我无法理解以下简单的一批代码,它们将整数序列编码为二进制矩阵。
def vectorize_sequences(sequences, dimension=10000):
# Create an all-zero matrix of shape (len(sequences), dimension)
results = np.zeros((len(sequences), dimension))
for i, sequence in enumerate(sequences):
results[i, sequence] = 1. # set specific indices of results[i] to 1s
return results
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
x_train = vectorize_sequences(train_data)
x_train的输出类似于
x_train [0] 数组([0.,1.,1。,...,0.,0.,0。])
有人可以对x_train数组中存在的0.
有所了解,而在每次下一次1.
次迭代中只有i
个附加吗?
我的意思是不应该全是1?
答案 0 :(得分:3)
该脚本将数据集转换为二进制向量空间模型。让我们一个一个地解决问题。
首先,如果我们检查x_train
内容,我们会看到每个评论都表示为一系列单词ID。每个单词id对应一个特定单词:
print(train_data[0]) # print the first review
[1, 14, 22, 16, 43, 530, 973, ..., 5345, 19, 178, 32]
现在,这对网络来说非常困难。评论的长度各不相同,任何整数之间的小数值都没有意义(例如,如果在输出上我们得到43.5,那是什么意思?)
所以我们能做的就是在你的例子中创建一个单一的looong向量,整个字典的大小dictionary=10000
。然后,我们将该向量的每个元素/索引与一个单词/ word_id相关联。因此,由单词id 14表示的单词现在将由该向量的第14个元素表示。
每个元素将为0(评论中不存在单词)或1(评论中存在单词)。我们可以将其视为一个概率,因此我们甚至对0到1之间的值有意义。此外,每个评论现在都由这个非常长的(稀疏)向量表示,该向量具有恒定的长度每次审核。
所以在较小的范围内如果:
word word_id
I -> 0
you -> 1
he -> 2
be -> 3
eat -> 4
happy -> 5
sad -> 6
banana -> 7
a -> 8
然后将以下列方式处理句子。
I be happy -> [0,3,5] -> [1,0,0,1,0,1,0,0,0]
I eat a banana. -> [0,4,8,7] -> [1,0,0,0,1,0,0,1,1]
现在我强调了稀疏这个词。这意味着,与之相比,会有更多的零。我们可以利用这一点。而不是检查每个单词,是否包含在评论中;我们将检查一个实质上较小的列表,仅列出我们的评论中出现的那些词。
因此,我们可以为我们提供便利,并通过reviews × vocabulary
立即创建np.zeros((len(sequences), dimension))
零矩阵。然后只需浏览每篇评论中的文字,并将指标翻到1.0
与该字词对应的位置:
result[review_id][word_id] = 1.0
因此,我们只执行25000 x 10000 = 250 000 000
而不是number of words = 5 967 841
次操作。这仅仅是原始操作量的2.5%。
答案 1 :(得分:2)
这里的for循环不处理所有矩阵。如您所见,它枚举序列的元素,因此它仅在一个维度上循环。 我们举一个简单的例子:
t = np.array([1,2,3,4,5,6,7,8,9])
r = np.zeros((len(t), 10))
输出
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
然后我们以与您相同的方式修改元素:
for i, s in enumerate(t):
r[i,s] = 1.
array([[0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
你可以看到for循环只修改了一组具有索引[i,s]的元素(len(t))(在这种情况下;(0,1),(1,2),(2, 3),等等))