为了能用深度学习来解决现实世界的问题,我们经常从预处理原始数据开始,而不是从那些准备好的张量格式数据开始。在 Python 中常用的数据分析工具中,我们通常使用 pandas 软件包。像庞大的 Python 生态系统中的许多其他扩展包一样,pandas 可以与张量兼容。本节我们将简要介绍使用 pandas 预处理原始数据,并将原始数据转换为张量格式的步骤。

创建数据集

创建一个 .csv 文件作为数据集。

1
2
3
4
5
6
7
8
9
import os
os.makedirs(os.path.join('..', 'VsCode', 'Python', 'DeepLearning', 'data'), exist_ok=True)
data_file = os.path.join('..', 'VsCode', 'Python', 'DeepLearning', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n') # 列名
f.write('NA,Pave,127500\n') # 每行表示一个数据样本
f.write('2,NA,106000\n')
f.write('4,NA,178100\n')
f.write('NA,NA,140000\n')

上述代码在 ../VsCode/Python/DeepLearning/ 目录下创建了一个 /data 文件夹,并在 /data 下创建了文件 house_tiny.csv

读取 csv 文件

1
2
import pandas as pd
data = pd.read_csv(data_file)

data 表格表示如下:

index NumRooms Alley Price
0 NaN Pave 127500
1 2.0 NaN 106000
2 4.0 NaN 178100
3 NaN NaN 140000

缺失数据处理

上面的表格中 NaN 为缺失的数据,我们要对这些数据进行差值操作。

利用 pandas.iloc 方法索引数据

pands.iloc 方法提供了一些 api 来索引数据:

  • pandas.iloc[:a]a 行;
  • pandas.iloc[a:b]a 行到第 b - 1 行;
  • pandas.iloc[:, a:b]a 列到第 b - 1 列;
  • pandas.iloc[a]a 行。

因此可以通过下面代码将 data 分成前两列和最后一列。

1
inputes, outputes = pd.iloc[:, :2], pd.iloc[:, 2]

利用 pandas.fillna 方法插值

pandas.fillna 会将数据集中非数值的部分 NaN 按照一定方法填入数据。这里我们用 main() 函数填入平均值。

1
inputs = inputs.fillna(inputs.mean(numeric_only=True))

上面的 numeric_omly 表示只对数值数据做平均,如果没有这一条可能会报错 can only concatenate str (not "int") to str

处理完之后的 inputesoutputes 分别为:

index NumRooms Alley
0 3.0 Pave
1 2.0 NaN
2 4.0 NaN
3 3.0 NaN
index Price
0 127500
1 106000
2 178100
3 140000

利用 get_dummies 将类别值转换为数值

inputes 中的类 Alley 接受两种类别值:PaveNaN,我们可以利用 get_dummies 方法将类别值识区分为两种状态 TrueFalse。在后面的张量转换中,这两个状态可以直接被识别为数值 01

1
inputs = pd.get_dummies(inputs, dummy_na=True)

由此得到数据集 inputes 如下。

index NumRooms Alley_Pave Alley_nan
0 3.0 True False
1 2.0 False True
2 4.0 False True
3 3.0 False True

将数据转化为张量

现在 inputsoutputs 中的所有条目都是数值类型,它们可以转换为张量格式。

1
2
3
4
5
import torch
X = torch.tensor(inputs.to_numpy(dtype=float))
y = torch.tensor(outputs.to_numpy(dtype=float))
print(X)
print(y)
1
2
3
4
5
tensor([[3., 1., 0.],
[2., 0., 1.],
[4., 0., 1.],
[3., 0., 1.]], dtype=torch.float64)
tensor([127500., 106000., 178100., 140000.], dtype=torch.float64)

练习

创建包含更多行和列的原始数据集。

  • 删除缺失值最多的列。
  • 将预处理后的数据集转换为张量格式。

创建包含更多行和列的原始数据集

1
2
3
4
5
6
7
8
import numpy as np
import pandas as pd
practice_data = pd.DataFrame(
[[np.nan , 2, np.nan, 0],
[3, 4, np.nan, 1],
[np.nan, np.nan, np.nan, 5],
[np.nan, 3, np.nan, 4]],
columns=list('ABCD'))

表示为表格为:

index A B C D
0 NaN 2 NaN 0
1 3 4 NaN 1
2 NaN NaN NaN 5
3 NaN 3 NaN 4

删除失值最多的列

调用 .isna 方法获取失值数量。

1
NaNnum = practice_data.isna().sum(axis=0)

上述表明沿着 axis = 0 的方向进行求和,在本例中即

其中 NaNnum 的类型是 Series。因此可以利用 pandas 中的 max 函数得到其中的最大值。

1
max = NaNnum.max()

接下来遍历 NaNnum 找到最大值 max 对应的列索引 index

1
2
3
for index in range(0,5):
if max == NaNnum[index]:
break

再利用 pandas 中的 columns 方法找到列索引并利用 drop 方法删除该列。

1
result_data = practice_data.drop(practice_data.columns[index], axis = 1)

这里的 axis = 1 表示的是索引排列的方向。

得到结果:

index A B D
0 NaN 2.0 0
1 3.0 4.0 1
2 NaN NaN 5
3 NaN 3.0 4

将预处理后的数据集转换为张量格式

首先对数据进行插值操作。

1
Filled_result_data = result_data.fillna(result_data.mean(axis = 0, numeric_only=True))

现在我们就可以将所有值都是数值的数据转换成张量。

1
data_t = torch.tensor(Filld_result_data.to_numpy(dtype = float))

得到结果:

1
2
3
4
tensor([[3., 2., 0.],
[3., 4., 1.],
[3., 3., 5.],
[3., 3., 4.]], dtype=torch.float64)