教程 | 如何在浏览器使用synaptic.js训练简单的神经网络推荐系统

选自Medium

作者:Mark Feng

机器之心编译

参与:Jane W、蒋思源

本文利用 synaptic 库构建简单的神经网络,并在浏览器中实现训练过程。该神经网络可以和其他框架共同打造一款简单的推荐系统应用。这种在浏览器上训练的神经网络因为将计算任务分配到各个终端设备,所以服务器的压力大大降低。此外,在终端上训练的神经网络也大大保护了用户的隐私。机器之心对本文做了简要介绍,全部代码请查看 Github 项目地址。

项目地址:https://github.com/markselby9/ml-in-browser

用 JS 进行机器学习?为什么不呢!

项目概览

我们将构建一个基于人工神经网络的简单 Web 应用程序推荐系统。该应用程序包含两页,第一页显示书籍,第二页显示电影。用户可以在第一页中选择他或她感兴趣的书籍,当他点击下一页按钮时,我们实际上可以在后台预测他可能会感兴趣的电影。在用户选择他喜欢的电影之后,我们会给用户显示他所选择的结果,以及我们对他的选择的预测。一些显示截屏如下所示:

在第一页中选择感兴趣的书籍

在第二页中选择感兴趣的电影

将选择与预测结果进行比较

这个应用程序使用 Vue.js 和 ElementUI(Vue.js 的 UI 框架)构建,并使用 synaptic 库构建神经网络。

有什么优点?

该项目的优势可以归结如下:

  • 我们将模型训练工作转移到前端而不是后端,这不仅降低了服务器的压力,同时还将一些计算任务分配给许多客户端。由于 npm 社区提供许多神经网络相关的 Javascript 库,这种方法是可行的。
  • 我们保护用户的隐私。用户的数据并没有实际被上传到服务器,当服务器更新训练模型时,他们的数据对于服务器是匿名的。

神经网络简要介绍

首先,这里使用的神经网络是最基础的人工神经网络,我们决定仅使用用户的选择作为输入和输出集。本节使用的图像来自一个介绍神经网络的博客:https://ujjwalkarn.me/2016/08/09/quick-intro-neural-networks/。

本项目涉及的概念包括:人工神经网络、神经元、层次和训练(反向传播)。如果你已经熟悉这些概念,你可以跳过此部分。人工神经网络(ANN)是一种由人脑启发的计算模型。它由神经元组成,神经元是神经网络的基本单元。神经元从其它来源接收输入,每个输入分配一个权重,权重根据输入的重要程度赋予。神经元使用激活函数作用于所有输入的加权之和,然后给出输出。

神经元

单层神经网络由几个神经元组成,如下图所示。神经网络可以包含或可以不包含多个隐藏层,每对相邻层之间具有连接,这种连接通常由前面提到的权重表示。

简单全连接神经网络的层级结构

但是如何通过正确衡量这些权重来架构神经网络呢?这些权重需要训练,来达到使神经网络正常工作的要求。假设我们有一个数据表,其中包含 1000 对输入和相应的输出。我们首先产生 0 和 1 之间的随机数给出所有权重,然后遍历所有数据对。在每对输入和输出中,我们使用神经网络的激活函数给出计算结果,并将其与实际输出进行比较。然后我们使用反向传播算法重新训练网络并调整权重。更新反向传播的权重可以通过随机梯度下降来完成,这是一种获得最优权重值的方法。

这里只是简要介绍神经网络的原理。更详细的内容,请参考以下链接:

  • https://ujjwalkarn.me/2016/08/09/quick-intro-neural-networks/
  • https://en.wikipedia.org/wiki/Artificial_neural_network
  • https://github.com/cazala/synaptic/wiki/Neural-Networks-101

神经网络在浏览器中的实现

最近有一些在浏览器中实现神经网络的相关研究,如:

  • Deeplearnjs:https://github.com/PAIR-code/deeplearnjs
  • ConvnetJS:http://cs.stanford.edu/people/karpathy/convnetjs/
  • synaptic.js:http://caza.la/synaptic/

