2.2 数据预处理

1. DataFrame 的数据类型与基本操作

Pandas 的 DataFrame 是一个表格型的数据结构,你可以把它想象成 Excel 表格。每一列(Series)都有自己的数据类型。

常见的 DataFrame 数据类型 (Dtypes)

Pandas 的底层大多基于 NumPy,所以类型很像,但也有扩展:

Pandas 中,转换类型的唯一通用标准方法.astype()。可以通过.astype()方法把某一列的数据类型转换

类型名称描述示例
object最常见。通常代表字符串 (str) 或 混合类型(数字+字符串)。"Hello", "Pave"
int6464位整数。1, 100, -5
float6464位浮点数。1.0, 3.14, NaN (空值通常算浮点)
bool布尔值。True, False
datetime64日期时间。2023-01-01
category类别型。省内存,用于有限的选项。["A", "B", "A"]
基本操作

假设你有一个 DataFrame df

A. 查看数据类型

# 查看每一列的类型
print(df.dtypes) 

# 查看详细信息(包括内存占用、非空数量等)
print(df.info())

B. 按类型选择列 (select_dtypes)

这个方法非常实用,比如“我只想把所有的数字列拿出来做标准化”:

# 只选数字类型的列 (整数和浮点数)
df_num = df.select_dtypes(include=['number'])

# 排除对象类型(字符串)的列
df_no_str = df.select_dtypes(exclude=['object'])

2. 课本中的例子详解

import os
import pandas as pd
import torch

# 新建一个csv数据文件
os.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
print(type(data_file)) # <class 'str'>
# print(type(type(data_file))) <class 'type'> 顺带一提, 这个type的返回的type是type
print(data_file) 
# 发现os.path.join返回的就是字符串格式的'../data/house_tiny.csv' 把这个改成下面的代码完全正确
# 之所以使用os.path.join为了 跨平台兼容性 和 健壮性。
# data_file = '../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')

# 读取刚刚新建的数据文件
data = pd.read_csv(data_file)
# read_csv()方法默认有表头, 如果数据无表头的话, 需要加上pd.read_csv(data_file, header=None)
# 读取出来的结果是DataFrame的数据类型
print(type(data)) # <class 'pandas.core.frame.DataFrame'>
print(data.info())
print(data.dtypes)
print(data)

# 把数据文件分为inputs和outputs两个列表, 并且把inputs使用均值进行插值计算
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
# DataFrame
print(inputs)
# inputs = inputs.fillna(inputs.mean()) 旧版本会报错
inputs = inputs.fillna(inputs.mean(numeric_only=True))
print(inputs)

# 把inputs的1维的列分类
inputs = pd.get_dummies(inputs, dummy_na=True).astype(float)
print(inputs)

# 把输入输出转换为tensor
print(inputs.values)
print(inputs.values.dtype)
print(outputs.values)
print(outputs.values.dtype)
x, y = torch.tensor(inputs.values).float(), torch.tensor(outputs.values).float()
print(x)
print(y)

2.3 线性代数

总表放到这里

函数参数1要求参数2要求数学运算
torch.dot(x, y)向量 (1D)向量 (1D)点积 (内积)
torch.mv(A, x)矩阵 (2D)向量 (1D)矩阵 ×\times× 向量
torch.mm(A, B)矩阵 (2D)矩阵 (2D)矩阵 ×\times× 矩阵
@ (或 matmul)任意任意智能判断,通吃

降维操作 sum()和mean()

这个按不同的维度sum和mean还有小坑,之所以称之为是降维操作, 原来是2维, 降低为了1维, 所以想要实现按行归一化和按列归一化, 要多一步操作

import torch

# 使用tensor.mean()操作的时候必须保证数据类型是float, 不管多少位, 是浮点数就行
x = torch.arange(20, dtype=torch.float).reshape(5, 4)

print(x.sum())
print(x)
print(x.sum(dim=0).shape)
print(x.sum(dim=0))  # 输出的维度是(4) dim是多少就把这一个维度给降了
print(x.sum(dim=1).shape)
print(x.sum(dim=1))  # 输出的维度是(5)
# 如果我想要实现按列归一化, 每个数字除以每一列的总和 应该是如下: 因为有广播机制
print(x / x.sum(dim=0))
# 如果我想要实现按行归一化, 每个数字除以每一行的总和 应该是如下操作:
print(x / x.sum(dim=1, keepdim=True)
print(x / x.sum(dim=1).view(5, 1))
print(x / x.sum(dim=1).unsqueeze(1))

print(x.mean())
print(x.mean(dim=1))
print(x.mean(dim=0))
print(x.sum(dim=0, keepdim=True)) # 
print(x.sum(dim=0, keepdim=True).shape) # torch.Size([1, 4])
print(x.sum(dim=0).shape) # torch.Size([4])

点积 torch.dot()

torch.dot()是一定只能使用在两个向量之间的, 并且数据类型一定要一样

物理意义: 可以求加权, 也可以用作单位向量之间的夹角的余弦

@torch.matmul是完全一样的运算, 可以用在任何可以相乘的俩张量之间, 但是要求数据类型是一样的

import torch

x = torch.arange(4, dtype=torch.float)
print(x.dtype)
y = torch.ones(4)
print(y.dtype)
print(torch.dot(x, y))
print(x @ y) # 结果是完全一样的
print(torch.matmul(A, x)) # 结果也是完全一样的

矩阵-向量积 torch.mv(A, x)

torch.mv(A, x)这也是必须使用在矩阵和向量之间, 并且矩阵在前向量在后, 并且数据类型也一定要一样

并且同样可以被@torch.matmul替换

import torch

A = torch.arange(4).view(2, 2)
print(A.dtype)
x = torch.arange(2)
print(x.dtype)
print(torch.mv(A, x))
print(A @ x)
print(torch.matmul(A, x))

范数

torch.norm已经是老版本废弃了, 现在推荐使用 torch.linalg.norm默认的是F范数

对于 torch.linalg.norm(x, ord=2) 输出的是谱范数 (Spectral Norm), 也就是矩阵的最大的奇异值

操作旧版写法 (torch.norm)新版推荐写法 (torch.linalg.norm)备注
向量 L2 范数torch.norm(x, p=2)torch.linalg.norm(x, ord=2)最常用的模长
向量 L1 范数torch.norm(x, p=1)torch.linalg.norm(x, ord=1)绝对值之和
矩阵 Frobeniustorch.norm(A)torch.linalg.norm(A, ord='fro')矩阵默认范数
矩阵核范数很难写torch.linalg.norm(A, ord='nuc')奇异值之和

更多推荐