跳到主要内容

PyTorch 数据预处理

数据预处理

为了能用深度学习来解决现实世界的问题,我们经常从预处理原始数据开始, 而不是从那些准备好的张量格式数据开始。 在 Python 中常用的数据分析工具中,我们通常使用 pandas 软件包。

Pandas 是什么?

Pandas 是一个Python编程语言的开源数据分析和数据处理库。它提供了高效、灵活的数据结构,使用户能够轻松地操作和分析结构化数据。Pandas 主要关注于两种核心数据结构:SeriesDataFrame

  • SeriesSeries 是一维标签化的数组,类似于带有标签索引的列表。每个元素可以是任何数据类型。Series 可以用于处理时间序列数据、数值数据等。
  • DataFrameDataFrame 是二维表格数据结构,类似于电子表格或SQL数据库表。它由多个行和列组成,每列可以包含不同的数据类型。DataFrame 用于处理结构化的表格型数据,可以进行各种数据操作和分析。

Pandas 提供了丰富的数据操作和处理功能,包括:

  • 数据加载和存储:从各种格式(如CSV、Excel、SQL数据库等)中加载数据,以及将数据保存为不同格式。
  • 数据清洗:处理缺失值、重复值和异常值。
  • 数据选择和索引:通过标签或位置进行数据选择和切片。
  • 数据转换:对数据进行重塑、合并、连接和分组等操作。
  • 数据分析:计算统计指标、绘制图表、执行聚合操作等。
  • 时间序列分析:支持处理日期和时间数据,进行时间序列分析。
  • 数据可视化:使用 Matplotlib 或其他库绘制各种图表。

Pandas 是数据科学和数据分析领域的重要工具,它提供了强大的数据操作和处理能力,使用户能够更轻松地处理和分析大规模数据。

Pandas 的常用方法

Pandas 数据切片(索引)

iloc 是 Pandas 中的一个方法,用于根据整数位置对 DataFrame 或 Series 进行索引和切片。它允许你通过行和列的整数索引来选择数据。

对于 DataFrame,iloc 方法可以接受两个整数索引或切片来指定需要选择的行和列。例如,df.iloc[1:3, 0:2] 会选择第 1 到第 2 行以及第 0 到第 1 列的数据。

对于 Series,iloc 方法只需要一个整数索引或切片,用于选择 Series 中的元素。

以下是一些示例说明 iloc 的用法:

import pandas as pd