我们在这里使用 synaptic.js,因为不管对于 node.js 还是浏览器,它都是一个无架构的神经网络库。我们可以通过 github 库中的 wiki 来检查文档:https://github.com/cazala/synaptic/wiki/Architect。我们计划在浏览器中实现所有的神经网络训练和部分激活函数,服务器(使用简单的 node.js 和 express 搭建服务器框架)只保留包含网络参数的 JSON 文件。synaptic.js 有一个方便的 API 来将神经网络解析成 JSON,并将 JSON 解析为神经网络实例。

应用程序由 Vue.js 和 ElementUI 构建。在创建主应用程序组件的生命周期中,应用程序从服务器获取模型的 JSON 文件,并基于 JSON 文件构建神经网络实例。然后该模型展示 20 张含有电影信息的卡片,让用户选择他/她感兴趣的项目,用户完成选择并单击下一步后,网络实例将调用激活函数,并给出该用户可能想要的书籍的预测值(基于 20 种书籍选项)。同时,应用程序还展示另外 20 张包含书籍信息的卡片,让用户选择。用户点击提交按钮后,应用程序会将预测的书籍列表和实际的书籍列表呈现给用户,并在后台使用新的训练数据来反向传播并重新训练模型。再次训练后,新的神经网络将被解析为 JSON 对象并发送回服务器。

下面是代码。服务器利用简单的 node.js 中的 I/O API 和 Express 构建。

app.post('/getNetwork', (req, res) => {
    if (req.body) {
        console.log(req.body);
        readJSONFromFile((network) => { // read local JSON file
            res.send({
                code: 200,
                network,
            });
        }, (err) => {
            console.log(err.toString());
        });
    }
});

app.post('/setNetwork', (req, res) => {
    if (req.body && req.body.networkJSON) {
        console.log(req.body);
        const { networkJSON } = req.body;
        saveJSONToFile(networkJSON, (err) => { // write to local JSON file
            if (err) {
                res.send({
                    code: 500,
                    err
                });
            } else {
                res.send({
                    code: 200,
                });
            }
        });
    } else {
        res.send({
            code: 406,
        })
    }
});
app.listen(3000, () => {
    console.log('server started');
});

以及在客户端。在本文中我们不会介绍 DOM 的细节,我们将仅关注组件 app.vue 下的脚本部分。

created() {
            // fetch the train model from server
            this.content_data = this.shuffle(book_data);
            this.loading = true;
            axios.post('http://localhost:3000/getNetwork')
                .then((response) => {
                    console.log(response);
                    this.loading = false;
                    const networkJSON = response.data.network;
                    if (networkJSON && Object.keys(networkJSON).length > 0) {
                        this.$message('Received neural network from server.');
                        localNetworkInstance = Network.fromJSON(networkJSON);
                    } else {
                        this.$message('Created a new network instance.');
                        // create a new network instance
                        const inputLayer = new Layer(20);
                        const hiddenLayer = new Layer(20);
                        const outputLayer = new Layer(20);

                        inputLayer.project(hiddenLayer);
                        hiddenLayer.project(outputLayer);

                        localNetworkInstance = new Network({
                            input: inputLayer,
                            hidden: [hiddenLayer],
                            output: outputLayer
                        });
                    }
                })
                .catch(function (error) {
                    this.loading = false;
                    console.log(error);
                });
        },

以上是我们在应用程序中创建的生命周期(lifecycle)。它尝试从「getNetwork」API 获取 JSON 对象:如果它是网络的可用 JSON 设置,则它将通过 synaptic 的 fromJSON 方法创建本地网络实例;否则,它将创建一个新的网络实例并保存到「localNetworkInstance」变量中。

当用户在第一页单击「下一页」按钮后,我们在「onClick」功能中调用激活函数,并将其作为预测结果保存在 Vue 组件的数据中。然后在用户选择他/她感兴趣的电影之后,调用重新训练函数。

reTrainByThisUserData() {
    // retrain the model by this user's data
    if (localNetworkInstance) {
        localNetworkInstance.propagate(learningRate, this.trainingSet.output);   // propagate the network

        this.$message('Neural Network retrained!');

        const successFunc = () => {
            console.log('success');
            this.$message('Successfully sent the new Neural Network!');
        };
        const errorFunc = (error) => {
            console.log('error', error);
            this.$message(error);
        };

        this.loading = true;
        axios.post('http://localhost:3000/setNetwork', {
            networkJSON: localNetworkInstance.toJSON()
        })
            .then((response) => {
                this.loading = false;
                if (response.data && response.data.code === 200) {
                    successFunc();
                } else {
                    errorFunc(response.data);
                }
            })
            .catch(function (error) {
                errorFunc(error)
            });
    } else {
        this.loading = false;
        console.log('network is undefined!');
    }
}

