dive into deep learning——数据操作&数据预处理

一、数据操作

  • 为了能够完成各种操作,我们需要某种方法来存储和操作数据。一般来说,我们需要做两件重要的事情:
    • 获取数据
    • 在数据读入计算机后对其进行处理。
  • 张量:表示一个数值组成的数组,这个数组可能有多个维度。具有一个轴的张量对应于数学上的向量。具有两个轴的张量对应于数学上的矩阵(matrix)/

1.1 入门

  • 首先我们需要导入torch。

  • 我们可以使用 arange 创建一个行向量 x。这个行向量包含以0开始的前12个整数,它们默认创建为浮点数。张量中的每个值都称为张量的 元素(element)。

  • 我们可以通过张量的 shape 属性来访问张量的 形状 (沿每个轴的长度)。

  • 如果我们只想知道张量中元素的总数,即形状的所有元素乘积,我们可以检查它的大小(size)。 因为这里在处理的是一个向量,所以它的 shape 与它的 size 相同。

  • 要改变一个张量的形状而不改变元素数量和元素值,我们可以调用 reshape 函数。 例如,我们可以把张量 x 从形状为 (12, ) 的行向量转换为形状 (3, 4) 的矩阵。这个新的张量包含与转换前相同的值,但是把它们看成一个三行四列的矩阵。要重点说明一下,虽然形状发生了改变,但元素值没有变。注意,通过改变张量的形状,张量的大小不会改变。

  • 不需要通过手动指定每个维度来改变形状。 如果我们的目标形状是 (高度, 宽度) ,那么在知道宽度后,高度应当会隐式得出,我们不必自己做除法。在上面的例子中,要获得一个有3行的矩阵,我们手动指定了它有3行和4列。幸运的是,张量在给出其他部分后可以自动计算出一个维度。我们可以通过将希望张量自动推断的维度放置 -1 来调用此功能。在上面的例子中,我们可以用 x.reshape(-1, 4) 或 x.reshape(3, -1)来取代x.reshape(3, 4)
  • 有时,我们希望使用全0、全1、其他常量或者从特定分布中随机采样的数字,来初始化矩阵。我们可以创建一个形状为 (2, 3, 4) 的张量,其中所有元素都设置为0。代码如下:

dive into deep learning——数据操作&数据预处理_第1张图片

  • 同样的,我们可以创建一个张量,其中所有元素都设置为1。代码如下:

dive into deep learning——数据操作&数据预处理_第2张图片

  • 有时我们想从某个概率分布中随机采样来得到张量中每个元素的值。例如,当我们构造数组来作为神经网络中的参数时,我们通常会随机初始化参数的值。以下代码创建一个形状为 (3, 4) 的张量。其中的每个元素都从均值为0、标准差为1的标准高斯(正态)分布中随机采样。

  • 我们还可以通过提供包含数值的 Python 列表(或嵌套列表)来为所需张量中的每个元素赋予确定值。在这里,最外层的列表对应于轴 0,内层的列表对应于轴 1。

1.2 运算

  • 对于任意具有相同形状的张量,常见的标准算术运算符(+-*/ 和 **)都可以被升级为按元素运算。我们可以在同一形状的任意两个张量上调用按元素操作。在下面的例子中,我们使用逗号来表示一个具有5个元素的元组,其中每个元素都是按元素操作的结果。

dive into deep learning——数据操作&数据预处理_第3张图片

  • 可以按按元素方式应用更多的计算,包括像求幂这样的一元运算符。

  • 可以把多个张量 连结(concatenate) 在一起,把它们端对端地叠起来形成一个更大的张量。 我们只需要提供张量列表,并给出沿哪个轴连结。下面的例子分别演示了当我们沿行(轴-0,形状的第一个元素)和按列(轴-1,形状的第二个元素)连结两个矩阵时会发生什么情况。我们可以看到,第一个输出张量的轴-0长度 (66) 是两个输入张量轴-0长度的总和 (3+33+3);第二个输出张量的轴-1长度 (88) 是两个输入张量轴-1长度的总和 (4+44+4)。

dive into deep learning——数据操作&数据预处理_第4张图片

  • 通过 逻辑运算符 构建二元张量。以 X == Y 为例子。 对于每个位置,如果 X 和 Y 在该位置相等,则新张量中相应项的值为1,这意味着逻辑语句 X == Y 在该位置处为真,否则该位置为 0。

  • 对张量中的所有元素进行求和会产生一个只有一个元素的张量。

1.3 广播机制

  • 在上面的部分中,我们看到了如何在相同形状的两个张量上执行按元素操作。在某些情况下,即使形状不同,我们仍然可以通过调用 广播机制 (broadcasting mechanism) 来执行按元素操作。这种机制的工作方式如下:首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状。其次,对生成的数组执行按元素操作。
  • 在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下例子:

