向量化序列说明

Sta*_*fas 3 python python-3.x deep-learning keras

使用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)
Run Code Online (Sandbox Code Playgroud)

x_train的输出类似于

x_train [0]数组([0.,1.,1。,...,0.,0.,0。])

有人可以0.在x_train数组中稍微介绍一下的存在,而1.在每次下i一次迭代中仅追加时吗?我的意思是不应该全1吗?

mou*_*lem 6

这里的 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.]])
Run Code Online (Sandbox Code Playgroud)

然后我们以与您相同的方式修改元素:

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.]])
Run Code Online (Sandbox Code Playgroud)

您可以看到 for 循环仅修改了一组具有索引 [i,s] 的元素 (len(t))(在本例中为 ; (0, 1), (1, 2), (2, 3),等等))


Aec*_*lys 6

该脚本将您的数据集转换为二进制向量空间模型。让我们一一剖析。

首先,如果我们检查x_train内容,我们会看到每个评论都由一个单词ID序列表示。每个单词ID对应一个特定单词:

print(train_data[0])  # print the first review
[1, 14, 22, 16, 43, 530, 973, ..., 5345, 19, 178, 32]
Run Code Online (Sandbox Code Playgroud)

现在,要养活网络将非常困难。评论的长度各不相同,任何整数之间的分数值都没有意义(例如,如果在输出中得到43.5,那是什么意思?)

因此,我们可以做的就是dictionary=10000在您的示例中创建一个单一的looong向量,即整个字典的大小。然后,我们将将此向量的每个元素/索引与一个word / 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
Run Code Online (Sandbox Code Playgroud)

然后将按照以下方式处理这些句子。

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]
Run Code Online (Sandbox Code Playgroud)

现在我突出显示稀疏一词。这意味着,与1相比,将有很多零。我们可以利用这一点。而不是检查每个单词,无论它是否包含在评论中;我们将只检查那些确实出现在我们评论中的单词的列表,该列表要小得多。

因此,我们可以使事情变得容易,并立即创建reviews × vocabulary零矩阵np.zeros((len(sequences), dimension))。然后只需在每个评论中浏览单词并将指示符翻转到1.0与该单词对应的位置即可:

result[review_id][word_id] = 1.0
Run Code Online (Sandbox Code Playgroud)

因此25000 x 10000 = 250 000 000,我们只做而不是进行操作number of words = 5 967 841。这只是原始操作量的〜2.5%。