重新训练过程是一个反向传播过程,利用当前用户的选择作为输入和输出数据对。用户对电影的选择将成为反向传播的数据。在反向传播后,神经网络的权重将被调整,神经网络的新数据将被上传到服务器并被保存。理想情况下,新网络应该更强大:)

进一步探索

正如很多读者可能已经意识到的那样,我们可以利用这个方法做比简单推荐系统更多的事情。改进此项目的一些可能方法包括:

  • 更多关于浏览器的信息可以当作输入,例如用户在每张卡上花费的时间、用户的点击事件和滚动事件等。这些信息可以从前端得到。
  • 神经网络可以具有更复杂的架构,但注意不能过拟合。
  • 前端项目应该考虑大小。目前,构建的文件大小约为 1Mb,这在 PC 上是可以接受的,但对于移动端网站来说可能太大了。如果要在移动设备上使用该项目,应采取优化措施。

有关此项目的完整代码,请查阅参考:https://github.com/markselby9/ml-in-browser/tree/feature/Recommendation_system_in_browser_demo。

原文链接:https://medium.com/@markselby9/neural-network-in-your-browser-3e6fc91709ca

本文为机器之心编译,转载请联系本公众号获得授权。

原文发布于微信公众号 - 机器之心(almosthuman2014)

原文发表时间:2017-08-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏新智元

【代码+教程】重现“世界模型”实验,无监督方式快速训练

1202
来自专栏ATYUN订阅号

将Keras权值保存为动画视频,更好地了解模型是如何学习的

将Keras权值矩阵保存为简短的动画视频,从而更好地理解你的神经网络模型是如何学习的。下面是第一个LSTM层的例子,以及一个经过一个学习周期训练的6级RNN模型...

3594
来自专栏AI研习社

Github 项目推荐 | ANSI C 的简单神经网络库

Genann是一个经过精心测试的库,用于在 C 中训练和使用前馈人工神经网络(ANN)。它的主要特点是简单、快速、可靠和可魔改(hackable),它只需要提供...

771
来自专栏杨熹的专栏

如何应用 BERT :Bidirectional Encoder Representations from Transformers

上一篇文章介绍了 Google 最新的BERT (Bidirectional Encoder Representations from Transformers...

1772
来自专栏用户2442861的专栏

Caffe学习:Blobs, Layers, and Nets

-注意:网络结构是设备无关的,Blob和Layer=隐藏了模型定义的具体实现细节。定义网络结构后,可以通过Caffe::mode()或者Caffe::set_m...

620
来自专栏机器之心

开源 | 浏览器上最快的DNN执行框架WebDNN:从基本特性到性能测评

选自Github 机器之心编译 参与:蒋思源、晏奇 WebDNN 是网页浏览器中最快的 DNN 执行框架,而本文首先简单介绍了 WebDNN 特征与其框架结构...

2916
来自专栏机器之心

资源 | 基于TensorFlow和Sonnet,DeepMind开源可微神经计算机实现包

选自Github 机器之心编译 参与:蒋思源 去年 DeepMind 在自然期刊上曾介绍过一种记忆增强式的神经网络形式-可微神经计算机。而近日,DeepMin...

2843
来自专栏SIGAI学习与实践平台

【免费线上实践】动手训练模型系列:条件GAN

从无序的输出到按照类别输出,Conditional Generative Neural Networks到底借助了什么样的魔(xin)法(xi)?点击下方小程序...

1155
来自专栏XAI

Java分布式神经网络库Deeplearning4j 环境搭建和运行一个例子

DeeplearningforJava简单介绍: deeplearning4j是一个Apache 2.0-licensed,开源的,分布式神经网络库编写的jav...

3938
来自专栏新智元

10 亿图片仅需 17.7微秒:Facebook AI 实验室开源图像搜索工具Faiss

【新智元导读】Facebook的 FAIR 最新开源了一个用于有效的相似性搜索和稠密矢量聚类的库,名为 Faiss,在10亿图像数据集上的一次查询仅需17.7 ...

3675

扫码关注云+社区