清华大学软件学院机器学习团队在GitHub上公开了其研究成果代码, 其代码完成度极高, 为后续学习提供了宝贵的参考资料. 该代码提供了一系列运行程序, 但在本地运行时出现了一些问题. 本文对目前出现的问题及解决方法进行记录. (声明: 并未使用sh脚本文件)
1. exp包
exp包是用于实验运行的程序包, 其主要程序为exp_main, 其中包括验证、训练和测试函数. 在本地运行时出现以下问题, 并提供解决方案.
1. 显存爆炸问题
在执行训练程序时, 最近时常发生爆显存的问题. 在单个 epoch 中, 积累了几次批操作就会爆显存. 解决方法是, 在每次批操作结束后, 加入以下代码清除内存碎片:
torch.cuda.empty_cache()
此外, 可以通过以下代码查询剩余显存:
import torch
# 获取当前设备上的 GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 获取已经分配但未使用的 GPU 内存(即预留但尚未使用的内存)
reserved_memory = torch.cuda.memory_reserved(device)
# 获取已经分配并正在使用的 GPU 内存
allocated_memory = torch.cuda.memory_allocated(device)
# 计算剩余内存量
free_memory = torch.cuda.get_device_properties(device).total_memory - allocated_memory
print(f"已分配但未使用的 GPU 内存: {reserved_memory / 1024 ** 3:.2f} GiB")
print(f"已分配并正在使用的 GPU 内存: {allocated_memory / 1024 ** 3:.2f} GiB")
print(f"剩余 GPU 内存: {free_memory / 1024 ** 3:.2f} GiB")
2. 运行时程序卡主或者出现 ValueError: too many values to unpack (expected 4) 错误
这个不是THUML代码中的错误, 我把另一个同名代码搞混了. 但因为是同一个语句就记录一下.
这种情况通常是在exp_main运行验证、训练和测试函数过程中, 在执行以下代码 (code.1) 出现:
for i, (batch_x, batch_y, batch_x_mark, batch_y_mark) in enumerate(train_loader):
造成这种情况的原因是通常发生在尝试将一个包含大于预期值的元素数量的序列解包给过少的变量时. 在 Python 中, 解包操作要求左侧的目标变量数量必须与右侧的元素数量相匹配,否则会引发 ValueError. 解决方法是补充一个index变量, 具体如下:
for i, (batch_x, batch_y, batch_x_mark, batch_y_mark,index) in enumerate(train_loader):
如果依然出现ValueError错误, 则检查parser变量在模型定义中输入输出参数是否设置对.
此外, 我之前还在其他代码中遇到执行上述代码 (code.1) 卡主的情况, Spyder是卡主, 但jupyter正常运行, pycharm报出RuntimeError错误. 该情况通常在使用多进程模块(如multiprocessing)时出现。它表明在启动子进程之前,当前进程尚未完成其引导阶段。为了解决这个问题,你需要在启动子进程的主模块中添加一些代码,以确保它只在主模块执行时运行。这可以通过以下方式完成:
import multiprocessing
def main():
# 主程序逻辑
if __name__ == '__main__':
# 当前脚本作为主模块运行时才执行下面的代码
multiprocessing.freeze_support() # 仅在Windows上需要,在Unix/Linux系统上不会产生影响
main() # 调用主函数
2. run程序
run程序是算法执行的主程序. 在运行过程种出现以下问题, 并提供解决方案.
1. SystemExit: 2错误
这个错误是由于必须赋值的变量并未赋值导致, 具体包括: --is_training, --model_id, --model, --data. 解决方法是, 将 ArgumentParser 对象赋值中的 ‘‘required=True’’ 语句删去. 以is_training为例, 具体如下:
# 原代码
parser.add_argument('--is_training', type=int, required=True, default=1, help='status')
# 修改为
parser.add_argument('--is_training', type=int, default=1, help='status')