Press "Enter" to skip to content

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

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

 

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

 

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 吗?这个结果也偏差太大了吧!

 

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

 

 

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

 

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

 

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

 

 

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

 

机器学习应用编写过程

 

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

 

 

准备训练数据

 

定义模型

 

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

 

训练模型

 

模型推理

 

 

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

 

小结

 

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

 

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

 

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

 

Be First to Comment

发表回复

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