cevalokas

personal website

Not because they are easy, but because they are hard.


python碎碎念

目录

super().__init__()

在Python中,super()函数用于调用父类(超类)的方法。super().__init__()这种用法尤其常见于类的构造函数中,即__init__()方法。这里是它的具体作用:

  1. 调用父类的构造函数:当你在一个子类中定义__init__()方法时,通常需要确保父类也被正确地初始化。使用super().__init__()可以确保父类的构造函数被调用,这样父类的所有属性和方法才能在子类中正常使用。

  2. 避免直接父类名的硬编码:使用super()可以避免在调用父类方法时硬编码父类的名称。这样,如果改变了类的继承关系,不需要修改每一个使用到父类方法的地方。

  3. 支持多重继承:在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)

注意事项

  1. 内存布局x.view()要求张量在内存中是连续的。如果张量在进行某些操作(如转置、扩展维度等)后不再连续,可能需要调用.contiguous()来重新排列内存,使之连续。

  2. 不复制数据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语句通过自动处理设置和清理逻辑,使得代码更简洁、更安全。它尤其适合用于需要确保资源释放的场合,如文件读写、网络通信和数据库交云。