日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于炼丹,你是否知道这些细节?

發布時間:2023/12/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于炼丹,你是否知道这些细节? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者丨Fatescript

來源丨https://zhuanlan.zhihu.com/p/450779978

編輯丨GiantPandaCV

本文算是我工作一年多以來的一些想法和經驗,最早發布在曠視研究院內部的論壇中,本著開放和分享的精神發布在我的知乎專欄中,如果想看干貨的話可以直接跳過動機部分。另外,后續在這個專欄中,我會做一些關于原理和設計方面的一些分享,希望能給領域從業人員提供一些看待問題的不一樣的視角。

動機

前段時間走在路上,一直在思考一個問題:我的時間開銷很多都被拿去給別人解釋一些在我看起來顯而易見的問題了,比如( https://link.zhihu.com/?target=https%3A//github.com/Megvii- BaseDetection/cvpods )里面的一些code寫法問題(雖然這在某些方面說明了文檔建設的不完善),而這變相導致了我實際工作時間的減少,如何讓別人少問一些我覺得答案顯而易見的問題?如何讓別人提前規避一些不必要的坑?只有解決掉這樣的一些問題,我才能從一件件繁瑣的小事中解放出來,把精力放在我真正關心的事情上去。

其實之前同事有跟我說過類似的話,每次帶一個新人,都要告訴他:你的實現需要注意這里blabla,還要注意那里blabla。說實話,我很佩服那些帶intern時候非常細致和知無不言的人,但我本性上并不喜歡每次花費時間去解釋一些我覺得顯而易見的問題,所以我寫下了這個帖子,把我踩過的坑和留下來的經驗分享出去。希望能夠方便別人,同時也節約我的時間。

加入曠視以來,個人一直在做一些關于框架相關的內容,所以內容主要偏向于模型訓練之類的工作。因為 一個擁有知識的人是無法想象知識在別人腦海中的樣子的(the curse of knowledge),所以我只能選取被問的最多的,和我認為最應該知道的

準備好了的話,我們就啟航出發(另,這篇專欄文章會長期進行更新)。

坑/經驗

Data模塊

  • python圖像處理用的最多的兩個庫是opencv和Pillow(PIL),但是兩者讀取出來的圖像并不一樣, opencv讀取的圖像格式的三個通道是BGR形式的,但是PIL是RGB格式的 。這個問題看起來很小,但是衍生出來的坑可以有很多,最常見的場景就是數據增強和預訓練模型中。比如有些數據增強的方法是基于channel維度的,比如megengine里面的HueTransform,這一行代碼 (https://github.com/MegEngine/MegEngine/blob/4d72e7071d6b8f8240edc56c6853384850b7407f/imperative/python/megengine/data/transform/vision/transform.py#L958 ) 顯然是需要確保圖像是BGR的,但是經常會有人只看有Transform就無腦用了,從來沒有考慮過這些問題。

  • 接上條,RGB和BGR的另一個問題就是導致預訓練模型載入后訓練的方式不對,最常見的場景就是預訓練模型的input channel是RGB的(例如torch官方來的預訓練模型),然后你用cv2做數據處理,最后還忘了convert成RGB的格式,那么就是會有問題。這個問題應該很多煉丹的同學沒有注意過,我之前寫CenterNet-better(https://github.com/FateScript/CenterNet-better)就發現CenterNet(https://github.com/xingyizhou/CenterNet)存在這么一個問題,要知道當時這可是一個有著3k多star的倉庫,但是從來沒有人意識到有這個問題。當然,依照我的經驗,如果你訓練的iter足夠多,即使你的channel有問題,對于結果的影響也會非常小。不過,既然能做對,為啥不注意這些問題一次性做對呢?

  • torchvision中提供的模型,都是輸入圖像經過了ToTensor操作train出來的。也就是說最后在進入網絡之前會統一除以255從而將網絡的輸入變到0到1之間。torchvision的文檔(https://pytorch.org/vision/stable/models.html)給出了他們使用的mean和std,也是0-1的mean和std。如果你使用torch預訓練的模型,但是輸入還是0-255的,那么恭喜你,在載入模型上你又會踩一個大坑(要么你的圖像先除以255,要么你的code中mean和std的數值都要乘以255)。

  • ToTensor之后接數據處理的坑。上一條說了ToTensor之后圖像變成了0到1的,但是一些數據增強對數值做處理的時候,是針對標準圖像,很多人ToTensor之后接了這樣一個數據增強,最后就是練出來的丹是廢的(心疼電費QaQ)。

  • 數據集里面有一個圖特別詭異,只要train到那一張圖就會炸顯存(CUDA OOM),別的圖訓練起來都沒有問題,應該怎么處理?通常出現這個問題,首先判斷數據本身是不是有問題。如果數據本身有問題,在一開始生成Dataset對象的時候去掉就行了。如果數據本身沒有問題,只不過因為一些特殊原因導致顯存炸了(比如檢測中圖像的GT boxes過多的問題),可以catch一個CUDA OOM的error之后將一些邏輯放在CPU上,最后retry一下,這樣只是會慢一個iter,但是訓練過程還是可以完整走完的,在我們開源的YOLOX里有類似的參考code(https://github.com/Megvii-BaseDetection/YOLOX/blob/0.1.0/yolox/models/yolo_head.py#L330-L334)。

  • pytorch中dataloader的坑。有時候會遇到pytorch num_workers=0(也就是單進程)沒有問題,但是多進程就會報一些看不懂的錯的現象,這種情況通常是因為torch到了ulimit的上限,更核心的原因是 torch的dataloader不會釋放文件描述符 (參考issue: https://github.com/pytorch/pytorch/issues/973)。可以ulimit -n 看一下機器的設置。跑程序之前修改一下對應的數值。

  • opencv和dataloader的神奇聯動。很多人經常來問為啥要寫cv2.setNumThreads(0),其實是因為cv2在做resize等op的時候會用多線程,當torch的dataloader是多進程的時候,多進程套多線程,很容易就卡死了(具體哪里死鎖了我沒探究很深)。除了setNumThreads之外,通常還要加一句cv2.ocl.setUseOpenCL(False),原因是cv2使用opencl和cuda一起用的時候通常會拖慢速度,加了萬事大吉,說不定還能加速。感謝評論區 @Yuxin Wu(https://www.zhihu.com/people/ppwwyyxx)?大大的指正

  • dataloader會在epoch結束之后進行類似重新加載的操作,復現這個問題的code稍微有些長,放在后面了。這個問題算是可以說是一個高級bug/feature了,可能導致的問題之一就是煉丹師在本地的code上進行了一些修改,然后訓練過程直接加載進去了。解決方法也很簡單,讓你的sampler源源不斷地產生數據就好,這樣即使本地code有修改也不會加載進去。

  • Module模塊

  • BatchNorm在訓練和推斷的時候的行為是不一致的。這也是新人最常見的錯誤(類似的算子還有dropout,這里提一嘴, pytorch的dropout在eval的時候行為是Identity ,之前有遇到過實習生說dropout加了沒效果,直到我看了他的code:x = F.dropout(x, p=0.5)

  • BatchNorm疊加分布式訓練的坑。在使用DDP(DistributedDataParallel)進行訓練的時候,每張卡上的BN統計量是可能不一樣的,仔細檢查broadcast_buffer這個參數 。DDP的默認行為是在forward之前將rank0 的 buffer做一次broadcast(broadcast_buffer=True),但是一些常用的開源檢測倉庫是將broadcast_buffer設置成False的(參考:mmdet(https://github.com/facebookresearch/detectron2/blob/f50ec07cf220982e2c4861c5a9a17c4864ab5bfd/tools/plain_train_net.py#L206)?和 detectron2(https://github.com/facebookresearch/detectron2/blob/f50ec07cf220982e2c4861c5a9a17c4864ab5bfd/tools/plain_train_net.py#L206),我猜是在檢測任務中因為batchsize過小,統一用卡0的統計量會掉點) 這個問題在一邊訓練一邊測試的code中更常見 ,比如說你train了5個epoch,然后要分布式測試一下。一般的邏輯是將數據集分到每塊卡上,每塊卡進行inference,最后gather到卡0上進行測點。但是 因為每張卡統計量是不一樣的,所以和那種把卡0的模型broadcast到不同卡上測試出來的結果是不一樣的。這也是為啥通常訓練完測的點和單獨起了一個測試腳本跑出來的點不一樣的原因 (當然你用SyncBN就不會有這個問題)。

  • Pytorch的SyncBN在1.5之前一直實現的有bug,所以有一些老倉庫是存在使用SyncBN之后掉點的問題的。

  • 用了多卡開多尺度訓練,明明尺度更小了,但是速度好像不是很理想?這個問題涉及到多卡的原理,因為分布式訓練的時候,在得到新的參數之后往往需要進行一次同步。假設有兩張卡,卡0的尺度非常小,卡1的尺度非常大,那么就會出現卡0始終在等卡1,于是就出現了雖然有的尺度變小了,但是整體的訓練速度并沒有變快的現象(木桶效應)。解決這個問題的思路就是 盡量把負載拉均衡一些

  • 多卡的小batch模擬大batch(梯度累積)的坑。假設我們在單卡下只能塞下batchsize = 2,那么為了模擬一個batchsize = 8的效果,通常的做法是forward / backward 4次,不清理梯度,step一次(當然考慮BN的統計量問題這種做法和單純的batchsize=8肯定還是有一些差別的)。在多卡下,因為調用loss.backward的時候會做grad的同步,所以說前三次調用backward的時候需要加ddp.no_sync(https://pytorch.org/docs/stable/generated/torch.nn.parallel.DistributedDataParallel.html?highlight=no_sync#torch.nn.parallel.DistributedDataParallel.no_sync)的context manager(不加的話,第一次bp之后,各個卡上的grad此時會進行同步),最后一次則不需要加。當然,我看很多倉庫并沒有這么做,我只能理解他們就是單純想做梯度累積(BTW,加了ddp.no_sync會使得程序快一些,畢竟加了之后bp過程是無通訊的)。

  • 浮點數的加法其實不遵守交換律的 ,這個通常能衍生出來GPU上的運算結果不能嚴格復現的現象??赡芤恍┓怯嬎銠C軟件專業的同學并不理解這一件事情,直接自己開一個python終端體驗可能會更好:

  • print(1e100?+?1e-4?+?-1e100)??#?ouptut:?0 print(1e100?+?-1e100?+?1e-4)??#?output:?0.0001

    訓練模塊

  • FP16訓練/混合精度訓練。使用Apex訓練混合精度模型,在保存checkpoint用于繼續訓練的時候,除了model和optimizer本身的state_dict之外,還需要保存一下amp的state_dict,這個在amp的文檔(https://link.zhihu.com/?target=https%3A//nvidia.github.io/apex/amp.html%23checkpointing)中也有提過。(當然,經驗上來說忘了保存影響不大,會多花幾個iter search一個loss scalar出來)

  • 多機分布式訓練卡死的問題。好友 @NoahSYZhang(https://www.zhihu.com/people/syzhangbuaa) 遇到的一個坑。場景是先申請了兩個8卡機,然后機器1和機器2用前4塊卡做通訊(local rank最大都是4,總共是兩機8卡)??梢猿跏蓟痯rocess group,但是在使用DDP的時候會卡死。原因在于pytorch在做DDP的時候會猜測一個rank,參考code(https://github.com/pytorch/pytorch/blob/0d437fe6d0ef17648072eb586484a4a5a080b094/torch/csrc/distributed/c10d/ProcessGroupNCCL.cpp#L1622-L1630)。對于上面的場景,第二個機器上因為存在卡5到卡8,而對應的rank也是5到8,所以DDP就會認為自己需要同步的是卡5到卡8,于是就卡死了。

  • 復現Code

    Data部分

    from?torch.utils.data?import?DataLoader from?torch.utils.data?import?Dataset import?tqdm import?timeclass?SimpleDataset(Dataset):def?__init__(self,?length=400):self.length?=?lengthself.data_list?=?list(range(length))def?__getitem__(self,?index):data?=?self.data_list[index]time.sleep(0.1)return?datadef?__len__(self):return?self.lengthdef?train(local_rank):dataset?=?SimpleDataset()dataloader?=?DataLoader(dataset,?batch_size=1,?num_workers=2)iter_loader?=?iter(dataloader)max_iter?=?100000for?_?in?tqdm.tqdm(range(max_iter)):try:_?=?next(iter_loader)except?StopIteration:print("Refresh?here?!!!!!!!!")iter_loader?=?iter(dataloader)_?=?next(iter_loader)if?__name__?==?"__main__":import?torch.multiprocessing?as?mpmp.spawn(train,?args=(),?nprocs=2,?daemon=False)

    當程序運行起來的時候,可以在Dataset里面的__getitem__方法里面加一個print輸出一些內容,在refresh之后,就會print對應的內容哦(看到現象是不是覺得自己以前煉的丹可能有問題了呢hhh)

    一些碎碎念

    一口氣寫了這么多條也有點累了,后續有踩到新坑的話我也會繼續更新這篇文章的。畢竟寫這篇文章是希望工作中不再會有人踩類似的坑 & 煉丹的人能夠對深度學習框架有意識(雖然某種程度上來講這算是個心智負擔)。

    如果說今年來什么事情是最大的收獲的話,那就是理解了一個開放的生態是可以迸發出極強的活力的,也希望能看到更多的人來分享自己遇到的問題和解決的思路。畢竟探索的答案只是一個副產品,過程本身才是最大的財寶。

    本文僅做學術分享,如有侵權,請聯系刪文。

    重磅!計算機視覺工坊-學習交流群已成立

    掃碼添加小助手微信,可申請加入3D視覺工坊-學術論文寫作與投稿?微信交流群,旨在交流頂會、頂刊、SCI、EI等寫作與投稿事宜。

    同時也可申請加入我們的細分方向交流群,目前主要有ORB-SLAM系列源碼學習、3D視覺CV&深度學習、SLAM、三維重建點云后處理自動駕駛、CV入門、三維測量、VR/AR、3D人臉識別、醫療影像、缺陷檢測、行人重識別、目標跟蹤、視覺產品落地、視覺競賽、車牌識別、硬件選型、深度估計、學術交流、求職交流等微信群,請掃描下面微信號加群,備注:”研究方向+學校/公司+昵稱“,例如:”3D視覺?+ 上海交大 + 靜靜“。請按照格式備注,否則不予通過。添加成功后會根據研究方向邀請進去相關微信群。原創投稿也請聯系。

    ▲長按加微信群或投稿

    ▲長按關注公眾號

    3D視覺從入門到精通知識星球:針對3D視覺領域的視頻課程(三維重建系列、三維點云系列、結構光系列、手眼標定、相機標定、激光/視覺SLAM、自動駕駛等)、知識點匯總、入門進階學習路線、最新paper分享、疑問解答五個方面進行深耕,更有各類大廠的算法工程人員進行技術指導。與此同時,星球將聯合知名企業發布3D視覺相關算法開發崗位以及項目對接信息,打造成集技術與就業為一體的鐵桿粉絲聚集區,近4000星球成員為創造更好的AI世界共同進步,知識星球入口:

    學習3D視覺核心技術,掃描查看介紹,3天內無條件退款

    ?圈里有高質量教程資料、可答疑解惑、助你高效解決問題

    覺得有用,麻煩給個贊和在看

    總結

    以上是生活随笔為你收集整理的关于炼丹,你是否知道这些细节?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。