一款可以用JS构建的机器学习应用,无需任何数学运算🙈
机器学习是构建人工智能应用的一种超酷方式——但说实话,它确实需要大量的数学知识。幸运的是,有了ml5.js,我们无需花费数月时间学习机器学习,只需几个小时就能将其应用到我们的应用中,并开发出一些很棒的功能😄
这是一份构建特征提取器的指南——它可以从你的网络摄像头获取视频流,并在用少量数据进行训练后预测它看到的内容——就像上面的视频中一样!
🍴 前端分支
我不想在前端部分浪费您太多时间——我认为直接跳到 JavaScript 和逻辑部分会更好。
你应该 fork 这个 repl - https://repl.it/@jajoosam/feature-extractor-start - 这样你就可以直接使用现有的 HTML 代码了!它本质上只是几个div用来显示视频和其他文本的 s 标签,以及一些用来控制我们应用的按钮!
我已经对所有内容都添加了注释(除了 CSS 代码😛),所以你应该能在几分钟内浏览前端并了解应用程序的基本布局。完成后,请前往……script.js
✏️ 声明变量
我们需要声明很多变量,所以我们首先要做的是创建它们。
我们的应用程序将包含许多功能,所有功能都必须能够访问变量——这就是为什么我们要在代码开头就声明变量的原因。
var featureExtractor, classifier, video, loss, redCount, blueCount;
redCount = blueCount = 0;
我会简要介绍一下这些功能的用途,但随着我们继续开发应用程序,你会更好地理解它们。
featureExtractor这些classifier变量我们将用于存储和初始化机器学习模型。
video是我们存储网络摄像头流的地方,同时loss让我们知道我们的特征提取器训练到了什么程度。
最后,blueCount和分别是每个类别中图像数量的计数器——我们在下一行redCount中将它们的值都初始化为。0
🛠️setup()
setup()这是一个会在我们的代码准备就绪后立即触发的函数。由于使用了p5.js,我们的代码非常易读易懂。
function setup() {
// Tells p5 to not automatically create a canvas element.
noCanvas();
// Starts capturing a video feed from the webcam
video = createCapture(VIDEO);
// Puts the video stream into the div in our html, with ID `video`
video.parent('video');
// Initializes a feature extractor, yet to be trained - from ml5.js
featureExtractor = ml5.featureExtractor('MobileNet');
classifier = featureExtractor.classification(video);
// What we're doing next - setting up buttons!
setupButtons();
}
这段代码要放在script.js声明变量之后——它的作用是获取视频流并将其显示在页面上,显示在divID 为 `<video>` 的 ` <div>` 标签内video。我们还使用 ml5.js 库创建了一些函数,并将捕获的视频作为参数传递——你很快就会看到这些函数的作用,但还有一些设置工作要做!
如您所见,在代码末尾setup(),我们调用了setupButtons()接下来要编写的函数。这里,我们为 HTML 中的按钮添加了事件监听器,以便在按钮被点击时运行相应的函数。
以下是我们为该函数编写的所有代码setupButtons()👇
// A function to create the buttons
function setupButtons() {
buttonA = select('#red');
buttonB = select('#blue');
buttonA.mousePressed(function() {
redCount++;
classifier.addImage('red');
select('#redCount').html(redCount);
});
buttonB.mousePressed(function() {
blueCount++;
classifier.addImage('blue');
select('#blueCount').html(blueCount);
});
train = select('#train');
train.mousePressed(function() {
classifier.train(function(lossValue) {
// This is where we're actually training our model
if (lossValue) {
loss = lossValue;
select('#info').html('Loss: ' + loss);
} else {
select('#info').html('Done Training! Final Loss: ' + loss);
select('#train').style("display", "none");
select('#predict').style("display", "inline");
}
});
});
// Predict Button
buttonPredict = select('#predict');
buttonPredict.mousePressed(classify);
}
这是我们应用程序中最大的艺术作品,我将把它分成几个部分,以便更容易解释!
🧙♂️但是这些按钮是做什么用的?!
不要恐慌。
我们先从这个模块开始:
buttonA = select('#red');
buttonB = select('#blue');
buttonA.mousePressed(function() {
redCount++;
classifier.addImage('red');
select('#redCount').html(redCount);
});
buttonB.mousePressed(function() {
blueCount++;
classifier.addImage('blue');
select('#blueCount').html(blueCount);
});
buttonA而buttonB这不正是我们应用程序中的两个不同的按钮吗!
我们.mousePressed()来定义按下这些按钮时会发生什么——具体来说:
++使用运算符将计数加 1。- 从网络摄像头视频中捕获当前帧并将其添加到分类器中。
classifier.addImage() - 通过更改按钮文本来更新我们应用程序中的计数,
.html()
接下来,我们来看这整个模块——我们在这里训练分类器本身:
train = select('#train');
train.mousePressed(function() {
classifier.train(function(lossValue) {
// This is where we're actually training our model
if (lossValue) {
loss = lossValue;
select('#info').html('Loss: ' + loss);
} else {
select('#info').html('Done Training! Final Loss: ' + loss);
select('#train').style("display", "none");
select('#predict').style("display", "inline");
}
});
});
当Train 🚋我们的应用程序上的按钮被按下时,我们会调用classifier.train()——并且每次迭代都会调用我们在那里提供的函数——这就是为什么我们看到损失值不断变化的原因。
当损失值为 时0,我们将隐藏该Train 🚋按钮,并显示之前隐藏的Predict 🔮按钮!
函数的最后两行setupButtons()是关于预测按钮的:
buttonPredict = select('#predict');
buttonPredict.mousePressed(classify);
看来我们正在调用这个classify函数——这就是我们接下来要构建的内容!
继续加油,我们快完成了💯
🔮 预测及结果展示
我们的classifier()职能非常简单明了——我们只做这件事:
function classify() {
classifier.classify(gotResults);
}
我们只是告诉 ml5classifier将当前帧分类为 🔴 或 🔵 类之一,并将结果发送到gotResults函数——这就引出了我们应用程序的最后一部分!
只要分类器没有向我们发送错误,我们就将整个页面的背景颜色更改为 0red或blue1,然后classify()再次调用,这样我们的代码就会一直运行下去,预测结果也会不断出现!
function gotResults(err, result) {
if (err) {
console.log(err);
}
select("body").style("background", result);
classify();
}
这就是构建示例特征提取器所需的所有代码。我强烈建议您通读一遍最终代码,以便了解各个部分是如何协同工作的——我知道有很多函数需要记住,但我已经为所有函数添加了注释,方便您理解😅
现在就去试试吧!以下是我为了验证特征提取器是否有效而做的一些操作(结果成功了!)👇
- 保持我的头在左边🔴,右边🔵
- 在🔴中画一个✌️,在🔵中画一个✋
- 在🔴和🔵中佩戴不同颜色的👕
告诉我它还有哪些其他很棒的用途👀
✨ 好吧,但我该用这些做什么呢?
你可以做的事情太多了!特征提取器让你能够为你的应用程序添加一种全新的、神秘的控制和输入方式!
这里有一些想法💡
- 一款可在浏览器中直接畅玩的手势控制游戏🎮
- 情绪追踪器——整天开着标签页,用不同的面部表情训练它🤔
- 自选热狗应用🌭
- 开发一款只能通过手势发送消息的应用程序💬
👨🏫 还有什么?
ml5.js 功能强大,令人惊叹!你可以像我一样将图像分类集成到自己的应用中,找到与文本内容相似的词语,获取人体精确的骨骼结构,甚至可以转换图像的风格——看看我的照片,用酷炫的绘画风格重新组合后的效果🖌️
你应该看看ml5.js 网站上的众多示例,或者看看Dan Shiffman 关于 ml5.js 的视频,他讲解了很多 ml5.js 的功能,而且讲解得非常生动有趣。我强烈推荐你在Coding Train 的YouTube 频道上观看他的视频!
如果有任何问题,欢迎在推特上联系我,或者在评论区留言 :)
文章来源:https://dev.to/jajoosam/an-ml-app-you-can-build-with-js-and-without-the-math-3dbk




