机器学习模型,包括我们将关注的神经网络,对数字而不是原始文本或抽象时间点进行运算。正如我们所讨论的,序列数据在其顺序和结构中包含意义。因此,难题在于将这些序列转换为模型可以处理的数字格式,同时尽可能保留其固有的序列信息。这个过程是构建序列模型的基本步骤。让我们查看将不同类型序列数据进行数字表示的常用策略。文本数据表示文本也许是自然语言处理 (NLP) 中最常见的序列数据类型。句子是词语序列,文档是句子序列。以下是将文本转换为数字的主要方法:整数编码最直接的方法是将数据集中每个独特的词语(有时是字符)映射到一个特定的整数。分词(Tokenization):首先,文本被分解为单个单元,称为词元(token)。这些通常是词语,但也可能是子词或字符,具体取决于任务。例如,句子 “The cat sat.” 可能会被分词为 ["The", "cat", "sat", "."]。词表构建(Vocabulary Building):创建一个词表,它是训练数据中所有词元的唯一集合。每个独特的词元都被分配一个不同的整数索引。通常会添加特殊词元,例如用于未知词(在测试中遇到但训练中未见的词)的 <UNK> 和用于填充的 <PAD>(我们很快会讨论)。编码(Encoding):然后,每个词元序列被替换为相应的整数索引序列。例子: 假设我们的词表是:{"<PAD>": 0, "<UNK>": 1, "the": 2, "cat": 3, "sat": 4, "on": 5, "mat": 6, ".": 7} 句子 “The cat sat.” 将被编码为整数序列:[2, 3, 4, 7]。 像 “The dog sat.” 这样的句子(如果 “dog” 不在词表中)可能会变成:[2, 1, 4, 7]。这种方法简单高效,但有一个局限性:整数本身暗示了词语之间任意的顺序和大小关系(例如,“cat”(3)是否某种程度上“小于” “sat”(4)?)。这种关系在语言上并不存在,模型可能会根据这些任意的整数值错误地学习模式。独热编码为避免整数编码中隐含顺序的问题,可以使用独热编码。每个词元由一个向量表示,该向量的长度等于词表的大小。此向量除在词表中与该词元对应的索引处为“1”外,其余均为零。例子: 使用上述词表(大小为 8):“the”(索引 2)-> [0, 0, 1, 0, 0, 0, 0, 0]“cat”(索引 3)-> [0, 0, 0, 1, 0, 0, 0, 0]“sat”(索引 4)-> [0, 0, 0, 0, 1, 0, 0, 0]句子 “The cat sat.” 变成这些向量的序列: [[0,0,1,0,0,0,0,0], [0,0,0,1,0,0,0,0], [0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,1]]digraph G { rankdir=LR; node [shape=plaintext, fontsize=10]; edge [arrowhead=none]; vocab [label="词表:\n0: <PAD>\n1: <UNK>\n2: the\n3: cat\n4: sat\n..."]; the [label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#1c7ed6">1</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">...</TD></TR> </TABLE> >]; cat [label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#1c7ed6">1</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">...</TD></TR> </TABLE> >]; sat [label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#a5d8ff">0</TD></TR> <TR><TD BGCOLOR="#1c7ed6">1</TD></TR> <TR><TD BGCOLOR="#a5d8ff">...</TD></TR> </TABLE> >]; label_the [label="\"the\" (索引 2)"]; label_cat [label="\"cat\" (索引 3)"]; label_sat [label="\"sat\" (索引 4)"]; label_the -> the; label_cat -> cat; label_sat -> sat; }词元“the”、“cat”和“sat”的独热向量。每个向量在词元索引处为“1”,其他地方为“0”。独热编码解决了整数编码的排序问题,但它引入了两个新问题:高维度: 词表大小可能非常大(数万或数十万个词),导致输入向量极其庞大且稀疏。语义关系缺失: 像“cat”和“dog”,或“run”和“ran”这样相关词的向量,与“cat”和“airplane”这样不相关词的向量一样不同(正交)。它不展现任何相似性。嵌入层(预习)一种更高级且广泛使用的技术涉及嵌入层。这些层为每个词元学习密集、低维的向量(称为嵌入)。与独热向量不同,这些嵌入捕捉语义关系,意味着相似的词倾向于拥有相似的向量。我们不会在本章中实现嵌入,但知道它们作为克服整数和独热编码局限性的强大替代方案而存在是很重要的。我们将在第8章讨论数据准备流程时详细介绍它们。时间序列数据表示时间序列数据,例如股票价格、传感器读数或天气测量值,通常已经是数字形式。然而,通常仍需要一些预处理。直接使用和缩放如果您的时间序列在每个时间步包含单个测量值(单变量),例如每日收盘股价,您可以直接使用这些值。如果每个时间步有多个测量值(多变量),例如温度、湿度和压力,那么每个时间步将有一个数字向量。然而,就像在标准机器学习中一样,在将数值特征输入神经网络之前对其进行缩放通常是有益的。常用技术包括:归一化(Min-Max 缩放):将数据缩放到固定范围,通常是 [0, 1] 或 [-1, 1]。计算公式为: $$X_{scaled} = \frac{X - X_{min}}{X_{max} - X_{min}}$$标准化(Z-score 归一化):将数据缩放为零均值和单位方差。计算公式为: $$X_{scaled} = \frac{X - \mu}{\sigma}$$ 其中 $\mu$ 是特征的均值,$\sigma$ 是特征的标准差。缩放有助于梯度下降算法更快地收敛,并防止具有较大值的特征在学习过程中占据主导地位。窗口化循环神经网络(RNN)通常以监督学习的方式进行训练。对于时间序列预测,这通常涉及使用滑动窗口方法创建输入/输出对。您选择一个窗口大小(过去时间步的数量)作为输入特征,并定义您想预测多少未来时间步作为输出标签。例子: 考虑一个时间序列:[10, 12, 11, 13, 14, 15, 16, 18] 使用窗口大小为 3 来预测下一个单一步骤:输入:[10, 12, 11] -> 输出:13输入:[12, 11, 13] -> 输出:14输入:[11, 13, 14] -> 输出:15输入:[13, 14, 15] -> 输出:16输入:[14, 15, 16] -> 输出:18这将无监督的时间序列转换为适合训练序列模型的监督学习问题。统一序列长度:填充和掩码一个实际问题出现了,因为序列的长度自然不同(例如,句子的词语数量各异)。然而,神经网络通常要求输入具有固定大小,尤其是在为提高效率而批量处理时。填充(Padding):标准的解决方案是填充。较短的序列会用一个特殊的填充词元(通常在整数编码后用 0 表示)进行扩充,直到它们达到预定的最大长度(可以是批次中最长序列的长度或一个固定的超参数)。掩码(Masking):仅仅填充序列是不够的。模型需要知道这些填充值是人工的,并且在计算过程中(例如,计算损失或传播状态时)应该被忽略。掩码是深度学习框架使用的一种机制,用于表明哪些时间步对应于实际数据,哪些只是填充。例子: 最大长度 = 6。填充值 = 0。序列 A(长度 4):[2, 3, 4, 7] -> 填充后:[2, 3, 4, 7, 0, 0] -> 掩码:[1, 1, 1, 1, 0, 0]序列 B(长度 5):[2, 1, 4, 5, 7] -> 填充后:[2, 1, 4, 5, 7, 0] -> 掩码:[1, 1, 1, 1, 1, 0] (这里,掩码中的 1 表示实际词元,0 表示填充)。序列模型的输入数据形状一旦以数字形式表示并填充后,序列数据通常被组织成一个 3D 张量,以作为深度学习框架中 RNN 层的输入。维度通常遵循以下约定:(批量大小, 时间步, 特征)batch_size:在一次训练迭代中一起处理的序列数量。time_steps:序列的长度(填充后)。这是 RNN 进行迭代的维度。features:在每个时间步表示输入的特征数量。对于独热编码的文本,这是词表大小。对于由嵌入层处理的整数编码文本,这通常是 1(整数索引),嵌入层会将其扩展。对于单变量时间序列,这是 1。对于多变量时间序列,这是每个时间步的不同测量值的数量。理解这些数字表示和数据结构约定非常重要。它弥合了原始序列数据与循环神经网络内部执行的数学运算之间的差距。在确定了如何准备数据之后,我们现在可以开始研究专门为有效处理这些数字序列而设计的网络架构,从下一章的循环神经网络的基本思想开始。