super().__init__()
在Python中,super()
函数用于调用父类(超类)的方法。super().__init__()
这种用法尤其常见于类的构造函数中,即__init__()
方法。这里是它的具体作用:
-
调用父类的构造函数:当你在一个子类中定义
__init__()
方法时,通常需要确保父类也被正确地初始化。使用super().__init__()
可以确保父类的构造函数被调用,这样父类的所有属性和方法才能在子类中正常使用。 -
避免直接父类名的硬编码:使用
super()
可以避免在调用父类方法时硬编码父类的名称。这样,如果改变了类的继承关系,不需要修改每一个使用到父类方法的地方。 -
支持多重继承:在Python的多重继承场景中,
super()
按照方法解析顺序(MRO,Method Resolution Order)调用父类的方法,这保证了所有父类被适当地初始化或者调用相应的方法。 ```python class Parent: def init(self): self.value = “Inside Parent”
class Child(Parent): def init(self): super().init() # 调用Parent类的构造函数 self.child_value = “Inside Child”
创建Child类的实例
child_instance = Child() print(child_instance.value) # 输出 “Inside Parent” print(child_instance.child_value) # 输出 “Inside Child”
# Tensorboard
## 安装
原本是tensorflow的可视化工具,pytorch从1.2.0开始支持tensorboard。之前的版本也可以使用tensorboardX代替。
在使用1.2.0版本以上的PyTorch的情况下,一般来说,直接使用pip安装即可。
```text
pip install tensorboard
这样直接安装之后,有可能打开的tensorboard网页是全白的,如果有这种问题,解决方法是卸载之后安装更低版本的tensorboard。
pip uninstall tensorboard
pip install tensorboard==2.0.2
Tensorboard的使用逻辑
Tensorboard的工作流程简单来说是
- 将代码运行过程中的,某些你关心的数据保存在一个文件夹中:
这一步由代码中的writer完成
- 再读取这个文件夹中的数据,用浏览器显示出来:
这一步通过在命令行运行tensorboard完成。
代码体中要做的事
首先导入tensorboard
from torch.utils.tensorboard import SummaryWriter
这里的SummaryWriter的作用就是,将数据以特定的格式存储到刚刚提到的那个文件夹中。
首先我们将其实例化
writer = SummaryWriter('./path/to/log')
这里传入的参数就是指向文件夹的路径,之后我们使用这个writer对象“拿出来”的任何数据都保存在这个路径之下。
这个对象包含多个方法,比如针对数值,我们可以调用
writer.add_scalar(tag, scalar_value, global_step=None, walltime=None)
这里的tag指定可视化时这个变量的名字,scalar_value是你要存的值,global_step可以理解为x轴坐标。
举一个简单的例子:
for epoch in range(100)
mAP = eval(model)
writer.add_scalar('mAP', mAP, epoch)
这样就会生成一个x轴跨度为100的折线图,y轴坐标代表着每一个epoch的mAP。这个折线图会保存在指定的路径下(但是现在还看不到)
同理,除了数值,我们可能还会想看到模型训练过程中的图像。
writer.add_image(tag, img_tensor, global_step=None, walltime=None, dataformats='CHW')
writer.add_images(tag, img_tensor, global_step=None, walltime=None, dataformats='NCHW')
可视化
我们已经将关心的数据拿出来了,接下来我们只需要在命令行运行:
tensorboard --logdir=./path/to/the/folder --port 8123
然后打开浏览器,访问地址http://localhost:8123/即可。这里的8123只是随便一个例子,用其他的未被占用端口也没有任何问题,注意命令行的端口与浏览器访问的地址同步。
如果发现不显示数据,注意检查一下路径是否正确,命令行这里注意是
--logdir=./path/to/the/folder
而不是
--logdir= './path/to/the/folder '
另一点要注意的是tensorboard并不是实时显示(visdom是完全实时的),而是默认30秒刷新一次。
细节
1.变量归类
命名变量的时候可以使用形如
writer.add_scalar('loss/loss1', loss1, epoch)
writer.add_scalar('loss/loss2', loss2, epoch)
writer.add_scalar('loss/loss3', loss3, epoch)
的格式,这样3个loss就会被显示在同一个section。
2.同时显示多个折线图
假如使用了两种学习率去训练同一个网络,想要比较它们训练过程中的loss曲线,只需要将两个日志文件夹放到同一目录下,并在命令行运行
tensorboard --logdir=./path/to/the/root --port 8123
torch-view
在PyTorch中,x.view()
函数是用来调整张量(Tensor)的形状而不改变其数据的函数。这是一种非常常用的操作,特别是在深度学习模型中处理数据和网络层之间的转换时。
功能
x.view()
的基本功能是重新排列一个张量的维度,但要求新的排列在总元素数量上与原张量保持一致。例如,如果你有一个形状为[4, 3]
的张量(即4行3列),你可以将其重新排列为[2, 6]
或[3, 4]
等,只要总元素数量(即12)保持不变。
参数
x.view()
函数接受一系列整数作为参数,这些整数定义了张量的新形状。你也可以在某个维度上使用-1
,让PyTorch自动计算这一维度的大小。
例子
下面是一些使用x.view()
的例子:
import torch
x = torch.randn(4, 4) # 创建一个随机的4x4张量
print("Original Tensor:\n", x)
# 将其重新形状为一个2x8张量
y = x.view(2, 8)
print("Reshaped Tensor to 2x8:\n", y)
# 使用-1来自动计算维度
z = x.view(-1, 2) # 会计算出另一个维度应为8
print("Reshaped Tensor with -1:\n", z)
注意事项
-
内存布局:
x.view()
要求张量在内存中是连续的。如果张量在进行某些操作(如转置、扩展维度等)后不再连续,可能需要调用.contiguous()
来重新排列内存,使之连续。 -
不复制数据:
x.view()
不会创建输入数据的副本,它仅仅是在同一块数据上提供了不同的视图。这意味着修改返回的张量会影响原始张量。
适用场景
在深度学习中,view()
经常用于将卷积层输出的多维张量转换为全连接层输入的一维张量,或者在数据预处理阶段改变输入数据的形状以符合模型的输入要求。
通过这种方式,view()
为张量形状的灵活操作提供了强大的工具,是PyTorch编程中不可或缺的一部分。
with
在Python中,with
语句是用于简化资源管理的一个语法结构,特别是在涉及到需要设置和清理的操作时。这通常与资源的分配和释放有关,如文件操作、网络连接或锁的管理。使用with
语句可以确保程序部分的执行完成后,无论执行过程中发生什么(例如错误或异常),都会执行必要的“清理”操作。
基本用法
with
语句通常与上下文管理器一起使用。上下文管理器是一个Python对象,它定义了在执行代码块前后应执行的操作。上下文管理器对象需要实现两个方法:__enter__()
和 __exit__()
。
__enter__()
方法在代码块执行之前调用,可以返回一个值(通常是资源对象),这个值可以被with
语句绑定到一个变量。__exit__(self, exc_type, exc_val, exc_tb)
方法在代码块执行完成后调用,无论代码块正常结束还是抛出异常都会执行。它可以用来处理异常、进行清理工作或释放资源。exc_type
,exc_val
, 和exc_tb
这三个参数用于传递异常类型、值和追踪记录。
示例:文件操作
一个常见的with
语句使用场景是文件操作。在不使用with
语句的情况下,如果在文件操作过程中发生异常,可能会导致文件没有被正确关闭,从而引发资源泄漏。使用with
语句可以避免这种情况:
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# 文件在这里自动关闭,即使读取过程中发生异常
网络和数据库连接
with
语句也常用于管理网络连接或数据库会话,确保它们在不再需要时被正确关闭:
import sqlite3
with sqlite3.connect('example.db') as conn:
cursor = conn.cursor()
cursor.execute('SELECT * FROM users')
print(cursor.fetchall())
# 数据库连接在这里自动关闭
自定义上下文管理器
你也可以创建自己的上下文管理器,通过定义一个类并实现__enter__
和__exit__
方法:
class ManagedResource:
def __enter__(self):
print("Acquire resource")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("Release resource")
if exc_type:
print(f"An error occurred: {exc_value}")
return True # 可以选择不向上抛出异常
with ManagedResource() as resource:
print("Using resource")
raise Exception("Something went wrong") # 异常被`__exit__`处理
在这个例子中,ManagedResource
类管理一个资源,它在进入with
代码块时被获取,在退出时被释放,即使发生了异常。
总结
with
语句通过自动处理设置和清理逻辑,使得代码更简洁、更安全。它尤其适合用于需要确保资源释放的场合,如文件读写、网络通信和数据库交云。