你的手泄露了性別與年齡 | 內附CNTK與PyTorch代碼
5 人贊了文章
因知乎文章字數限制,本文的大量代碼均為截圖,如需更好的閱讀體驗,可跳轉:你的手泄露了你的性別與年齡(內附CNTK與PyTorch 代碼)
用手就能夠知道性別與年齡,透過卷積神經網路就能做到這麼神奇的效果。從數據到模型,手把手教你用cntk或pytorch做出來。
隨著深度學習的技術發展,越來越多的深度學習應用也進入到我們的世界。其中最為普遍的就是人臉識別,包括微軟也推出了cognitive
face api,可以透過人臉來識別身份,甚至可以用他來判斷性別與年齡。各位以為用人臉識別性別年齡就很厲害了嗎?在這邊要來讓各位瞧瞧深度學習的黑科技可以黑到甚麼程度。我們將會透過微軟的深度學習框架cntk以及臉書的pytorch(以下解說部份張貼的皆為cntk代碼,文章最後會一次貼出兩個框架個代碼)來實作根據手的照片來判斷人的性別與年齡。(什麼,你想問為何沒有tensorflow,不好意思,我就是不喜歡tensorflow.....哈)首先關於使用的數據來自與谷歌(好吧,谷歌的戲份到此為止),他提供了一組數據包含了11000張手部的照片,同時包含手的主人的性別年齡與種族。我們將會擷取裡面的性別(類別)與年齡(連續)數據來作為輸出變數,手部圖片作為輸入特徵。下載圖片的路徑如下:
https://sites.google.com/view/11khands
如果你嫌下載後還要自己整理圖片麻煩,我也有做好的圖片懶人包,我已經有將圖片數據向量化(為了方便下載,我把圖片大小縮到64*64,原始圖檔是1600*1200,如果你想要大張一點的圖片可以用以下介紹的方法來調整),以及比對好標籤檔的結果,我將他以pickle檔案格式儲存。您可以使用以下語法解析pickle檔。解析完的結果是一個清單,清單內的每個項目也是一個子清單,裡面分別包含兩個ndarray,第一個是形狀3*64*64的向量代表圖檔(請注意,cntk與pytorch都是CHW格式:通道*高*寬),另一個則是形狀為3的向量,裡面三個數值分別為id(數值相同代表是同一個人的不同角度的手)、年齡(介於0~100)以及性別(0是女1是男)
懶人包下載位置:
https://1drv.ms/u/s!AsqOV38qroofiOWrBW79ytqmS0pvJDE
imagearr=[]with open(Data/hands.pkl, rb) as fp: imagearr=pickle.load(fp)
CNTK與pytorch的圖片格式要求是一樣的(tensorflow跟全業界唱反調,順序都是反的),向量維度的排列是CHW(通道*高*寬),顏色的排列順序是BGR(藍綠紅),也就都是依照字母順序排列。
關於圖片與向量的轉換方法如下:
為了供給建模使用的資料讀取器,而且因為我想要畢其功於一役,讓兩種框架都可以一次適用,所以我寫了一個通用的讀取器來供應每個minibatch所需要的數據,其中讀取圖片時,我將圖片向量除以255,而且讀取年齡時,我將數值除以100,都是為了確保數據可以界於0~1之間,以方便收斂。在這個範例中因為篇幅關係暫時不放數據增強(data augmentation)。利用以下函數,每次調用都可以回傳圖片以及所需要標籤。此外,要注意的是打亂圖片順序這個步驟很重要,谷哥的數據是有按照性別排序的。
在這裡要示範的卷積神經網路骨幹網路用的是我最近很推崇的一篇文章所介紹的新架構「DenseNet」,原始論文出處如下。
Densely Connected Convolutional Networks
Gao Huang, Zhuang Liu, Laurens van der Maaten, Kilian Q. Weinbergerhttps://arxiv.org/abs/1608.06993
傳統的卷積網路都是線性的,但當層數越多時,就有可能發生梯度彌散的問題,造成模型無法收斂,所以微軟亞洲院2015年發展出的ResNet(殘差神經網路)就使用了跳轉連接(skip connection),來有效的將梯度挹注到後面神經層,這樣模型就可以做出超深的架構,也不用擔心難以收斂,微軟2015年就以152層的ResNet獲得了當年的imageNet冠軍。但是深度學習在訓練的過程中,當卷積神經網路將梯度傳送到後層的時候,都會發生特徵被隨機遺失,這樣這個特徵就在也傳不下去而無用了。為了解決這個問題,DenseNet的基本概念就是,每一層的特徵都會傳送到後面的「每」一層,這樣就可以有效的確保信號不被丟失。
DenseNet的基本結構稱之為「稠密單元(Dense Block)」,他有幾個重要的超參數:
k: 稠密單元層數
n_channel_start:初始通道數
glowth_rate:通道成長數
我們以下圖為例,假設下圖是一個k=4(向下傳遞4次,所以共5層),初始通道數32,成長數為16的Dense Block,我們分別計算每一層的輸入通道數(從前面傳進來的):
綠色:32+16(來自於紅色)=48
紫色:48+16(來自於綠色)=64黃色:64+16(來自於紅色)+16(來自於綠色)=96褐色:96+16(來自於紅色)+16(來自於綠色)+16(來自於紫色)=144
rate有就是每次會傳遞多少通道到後面的層數,以上面說明案例固定數值為16,但該卷積層的的通道數比這數字更大,因此等於是強迫每個卷積層要做一次特徵選取,將特徵精選之後傳至後方,這種「Save the best for last (讓人想起這首凡妮莎維廉斯的老歌)」,可以高度保全有效特徵,以強化模型的收斂。DenseNet就是利用多個DenseBlock構成的網路。
cntk與pytorch都沒有預設的DenseNet,所以我用自訂網路的方式實作了兩個框架下的DenseNet
由於圖片只有64*64,經不起太多次圖片縮小,因此我使用了5層k=4的Dense Block(我測試過3層,收斂快,但是結果測試集落差很大,顯著過擬合)。由於我想要同時預測性別與年齡,cntk一個很神奇的特性就是可以在一個主要骨架下,同時接兩個輸出,只需要使用combine()函數,就可以將兩個輸出合併,未來只要做一次預測,就能產出兩個預測結果,而且訓練時也只要訓練一次,而且骨幹部分特徵選取流程不需要做兩次,是不是很方便呢。如果你是使用其他框架就只好做兩個模型了。預測性別部分,使用的是長度為2的向量,最後一層全連接層活化函數使用softmax已進行分類。預測年齡部分,由於我們讀取數據時已經將年齡除以100,因此年齡分布為0~1之間的常態分布,因此使用sigmoid函數效果較好。
def densenet(input,depths=(4, 4, 4, 4, 4), growth_rate=16, n_channel_start=32,drop_rate=0.5, activation=leaky_relu): x = conv_bn((3, 3), n_channel_start, pad=True, strides=1, init=he_normal(0.02), activation=activation,bias=True)(input) skips, x = down_path(x, depths, growth_rate, drop_rate=drop_rate, activation=leaky_relu) x = conv_bn((1, 1), 64, (1, 1), pad=True, drop_rate=0, activation=activation)(x) z_gender = Dense(2, activation=softmax, init=he_normal(), init_bias=0)(x) # 預測性別,使用softmax z_age=Dense(1,activation=sigmoid,init=he_normal(),init_bias=0)(x) #預測年齡,使用sigmoid,因為是預測連續數值,輸出為0~1 return combine([z_gender,z_age])
最後的訓練過程可以透過以下函數來控制。首先宣告輸入變數以及兩個輸出變數(性別與年齡),然後宣告模型、損失函數以及正確率指標。優化器使用的是adam,然後每50個minibatch就用測試集測試一次。
我使用gtx-1080(minibatch size=64)跑完第3個epoch的結果如下,年齡誤差只有1.8%,性別目前仍有20.31%的錯誤率,看來手真的藏不住年齡啊。這個模型若是希望提升他的泛化效果,應該要在輸入數據加入數據增強,後續的文章中我會們在來介紹數據增強的作法,以及介紹如何將深度學習模型工程化,與硬體連接變成可以落地的實際應用,請期待後續文章。
cntk完整語法
pytorch 完整語法
本文作者
尹相志
- 微軟金牌講師,在2006年-2017年連續獲得微軟最有價值專家稱號(MVP)
- 曾任華院數據首席數據科學家,數據決策技術長
- 連續16年機器學習與 NLP 經驗,領導多個領域的數據挖掘項目
今日課程直播
在本周三的集智AI學園直播課程《推估預測問題的建模與評測方法》中,具有 16 年數據處理經驗的尹相志老師,會針對機器學習任務中最普遍的推估預測問題進行詳細的講解。
聽課時間:7月11日(周三)19:30-21:30
直播內容:
- 推估問題:回歸、神經網路、時間序列
- 推估問題案例:不動產價格預測、電力需求預測
- 如何處理與時間周期相關的數據
- 如何找出數值間的潛在關聯
- 如何評估推估模型
- 實作:運用python演練推估問題
直播地址:
http://campus.swarma.org/gcou=10430 (二維碼自動識別)
http://campus.swarma.org/gcou=10430 (二維碼自動識別)
來源:
https://dotblogs.com.tw/allanyiin/2018/07/06/082817
關注集智AI學園公眾號
獲取更多更有趣的AI教程吧!搜索微信公眾號:swarmAI
集智AI學園QQ群:426390994
學園網站:http://campus.swarma.org
商務合作和投稿轉載|swarma@swarma.org
推薦閱讀:
TAG:PyTorch | 深度學習DeepLearning | 人工智慧 |