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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

blazeface学习笔记

發布時間:2023/11/27 生活经验 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 blazeface学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

完整的應該是一個人臉識別項目,人臉識別,大言不慚的說,我之前其實也做過,比如用dlib來做人臉識別,就是用opencv那一套來實現,說句實在話,速度非常慢,即便是在intel CPU上,一秒也就兩三幀,確實是太慢了

我其實也用過其他方案,比如前幾年,下載虹軟的免費的庫,進行試用,效果確實驚人,給我印象最深刻的,倒不是識別準確度有多高,而是速度真的飛快,

我也試過MTCNN,這個只要網上搜索人臉檢測,基本都是搜到這個結果,我也嘗試過,我不知道別人是如何夸獎這個庫的,我試用的體會就是,經常誤識別,就是本來就不是個人臉,卻非要識別成一個人臉,通常認為,可以提高閾值,進行過濾,可是我的體會是,有些明明不是人臉的地方,其confidence卻非常高,而有些明明是人臉的地方,卻又漏減,我不知道為啥別人還到處推薦.

人臉檢測,用我這外行的話,應該是分為四個步驟

1.人臉檢測,不僅要檢測出人臉,而且要檢測出關鍵點,

?2.根據檢測到的關鍵點進行人臉對齊,也就是alignment,也就是仿射變換,那是不是可以不對齊呢?按說也可以,但研究發現,人臉對齊后,人臉識別的難度就大大降低了

3.把對齊后的人臉送到神經網絡中去計算,得到一個128維的向量

4.把這個向量,跟其他人臉的向量進行對比,如果比較接近,那就認為是同一個人

除了上面提到的幾個庫,我還用過商湯的人臉識別庫,在imx6(Cortex-A9)的芯片上,其檢測速度可以達到12FPS,還是相當出色的,不過我記得其加載速度比較慢,加載可能要半分鐘,不過好在只需啟動的時候加載一次。

當然,無論是商湯的庫,還是虹軟的庫,都是閉源的,而且還需要Licence,如果Licence過期就無法使用了;

目前開源的人臉識別庫,比較優秀的,有arcface,跟虹軟重名,比較可靠的實現,可以參考

https://github.com/deepinsight/insightface/tree/master/recognition/arcface_paddle

或者

https://github.com/onnx/models/tree/main/vision/body_analysis/arcface

當然我也寫了一點點筆記,

基于onnx的人臉識別_zhqh100的博客-CSDN博客

下面說回人臉檢測,之前在YouTube上看到過Google宣傳的FaceMesh的功能,印象深刻

不僅速度很快,而且結果穩定,只不過其沒有開放訓練的源碼,我在網上搜到了一個Pytorch版本的實現,

https://github.com/zmurez/MediaPipePyTorch.git

這個是一個演示,復現了上面的功能,以及速度,我看單幀平均速度為22ms,在Intel I7上。

不過可惜該項目中沒有訓練代碼,只有推理demo代碼。

然后我又找到了一個項目,是

https://github.com/zineos/blazeface.git

其中包含推理代碼和訓練代碼,

該工程是從另一個工程改過來的,拿到手有點迷茫,就是直接運行會報錯,我fork之后稍微改了一下,我的工程是

https://github.com/moneypi/blazeface

還有一點是這個訓練數據,在百度網盤上的鏈接失效了,我就重新從Google上下載下來,重新傳了一份,

鏈接:https://pan.baidu.com/s/1ao-XwW6i8VXsSvh_fSelgQ?pwd=u7ii

提取碼:u7ii

--來自百度網盤超級會員V1的分享

打印出的網絡結構如下:

