<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          CV入門賽最全思路&上分技巧匯總!

          共 10013字,需瀏覽 21分鐘

           ·

          2020-08-14 16:30

          ↑↑↑關(guān)注后"星標(biāo)"Datawhale
          每日干貨?&?每月組隊(duì)學(xué)習(xí),不錯(cuò)過
          ?Datawhale干貨?
          作者:安晟,算法工程師,Datawhale成員

          賽題數(shù)據(jù)及背景

          https://tianchi.aliyun.com/competition/entrance/531795/introduction(阿里天池-零基礎(chǔ)入門CV賽事)

          本文分為以下幾部分:

          • 如何優(yōu)化官方baseline的效果?
          • 其它解題思路的整理和分析
          • 字符級目標(biāo)檢測的優(yōu)化技巧整理

          在這里要特別感謝多位前排選手對于比賽技巧的無私分享,那么不多bb,下面直接進(jìn)入正題

          一、如何優(yōu)化官方baseline的效果?

          本次入門賽的官方baseline入門材料,已經(jīng)提供了完整的實(shí)踐思路:Task1 賽題理解[1]、Task2 數(shù)據(jù)讀取與數(shù)據(jù)擴(kuò)增[2]、Task3 字符識別模型[3]、Task4 模型訓(xùn)練與驗(yàn)證[4]、Task5 模型集成[5],本質(zhì)上,baseline的思路就是將賽題轉(zhuǎn)換為了一個(gè)定長的字符識別問題,用包含多個(gè)輸出的分類問題來進(jìn)行求解。

          1.1 改進(jìn)版baseline

          那么如何進(jìn)行進(jìn)一步優(yōu)化呢?在比賽進(jìn)行的過程中,我在天池進(jìn)行了一次如何調(diào)參上分[6]的直播分享。

          直播對應(yīng)的代碼可以在我們的《動(dòng)手學(xué)CV項(xiàng)目》[7]的2.5節(jié)找到。

          這份代碼相當(dāng)于一個(gè)加強(qiáng)版的baseline,簡短來說,介紹了以下幾點(diǎn):

          • 重新回顧baseline的代碼
          • 階段性下降的學(xué)習(xí)率調(diào)整策略
          • 分析了很多人提交出0.3-0.4分成績的原因和解決方案
          • 加入數(shù)據(jù)增強(qiáng)策略

          這份代碼我相信是幫到了一些剛?cè)腴T的同學(xué)的,提交的成績大概在0.75分左右。

          那么在這樣一個(gè)baseline的基礎(chǔ)上,如何進(jìn)一步的優(yōu)化呢?

          1.2 改進(jìn)backbone

          baseline中我們的網(wǎng)絡(luò)結(jié)構(gòu)是這樣定義的:

          class SVHN_Model1(nn.Module):
          def __init__(self):
          super(SVHN_Model1, self).__init__()

          model_conv = models.resnet18(pretrained=True)
          model_conv.avgpool = nn.AdaptiveAvgPool2d(1)
          model_conv = nn.Sequential(*list(model_conv.children())[:-1]) # 去除最后一個(gè)fc layer
          self.cnn = model_conv

          self.fc1 = nn.Linear(512, 11)
          self.fc2 = nn.Linear(512, 11)
          self.fc3 = nn.Linear(512, 11)
          self.fc4 = nn.Linear(512, 11)
          self.fc5 = nn.Linear(512, 11)

          def forward(self, img):
          feat = self.cnn(img)
          #print(feat.shape)
          feat = feat.view(feat.shape[0], -1)
          c1 = self.fc1(feat)
          c2 = self.fc2(feat)
          c3 = self.fc3(feat)
          c4 = self.fc4(feat)
          c5 = self.fc5(feat)
          return c1, c2, c3, c4, c5

          我們可以對使用的backbone網(wǎng)絡(luò)進(jìn)行一系列的改進(jìn):

          • 由resnet18換為更大的resnet50
          • 為每一個(gè)分類模塊加上一層全連接隱藏層
          • 為隱含層添加dropout

          由resnet18換為resnet50,更深的模型就擁有更好的表達(dá)能力,添加一層隱含層同樣起到了增加模型擬合能力的作用,與此同時(shí)為隱含層添加dropout來進(jìn)行一個(gè)balance,一定程度上防止過擬合。(這只是我個(gè)人對于baseline的改進(jìn)方案,不一定是最優(yōu)的)

          改進(jìn)后的模型定義代碼如下:

          class SVHN_Model2(nn.Module):
          def __init__(self):
          super(SVHN_Model2, self).__init__()

          # resnet18
          model_conv = models.resnet18(pretrained=True)
          model_conv.avgpool = nn.AdaptiveAvgPool2d(1)
          model_conv = nn.Sequential(*list(model_conv.children())[:-1]) # 去除最后一個(gè)fc layer
          self.cnn = model_conv

          self.hd_fc1 = nn.Linear(512, 128)
          self.hd_fc2 = nn.Linear(512, 128)
          self.hd_fc3 = nn.Linear(512, 128)
          self.hd_fc4 = nn.Linear(512, 128)
          self.hd_fc5 = nn.Linear(512, 128)
          self.dropout_1 = nn.Dropout(0.25)
          self.dropout_2 = nn.Dropout(0.25)
          self.dropout_3 = nn.Dropout(0.25)
          self.dropout_4 = nn.Dropout(0.25)
          self.dropout_5 = nn.Dropout(0.25)
          self.fc1 = nn.Linear(128, 11)
          self.fc2 = nn.Linear(128, 11)
          self.fc3 = nn.Linear(128, 11)
          self.fc4 = nn.Linear(128, 11)
          self.fc5 = nn.Linear(128, 11)

          def forward(self, img):
          feat = self.cnn(img)
          feat = feat.view(feat.shape[0], -1)

          feat1 = self.hd_fc1(feat)
          feat2 = self.hd_fc2(feat)
          feat3 = self.hd_fc3(feat)
          feat4 = self.hd_fc4(feat)
          feat5 = self.hd_fc5(feat)
          feat1 = self.dropout_1(feat1)
          feat2 = self.dropout_2(feat2)
          feat3 = self.dropout_3(feat3)
          feat4 = self.dropout_4(feat4)
          feat5 = self.dropout_5(feat5)

          c1 = self.fc1(feat1)
          c2 = self.fc2(feat2)
          c3 = self.fc3(feat3)
          c4 = self.fc4(feat4)
          c5 = self.fc5(feat5)

          return c1, c2, c3, c4, c5

          改進(jìn)后的模型訓(xùn)起來會(huì)慢很多,不過增加了模型的表達(dá)力,自然效果也會(huì)好一些。此外,你也可以嘗試一些更"state-of-the-arts"的模型,比如SENet,EfficientNet等。

          1.3 數(shù)據(jù)增強(qiáng)優(yōu)化

          關(guān)于數(shù)據(jù)增強(qiáng),我們在直播中已經(jīng)探討過了,從原理上分析我們更應(yīng)該用一些基于空間、位置相關(guān)的數(shù)據(jù)增強(qiáng),比如Randomcrop,平移,旋轉(zhuǎn)等。而顏色空間相關(guān)的變換,也可以嘗試,但很可能會(huì)起到副作用。

          數(shù)據(jù)增強(qiáng)是非常普遍的訓(xùn)練技巧了,肯定要用,但對這個(gè)賽題的結(jié)果提升不會(huì)很顯著。關(guān)于這部分,這位小伙伴寫的比賽實(shí)驗(yàn)記錄[8]對相關(guān)的實(shí)驗(yàn)進(jìn)行了很詳細(xì)的記錄,大家感興趣可以閱讀一下~

          1.4 和文本長度相關(guān)的探索

          baseline方案將識別問題轉(zhuǎn)化為了定長識別問題,那么定多長合適?就是個(gè)值得思考的問題,有的小伙伴通過一個(gè)小腳本進(jìn)行了統(tǒng)計(jì),訓(xùn)練集中的樣本的字符長度分別為1,2,3,4,5,6的樣本數(shù)量分別為4636,16262,7813,1280,8,1。

          可以看到,數(shù)據(jù)集中長度為5和6的圖片都是可以忽略不計(jì)的,因此主動(dòng)放棄這部分極少數(shù)情況的case可以很好的為模型“減負(fù)”,從而獲得更好的效果。

          baseline模型設(shè)定定長len=5,不妨嘗試下len=4,會(huì)帶來進(jìn)一步的提升。

          我們的這個(gè)方案需要CNN自己找到文字在圖中的位置,還要自己判斷出字符的個(gè)數(shù)并完成正確的識別,感覺上是相當(dāng)難的任務(wù),之所以能夠work是因?yàn)閳鼍跋鄬碚f比較簡單。

          如果你做了一些更進(jìn)一步得分析工作你會(huì)發(fā)現(xiàn),模型對于長度不同的圖片的效果是不一樣的。更詳細(xì)來說,根據(jù)我的訓(xùn)練日志的記錄,訓(xùn)練時(shí)第3個(gè)字符的loss是相對比較小的,而預(yù)測時(shí)長度為3的圖片出現(xiàn)的預(yù)測錯(cuò)誤是比較多的,主要是漏檢。

          我分析這是因?yàn)椋▊€(gè)人觀點(diǎn)可能存在誤導(dǎo)):對于輸出第一個(gè)字符結(jié)果的fc layer來說,所有圖片它都會(huì)參于訓(xùn)練,而輸出第二個(gè)字符結(jié)果的fc layer,只有當(dāng)圖片字符數(shù)>=2,它才會(huì)參于“有效”訓(xùn)練,以此類推。所以越是對應(yīng)靠后的fc layer,訓(xùn)練的越不充分,越容易過擬合導(dǎo)致實(shí)際效果越差。

          因此可以圍繞不同長度的圖片效果不同來做些文章,依然是這篇比賽實(shí)驗(yàn)記錄[9]

          他嘗試了兩個(gè)方案,可供大家參考,提供些思路:

          • 損失加權(quán)
          • 樣本加權(quán)

          其中第二個(gè)方案,樣本加權(quán)看起來是更合理來解決這個(gè)問題的,我們可以通過重復(fù)采樣,提高較長的字符數(shù)量的圖片出現(xiàn)的比例,來讓對應(yīng)第3個(gè)字符和第4個(gè)字符對應(yīng)的輸出層訓(xùn)練的更充分。

          這是個(gè)蠻有新意的角度,你是否還可以碰撞出其它的idea來解決這個(gè)問題呢~

          1.5 集成學(xué)習(xí)

          對于這個(gè)比賽來說,比較適合baseline的集成方案是:

          首先將單模型盡可能訓(xùn)到最高,然后單模型的輸出使用TTA(test time augmentation),可以大幅提升單模型的預(yù)測效果。

          然后訓(xùn)練多個(gè)有差異化的模型,將多個(gè)單模型的預(yù)測結(jié)果進(jìn)行投票,得到最終的預(yù)測結(jié)果。單模型間的差異化可以從數(shù)據(jù)的角度通過重新劃分訓(xùn)練集和驗(yàn)證集來達(dá)到,也可以從模型的角度,使用不同的backbone來達(dá)到。從原理上講,單模型間越是獨(dú)立和具有差異化,融合的效果就越好。

          1.6 讓baseline進(jìn)入Top 2%的6行代碼

          最后再偷偷告訴你一個(gè),只需修改6行代碼,就能讓目前的優(yōu)化后baseline單模型進(jìn)入Top 2%的方法。

          不知大家有沒有發(fā)現(xiàn),測試集相比于訓(xùn)練數(shù)據(jù),要更簡單。

          具體地,體現(xiàn)在測試集最終的分?jǐn)?shù)反而要比驗(yàn)證集高一些,如果你直接觀察數(shù)據(jù),也可以看出來,測試集的圖片中字符在圖片中的占比更大,而訓(xùn)練集中圖片的字符占比更小。直觀感受就是訓(xùn)練數(shù)據(jù)和測試集對應(yīng)的場景不一致,訓(xùn)練集的字符感覺更“遠(yuǎn)”,預(yù)處難度也更高。

          提示到這里,你可以先停下來思考下,如果是你,會(huì)如何來針對這個(gè)問題進(jìn)行優(yōu)化呢?

          驗(yàn)證集圖片示例:

          測試集圖片示例:

          對于這個(gè)問題,很多人很自然的想到了進(jìn)行目標(biāo)檢測,這也是幾乎所有前排選手的一致選擇。但是,我們的baseline就沒有一戰(zhàn)之力了嗎?當(dāng)然不是,我個(gè)人用resnet50作為backbone將單模型的分?jǐn)?shù)訓(xùn)到了0.91,相當(dāng)于正式賽Top2%的分?jǐn)?shù),而且因?yàn)槲覜]有時(shí)間做太多的超參數(shù)調(diào)整實(shí)驗(yàn),這個(gè)成績也并沒有達(dá)到baseline的上限。

          那么baseline要如何相應(yīng)的進(jìn)行改造來解決這個(gè)問題呢?

          文字描述出來就是:訓(xùn)練時(shí)把場景拉近,測試基本保持不變,這樣一定程度上讓訓(xùn)練和測試的數(shù)據(jù)的場景更加一致,從而讓模型學(xué)到的預(yù)測能力完全發(fā)揮出來。

          可以有很多方案來達(dá)到這個(gè)目的,最簡單有效的方法僅僅需要修改數(shù)據(jù)增強(qiáng)相關(guān)的6行代碼,我用TODO作為后綴標(biāo)注出來,代碼如下:

          train_loader = torch.utils.data.DataLoader(
          SVHNDataset(train_path, train_label,
          transforms.Compose([
          transforms.Resize((80, 160)), # TODO
          transforms.RandomCrop((64, 128)), # TODO
          transforms.ColorJitter(0.3, 0.3, 0.2),
          transforms.RandomRotation(5),
          transforms.ToTensor(),
          transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
          ])),
          batch_size=40,
          shuffle=True,
          num_workers=2,
          )
          val_loader = torch.utils.data.DataLoader(
          SVHNDataset(val_path, val_label,
          transforms.Compose([
          transforms.Resize((80, 160)), # TODO
          transforms.CenterCrop((64, 128)), # TODO
          transforms.ToTensor(),
          transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
          ])),
          batch_size=40,
          shuffle=False,
          num_workers=2,
          )
          test_loader = torch.utils.data.DataLoader(
          SVHNDataset(test_path, test_label,
          transforms.Compose([
          transforms.Resize((68, 136)), # TODO
          transforms.RandomCrop((64, 128)), # TODO
          transforms.ToTensor(),
          transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
          ])),
          batch_size=40,
          shuffle=False,
          num_workers=2,
          )

          這個(gè)優(yōu)化雖然很trick,但是效果顯著,大家可以思考下這6行代碼的修改是如何帶來成績的巨大提升的。

          二、不同解題思路的整理與分析

          除了baseline的思路以外,還有多種不同的解題思路,這里簡單進(jìn)行總結(jié)。

          2.1 CRNN

          純識別的思路,除了baseline的定長字符識別方案外,還可以用CRNN來做,屬于一種端到端的不定長字符識別的解決方案。

          關(guān)于CRNN,賽事組織者 阿水 已經(jīng)為我們提供了一個(gè)CRNN baseline[10],感謝去可以學(xué)習(xí)一下~

          2.2 檢測+識別

          除了兩種端到端的識別方案,還可以引入目標(biāo)檢測來解題,根據(jù)具體使用中檢測框粒度的不同,還可以細(xì)分為三種不同的方案:

          方案一:文本行檢測+文本行識別

          方案二:字符級目標(biāo)檢測+字符識別模型

          方案三:純目標(biāo)檢測方案

          根據(jù)我最近兩周持續(xù)對前排選手進(jìn)行的騷擾+在線乞討收集到的情報(bào)來看,前排選手使用的普遍是方案三,但是方案一、方案二也有人用,而且成績不差。也就是說,對于這個(gè)賽題,從實(shí)際結(jié)果上看這三個(gè)方案上限差不多。

          方案一是更標(biāo)準(zhǔn)的字符識別類問題的解決方案,如果我們的問題不是數(shù)字之間無關(guān)聯(lián)的門牌號識別,而是比如場景文字識別,那么方案一由于可以對不同字符間的關(guān)聯(lián)進(jìn)行建模,效果將會(huì)顯著優(yōu)于其它方案,但是本賽題這種優(yōu)勢無法發(fā)揮出來。

          而方案三作為一種端到端的解決方案,思路更直接,整個(gè)訓(xùn)練流程更簡單,更容易在有限的比賽時(shí)間內(nèi)優(yōu)化出好的效果,再加上有眾多簡單好用的開源庫,因此也是絕大多數(shù)前排選手選擇的原因。

          三、字符級目標(biāo)檢測的優(yōu)化技巧整理

          本文的最后一部分,再針對大家使用最多的字符級目標(biāo)檢測的方案,進(jìn)行一些簡單的整理。

          網(wǎng)絡(luò)框架選擇方面,前排普遍采用的是YOLOv3-v5的版本,還有一位選手使用的CenterNet獲得了非常好的效果。

          除了模型訓(xùn)練的各種小的trick以外,如何對模型結(jié)果進(jìn)行后處理,以及如何融合多個(gè)模型的結(jié)果,會(huì)對最終結(jié)果有很大影響。關(guān)于這部分,眾多選手都在天池的論壇熱心分享了自己的經(jīng)驗(yàn),細(xì)節(jié)太多很難一一列舉,我也有很多要學(xué)習(xí)的地方,這里就不班門弄斧了,感興趣的小伙伴趕快去學(xué)習(xí)吧~ 分別包括:

          天池街景字符識別總結(jié)[11]、第五名 yolov4 加 投票法方案[12]、街景字符編碼識別-第6名 線上0.938 方案分享[13]、yolov5加全局nms 第八名方案分享[14]、零基礎(chǔ)入門CV賽事-分享一些適合新手的0.92+的上分技巧吧[15]、真正零基礎(chǔ),單模型非融合,上93的最簡單技巧[16]參賽歷程以及方案分享[17]、零基礎(chǔ)CV賽--街景字符識別,小小白分享,從0.002~0.926[18]



          寫在最后

          如果覺得有收獲,可否給我們的《動(dòng)手學(xué)CV項(xiàng)目》[7]項(xiàng)目點(diǎn)個(gè)star呢,我的老火雞~

          (小聲叨叨,目前項(xiàng)目只更新了兩章,但大家天天私信催我的目標(biāo)檢測的入門教程已經(jīng)在做了)

          本文PDF后臺回復(fù)?上分?下載

          參考資料

          [1]

          賽題理解: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.21.2ce879dekK1l1d&postId=108659

          [2]

          數(shù)據(jù)讀取與數(shù)據(jù)擴(kuò)增: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.6.2ce879dekK1l1d&postId=108150

          [3]

          字符識別模型: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.3.2ce879dekK1l1d&postId=108711

          [4]

          模型訓(xùn)練與驗(yàn)證: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.18.2ce879dekK1l1d&postId=108780

          [5]

          模型集成: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.24.2ce879dekK1l1d&postId=108656

          [6]

          如何調(diào)參上分: https://tianchi.aliyun.com/course/video?spm=5176.12586971.1001.1.11be79delsbf6G&liveId=41169

          [7]

          動(dòng)手學(xué)CV項(xiàng)目: https://github.com/datawhalechina/dive-into-cv-pytorch

          [8]

          比賽實(shí)驗(yàn)記錄之?dāng)?shù)據(jù)增強(qiáng): https://github.com/tiantianheheaa1995/tianchi_CV_SVHN?spm=5176.12282029.0.0.45b24adcxaghR6

          [9]

          比賽實(shí)驗(yàn)記錄之定長識別問題: https://github.com/tiantianheheaa1995/tianchi_CV_SVHN?spm=5176.12282029.0.0.45b24adcxaghR6

          [10]

          CRNN-baseline: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.12.2ce879deix0lKP&postId=111274

          [11]

          天池街景字符識別總結(jié): https://tianchi.aliyun.com/forum/postDetail?spm=5176.12586969.1002.36.2ce879deix0lKP&postId=118992

          [12]

          第五名 yolov4 加 投票法方案: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.30.2ce879deix0lKP&postId=118791

          [13]

          街景字符編碼識別-第6名 線上0.938 方案分享: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.42.2ce879deix0lKP&postId=118810

          [14]

          yolov5加全局nms 第八名方案分享: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.27.2ce879deiwn8Cw&postId=116822

          [15]

          零基礎(chǔ)入門CV賽事-分享一些適合新手的0.92+的上分技巧吧: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.36.2ce879deiwn8Cw&postId=116724

          [16]

          真正零基礎(chǔ),單模型非融合,上93的最簡單技巧: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.27.2ce879deix0lKP&postId=118780

          [17]

          參賽歷程以及方案分享: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.33.2ce879deix0lKP&postId=118799

          [18]

          零基礎(chǔ)CV賽--街景字符識別,小小白分享,從0.002~0.926: https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.48.2ce879deix0lKP&postId=118789

          整理不易,點(diǎn)三連
          瀏覽 64
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久躁日日躁AAAAXXXX | 无码在线观看播放 | 亚洲中文字幕在线播放视频 | 国产一级一级毛片在线 | 国产theporn |