dive into deep learning——数据操作&数据预处理_第5张图片

  • 由于 a 和 b 分别是 3×13×1 和 1×21×2 矩阵,如果我们让它们相加,它们的形状不匹配。我们将两个矩阵广播为一个更大的 3×2 矩阵,如下所示:矩阵 a将复制列,矩阵 b将复制行,然后再按元素相加。

1.4 切片索引

  • 就像在任何其他 Python 数组中一样,张量中的元素可以通过索引访问。与任何 Python 数组一样:第一个元素的索引是 0;可以指定范围以包含第一个元素和最后一个之前的元素。与标准 Python 列表一样,我们可以通过使用负索引根据元素到列表尾部的相对位置访问元素。
  • 我们可以用 [-1] 选择最后一个元素,可以用 [1:3] 选择第二个和第三个元素,如下所示:

  • 除读取外,我们还可以通过指定索引来将元素写入矩阵。

  • 如果我们想为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值。 例如,[0:2, :] 访问第1行和第2行,其中 “:” 代表沿轴 1(列)的所有元素。虽然我们讨论的是矩阵的索引,但这也适用于向量和超过2个维度的张量。

1.5 节省内存

  • 运行一些操作可能会导致为新结果分配内存。例如,如果我们用 Y = X + Y,我们将取消引用 Y 指向的张量,而是指向新分配的内存处的张量。
  • 在下面的例子中,我们用 Python 的 id() 函数演示了这一点,它给我们提供了内存中引用对象的确切地址。运行 Y = Y + X 后,我们会发现 id(Y) 指向另一个位置。这是因为 Python 首先计算 Y + X,为结果分配新的内存,然后使 Y 指向内存中的这个新位置。

  • 这可能是不可取的,原因有两个:首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新。其次,我们可能通过多个变量指向相同参数。如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。
  • 执行原地操作非常简单。我们可以使用切片表示法将操作的结果分配给先前分配的数组,例如 Y[:] = 。为了说明这一点,我们首先创建一个新的矩阵 Z,其形状与另一个 Y 相同,使用 zeros_like 来分配一个全00的块。

dive into deep learning——数据操作&数据预处理_第6张图片

  • 如果在后续计算中没有重复使用 X,我们也可以使用 X[:] = X + Y 或 X += Y 来减少操作的内存开销。

1.6 转换为其他Python对象

  • 转换为 NumPy 张量很容易,反之也很容易。转换后的结果不共享内存

  • 要将大小为1的张量转换为 Python 标量,我们可以调用 item 函数或 Python 的内置函数。

二、数据预处理

2.1 读取数据集

  • 我们首先创建一个人工数据集,并存储在csv(逗号分隔值)文件 ../data/house_tiny.csv 中。
  • 下面我们将数据集按行写入 csv 文件中。

dive into deep learning——数据操作&数据预处理_第7张图片

  • 要从创建的 csv 文件中加载原始数据集,我们导入 pandas 包并调用 read_csv 函数。该数据集有四行三列。其中每行描述了房间数量(“NumRooms”)、巷子类型(“Alley”)和房屋价格(“Price”)。

dive into deep learning——数据操作&数据预处理_第8张图片

2.2 处理缺失值

  • 注意,“NaN” 项代表缺失值。为了处理缺失的数据,典型的方法包括 插值 和 删除,其中插值用替代值代替缺失值。而删除则忽略缺失值。在这里,我们将考虑插值。
  • 通过位置索引iloc,我们将 data 分成 inputs 和 outputs,其中前者为 data的前两列,而后者为 data的最后一列。对于 inputs 中缺少的的数值,我们用同一列的均值替换 “NaN” 项。

dive into deep learning——数据操作&数据预处理_第9张图片

  • 对于 inputs 中的类别值或离散值,我们将 “NaN” 视为一个类别。由于 “巷子”(“Alley”)列只接受两种类型的类别值 “Pave” 和 “NaN”,pandas 可以自动将此列转换为两列 “Alley_Pave” 和 “Alley_nan”。巷子类型为 “Pave” 的行会将“Alley_Pave”的值设置为1,“Alley_nan”的值设置为0。缺少巷子类型的行会将“Alley_Pave”和“Alley_nan”分别设置为0和1。

dive into deep learning——数据操作&数据预处理_第10张图片

2.3 转换格式为张量格式

  • 现在 inputs 和 outputs 中的所有条目都是数值类型,它们可以转换为张量格式。当数据采用张量格式后,可以通过在前面引入的那些张量函数来进一步操作。

dive into deep learning——数据操作&数据预处理_第11张图片

 

你可能感兴趣的:(机器学习&深度学习)