Press "Enter" to skip to content

利用tensorflow.js实现JS中的AI

非常感谢( Seth Juarez)[ twitter.com/sethjuarez ]提供的这篇文章。

 

这不是一篇关于数学的文章,也不是一篇阐述邪恶的有知觉的人工智能最终会杀死我们所有人文章(我是不会订阅这类的文章)。亲爱的读者们,这篇文章的目的是带你走上一条别人未走过的路,那便是讲述关于软件工程的过程以及AI和JS目前的样子。 每当我们试图创建软件时,我们都会提出无数个问题并编写代码来解决问题(包括所有的边界情况)。考虑这样一种情况,你的任务是编写一个函数,该函数给定一个由整数组成的二维数组,要求您返回它看上去最相似的数字。

 

准确的说,你正在编写一个识别数字的函数,得到的数组看上去是下面这样的(在这种情况下你应该返回5)。

我们为了完成这种任务,不得不编写蹩脚代码——我们知道这种代码太过松散,一旦将其投入生产,我们就会觉得需要重构(或做点什幺)。

 

你和我都会发现代码中有充斥着大量的if判断和for循环语句,但是我们又必须使用它们,来创建必要的程序。

 

然而,面对这类任务,最佳选择便是机器学习(人工智能的一个子领域)。机器学习的优势在于我们不需要为了解决问题考虑一系列的步骤,而是给予机器学习算法一些正确的例子,如下图。它便会给出正确的步骤。

过程

 

虽然本文的主要目的不是去研究这些算法如何实现,但是在实际软件程序中,了解其运用的基本过程和主要输出是非常重要的(本文以JS为例)。数据科学家经常会使用以下几个步骤:

 

 

    1. 定义问题(识别数字);

 

    1. 给出数据(MNIST数据集);

 

    1. 创建最优模型(实际功能的抽象);

 

    1. 模型运用

 

 

作为开发人员,我们的工作介于步骤3和步骤4之间。

 

模型

 

通常,这些模型利用机器学习框架,以Python语言进行创建。这个过程需要很长的时间,并且依赖大量的数据。这是非常容易让人乏味和感觉沮丧的。然而,一旦完成了冗长和令人沮丧的部分,就会有一个实际文件输出来表示模型。你应该把它看作是你项目的一项资产。在使用TensorFlow的情况下,输出通常是一个protobuf文件。

 

TensorFlow.js

 

这里,我要提醒大家,我并不认为我自己是一个JS专家,所以,如果我错了或有更好的解决方案,请务必告知我。这部分内容重点是向你展示如何在JavaScript应用程序中使用模型,我们会用到(TensorFlow.js)[js.tensorflow.org/],它被宣传为训练和部署机器学习模型的框架,而我们将重点关注部署部分,因为通常大多数模型都是由使用全强度TensorFlow python包的数据科学家创建的。我承认,在某些情况下,在客户端进行迁移学习听起来非常有趣。

 

创建模型并将它转换到TensorFlow.js的过程还是非常简单的(这里不做介绍,但它确实是一个很有趣的练习,建议有机会你还是完全可以做一下),参考( github.com/sethjuarez/… )

 

现在,我们开始实际例子:

 

在这个情况下,我决定使用vue.js。因为我有一些框架方面的经验,而且已经有一个(组件)[ codepen.io/getflourish… ]完成了大部分的画布绘制工作。

 

code

 

使用实际模型时,有两个重要的部分:

 

 

    1. 加载模型

 

    1. 调用模型

 

 

让我们依次看一下:

 

加载模块

 

创建一个vue组件看上去时一个不错的idea,因为我可以为整个组件只加载一次模型,并且把它保留在内存中。

 

mounted: async function () {
        ... other things...
        // load model
        const MODEL = 'model/tensorflowjs_model.pb';
        const WEIGHTS = 'model/weights_manifest.json';
        this.model = await tf.loadFrozenModel(MODEL, WEIGHTS);
    }

 

我认为我可以选择vue生命周期中的另外一个钩子,但是目前 mounted 看上去不错。一旦this.model被挂载,无论什幺时候 Predict 按钮被点击,这个模型都会被使用。(另外一个有趣的现象是鼠标抬起时,模型也会使用,进行预测)。

 

调用模块

 

现在我们来看我们如何来调用模型的例子:

 

predict: async function() {
            const digit = this.getDigit();
            const d = tf.tensor1d(digit).reshape([1, digit.length]);
            this.probabilities = await this.model.execute({'x': d}).reshape([10]).data();
            this.prediction = this.probabilities.indexOf(Math.max(...this.probabilities));
        }

 

getDigit()方法获取手绘的图像,做两件事:

 

 

    1. 缩小到28*28的图像

 

    1. 获取数字类型的数组,将其输入进模型

 

 

关键调用是 this.model.execute(…) 。这是我们实际传递数组并使模型运转的地方。 模型输出的结果是一个长度为10,包含每个数字出现概率的数组。换句话说,在数组索引为0是它认为数字为0的概率(以此类推)。

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注