Blaze((conv1): Sequential((0): Conv2d(3, 24, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True))(conv2): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=24, bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(conv3): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=24, bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(conv4): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2), groups=24, bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(shortcut): Sequential((0): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(1): Conv2d(24, 48, kernel_size=(1, 1), stride=(1, 1))(2): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(3): ReLU(inplace=True)))(conv5): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(48, 48, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=48, bias=False)(1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(conv6): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(48, 48, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=48, bias=False)(1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(conv7): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(48, 48, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2), groups=48, bias=False)(1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(48, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(1): ReLU(inplace=True)(2): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(3): ReLU(inplace=True))(shortcut): Sequential((0): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(1): Conv2d(48, 96, kernel_size=(1, 1), stride=(1, 1))(2): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(3): ReLU(inplace=True)))(conv8): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=96, bias=False)(1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(96, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(1): ReLU(inplace=True)(2): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(3): ReLU(inplace=True)))(conv9): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=96, bias=False)(1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(96, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(1): ReLU(inplace=True)(2): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(3): ReLU(inplace=True)))(conv10): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2), groups=96, bias=False)(1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(96, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(1): ReLU(inplace=True)(2): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(3): ReLU(inplace=True))(shortcut): Sequential((0): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(1): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1))(2): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(3): ReLU(inplace=True)))(conv11): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=96, bias=False)(1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(96, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(1): ReLU(inplace=True)(2): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(3): ReLU(inplace=True)))(conv12): BlazeBlock((actvation): ReLU(inplace=True)(conv): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), groups=96, bias=False)(1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(96, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(1): ReLU(inplace=True)(2): Sequential((0): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False)(1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(24, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)(4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(3): ReLU(inplace=True)))(loc): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96)(1): ReLU(inplace=True)(2): Conv2d(96, 8, kernel_size=(1, 1), stride=(1, 1)))(1): Sequential((0): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96)(1): ReLU(inplace=True)(2): Conv2d(96, 24, kernel_size=(1, 1), stride=(1, 1))))(conf): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96)(1): ReLU(inplace=True)(2): Conv2d(96, 4, kernel_size=(1, 1), stride=(1, 1)))(1): Sequential((0): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96)(1): ReLU(inplace=True)(2): Conv2d(96, 12, kernel_size=(1, 1), stride=(1, 1))))(landm): Sequential((0): Sequential((0): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96)(1): ReLU(inplace=True)(2): Conv2d(96, 20, kernel_size=(1, 1), stride=(1, 1)))(1): Sequential((0): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96)(1): ReLU(inplace=True)(2): Conv2d(96, 60, kernel_size=(1, 1), stride=(1, 1))))
)

inputs的shape為[1, 3, 320, 320],其中backbone有四次下采樣,會把第四次下采樣前和網絡的最后結果保存到detections中,分別為[1, 96, 40, 40]和[1, 96, 20, 20]

這兩個結果會分別送到loc_layers、conf_layers和landm_layers中去計算,得出的尺寸為

loc[0]的shape是[1, 40, 40, 8],loc[1] 的shape是?[1, 20, 20, 24],加一塊,再分成四個坐標,就是bbox_regressions.shape=[1, 5600, 4]

conf[0].shape=[1, 40, 40, 4]

conf[1].shape=[1, 20, 20, 12]

加一塊得到classifications.shape=[1, 5600, 2]

landm[0].shape=torch.Size([1, 40, 40, 20])
landm[1].shape=torch.Size([1, 20, 20, 60])

加一塊得到?ldm_regressions.shape=torch.Size([1, 5600, 10])

回過頭來看anchors,配置文件中'steps': [8, 16],而圖像尺寸為320*320,那么就得出小框為320/8,即40*40個,大框為320/16,即20*20個,

然后'min_sizes': [[8, 11], [14, 19, 26, 38, 64, 149]],,即40*40的框,分別會生成尺寸為8和11的anchor,而20*20的框,就遍歷[14, 19, 26, 38, 64, 149],也就是總共會生成40 * 40 * 2 + 20 * 20 *6=3200+2400=5600個框

所以,綜上,基本證實了,blazeface,就是一個小號的ssd,其沒有FPN的融合,然后,也是基于anchor的實現,所以,如果用anchor-free的方法,網絡還有進一步減小的空間?

損失函數,landmark 和 location 都是使用了?smooth_l1_loss,

loss_c,分類的損失函數為focalloss

按說給各個損失都添加了權重的比重系數,不過我看其代碼中只用到了分類的系數,也就是 loss_c會再乘以6,然后各個損失相加,就是總損失

計算各損失的時候,都是采樣一部分進行計算

我基本沒有做修改(其實修改了batchsize,原工程默認值為256, 我修改為了64,顯卡為GeForce RTX 2060, 6G,沒那么闊),評估精度為:

==================== Results ====================
Easy   Val AP: 0.8039773948120692
Medium Val AP: 0.7454040908046184
Hard   Val AP: 0.4292227434416538
=================================================

用工程中自帶的模型參數測試,

==================== Results ====================
Easy   Val AP: 0.7667513659507036
Medium Val AP: 0.6894514595432863
Hard   Val AP: 0.34819400614673535
=================================================

我靠,我沒優化,我訓練的結果居然比他自帶的精度還高一些,Surprise

