在 VS Code 中调试 Tensor 形状不显示的问题及解决方案
通过自定义__repr__方法,我们成功地解决了 VS Code 中调试Tensor变量时无法快速查看其形状的问题。我们同样可以使用类似的方式来扩展其他数据类型,使得调试时变量信息更加直观清晰。该方法非常实用,尤其适合处理大型数据集或高维度张量的深度学习项目。
在使用 VS Code 调试 PyTorch 代码时,可能会遇到一个常见问题:调试时 variables 窗口中不显示 Tensor 的形状信息。这会使得调试时观察数据的结构变得不便,尤其是在处理高维度的张量时。
在这篇博客中,我将提供一个改进方案,通过自定义 __repr__ 方法,让 PyTorch Tensor 的形状在调试信息中更清晰地呈现。我们还将展示如何针对其他 Python 对象(如 list、dict 以及 pandas.DataFrame)进行类似的处理,使调试时可以直观地看到这些对象的尺寸或内容。
常见问题
在调试 PyTorch 项目时,VS Code 的 variables 窗口默认不会显示张量的形状信息,除非你展开查看具体的变量内容。这种行为对于需要快速检查张量维度的场景是比较不便的。Python 的内置类型(如 bool、int、str)也无法直接继承,因此我们不能简单地扩展这些类型来自定义调试信息。
为了解决这些问题,我们可以通过创建包装类(wrapper classes)或直接重写对象的 __repr__ 方法,来定制它们在调试窗口中的显示内容。
解决方案
我们可以通过以下步骤来自定义调试时 Tensor 以及其他对象的显示方式。
1. 定制类包装和 __repr__ 方法
- 我们可以为 Python 的内置类型创建包装类,重写
__repr__方法以自定义它们的显示形式。 - 对于 PyTorch 的
Tensor和pandas.DataFrame,可以直接重写它们的__repr__方法来显示额外的信息(如张量形状或 DataFrame 的维度)。
下面是一个完整的代码示例:
import torch
import pandas as pd
# -------------------- 自定义包装类 --------------------
class CustomBool:
def __init__(self, value):
self.value = bool(value)
def __repr__(self):
return f'{{bool}} {self.value}'
class CustomInt:
def __init__(self, value):
self.value = int(value)
def __repr__(self):
return f'{{int}} {self.value}'
class CustomStr:
def __init__(self, value):
self.value = str(value)
def __repr__(self):
return f'{{str}} {self.value}'
# 自定义 list 和 dict 子类
class CustomList(list):
def __repr__(self):
return f'{{list: {len(self)}}} {super().__repr__()}'
class CustomDict(dict):
def __repr__(self):
return f'{{dict: {len(self)}}} {super().__repr__()}'
# 自定义 Tensor 的 __repr__ (Torch)
original_tensor_repr = torch.Tensor.__repr__
def custom_tensor_repr(self):
return f'{{Tensor: {tuple(self.shape)}}} {original_tensor_repr(self)}'
torch.Tensor.__repr__ = custom_tensor_repr
# 自定义 DataFrame 的 __repr__ (Pandas)
original_dataframe_repr = pd.DataFrame.__repr__
def custom_dataframe_repr(self):
return f'{{DataFrame: {self.shape}}} {original_dataframe_repr(self)}'
pd.DataFrame.__repr__ = custom_dataframe_repr
# 自定义 DataLoader 的类
class DataLoader:
def __init__(self, data_size):
self.data_size = data_size
def __len__(self):
return self.data_size
def __repr__(self):
return f'{{DataLoader: {len(self)}}} DataLoader object'
# -------------------- __main__ 函数 --------------------
def main():
# 使用自定义类型代替原生类型
my_list = CustomList([1, 2, 3, 4, 5, 6])
my_dict = CustomDict({'a': 1, 'b': 2, 'c': 3})
my_bool = CustomBool(True)
my_int = CustomInt(42)
my_str = CustomStr("hello")
# 测试 Tensor
my_tensor = torch.randn(100, 512)
# 测试 DataFrame
my_dataframe = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})
# 测试 DataLoader
my_dataloader = DataLoader(220)
# 输出内容
print(my_list) # {list: 6} [1, 2, 3, 4, 5, 6]
print(my_dict) # {dict: 3} {'a': 1, 'b': 2, 'c': 3}
print(my_bool) # {bool} True
print(my_int) # {int} 42
print(my_str) # {str} 'hello'
print(my_tensor) # {Tensor: (100, 512)} tensor([...])
print(my_dataframe) # {DataFrame: (3, 3)} A B C
print(my_dataloader) # {DataLoader: 220} DataLoader object
# 如果是直接运行文件,则调用 main 函数
if __name__ == "__main__":
main()
解释
-
包装类的实现:
- 我们为
bool、int和str创建了包装类CustomBool、CustomInt和CustomStr,并通过重写__repr__方法来定制它们的显示格式。
- 我们为
-
自定义
list和dict:- 使用
CustomList和CustomDict继承自 Python 的内置list和dict类型,并且通过重写__repr__方法来显示列表或字典的长度。这对于调试包含大量数据的容器类非常有用。
- 使用
-
Tensor 和 DataFrame 的自定义
__repr__:- 我们通过直接修改
torch.Tensor和pandas.DataFrame的__repr__方法,分别让它们在打印时显示张量的形状和 DataFrame 的维度信息。这在调试过程中可以让你一眼就看到数据的结构,而不需要展开变量。
- 我们通过直接修改
-
DataLoader 自定义类:
- 我们还创建了一个自定义的
DataLoader类,并重写了它的__repr__方法来显示加载的数据大小。这对于在训练模型时检查数据集大小十分有用。
- 我们还创建了一个自定义的
如何应用
步骤 1:创建一个 Python 文件
将上述代码保存到一个 Python 文件中,比如 custom_repr.py,这个文件将封装所有对 __repr__ 方法的自定义实现。
步骤 2:在项目中引入这个文件
在你的主程序或者调试代码的入口处,导入这个 custom_repr.py 文件。这样,在运行代码或调试时,自定义的 __repr__ 方法就会自动生效。
例如:
# 假设你将上述代码保存为 custom_repr.py
import custom_repr # 确保此导入是在你项目的最开始
# 你的代码
总结
通过自定义 __repr__ 方法,我们成功地解决了 VS Code 中调试 Tensor 变量时无法快速查看其形状的问题。我们同样可以使用类似的方式来扩展其他数据类型,使得调试时变量信息更加直观清晰。该方法非常实用,尤其适合处理大型数据集或高维度张量的深度学习项目。
更多推荐


所有评论(0)