我一生中大约73%的时间都在思考网络性能:如何在慢速手机上能播放60FPS的画面,用完美的顺序加载资源,通过离线缓存能做的一切。等等等等。
但最近我一直在想,我对Web性能定义是否太狭隘了。从用户的角度来看,所有的炫酷事情都只是性能的一小部分。
所以我打开了一个非常熟悉的网站,并把用户需要做的任务都过了一遍,而且还给每个任务定了时。 (我们需要一个定制用户旅程的时间线工具)
很快我就发现有一些可以改进的步骤了。
本文的其余部分重点介绍一个特定网站上的特定步骤。但是我想这一解决方案(也就是机器学习)可以在许多不同的站点中与许多不同场景有相似的应用。
这一例子网站是用户可以卖二手物品,其他用户可以淘宝的地方。
当用户在网站上发帖出售东西时,他们要先选择物品的类别,选择期望的广告包,填好细节内容,然后预览广告内容,最后发布这个广告。
第一步:选择一个类别,就把我带坑里了。
首先, 这里一共有674个类别。我真不知道我的破皮艇到底是哪一类。Steve Krug说的很好:别让我思考。
其次,即便我清楚我的东西在哪个类,在哪个子类,在哪个子类的子类,这个过程也要起码花上12秒。
如果我给你说,你的页面加载时间可以减少12秒,你肯定会想怎么做。那为什么不想想怎么在其他地方减少12秒呢?
就像 Julius Caesar说的:“12秒能做多少事!”。
还有,对用户来说,无知即幸福。我认为如果我把标题、描述、商品价格输入一个训练好的机器学习的模型里,它就能自动的识别这个东西是什么类别的。
因此,相比让用户花了那么多时间来选择分类,那不如让他们在reddit上找一个手工床上多花12秒。
When this began, I knew absolutely nothing about machine learning, other than it could play video games, and outperform the world’s best go-go dancer at chess. 起初,我完全不知道什么是机器学习,只知道它能打打游戏,最近还甚至打败世界顶级的下棋选手。
所以我就尝试学习一下。下面的步骤花了我不到一小时:
(注意:既然我没有认真的学习过机器学习,那我这整篇文章的措辞都可能是用错了的。)
亚马逊 在他们的ML文档里 搞定了这件事。如果你觉得智商被我的文章侮辱了,那么你可以先把这篇文章放一边,过5个小时再来读读看。我可不会尝试在这里总结有关机器学习的内容。
读完文档,我计划如下:
我放了一个大大的表单来模拟用户的输入输出。
现在你就能看到一些感兴趣的内容了。相信我,这些分类都是从这个机器学习的模型里自动计算出的。
Let’s try selling a fridge: 现在让我们来卖个冰箱
duang~
鱼缸呢?
看来这个小可爱知道鱼缸是什么!
必须承认,看到这个我还是挺开心的。你看,这还挺赞的,不是么?
如果你很好奇我是怎么做这个表单的,,我用到了React、Redux、jQuery、Mobx、BlueBird、Bootstrap、Sass、Compass、NodeJS、Express、Lodash,另外再用Webpack打个包。所有文件加起来不超过1M,
好了,现在我们看看次要点的部分。
因为我只是随便试试,我需要从某些地方拿到足够多的数据。我需要至少十几个类别的10000多个物品。我找了一个当地的交易网站,看了下他们的URL和DOM,然后写了个脚本抓了数据,并且输出到一个CSV中去。这件事大概花了我4个多小时,一半的时间花在调通这个脚本上。
我把得到的CSV上传到S3上去,然后按着教程又建了新的模型,再训练。总共消耗的CPU时间是3分钟。
界面上有一个很好的实时预测的部分,所以我可以测试。如果我设定某些参数,它就会显示预测结果
很好,正常工作。High Five。
现在,我并不想用Amazon API,因为我不希望这个API是公开的。所以,我需要用我自己的node server提供这个API。
方法很简单。我只需要传入model ID和一些数据,然后它返回预测结果。
const AWS = require('aws-sdk');
const machineLearning = new AWS.MachineLearning();
const params = {
MLModelId: 'some-model-id',
PredictEndpoint: 'some-endpoint',
Record: {},
};
machineLearning.predict(params, (err, prediction) => {
// we have a prediction!
});
中途我差点放弃了,因为大小写变化太多,我很难集中注意力。不过还要坚持战斗。
这个纪录
,哦,抱歉,我是说这条记录
,是一个JSON对象,它的属性就是用来训练模型的那些属性(标题,描述和价格)。
我可不想成为那些发很少代码对大家没帮助的人,所以,下面是我所有的 server.js
,以及/predict
的入口。
const express = require('express');
const bodyParser = require('body-parser');
const AWS = require('aws-sdk');
const app = express();
app.use(express.static('public'));
app.use(bodyParser.json());
AWS.config.loadFromPath('./private/aws-credentials.json');
const machineLearning = new AWS.MachineLearning();
app.post('/predict', (req, res) => {
const params = {
MLModelId: 'my-model-id',
PredictEndpoint: 'https://realtime.machinelearning.us-east-1.amazonaws.com',
Record: req.body,
};
machineLearning.predict(params, (err, data) => {
if (err) {
console.log(err);
} else {
res.json({ category: data.Prediction.predictedLabel });
}
});
});
app.listen(8080);
你还记得不能用JavaScript写后端代码的日子么?
还有aws-credentials.json
的部分:
{
"accessKeyId": "my-access-key-id",
"secretAccessKey": "shhh-secret-squirrel",
"region": "us-east-1"
}
对了,我的/private
目录在.gitignore
里,所以不会上传
恩,后端代码就完成了。
表单后的代码部分其实很简单,就做这么几件事:
POST
到我刚创建的 /predict
入口(function() {
const titleEl = document.getElementById('title-input');
const descriptionEl = document.getElementById('desc-input');
const priceEl = document.getElementById('price-input');
const catSuggestionsEl = document.getElementById('cat-suggestions');
const catSuggestionEl = document.getElementById('suggested-category');
function predictCategory() {
const fetchOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: titleEl.value,
description: descriptionEl.value,
price: priceEl.value,
})
};
fetch('/predict', fetchOptions)
.then(response => response.json())
.then(prediction => {
catSuggestionEl.textContent = prediction.category;
catSuggestionsEl.style.display = 'block';
});
}
document.querySelectorAll('.user-input').forEach(el => {
el.addEventListener('blur', predictCategory);
});
})();
还记得不能对NodeList
用forEach
的日子么?
完成。这就是全部的代码。功能就是把用户输入的数据作为输入,调用一个机器学习的机器人对物品进行预测,最后输出物品的类别。
先别着急走,朋友。这好魔法也不是免费的...
用来训练的上述模型(大约10,000行/ 4列的CSV)是6.3 MB。建一个server接受请求,又要花掉6.3M的内存。成本大概是每小时$0.0001,大约一年8刀。我买手套的钱都比这多。
每条预测结果也收费,大概是$0.0001。所以,你懂的,别做太随机的预测。
当然了,不只是Amazon提供这些好货,我只是没从别人那找到更便宜的。
Google有 TensorFlow,但是他们的getting started guide文档里我就看不下去。
Microsoft也有一个Machine Learning offering,不过我还在为IE6生气(不过,或许以后我会写一篇Amazon VS Microsoft的博文)。
也许我很容易惊讶(我还记得当我意识到'news'是'new'的复数形式的情景),但我还是认为这是非常了不起的事。它允许像你这样的普通人(在某种程度上来说,比如我也是)能够在操作机器学习,并可能对用户体验进行一些很大的改进。
上面这个例子肯定是我设计出来的,我承认。我还留了一张把烤面包机分类成马的截图。
我可以列出所有我能预见的问题,但如果你能自己发现这些问题,会更有意思。
所以,你自己去试试把。
往期精选文章 |
---|
使用虚拟dom和JavaScript构建完全响应式的UI框架 |
扩展 Vue 组件 |
使用Three.js制作酷炫无比的无穷隧道特效 |
一个治愈JavaScript疲劳的学习计划 |
全栈工程师技能大全 |
WEB前端性能优化常见方法 |
一小时内搭建一个全栈Web应用框架 |
干货:CSS 专业技巧 |
四步实现React页面过渡动画效果 |
让你分分钟理解 JavaScript 闭包 |
小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。