动手学深度学习笔记-第二章数据预处理与线性代数
·
2.2 数据预处理
1. DataFrame 的数据类型与基本操作
Pandas 的 DataFrame 是一个表格型的数据结构,你可以把它想象成 Excel 表格。每一列(Series)都有自己的数据类型。
常见的 DataFrame 数据类型 (Dtypes)
Pandas 的底层大多基于 NumPy,所以类型很像,但也有扩展:
在 Pandas 中,转换类型的唯一通用标准方法是 .astype()。可以通过.astype()方法把某一列的数据类型转换
| 类型名称 | 描述 | 示例 |
|---|---|---|
| object | 最常见。通常代表字符串 (str) 或 混合类型(数字+字符串)。 | "Hello", "Pave" |
| int64 | 64位整数。 | 1, 100, -5 |
| float64 | 64位浮点数。 | 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) | 绝对值之和 |
| 矩阵 Frobenius | torch.norm(A) | torch.linalg.norm(A, ord='fro') | 矩阵默认范数 |
| 矩阵核范数 | 很难写 | torch.linalg.norm(A, ord='nuc') | 奇异值之和 |
更多推荐
所有评论(0)