train正常,evaluation的时候GPU爆炸???代码工整的谎言

快半个月前遇到的问题了,还是记录一下

问题描述

在用LG训练的时候,train_batch_size=8,eval_batch_size=4。按道理这种情况下GPU占用峰值停留在train, 而eval的时候应该很低才对,因为没有计算图的accumulate,GPU上只包括model和data。
但是问题就是出现的那么惊悚,我在训练的时候老是炸显存,而且每次炸的时候都是在eval.后来继续调小train和eval的batch_size,居然发现eval的时候显存占用居然是train的2倍左右,而test的时候则是3、4倍.
在这里插入图片描述

解决方案

根据观察,很明显,eval和test的时候,网络仍然在积累计算图,因此eval的时候由于train的计算图还在,所以大概会有两倍的消耗。
google上到处查阅,发现出现这种问题原因是没有加上torch.no_grad(),但是自己的代码从始至终都没有漏掉no_grad(),后面还在各个和eval有关的function外面包上no_grad。可谓是里里外外包了好几层no_grad,但是问题依旧…

终于在一个forum找到了问题的原因:
在这里插入图片描述

put everything in a function!!!

原来是因为自己的代码写的所谓的"太规整了",我充分地运用面向对象思维,将一个model封装一层又一层,因为考虑到eval和train都需要forward model,所以把forward和compute loss等,那些共同的部分全部抽象出来,到一个父类里面,结果就和上面说的那样,still return loss,也就是计算loss的那个fuc return出来,一层层返回到最外层,然后return了好几层之后才loss.backward()

而出现这个问题的原因就和python本身的生态有关系了,因为python的每个function会保留里面的variable.所以要是把loss写在另一个function里面,通过return调用返回,而trian和eval都是共用一块代码的,那么eval的时候,train留下的reference还会保留,而eval的时候no_grad会失效,不管你包几层都没用,因为你计算loss,to.device()等和GPU有关的操作不在一片代码块。

所以说,这塔玛不是吃力不讨好,一顿操作秀翻自己???
在这里插入图片描述

结论

由于自己是SE出身,现在本科阶段学了不少OOP思想,啥封装隐藏,共用抽象,代码重用、复用,以及大量的文档注释这些工程化思维。可以略微看一下我的代码:
在这里插入图片描述
在这里插入图片描述
这还是我后面改过的,最原始的版本那真的是工整他ma给工整开门——工整到了家啊!注释写的比代码多,你敢信???

感悟:

要问,这些工程化的编码习惯好不好呢?
答案是,当然好了,应该说是非常好! 本科阶段就养成那么好的编码习惯以后进工业可以少吃很多无知亏。

但是——没必要,我说的没必要是指现在没必要大花心思取保证自己的代码工程化程度,因为说实在的,在整个project代码量本来就称不上一个工程的时候,费尽心思,吹毛求疵地用工程化思想框住自己的代码,那就是个错误,或者说纯属吃饱了撑。

SE这个课程本身传授的就不是啥算法啊,啥很具体技术,它传授的是前人的经验,是血泪,是前人在面对巨大代码量软件开发过程中,因为缺乏工程化思想严格把控,而流下的血泪!是几十个、几百个人的大团队,在真刀真枪开发软件的时候才能派的上用场的!

我这么个半吊子三脚猫的丹童,就跑点experiment,先不说代码量算不算的上一个工程(虽然我觉得我这个exp 用python写了上千行了,应该快算得上了),关键是这代码本来就不是用在工程上的。就好比,在练习九阳神功的时候,挥刀自宫了。这拟码真没必要啊…

参考:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
训练LBPH人脸识别器,你需要先收集一些人脸图像,并将它们分为不同的类别,每个类别代表一个人。然后,对每个类别的人脸图像进行特征提取,得到一个LBPH特征向量。最后,将所有LBPH特征向量作为训练集,训练一个分类器,得到一个模型文件`trainer.yml`。 以下是一个简单的示例代码,可以用于训练LBPH人脸识别器: ```python import cv2 import os import numpy as np # 加载人脸分类器 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # 加载训练数据 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) image_dir = os.path.join(BASE_DIR, 'images') current_id = 0 label_ids = {} x_train = [] y_labels = [] for root, dirs, files in os.walk(image_dir): for file in files: if file.endswith('jpg') or file.endswith('png'): path = os.path.join(root, file) label = os.path.basename(root).replace(' ', '-').lower() if not label in label_ids: label_ids[label] = current_id current_id += 1 id_ = label_ids[label] pil_image = cv2.imread(path, cv2.IMREAD_GRAYSCALE) size = (550, 550) final_image = cv2.resize(pil_image, size) faces = face_cascade.detectMultiScale(final_image, scaleFactor=1.1, minNeighbors=5) for (x, y, w, h) in faces: roi = final_image[y:y+h, x:x+w] x_train.append(roi) y_labels.append(id_) # 训练分类器 recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.train(x_train, np.array(y_labels)) recognizer.save("trainer.yml") # 保存标签 with open("labels.pickle", 'wb') as f: pickle.dump(label_ids, f) ``` 你需要将上述代码中的`images`替换为你收集的人脸图像所在的目录,运行代码后,将会得到一个训练好的模型文件`trainer.yml`和一个标签文件`labels.pickle`,用于人脸识别。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值