訓練時間是從2022-03-23 22:43到2022-03-24 04:55,大概6個小時

因為看到訓練的loss曲線波動很大,所以嘗試降低lr,降了一半,看起來loss曲線確實好了一點,但精度卻降低了?

==================== Results ====================
Easy   Val AP: 0.7789928144856131
Medium Val AP: 0.7163551912058919
Hard   Val AP: 0.3995628884327997
=================================================

所以,暫時還是用原來的學習率,做其他嘗試

我嘗試替換激活函數,看是否能提高準確率,我用nn.Softplus()來替換了原來所有的?nn.ReLU(inplace=True),意識到了一個問題,Softplus這個激活函數沒有inplace這個參數,那么需要的顯存空間會更大,我原本6G的顯存,在Relu的時候,'batch_size': 64,基本跑滿,而替換為Softplus之后,我只好設置為'batch_size': 40,不過好消息是,精度確實提高了,這是目前為止,最高的一個點

==================== Results ====================
Easy   Val AP: 0.8155068518500983
Medium Val AP: 0.7586505701251691
Hard   Val AP: 0.4390300734203851
=================================================

執行測試,運行的是

python test_widerface.py

獲取上面結果,運行的是

cd widerface_evaluate/
python evaluation.py

下面學習權重量化,先嘗試了一下?quantize_dynamic,發現精度和量化前完全一致,所以查一下到底是哪里的問題,從網上別人的教程,順便跳轉到?quantize_dynamic?的源碼看了一下,其默認只會對如下模塊進行量化:

nn.Linear, nn.LSTM, nn.GRU, nn.LSTMCell, nn.RNNCell, nn.GRUCell

那我們這里基本沒有用到上面的模塊,所以也基本沒啥變化.

然后,我嘗試做了一下模型量化,但水平不行,沒有實現,參考?

一次失敗的Pytorch模型量化嘗試_zhqh100的博客-CSDN博客我的原工程模型是blazeface學習筆記_zhqh100的博客-CSDN博客完整的應該是一個人臉識別項目,人臉識別,大言不慚的說,我之前其實也做過,比如用dlib來做人臉識別,就是用opencv那一套來實現,說句實在話,速度非常慢,即便是在intel CPU上,一秒也就兩三幀,確實是太慢了我其實也用過其他方案,比如前幾年,下載虹軟的免費的庫,進行試用,效果確實驚人,給我印象最深刻的,倒不是識別準確度有多高,而是速度真的飛快,我也試過MTCNN,這個只要網上搜索人臉檢測,基本都是搜到這個結果,我也嘗試過,我https://blog.csdn.net/zhqh100/article/details/123742045

昨天試了一下加FPN,當然這里就是修改模型了,而不是復現論文,我在模型里加了如下幾行

fpn_bak = F.interpolate(detections[1], size=(detections[0].size(2), detections[0].size(3)))
# detections[0] = torch.cat((detections[0], fpn_bak), dim=1)
detections[0] = torch.add(detections[0], fpn_bak)

當然用cat可能也行,但是用cat的花,就需要增加參數量,我盡量還是不增加參數量,訓練完成的精度為:

==================== Results ====================
Easy   Val AP: 0.8127231180335884
Medium Val AP: 0.7547545989153277
Hard   Val AP: 0.43340084728149164
=================================================

說一下我這里的配置,我目前的batchsize是40,初始學習率是1e-3,激活函數在試量化的時候改回了ReLU,

因為之前使用Softplus的時候,精度提高了很多,所以我再次替換類ReLU激活函數,看是否能提高精度,我在網上看到一篇文章,

激活函數 | Squareplus性能比肩Softplus激活函數速度快6倍(附Pytorch實現)-技術圈本文提出了Squareplus激活函數,這是一個類似softplus的激活函數,但只需要通過簡單的代數運算來實現:加法、乘法和平方根。由于Squarhttps://jishuin.proginn.com/p/763bfbd704d4當然我也不知道他是不是原創,他里面貼了一個pytorch實現的squareplus,我用了之后發現他是一個坑,他代碼寫錯了,少寫一個平方,所以我這里貼一下我改之后的實現

class Squareplus(nn.Module):def __init__(self, b=0.2):super(Squareplus, self).__init__()self.b = bdef forward(self, x):x = 0.5 * (x + torch.sqrt(torch.square(x)+self.b))return x

然后精度還是有提高的

