【小白笔记】关于 Python 类、初始化以及 PyTorch 数据处理的问题
1. def __init__(self, k=3):
这个 __init__
是所有的 class
都可以用吗?
是的,__init__
是 Python 中一个特殊的方法,被称为构造函数(Constructor)。
- 用途: 它是创建类的新实例(对象)时自动调用的方法。它的主要作用是初始化新创建对象的属性。
- 并非强制: 所有的
class
都可以定义__init__
,但并非必须。如果一个类没有定义__init__
,Python 会默认提供一个空的构造函数。 - 记忆点: 只要你想在创建对象时设置它的初始状态(比如这里的 KKK 值),就应该定义
__init__
。
2. 为什么 self.X_train = None
初始化使用的是 None
,不是 []
? None
初始化是一个表格吗?
None
在 Python 中有非常特殊的含义,它不是表格,也不是空列表。
-
None
的含义:None
是 Python 语言中一个特殊的常量,表示空值(Null Value)或缺失值。- 它表示缺少值,表示该变量没有指向任何对象。
-
为什么使用
None
:- 在
__init__
中,我们知道X_train
将在稍后的fit
方法中被赋值为 PyTorch 张量。在初始化阶段,我们还没有数据,所以用None
表示该属性目前还没有值。 - 如果初始化为
[]
(空列表),那么这个属性的类型就是list
。后续代码可能需要检查类型或者处理类型转换的逻辑会变得复杂。用None
表示一个尚未被赋值的占位符,是一种更清晰和通用的做法。
- 在
-
数据结构与初始化对比:
数据结构/值 Python 表示 含义 无值/缺失值 None
缺少值(占位符) 空列表 []
或list()
有值的(列表)集合,但集合内无元素 空数值 0
数值 0 空字典 {}
或dict()
有值的(字典)集合,但集合内无键值对
3. self.X_train
这里的 self
是什么含义,为什么我经常看到有的类就会括号写 self
?
self
是 Python 类方法中一个约定俗成的特殊参数,它代表实例自身(The instance itself)。
-
self
的含义:self
永远是类方法的第一个参数。- 当你创建一个对象(例如
knn_torch = KNearestNeighborsClassifierTorch(k=3)
)时,PyTorch 会在调用方法时自动把这个新创建的对象(即knn_torch
本身)作为self
参数传递进去。
-
用途:
self.X_train
:这表示访问或创建一个属于当前对象实例的属性X_train
。这样,不同的KNN
对象可以存储它们各自的训练数据。def __init__(self, k=3):
:括号中的self
只是一个占位符,表示这个方法是作用于对象自身的。你在实际调用时(比如KNearestNeighborsClassifierTorch(k=3)
)不需要显式传入它。
-
记忆点:
self
就是对象自己。方法内部要操作对象自己的属性时,必须用self.属性名
。
4. self.X_train
这个命名是本身库里面的还是我自己创建的?
这个命名是您自己创建的。
self.
后面的任何名称(例如X_train
,k
,device
)都是由程序员(也就是您)在类定义时自由命名的。- Python 或 PyTorch 库不会强制您必须使用
X_train
这个名称。您可以使用self.training_features
或self.data_x
等任何合法名称,只要您在类内部保持一致即可。 - 约定俗成: 命名为
X_train
只是遵循了数据科学和机器学习社区的惯例,即X
代表特征,train
代表训练集。
5. isinstance
是啥意思?
-
英文词源和解释:
- isinstance 是 Python 的一个内置函数,由 is 和 instance 组成。
- Instance (实例):源自拉丁语 instantia(存在,状态)。在这里指一个对象是某个类(或类型)的实例。
- 解释:
isinstance(object, classinfo)
用于检查一个对象object
是否是指定类型classinfo
的一个实例。
-
在代码中的作用:
if isinstance(X_train, np.ndarray):X_train = torch.from_numpy(X_train).float()
- 作用: 检查输入参数
X_train
是否是 NumPy 的数组 (np.ndarray
)。 - 目的: 如果是 NumPy 数组,则执行转换步骤 (
torch.from_numpy()
),确保后续的 PyTorch 代码可以顺利运行。这增强了代码的兼容性。
- 作用: 检查输入参数
6. from_numpy().float():
转换为特征张量。特征张量我记得是一群矩阵连在一起?只能 float
?可以 from_numpy().int():
吗?
这是一个关于 PyTorch 张量类型的关键问题。
A. 特征张量(Feature Tensor)
- 定义: 在 PyTorch 中,张量(Tensor)是核心数据结构,它是一个多维数组。特征张量就是存储你的输入特征数据(例如鸢尾花的四个测量值)的多维数组。
- “一群矩阵连在一起”: 您的理解是正确的,一个 N×MN \times MN×M 的特征张量可以看作是 NNN 个特征向量(样本)堆叠在一起。
B. 为什么特征数据通常是 float
?
float()
/torch.float32
(默认): 用于存储连续的、实数值数据。- 原因: 机器学习中的特征(如身高、温度、距离等)通常是连续的浮点数。
- 核心原因: 深度学习和梯度下降算法需要进行求导和高精度运算。在 PyTorch 中,只有浮点类型的张量才会被默认跟踪梯度并参与自动求导(Autograd)。即使对于 KNN 这种无需训练的算法,特征数据也通常保持为浮点数,以确保距离计算(涉及减法、平方、开方)的精度。
C. 可以使用 from_numpy().int()
/ torch.int
吗?
- 可以,但仅用于特定数据。
int()
/torch.int32
或long()
/torch.int64
用于存储离散的、整数值数据。- 常见用途: 标签(Label)(如类别 0, 1, 2)、索引(Index)、或者计数(Count)。
- 代码中的例子:
KNN 代码中,# 标签数据使用 long (64位整数) y_train = torch.from_numpy(y_train).long()
y_train
(类别标签)就是使用long()
进行转换的。特征数据 (X_train
) 应该使用float()
,而标签数据 (y_train
) 应该使用long()
。