- 很多同学在深度学习入门时,面向对象编程不熟练,相关调用不好理解,所以这里详细介绍一下pytorch中的相关用法
- 这里只是举例说明,便于快速入门深度学习,具体面向对象编程还需自行细致学习
- 有不恰当处请指出
1. 一段简单的类实例化定义
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print(f"Hello, my name is {self.name} and I am {self.age} years old.")
# 创建一个 Person 类的实例对象
person = Person("Alice", 30)
# 调用实例对象的方法
person.say_hello()
1.1 实例解释
- 定义了一个名为 Person 的类,并在其 _ init_ 方法中初始化了 name 和 age 属性。
- _ init _: 这是一个特殊的方法名,表示构造方法。(它是一个特殊的函数,每当实例化该类的新对象时都会调用它,可以将其视为 initialize 方法,即对象初始化方法)
- self: 这是 _ init_ 方法必须设置的第一个参数,用于传递实例对象自身的引用。在方法中,可以通过 self 来访问实例的属性和调用其他方法。
- name 和 age: 这是 _ init_ 方法的两个参数。它们用于接收在创建类的实例对象时传入的参数。在这个例子中,name 和 age 分别用于初始化类的 name 属性和 age 属性。
- 然后创建 Person 类的实例对象 person 时,会调用 _ init_ 方法并传递 “Alice” 和 30 作为参数,从而初始化实例对象的 name 和 age 属性。
- 当创建 Person 类的实例对象 person 并调用 say_hello() 方法时,self 会自动指向 person 实例对象,因此方法中的属性访问会获取到正确的属性值。
- print中使用了Python 格式化字符串的方法 f-string。在字符串中的花括号 { } 内部,self.name 和 self.age 是实例对象的属性,它们会被求值并插入到字符串中的相应位置。
1.2 构造方法介绍
构造方法是面向对象编程中的一个特殊方法,它用于在创建类的实例对象时进行初始化操作。在 Python 中,构造方法的特殊名称是 _ init_。
构造方法通常用于初始化类的属性或执行其他必要的初始化操作。当创建类的实例对象时,Python 会自动调用构造方法,并将实例对象自身(通常用 self 表示)以及传入的参数作为参数传递给构造方法。
2. 深度学习常用 Model类的简单定义
import torch
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(Model, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.fc2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
2.1 网络结构
- 在这个简单的神经网络模型中,我们定义了一个名为 Model 的类,它继承自 nn.Module。该模型包含两个全连接层(线性层),一个隐藏层和一个输出层。
- 构造方法 _ init_ 接收三个参数:input_size、hidden_size 和 output_size,分别表示输入层的特征数、隐藏层的神经元数和输出层的特征数。
- 在前向传播方法 forward 中,我们使用 F.relu 函数对输入数据进行 ReLU 激活函数操作,并通过两个全连接层进行线性变换。其中,self.fc1 表示第一个全连接层,self.fc2 表示第二个全连接层。
2.2 super( ) 函数
-
调用方法:
super(子类, self).父类方法(参数)
-
该函数是 Python 中的一个内置函数,用于调用父类的方法。在面向对象编程中,子类可以继承父类的属性和方法,但有时候我们需要在子类中重写父类的方法,并在子类的方法中调用父类的方法。这时就可以使用 super() 函数来实现这个目的。
class Parent: def __init__(self, name): self.name = name class Child(Parent): def __init__(self, name, age): super().__init__(name) # 调用父类的构造方法 self.age = age child = Child("Alice", 30) print(child.name) # 输出: Alice print(child.age) # 输出: 30
在上面的代码中,我们定义了一个父类 Parent 和一个子类 Child。在子类的构造方法中,我们使用 super()._ init_(name) 调用父类的构造方法,从而初始化父类的属性 name,并在子类中添加额外的属性 age。通过这样的调用,我们保证了子类 Child 能够正确地继承父类 Parent 的属性和特性。
-
所以在model类的代码中,super(Model, self)._ init_() 是在子类 Model 的构造方法中调用父类 nn.Module 的构造方法。
-
在使用 super() 函数时,我们传递两个参数:子类的名称(Model)和 self。super(Model, self) 表示调用 Model 类的父类的构造方法。这样,我们在子类中定义的 _ init_() 方法就能继承父类 nn.Module 的构造方法,并确保模型类正确初始化,获得 nn.Module 的功能。
2.3 forward 函数
-
forward 方法是 PyTorch 中 nn.Module 类的一个重要方法,它定义了模型的前向传播过程。
-
在这个方法中,输入 x 是一个张量,表示输入数据。这个方法通过神经网络的层进行一系列的操作,并生成输出特征 x。
-
张量介绍:
张量是一个x变量中有多个元素 x i 其中 i = 1 , 2 , 3... x_{i} 其中 i = 1,2,3... xi其中i=1,2,3...
标量即 i = 1 i = 1 i=1时 -
在实际使用中,通常会使用 Model(input_data) 来调用 forward 方法,因为 nn.Module 类中已经定义了 _ call_ 方法,使得我们可以直接通过 Model(input_data) 调用 forward 方法,无需显式调用。
-
代码过程:
使用第一个全连接层 self.fc1 对输入 x 进行线性变换,并通过 ReLU 激活函数 F.relu() 进行非线性激活,得到激活后的输出 x。
使用第二个全连接层 self.fc2 对激活后的输出 x 进行线性变换,得到最终的输出特征 x。 -
在神经网络的前向传播过程中,输入数据通过一层一层的线性变换和非线性激活,逐渐得到高级的特征表示,最终得到输出结果。这个过程中,forward 方法定义了数据的流动路径,决定了神经网络的计算过程。