# 创建示例 DataFrame
data = {'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8]}

df = pd.DataFrame(data)

# 使用 iloc 进行索引和切片
subset = df.iloc[1:3, 0:2] # 选择第 1 到第 2 行和第 0 到第 1 列的数据
column_data = df['A'].iloc[0:2] # 选择 'A' 列中的第 0 到第 1 个元素

print("Subset of DataFrame:")
print(subset)
print("Selected Data from 'A' Column:")
print(column_data)

在这个示例中,我们展示了如何在 DataFrame 和 Series 上使用 iloc 进行索引和切片操作。

读取数据集

下面将模拟的数据集按行写入 CSV 文件中

import os

os.makedirs(os.path.join('.', 'data'), exist_ok=True)
data_file = os.path.join('.', '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')

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

# 如果没有安装 pandas,只需取消对以下行的注释来安装 pandas
# !pip install pandas
import pandas as pd

data = pd.read_csv(data_file)
print(data)

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

处理缺失的数据

可以看到上面包含了部分 “NaN” 项,这个 “NaN”项代表缺失值。

在 Pandas 中,处理缺失数据是数据清洗的一个重要步骤。缺失数据可能会影响分析和模型的准确性,因此需要采取适当的方法来处理。以下是一些处理缺失数据的常见方法:

  1. 检测缺失值: 使用 isnull()notnull() 函数来检测 DataFrame 或 Series 中的缺失值。这些函数将返回布尔值,指示每个元素是否为缺失值。
import pandas as pd
data = {'A': [1, 2, None, 4],
'B': [5, None, 7, 8]}
df = pd.DataFrame(data)
# 检测缺失值
print(df.isnull())

A B 0 False False 1 False True 2 True False 3 False False

  1. 删除缺失值: 使用 dropna() 函数删除包含缺失值的行或列。可以通过设置 axis 参数来指定是删除行(axis=0)还是列(axis=1)。
# 删除包含缺失值的行
cleaned_df = df.dropna()
print("============df.dropna()============")
print(cleaned_df)

# 删除包含缺失值的列
cleaned_df = df.dropna(axis=1)
print("============df.dropna(axis=1)============")
print(cleaned_df)

============df.dropna()============ A B 0 1.0 5.0 3 4.0 8.0 ============df.dropna(axis=1)============ Empty DataFrame Columns: [] Index: [0, 1, 2, 3]

  1. 填充缺失值: 使用 fillna() 函数填充缺失值。你可以提供一个常数值、平均值、中位数等来填充缺失值。
# 使用常数填充缺失值
filled_df = df.fillna(0)
print(filled_df)

# 使用列的平均值填充缺失值
filled_df = df.fillna(df.mean())
print(filled_df)

A B 0 1.0 5.0 1 2.0 0.0 2 0.0 7.0 3 4.0 8.0 A B 0 1.000000 5.000000 1 2.000000 6.666667 2 2.333333 7.000000 3 4.000000 8.000000

  1. 插值填充: 使用 interpolate() 函数进行插值填充,以使用相邻值推断缺失值。这在处理时间序列数据时特别有用。
# 使用插值填充
interpolated_df = df.interpolate()
print(interpolated_df)

A B 0 1.0 5.0 1 2.0 6.0 2 3.0 7.0 3 4.0 8.0

  1. 设定缺失值标记: 在读取数据时,可以使用 na_values 参数指定输入文件中表示缺失值的特定标记。例如标记上面创建的数据集中 NANaN-1 为缺失值:
# 读取 CSV 文件时指定缺失值标记
df = pd.read_csv('data/house_tiny.csv', na_values=['NA', 'NaN', '-1'])
print(df)

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

这些方法可以根据情况选择,根据数据类型、分析任务以及数据缺失的程度来决定。处理缺失数据需要根据具体情况进行调整,以确保清洗后的数据适合进行后续分析和建模。

切割数据为输入输出

现在我想把输入的数据切割成输入和输出,例如下面的

NumRooms,Alley,Price
NA,Pave,127500
2,NA,106000
4,NA,178100
NA,NA,140000

前面的两行是输入,最后一行是输出,并且处理一下上面的缺失值

提示

Pandas 会自动读取第一行作为列名

df_example = pd.read_csv('Pandas_example_read.csv')
# 等同于:
df_example = pd.read_csv('Pandas_example_read.csv', header=0)

如果不想要第一行作为列名,可以设置 header=None

df_example = pd.read_csv('Pandas_example_read.csv', header=None)

下面是填充缺失值的方法

# 读取数据文件
data = pd.read_csv('data/house_tiny.csv', na_values=['NA'])

print("Original Data:")
print(data)

# 使用每列的均值来填充缺失值
# 2.0 版本,API 有一些细微的变化。
# 调用 inputs.mean() 的时候会出现字符串和数字不能拼接的错误是因为 NaN 是数字,‘Pave’ 是字符串。
# 解决方案:添加额外参数 inputs.mean(numeric_only=True),从而忽略对于字符串的处理。
data_filled = data.fillna(data.mean(numeric_only=True))

print("Missing Values Filled:")
print(data_filled)

# 划分输入和输出
inputs = data_filled.iloc[:-1, :-1] # 前三行是输入
outputs = data_filled.iloc[-1:, -1] # 最后一行是输出

print("Inputs with Missing Values Filled:")
print(inputs)
print("Outputs:")
print(outputs)

Original Data: NumRooms Alley Price 0 NaN Pave 127500 1 2.0 NaN 106000 2 4.0 NaN 178100 3 NaN NaN 140000 Missing Values Filled: NumRooms Alley Price 0 3.0 Pave 127500 1 2.0 NaN 106000 2 4.0 NaN 178100 3 3.0 NaN 140000 Inputs with Missing Values Filled: NumRooms Alley 0 3.0 Pave 1 2.0 NaN 2 4.0 NaN Outputs: 3 140000 Name: Price, dtype: int64

转换为张量格式

如果你想将 Pandas DataFrame 转换为 PyTorch 张量(Tensor)格式,你可以使用 torch.tensor() 函数将 DataFrame 的值转换为张量。在转换过程中,确保数据类型一致,以便能够有效地在 PyTorch 中进行计算。以下是一个将输入和输出数据转换为张量格式的示例:

import torch

# 选择只包含数值类型的列
numeric_columns = data_filled.select_dtypes(include=[float, int])

# 划分输入和输出
inputs = numeric_columns.iloc[:-1, :-1] # 前三行是输入
outputs = numeric_columns.iloc[-1:, -1] # 最后一行是输出

# 转换为 PyTorch 张量
inputs_tensor = torch.tensor(inputs.values, dtype=torch.float32)
outputs_tensor = torch.tensor(outputs.values, dtype=torch.float32)

print("Inputs as Tensors:")
print(inputs_tensor)
print("Outputs as Tensors:")
print(outputs_tensor)

Inputs as Tensors: tensor([[3.], [2.], [4.]]) Outputs as Tensors: tensor([140000.])