==================== Results ====================
Easy   Val AP: 0.8200590574413846
Medium Val AP: 0.7649220162383361
Hard   Val AP: 0.4490872484483122
=================================================

這個精度已經超過了上面的最高精度

稍微說一下,就是我這里用自己實現的Squareplus函數,訓練顯存又大了一點,所以batchsize又從40改為了30,然后推理速度的話,用ReLU的時候,推理速度大概是不到4ms,當然這里不說后處理,后處理也要2.4ms左右,然后用Squareplus的時候,推理速度大概算6ms了,所以慢很多

我總是感覺ReLU的激活函數太過粗暴,我希望能找到一個平滑的,能參數自適應的激活函數,看是否能得出更好的效果,而squareplus就是一個單調遞增的,平滑的函數,我修改為了自適應版本,如下:

class Squareplus(nn.Module):def __init__(self):super(Squareplus, self).__init__()self.b = torch.nn.Parameter(torch.tensor([1., 1., 1e-8]))def forward(self, x):x = 0.5 * (self.b[0] * x + self.b[1] * torch.sqrt(torch.square(x)+torch.square(self.b[2])))return x

因為squareplus的公式為

那如果b=0的時候,其實SquarePlus就跟ReLU完全相等,我最開始的時候,是想上面代碼中直接用self.b[2] = 0.應該也能訓練,但實際情況是如果self.b[2]=0.的時候,loss直接就NaN,inf了,所以我給了一個接近0的值,那實際效果來看,精度確實提升了一點點:

==================== Results ====================
Easy   Val AP: 0.8227621694850481
Medium Val AP: 0.7662798102976387
Hard   Val AP: 0.4513160808024386
=================================================

這個比上面所有的精度都高,但也不算驚人吧,但比較顯著的是,推理速度慢了很多,升到了差不多8ms,

我預測時候,把所有的self.b打印出來了,如下:

[0.8454, 0.3644, 0.1367]
[ 0.8873,  0.7530, -0.1533]
[0.7036, 0.6800, 0.2724]
[ 0.4455,  1.2127, -0.0125]
[0.9210, 0.5843, 0.1486]
[0.9819, 0.7223, 0.4142]
[ 1.0522,  0.6184, -0.2266]
[ 0.8519,  0.4931, -0.3491]
[0.8119, 0.8772, 0.6076]
[ 0.8358,  0.4341, -0.3027]
[ 0.7915,  0.9259, -0.6816]
[ 0.6944,  0.8840, -0.6110]
[0.9455, 0.5593, 0.4089]
[0.8080, 0.8872, 0.4731]
[0.7749, 0.7353, 0.7412]
[ 1.0064,  0.6360, -0.3702]
[1.3030, 0.3886, 0.2978]
[1.2454, 0.5487, 0.1881]
[0.6192, 1.0405, 0.6971]
[0.7321, 0.9983, 0.5140]
[0.6235, 1.0673, 0.8745]
[1.1215, 0.7250, 0.2422]
[ 1.2247,  0.7770, -0.0237]
[0.5734, 1.0426, 0.8500]
[0.8035, 1.0243, 0.4659]
[ 0.5823,  1.1394, -1.0904]
[ 1.8497,  0.8324, -0.1130]
[ 1.9515,  1.0291, -0.0616]
[ 0.5608,  1.0035, -0.5520]
[ 0.7945,  0.8310, -0.3079]
[0.7418, 0.9905, 0.5818]
[ 0.9830,  0.4994, -0.2175]
[1.0192, 0.6735, 0.4724]
[ 0.8990,  0.6039, -0.0406]
[ 0.5347,  1.1900, -0.3618]
[0.8685, 0.9823, 0.1829]
[0.7512, 0.9619, 0.5523]
[ 1.1577,  0.7502, -0.2851]
[0.9508, 0.7332, 0.0213]
[0.6115, 1.0775, 0.5334]
[0.8370, 1.0327, 0.4429]
[0.8130, 1.0963, 0.8485]
[ 1.8354,  0.8548, -0.1749]
[ 1.4897,  0.7104, -0.0795]
[1.1626, 1.1678, 0.0058]
[ 0.9293,  0.8205, -0.1558]
[1.2170, 1.4804, 0.0718]
[ 1.7995,  0.9660, -0.0163]
[ 1.3056,  1.1443, -0.0841]
[1.6489, 1.1632, 0.1204])

感覺還蠻有意思的

總結

以上是生活随笔為你收集整理的blazeface学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

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