前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用机器学习加速你的网站

用机器学习加速你的网站

作者头像
疯狂的技术宅
发布2019-03-27 15:57:11
1.6K0
发布2019-03-27 15:57:11
举报
文章被收录于专栏:京程一灯京程一灯

我一生中大约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. 起初,我完全不知道什么是机器学习,只知道它能打打游戏,最近还甚至打败世界顶级的下棋选手。

所以我就尝试学习一下。下面的步骤花了我不到一小时:

  1. Google "Machine Learning"
  2. 点开了很多页面
  3. 发现了Amazon的机器学习
  4. 意识到我可以不需要了解机器学习
  5. 松了一口气

(注意:既然我没有认真的学习过机器学习,那我这整篇文章的措辞都可能是用错了的。)

整个过程,是黑箱的

亚马逊 在他们的ML文档里 搞定了这件事。如果你觉得智商被我的文章侮辱了,那么你可以先把这篇文章放一边,过5个小时再来读读看。我可不会尝试在这里总结有关机器学习的内容。

读完文档,我计划如下:

  • 在一个CSV文件里放一些数据。每一行代表一件物品,比如我的皮艇。列就是标题、目录、价格、分类。
  • 把CSV上传到ASW的S3 bucket里去。
  • 用这个数据‘train’机器理解这个数据(这在他们的界面上都做好了,还有在线帮助)。他们的云机器人就能知道如何根据标题、描述和价格预测分类了。
  • 然后在加入一些代码,把用户输入发给AWS的接入点(Amazon会自动创建接入点),预测分类就在界面上显示了。

实例网站

我放了一个大大的表单来模拟用户的输入输出。

现在你就能看到一些感兴趣的内容了。相信我,这些分类都是从这个机器学习的模型里自动计算出的。

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和一些数据,然后它返回预测结果。

代码语言:javascript
复制
 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的入口。

代码语言:javascript
复制
 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的部分:

代码语言:javascript
复制
{
  "accessKeyId": "my-access-key-id",
  "secretAccessKey": "shhh-secret-squirrel",
  "region": "us-east-1"
}

对了,我的/private目录在.gitignore里,所以不会上传

恩,后端代码就完成了。

前端代码

表单后的代码部分其实很简单,就做这么几件事:

  • 监听相关字段的blur事件
  • 获取元素的具体值
  • 把数据 POST到我刚创建的 /predict入口
  • 把返回的结果填到category字段,
代码语言:javascript
复制
(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);
  });
})();

还记得不能对NodeListforEach的日子么?

完成。这就是全部的代码。功能就是把用户输入的数据作为输入,调用一个机器学习的机器人对物品进行预测,最后输出物品的类别。

安静的把我的钱带走

先别着急走,朋友。这好魔法也不是免费的...

用来训练的上述模型(大约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 闭包



小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京程一灯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 拨开问题的云雾
  • 机器学习 -- 不要逃避,拥抱它
  • 整个过程,是黑箱的
  • 实例网站
  • 后端代码
  • 前端代码
  • 安静的把我的钱带走
  • 简单总结
  • 下一步呢?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档