作者:MOHD SANAD ZAKI RIZVI
翻譯:吳金笛
校對:丁楠雅
文章來源:微信公衆号 資料派THU
----
本文首先介紹了TensorFlow.js的重要性及其元件,并介紹使用其在浏覽器中建構機器學習模型的方法。然後,建構使用計算機的網絡攝像頭檢測身體姿勢的應用程式。
概述
TensorFlow.js (deeplearn.js)使我們能夠在浏覽器中建構機器學習和深度學習模型,而無需任何複雜的安裝步驟。
TensorFlow.js的兩個元件——Core API和Layer API。
了解如何建構一個很棒的使用Tensorflow.js對網絡攝像頭中的圖像進行分類的模型。
介紹
你最喜歡用什麼工具來編寫機器學習模型?資料科學家們對這個永恒的問題會給出各種不同的答案。一些人喜歡RStudio,另一些人更喜歡Jupyter Notebooks。我絕對屬于後者。
是以,當我第一次遇到TensorFlow.js(以前是deeplearn.js)時,我的心都要炸開了。在浏覽器中建構機器學習模型?使用JavaScript?聽起來好得令人難以置信!
超過43億人使用網絡浏覽器——約占世界人口的55%。——維基百科(2019年3月)
谷歌的TensorFlow.js不僅将機器學習引入浏覽器中,使機器學習大衆化,而且對于經常使用JavaScript的開發人員來說,它也是一個完美的機器學習門戶。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CMiRmYkF2M0MDN2MmNiBjYwEDN0YWYzYmMhZ2NwgTM28CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
我們的網絡浏覽器是最容易通路的平台之一。這就是為什麼建構不僅能夠訓練機器學習模型而且能夠在浏覽器本身中“學習”或“遷移學習”的應用程式是有意義的。
在本文中,我們将首先了解使用TensorFlow.js的重要性及其它的不同元件。然後,我們将深入讨論使用TensorFlow.js在浏覽器中建構我們自己的機器學習模型。然後我們将建構一個應用程式,來使用計算機的網絡攝像頭檢測你的身體姿勢!
如果你是TensorFlow的新手,你可以在下面文章中了解更多:
- TensorFlow 101: Understanding Tensors and Graphs to get you Started with Deep Learning
- Introduction to Implementing Neural Networks using TensorFlow
目錄
一、為什麼你應該使用TensorFlow.js?
1.1 使用網絡攝像頭在浏覽器中進行圖像分類
1.2 TensorFlow.js的特征
二、了解浏覽器中的機器學習
2.1 Core API:使用Tensors工作
2.2 Layer API:像Keras一樣構模組化型
三、利用谷歌的預訓練模型:PoseNet
一、為什麼要使用TensorFlow.js?
我将用一種獨特的方法來回答這個問題。我不會深入研究TensorFlow.js的理論方面,也不會列出它為什麼是一個如此不可思議的工具。
相反,我将簡單地向你展示如果不使用TensorFlow.js将會錯過什麼。那麼,讓我們在5分鐘内建構一個應用程式,來使用你的網絡攝像頭對圖像進行分類。沒錯——我們将直接進入代碼部分!
這是最好的部分——你不需要安裝任何東西來做這個!隻要一個文本編輯器和一個網絡浏覽器即可。下面的動圖展示了我們将要建構的應用程式:
這多酷啊!我在浏覽器裡幾分鐘就完成了。那麼,讓我們看一下步驟和代碼,以幫助你在Web浏覽器中建構自己的圖像分類模型。
1.1 使用網絡攝像頭在浏覽器中建構圖像分類模型
打開你選擇的文本編輯器并建立一個檔案index.html。将以下代碼儲存于此檔案内:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- title of the page -->
<title>image_classification</title>
<!-- load processing library-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/addons/p5.dom.min.js"></script>
<!-- load ml5.js -->
<script src="https://unpkg.com/[email protected]/dist/ml5.min.js"></script>
<!-- load index.js -->
<script src="index.js"></script>
</head>
<body>
<!-- this is where the video will be shown -->
<video id="video"></video>
</body>
</html>
接下來,建立另一個檔案index.js并在其中編寫以下代碼:
let mobilenet;
let video;
let label = '';
// when model is ready make predictions
function modelReady() {
console.log('Model is ready!!!');
mobilenet.predict(gotResults);
}
function gotResults(error, results) {
if (error) {
console.error(error);
} else {
label = results[0].className;
// loop the inference by calling itself
mobilenet.predict(gotResults);
}
}
// setup function
function setup() {
createCanvas(640, 550);
// ml5 to create video capture
video = createCapture(VIDEO);
video.hide();
background(0);
// load the MobileNet and apply it on video feed
mobilenet = ml5.imageClassifier('MobileNet', video, modelReady);
}
function draw() {
background(0);
// show video
image(video, 0, 0);
fill(255);
textSize(32);
// show prediction label
text(label, 10, height - 20);
}
儲存這兩個檔案,然後在谷歌Chrome或Mozilla Firefox等浏覽器中打開index.html檔案。就是這樣!你現在已經建立了一個可以使用你的網絡攝像頭在浏覽器本身實時分類圖像的應用程式!下面是它在我的計算機上的樣子:
視訊連接配接:
https://s3-ap-south-1.amazonaws.com/av-blog-media/wp-content/uploads/2019/05/mobilenet_demo.mp4?_=1在這個例子中需要注意的要點:
- 在上面的例子中,我們使用了一個預先訓練的圖像分類模型MobileNet( https://ai.googleblog.com/2017/06/mobilenets-open-source-models-for.html )
- 我們使用ml5.js( https://ml5js.org/ )一個建構在TensorFlow之上的庫。它将MobileNet模型加載到浏覽器中,并對視訊提要執行推理。
- 我們還利用P5.js( https://p5js.org/ )庫來處理視訊輸入并在視訊本身上顯示标簽。
我不需要在電腦上安裝任何東西。這個例子應該适用于任何現代系統,不管它是Linux、Windows還是MacOS——這就是使用JavaScript在web上構模組化型的強大功能。
現在,讓我們看看TensorFlow.js提供的強大功能,以及如何利用它們在浏覽器中部署機器學習模型。
1.2 TensorFlow.js的特征
TensorFlow.js是一個庫,用于JavaScript開發和訓練ML模型,并在浏覽器或Node.js上部署。
TensorFlow.js提供了許多的功能來供我們使用。
它是TensorFlow在JavaScript中的擴充,JavaScript是我們在網際網路上使用的幾乎所有網站、浏覽器或應用程式邏輯背後的程式設計語言。JavaScript和Python一樣用途廣泛,是以使用它來開發機器學習模型給我們帶來了很多好處:
- 如果ML模型是用web語言編寫的,則更容易部署。
- 由于所有主流浏覽器都支援JavaScript,是以你可以無處不在地使用它,而不必擔心平台類型或其他相容性問題。對于你的使用者也是如此。
- TensorFlow.js是一個用戶端庫,這意味着它可以在使用者的浏覽器中訓練或運作ML模型。這減輕了與資料隐私有關的任何擔憂。
- 在你的用戶端上運作實時推斷可使你的應用程式更具互動性,因為它們可以立即響應使用者輸入(例如我們前面建構的webcam應用程式)。
TensorFlow.js以其目前的形式提供了以下主要功能:
- 浏覽器中的機器學習:你可以使用TensorFlow.js在浏覽器中建立和訓練ML模型。
- 谷歌的預訓練模型:TensorFlow.js配備了一套由谷歌預訓練的模型,用于對象檢測、圖像分割、語音識别、文本毒性分類等任務。
- 遷移學習:你可以通過對已經訓練過的模型的部分進行再訓練來執行轉移學習,比如TensorFlow.js中的MobileNet。
- 部署python模型:使用Keras或TensorFlow訓練的模型可以很容易地導入浏覽器/使用TensorFlow.js的部署。
在本文中,我們将關注前兩個功能。在本系列的第二部分(即将推出!)中,我們将讨論如何在Python中轉移學習和部署我們的模型。
二、浏覽器中的機器學習
TensorFlow.js提供了兩種方法來訓練模型(非常類似于TensorFlow):
- 第一種方法是使用Core API使用低級張量操作來定義模型。
- 第二種方法是使用Layers API定義模型,類似于Keras。
讓我們通過幾個例子來了解這兩種方法。畢竟,學習一個概念最好的方法就是把它付諸實踐!
首先,設定你的HTML檔案:
在你的電腦上建立一個新的index.html檔案,并在其中編寫以下代碼:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- load Tensorflow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
</head>
<body>
<h1>Tensorflow.js Core API</h1>
<!-- <script src="index.js"></script> -->
<script type="text/javascript">
</script>
</body>
</html>
我們建立了一個基本的HTML頁面,并從雲URL中加載了Tensorflow.js(第7行)。
關于安裝TensorFlow.js(deeplearn.js)的說明:
由于TensorFlow.js是為浏覽器而設計的,是以安裝和使用TensorFlow.js最簡單的方法就是根本不安裝它。你可以簡單地從HTML中的URL加載它即可。
如果你想在本地工作怎麼辦呢?實際上,你可以在Jupyter Notebook中使用TensorFlow.js,就像你在Python或R中通常做的那樣。這是一個适合每個人的解決方案!
這種本地方法稍微長一些,并且需要一些時間,是以本文不會使用它。如果你确實想學習如何操作,可以從為Jupyter安裝ijavascript核心開始。下面是我的Jupyter Notebook的截圖:
現在,使用TensorFlow.js的推薦方法是使用庫的官方URL直接加載它。你隻需将以下行添加到HTML檔案中:
<scriptsrc="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
完成了!這真的很簡單。
2.1 Core API:使用Tensors工作
Core API與TensorFlowCore非常相似,我們可以使用低級張量運算和線性代數定義模型。
如果我們想要建構自定義模型或想要從頭開始建構神經網絡,這非常有用。讓我們舉一個在浏覽器中使用張量的例子。
首先在index.html檔案中的
const a = tf.tensor([1, 2, 3, 4]);
const b = tf.tensor([10, 20, 30, 40]);
const y = a.add(b); // equivalent to tf.add(a, b)
const z = a.mul(b);
y.print();
z.print();
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- load Tensorflow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
</head>
<body>
<h1>Tensorflow.js Core API</h1>
<!-- <script src="index.js"></script> -->
<script type="text/javascript">
const a = tf.tensor([1, 2, 3, 4]);
const b = tf.tensor([10, 20, 30, 40]);
const y = a.add(b); // equivalent to tf.add(a, b)
const z = a.mul(b); // equivalent to tf.mul(a, b)
y.print();
z.print();
</script>
</body>
</html>
在上面的代碼中,我們在兩個張量a和b上執行基本的加法和乘法運算,并将結果列印在浏覽器中。現在,轉到終端,打開項目檔案夾,然後使用以下指令啟動Python伺服器:
python3 -m http.server
然後在你的浏覽器打開以下位址:
http://localhost:8000/
當你看到一個頁面顯示“Tensorflow.js Core API”時,使用Ctrl+Shift+I鍵打開控制台(console)。這應該在Chrome和Firefox都适用。我們在控制台得到上述操作的輸出:
如果你想深入閱讀有關Core API的更多資訊,那麼我建議你閱讀CoreAPI官方文檔。
CoreAPI文檔:
https://www.tensorflow.org/js/guide/tensors_operations2.2 Layer API:像Keras一樣構模組化型
Layers API與Python中的Keras非常相似。就像Keras一樣,你可以使用序列的和函數的方法建立模型。
讓我們通過一個例子仔細研究序列方法。我們将在這些資料點上訓練回歸模型:
這裡,X和Y有一個線性關系——每個Y對應于X + i(其中i是0、1、2、3……n+1)。讓我們在這個資料集上訓練一個基本的回歸模型。你可以在index.html檔案中的标記之間編寫以下代碼:
const callbacks = {
onEpochEnd: async (epoch, logs) => {
console.log("epoch: " + epoch + JSON.stringify(logs))
}
};
// Generate some synthetic data for training.
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
const ys = tf.tensor2d([[1], [3], [5], [7]], [4, 1]);
// Build and compile model.
async function basicRegression(){
// Build a sequential model
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});
// Train model with fit().
await model.fit(xs, ys, {epochs: 100, validationSplit: 0.1, callbacks: callbacks});
// Run inference with predict().
model.predict(tf.tensor2d([[5]], [1, 1])).print();
}
// Create a basic regression model
basicRegression();
敏銳的讀者一定注意到,上面的文法與用Python建構順序模型的Keras文法非常相似。我們回到浏覽器控制台(console)時會得到預測。
我們的簡單回歸模型預測7.556,非常接近8的期望值。這是一個基本的例子,但我們可以清楚地看到,在浏覽器中直接建構機器學習模型是多麼容易和有用。
TensorFlow.js能夠在浏覽器中建構機器學習和深度學習模型。它還自動利用GPU(s)的強大功能,如果在你的系統模型訓練期間可用。
下面是一些使用TensorFlow.js在一些标準資料集上訓練的深度學習模型的例子:
你可以在tfjs-examples repository中浏覽這些示例。
tfjs-examples repository:
https://github.com/tensorflow/tfjs-examplesTensorFlow.js提供了大量來自谷歌的預訓練模型,用于許多有用的任務,如目标檢測、語音識别、圖像分割等。預先訓練的模型的優點是,我們可以使用它們而不需要任何重大的依賴關系或安裝,并且可以開箱即用。
人們普遍預計谷歌将在未來幾個月推出更多模型。你可以在下面連結檢視可用的預訓練模型:
相關連結:
https://www.tensorflow.org/js/models我們将在本文中使用PoseNet。PoseNet是一種視覺模型,可以通過估計人體關鍵關節的位置來估計一個人在圖像或視訊中的姿勢。
PoseNet是如何工作的?
這是一個迷人的概念。姿勢估計是一種計算機視覺技術,用于檢測圖像和視訊中的人物。例如,這可以幫助我們确定某人的肘部在圖像中出現的位置。
隻是要清楚-姿勢估計不是關于識别誰在一個圖像中。該算法隻是簡單地估計關鍵身體關節的位置。
檢測到的關鍵點設定為“Part”和“ID”索引,置信度得分在0.0和1.0之間(1.0是最高的)。
以下是PoseNet給出的輸出類型的示例:
難以置信,對吧?!我們将使用ml5.js庫來使用PoseNet。ml5.js是一個基于TensorFlow.js和p5.js的庫。p5.js是另一個庫可以使你更容易在浏覽器中通路網絡攝像頭。
ml5.js旨在使機器學習對廣大的藝術家,創意編碼員和學生來說變得平易近人。該庫以TensorFlow.js為基礎,通過簡單的文法在浏覽器中提供對機器學習算法和模型的通路。
例如,你可以使用ml5.js在5行代碼中使用MobileNet建立圖像分類模型,如下所示:
正是由于Ml5.js的簡單性,使得它非常适合在浏覽器中快速建構原型,這也是我們在項目中使用它的原因。
讓我們回到PoseNet。建立一個新檔案index.html并添加以下代碼:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- load p5.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/addons/p5.dom.min.js"></script>
<!-- load ml5.js -->
<script src="https://unpkg.com/[email protected]/dist/ml5.min.js" type="text/javascript"></script>
<!-- keep the video in center of browser -->
<style type="text/css">
body{
text-align: center;
}
</style>
</head>
<body>
<h1>PoseNet demo with Ml5.js</h1>
<p id="status">Loading Model...</p>
<div id="videoContainer"></div>
<!-- load the posenet.js file -->
<script src="posenet.js"></script>
</body>
</html>
這将建立一個基本的HTML網頁并加載必要的檔案:
- ml5.js和p5.js是通過其官方URL加載的。
- posenet.js是我們将編寫用于使用PoseNet的代碼的檔案。
現在,我們将編寫用于使用PoseNet的JavaScript代碼。在與index.html相同的檔案夾中建立一個新檔案posenet.js。以下是完成此項工作所需的步驟:
加載PoseNet模型并從網絡攝像頭捕獲視訊
檢測身體關節的關鍵點
顯示檢測到的身體關節
繪制估計的身體骨骼
讓我們從第一步開始。
步驟1:加載PoseNet模型并從網絡攝像頭捕獲視訊
我們将使用ml5.js加載PoseNet。與此同時,p5.js使我們可以用幾行代碼從網絡攝像頭捕獲視訊:
let video;
let poseNet;
let poses = [];
function setup() {
const canvas = createCanvas(640, 480);
canvas.parent('videoContainer');
// Video capture
video = createCapture(VIDEO);
video.size(width, height);
// Create a new poseNet method with a single detection
poseNet = ml5.poseNet(video, modelReady);
// This sets up an event that fills the global variable "poses"
// with an array every time new poses are detected
poseNet.on('pose', function(results) {
poses = results;
});
function modelReady(){
select('#status').html('model Loaded')
}
以上代碼塊中最重要的是:
- createCapture(VIDEO):它是一個p5.js函數,用于通過攝像頭捕獲視訊來建立視訊元素。
- ml5.poseNet(video,modelRead):我們使用ml5.js加載poseNet模式。通過傳入視訊,我們告訴模型處理視訊輸入。
- PoseNet.on():每當檢測到一個新的姿勢時,就執行這個函數。
- modelReady():當PoseNet完成加載時,我們調用這個函數來顯示模型的狀态。
步驟2:檢測身體關節的關鍵點
下一步是檢測姿勢。你可能已經注意到,在前面的步驟中,我們通過調用poseNet.on()将每個檢測到的位姿儲存到pose變量中。這個函數在背景連續運作。無論何時找到一個新的姿勢,它都會以以下格式給出身體關節的位置:
- 'score'是指模型的置信度
- 'part'表示檢測到的身體關節/關鍵點
- 'position'包含檢測到的部分的x和y位置
我們不必為此部分編寫代碼,因為它是自動生成的。
步驟3:顯示檢測到的人體關節
我們知道被檢測到的人體關節及其x和y位置。現在,我們隻需要在視訊上畫出它們來顯示檢測到的人體關節。我們已經看到,PoseNet給出了一個檢測到的人體關節清單,每個關節及其x和y位置的置信度評分。
我們将使用20%的門檻值(keypoint.score > 0.2)置信度得分,以便繪制一個關鍵點。下面是實作這一操作的代碼:
// A function to draw ellipses over the detected keypoints
function drawKeypoints() {
// Loop through all the poses detected
for (let i = 0; i < poses.length; i++) {
// For each pose detected, loop through all the keypoints
let pose = poses[i].pose;
for (let j = 0; j < pose.keypoints.length; j++) {
// A keypoint is an object describing a body part (like rightArm or leftShoulder)
let keypoint = pose.keypoints[j];
// Only draw an ellipse is the pose probability is bigger than 0.2
if (keypoint.score > 0.2) {
fill(255, 0, 0);
noStroke();
ellipse(keypoint.position.x, keypoint.position.y, 10, 10);
}
}
}
}
步驟4:繪制估計的身體骨架
除了關鍵點或身體關節,PoseNet還可以檢測估計的身體骨架。我們可以使用pose變量來繪制骨架:
// A function to draw the skeletons
function drawSkeleton() {
// Loop through all the skeletons detected
for (let i = 0; i < poses.length; i++) {
let skeleton = poses[i].skeleton;
// For every skeleton, loop through all body connections
for (let j = 0; j < skeleton.length; j++) {
let partA = skeleton[j][0];
let partB = skeleton[j][1];
stroke(255, 0, 0);
line(partA.position.x, partA.position.y, partB.position.x, partB.position.y);
}
}
}
在這裡,我們周遊檢測到的骨架并建立連接配接關鍵點的線。代碼還是相當簡單。
現在,最後一步是重複調用drawSkeleton()和drawKeypoints()函數,以及我們從網絡攝像頭捕獲的視訊源。我們可以使用p5.js的draw()函數來實作,該函數在setup()之後直接調用,并重複執行:
function draw() {
image(video, 0, 0, width, height);
// We can call both functions to draw all keypoints and the skeletons
drawKeypoints();
drawSkeleton();
}
接下來,轉到終端視窗,進入項目檔案夾,然後啟動Python伺服器:
python3 -m http.server
然後轉到你的浏覽器并打開以下位址:
http://localhost:8000/
瞧!你的PoseNet應該很好地檢測到了你的身體姿勢(如果你已經正确地遵循了所有步驟)。以下是我的模型的情況:
尾記
你可以看到我為什麼喜歡TensorFlow.js。它非常有效率,甚至不需要你在構模組化型時擔心複雜的安裝步驟。
TensorFlow.js展示了通過将機器學習帶到浏覽器中使機器學習更容易通路的許多前景。同時,它還具有資料隐私、互動性等優點。這種組合使得它成為資料科學家工具箱中的一個非常強大的工具,特别是如果你想部署你的機器學習應用程式的話。
在下一篇文章中,我們将探讨如何在浏覽器中應用遷移學習,并使用TensorFlow.js部署機器學習或深度學習模型。
我們用PoseNet做的項目可以更進一步,通過訓練另一個分類器來建構一個姿态識别應用程式。我鼓勵你去嘗試一下!
原文标題:
Build a Machine Learning Model in your Browser using TensorFlow.jsand Python
原文連結:
https://www.analyticsvidhya.com/blog/2019/06/build-machine-learning-model-in-your-browser-tensorflow-js-deeplearn-js/譯者簡介
吳金笛,雪城大學計算機科學碩士一年級在讀。迎難而上是我最舒服的狀态,動心忍性,曾益我所不能。我的目标是做個早睡早起的Cool Girl。
翻譯組招募資訊
工作内容:需要一顆細緻的心,将選取好的外文文章翻譯成流暢的中文。如果你是資料科學/統計學/計算機類的留學生,或在海外從事相關工作,或對自己外語水準有信心的朋友歡迎加入翻譯小組。
你能得到:定期的翻譯教育訓練提高志願者的翻譯水準,提高對于資料科學前沿的認知,海外的朋友可以和國内技術應用發展保持聯系,資料派THU産學研的背景為志願者帶來好的發展機遇。
其他福利:來自于名企的資料科學工作者,北大清華以及海外等名校學生他們都将成為你在翻譯小組的夥伴。