14

手把手教你开发人工智能微信小程序(一):线性回归模型

 4 years ago
source link: https://mp.weixin.qq.com/s/4ECPgLplLSJRdDXD2ebZ5A
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

谈到人工智能、机器学习,我们可能会觉得很神秘,其实机器学习背后的理论并不复杂。就如同原子弹这么尖端的科技,其背后的理论就是一个很简单的公式:

E = mc²

机器学习的最基础理论其实也不复杂,本文先尝试从一个线性回归问题出发,探讨一下机器学习的一般步骤。通过本文,你将学习到:

  • 定义机器学习模型

  • 定义损失函数

  • 模型训练

  • 从训练的模型进行推导

线性回归

想必大家应该做过物理实验,还记得有这样的实验吗?就是观察一系列根据某个因素变化(比如质量)的实验数据,然后建立平面坐标,在坐标系中标记一系列离散的点,然后拟合出曲线或直线。如果结果和因子之间是线性关系,那么拟合出来就近似于一条直线。一般而言,线性关系可以用如下公式表示:

y = a * x + b

现在我们有一系列的x值以及与之对应的y值,如何得到a和b的值呢?我们以前的方法可能是将这些点描在坐标上,然后描一条近似连接所有点的直线(在实际实验中,可能有一些干扰因素,所有的点连接起来并非一条直线),在坐标轴上可以很容易看出a和b的值。

机器学习所要解决的问题也是一样,就是知道一系列x和y的值(数据集),需要找出它们之间的关系。如果是线性问题,就是求解a和b的值。

机器学习通常采用回归解决参数求解问题。

为了简单起见,我们以线性回归为例。所谓线性回归,就是首先给一个a和b的值(通常给0值),然后计算出y的值,和实际的y值进行比较,如果发现误差比较大,就调整a和b的值,比如a和b都加上0.0001,然后再计算y的值,和实际的y值比较,依次反复,只要误差是在逐步减小,最终选择的a和b的值,就接近理论的a和b的值。

比如下面几个x、y的对应值:

x = [1, 2, 3, 4];

y = [1, 3, 5, 7];

你可能立刻就能看出x和y之间的关系是:

y = 2 * x - 1;

这样理论上 a = 2,b = -1。但对于计算机,它没有这样的直觉,我们就先给它a = 0, b = 0,让它通过递归算法,逐步接近这个值,可能最终得到的值是 a = 1.99,b = -0.99。

所以我们需要理解机器学习的结果,最后推算出的结果并非理论上的真实值,而是一个接近真实的值。

至于机器学习如何保证调整a和b的值,误差能够越来越小,这背后也有复杂的算法。对于机器学习应用开发者而言,我们并不需要去实现算法,只需要做简单的了解即可,机器学习框架,如tensorflow,帮我们解决了这些问题。

好吧,我们就以实际代码,来说明如何完成一个机器学习任务。

线性回归代码实例

我们就开门见山,直接放代码:

const tf = require('@tensorflow/tfjs');


//定义一个线性回归模型。

const model = tf.sequential();

model.add(tf.layers.dense({ units: 1, inputShape: [1] }));


model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });


// 为训练生成一些合成数据

const xs = tf.tensor2d([1, 2, 3, 4], [4, 1]);

const ys = tf.tensor2d([1, 3, 5, 7], [4, 1]);


// 使用数据训练模型

model.fit(xs, ys, { epochs: 10 }).then(() => {

// 在该模型从未看到过的数据点上使用模型进行推理

model.predict(tf.tensor2d([5], [1, 1])).print();

});

第1行代码引入 tfjs 模块,需要注意,在上一篇文章中引入的是 tfjs-core ,这里为了方便,直接引入tfjs,它包含了 tfjs-core ,  tfjs-layers 等。所以需要修改 package.json 文件,将其中的 @tensorflow/tfjs-core 替换为 @tensorflow/tfjs 。

第4、5行代码定义线性回归模型。sequential()返回一个序列模型,dense为全连接层。一般来说,我们不用自行设计模型,所以一般模型代码照搬即可。

第7行代码编译模型,其中有两个重要的参数,一个是损失函数,一个是优化器,它们决定着模型是否能够很快收敛。对于不同的任何以及模型,在损失函数的选择有考量,不过我们一般也是按照模型设计者的建议使用对应的损失函数。优化器就那几种选择,翻翻文档,这里选择最普通的 sgd (随机梯度下降)优化器。

第10、11行代码是给出训练数据,这里出于演示的目的,直接在代码中写定,一般情况需要从文件或网络读取。

第14行代码是进行模型训练,就是逐步尝试获得最优解的过程,我们不能无限训练下去,所以这里指定 10 个轮次。

第16行代码根据训练的模型,求 x=5 时的 y 值。

怎么样?有了机器学习框架,从定义模型、训练,到最后的推理,是不是很简单?我们并不需要理解复杂的随机梯度下降算法,就可以完成机器学习的任务。

如果我们在微信小程序中运行上述代码,会得出以下结果:

Tensor

[[6.0889206],]

而且每次的结果还不同,有同学可能会问,正确结果不是应该接近 9 吗?这个结果也偏差太大了吧!

因为上述代码只是出于演示目的,还存在如下问题:

  1. 数据不足,我们只给出了4个样本数据,样本太少,很难找出x,y之间的关系。这也是现代机器学习,特别是深度学习,需要大量训练数据的原因。

  2. 迭代次数太少,在误差还在减少的中途,我们就退出了计算,这样得到的参数,就存在比较大的误差。

  3. 每次推理之前都需要训练,而在实际的项目中,一般是训练和推理是两个分开的过程。

没关系,这只是一个入门的机器学习程序,后续我们会学习到比较完善的例子。

机器学习应用编写过程

虽然上面的代码非常简短,但也具有机器学习应用的基本框架。机器学习应用的通常过程是:

  1. 准备训练数据

  2. 定义模型

  3. 编译模型(定义损失函数、优化器等参数)

  4. 训练模型

  5. 模型推理

在后面的文章,我们可以看到,不管多复杂的机器学习应用,都不外乎这些步骤,区别就在于复杂程度。就如同虽然有了 E = mc² 这个理论,要造成原子弹,还有很多路需要走。

小结

本章主要讲解了建立线性回归模型,虽然是一个精简的程序,但具备了机器学习程序的基本框架。在下一篇文章中,我将说明如何在微信小程序中加载训练数据。没有数据,就没有机器学习。如果你有什么建议,欢迎留言。

本系列文章的源码请访问:

https://github.com/mogotech/wechat-tfjs-examples

qiUN3iI.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK