Mars演算法實踐——人臉識別
源於MaxCompute,阿里首款自研科學計算引擎Mars1月16日開源釋出
https://promotion.aliyun.com/ntms/act/cloud/marsfbh.html
Mars 是一個基於矩陣的統一分散式計算框架,在之前的文章中已經介紹了 Mars 是什麼, 以及 Mars 分散式執行 ,而且 Mars 已經在 GitHub 中開源。當你看完 Mars 的介紹可能會問它能做什麼,這幾乎取決於你想做什麼,因為 Mars 作為底層運算庫,實現了 numpy 70% 的常用介面。這篇文章將會介紹如何使用 Mars 完成你想做的事情。
奇異值分解 (SVD)
在處理紛繁的資料時,作為資料處理者,首先想到的就是降維,SVD 就是其中一種比較常見的降維方法,在 numpy.linalg
模組中就有 svd
方法,當我們有20000個100維的資料需要處理,呼叫 SVD 介面:
In [1]: import numpy as np
In [2]: a = np.random.rand(20000, 100)
In [3]: %time U, s, V = np.linalg.svd(a)
CPU times: user 4min 3s, sys: 10.2 s, total: 4min 13s
Wall time: 1min 18s
可以看到即使 Numpy 使用了 mkl 加速,也需要1分多鐘的執行時間,當資料量更大時,單機的記憶體已經無法處理。
Mars 也實現了 SVD ,但是它比 Numpy 有更快的速度,因為利用矩陣分塊計算的演算法,能夠平行計算:
In [1]: import mars.tensor as mt
In [2]: a = mt.random.rand(20000, 100, chunk_size=100)
In [3]: %time U, s, V = mt.linalg.svd(a).execute()
CPU times: user 5.42 s, sys: 1.49 s, total: 6.91 s
Wall time: 1.87 s
可以看到在相同資料量情況下,Mars 有幾十倍速度的提升,僅僅需要1秒多鍾就可以解決20000資料量的降維問題。想象一下淘寶使用者資料做矩陣分解時,分散式的矩陣運算就顯現出其價值。
主成分分析 (PCA)
提到降維,主成分分析也是一種重要的手段。PCA 會選取包含資訊量最多的方向對資料進行投影,其投影方向可以從最大化方差或者最小化投影誤差兩個角度理解。也就是通過低維表徵的向量和特徵向量矩陣,可以基本重構出所對應的原始高維向量。其最主要的公式如下所示:
$$
mathop {max }limits_{{mu _j}} frac{1}{n}{sumlimits_i^n {left( {{x_i}{mu _j} – overline x }
ight)} ^T}left( {{x_i}{mu _j} – overline x }
ight) = {mu _j}^TC{mu _j}
$$
$x_i$為每個樣本的資料,$mu _j$為新的投影方向,我們的目標就是使得投影方差最大化,從而找到主特徵。上面式子中的矩陣$C$在數學中可以用協方差矩陣表示,當然首先要對輸入的樣本做中心化調整。我們可以用隨機產生的陣列看一下 Numpy 是如何實現 PCA 降維操作:
import numpy as np
a = np.random.randint(0, 256, size=(10000, 100))
a_mean = a.mean(axis=1, keepdims=True)
a_new = a - a_mean
cov_a = (a_new.dot(a_new.T)) / (a.shape[1] - 1)
#利用SVD求協方差矩陣前20個特徵值
U, s, V = np.linalg.svd(cov_a)
V = V.T
vecs = V[:, :20]
#用低緯度的特徵向量表示原資料
a_transformed = a.dot(vecs)
由於隨機產生的資料本身就沒有太強的特徵,所以在100維資料中象徵性的取出前20維,一般可以用特徵值的比例取總和的前99%之類的數值。
再看一下 Mars 是如何實現的:
import mars.tensor as mt
a = mt.random.randint(0, 256, size=(10000, 100))
a_mean = a.mean(axis=1, keepdims=True)
a_new = a - a_mean
cov_a = (a_new.dot(a_new.T)) / (a.shape[1] - 1)
#利用SVD求協方差矩陣前20個特徵值
U, s, V = mt.linalg.svd(cov_a)
V = V.T
vecs = V[:, :20]
#用低緯度的特徵向量表示原資料
a_transformed = a.dot(vecs).execute()
可以看到除了 import 的不同,再者就是對最後需要資料的變數呼叫 execute
方法,甚至在未來我們做完 eager 模式後, execute
都可以省去,以前用 Numpy 寫的演算法可以幾乎無縫轉化成多程式以及分散式的程式,再也不用自己手動去寫MapReduce。
人臉識別
當 Mars 實現了基礎演算法時,便可以使用到實際的演算法場景中。PCA最著名的應用就是人臉特徵提取以及人臉識別,單個人臉圖片的維度很大,分類器很難處理,早起比較知名的人臉識別 Eigenface 演算法就是採用PCA演算法。本文以一個簡單的人臉識別程式作為例子,看看 Mars 是如何實現該演算法的。
本文的人臉資料庫用的是ORL face database,有40個不同的人共400張人臉圖片,每張圖片為 92*112 畫素的灰度圖片。這裡選取每組圖片的第一張人臉圖片作為測試圖片,其餘九張圖片作為訓練集。
首先利用 python 的 OpenCV 的庫將所有圖片讀取成一個大矩陣,也就是 360*10304大小的矩陣,每一行是每個人臉的灰度值,一共有360張訓練樣本。利用 PCA 訓練資料,data_mat
就是輸入的矩陣,k
是需要保留的維度。
import mars.tensor as mt
from mars.session import new_session
session = new_session()
def cov(x):
x_new = x - x.mean(axis=1, keepdims=True)
return x_new.dot(x_new.T) / (x_new.shape[1] - 1)
def pca_compress(data_mat, k):
data_mean = mt.mean(data_mat, axis=0, keepdims=True)
data_new = data_mat - data_mean
cov_data = cov(data_new)
U, s, V = mt.linalg.svd(cov_data)
V = V.T
vecs = V[:, :k]
data_transformed = vecs.T.dot(data_new)
return session.run(data_transformed, data_mean, vecs)
由於後續做預測識別,所以除了轉化成低維度的資料,還需要返回平均值以及低維度空間向量。可以看到中間過程平均臉的樣子,前幾年比較火的各地的平均臉就可以通過這種方式獲取,當然這裡的維度以及樣本比較少,大概只能看出個人臉的樣子。
其實 data_transformed
中儲存的特徵臉按照畫素排列之後也能看出特徵臉的形狀。圖中有15個特徵臉,足以用來做一個人臉分類器。
另外在函式 PCA
中用了 session.run
這個函式,這是由於三個需要返回的結果並不是相互獨立的,目前的延遲執行模式下提交三次運算會增加運算量,同一次提交則不會,當然立即執行模式以及運算過的部分圖的剪枝工作我們也在進行中。
當訓練完成之後,就可以利用降維後的資料做人臉識別了。將之前非訓練樣本的圖片輸入,轉化成降維後的維度表示,在這裡我們就用簡單的歐式距離判斷與之前訓練樣本中每個人臉資料的差距,距離最小的就是識別出的人臉,當然也可以設定某個閾值,最小值超過閾值的判斷為識別失敗。最終在這個資料集下跑出來的準確率為 92.5%,意味著一個簡單的人臉識別演算法搭建完成。
# 計算歐氏距離
def compare(vec1, vec2):
distance = mt.dot(vec1, vec2) / (mt.linalg.norm(vec1) * mt.linalg.norm(vec2))
return distance.execute()
未來
上文展示瞭如何利用 Mars 一步一步地完成人臉識別小演算法的過程,可以看到 Mars 類 Numpy 的介面對演算法開發人員十分友好,演算法規模超出單機能力時,不再需要關注如果擴充套件到分散式環境,Mars 幫你處理背後所有的並行邏輯。
當然,Mars 還有很多可以改進的地方,比如在 PCA 中對協方差矩陣的分解,可以用特徵值、特徵向量計算,計算量會遠小於 SVD 方法,不過目前線性代數模組還沒有實現計算特徵向量的方法,這些特性我們會一步步完善,包括 SciPy 裡各種上層演算法介面的實現。大家有需求的可以在 GitHub 上提 issue 或者幫助我們共建 Mars。
Mars 作為一個剛剛開源的專案,十分歡迎提出其他任何想法與建議,我們需要大家的加入,讓 Mars 越來越好。
相關文章
- 1月9日雲棲精選夜讀|Mars演算法實踐——人臉識別演算法
- 人臉識別:技術應用與商業實踐
- opencv 人臉識別OpenCV
- 影象格式轉化在人臉識別應用中的實踐
- 人臉檢測識別,人臉檢測,人臉識別,離線檢測,C#原始碼C#原始碼
- 人臉識別之特徵臉方法(Eigenface)特徵
- 人臉識別檢測專案實戰
- C#人臉識別入門篇-STEP BY STEP人臉識別--入門篇C#
- 智慧人臉識別門禁系統開發,人臉識別開鎖流程
- 前端人臉識別--兩張臉相似度前端
- python—呼叫API人臉識別PythonAPI
- 基於Android平臺實現人臉識別Android
- 人臉活體檢測人臉識別:眨眼+張口
- python ubuntu dlib人臉識別3-人臉對齊PythonUbuntu
- 人臉識別之Python DLib庫進行人臉關鍵點識別Python
- 乾貨 | AI人臉識別之人臉搜尋AI
- 人臉識別智慧考勤系統開發_人臉識別考勤管理系統開發
- 人臉識別影像的模糊度判別演算法的最佳化演算法
- matlab實現人臉識別(數學基礎原理)Matlab
- 如何用Excel 9步實現CNN人臉識別ExcelCNN
- 從零玩轉人臉識別
- 前端如何玩轉人臉識別前端
- Python人臉識別微笑檢測Python
- 人臉識別技術應用
- 基於開源模型搭建實時人臉識別系統(五):人臉跟蹤模型
- 基於開源模型搭建實時人臉識別系統(四):人臉質量模型
- 機器學習實戰-SVM模型實現人臉識別機器學習模型
- 人臉識別之人臉檢測的重要性
- 保障人臉安全!頂象釋出《人臉識別安全白皮書》
- 刷臉支付人臉識別特徵點越多是別越精確特徵
- 【ROS】OpenCV+ROS 實現人臉識別(Ubantu16.04)ROSOpenCV
- 64行程式碼實現簡單人臉識別行程
- 手把手教你實現人臉識別,有手就行
- 虹軟人臉識別ArcSoft3.0NodeJs 版本實現NodeJS
- TensorFlow2.0 + CNN + keras + 人臉識別CNNKeras
- OpenCV-Python 人臉眼睛嘴識別OpenCVPython
- 人臉識別系列(三):DeepID2
- 人臉識別系列(二):DeepID1