[ch04-03] 用神经网络解决线性回归问题

系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI
点击star加星不要吝啬,星越多笔者越努力。

4.3 神经网络法

在梯度下降法中,我们简单讲述了一下神经网络做线性拟合的原理,即:

  1. 初始化权重值
  2. 根据权重值放出一个解
  3. 根据均方差函数求误差
  4. 误差反向传播给线性计算部分以调整权重值
  5. 是否满足终止条件?不满足的话跳回2

一个不恰当的比喻就是穿糖葫芦:桌子上放了一溜儿12个红果,给你一个足够长的竹签子,选定一个角度,在不移动红果的前提下,想办法用竹签子穿起最多的红果。

最开始你可能会任意选一个方向,用竹签子比划一下,数数能穿到几个红果,发现是5个;然后调整一下竹签子在桌面上的水平角度,发现能穿到6个......最终你找到了能穿10个红果的的角度。

4.3.1 定义神经网络结构

我们是首次尝试建立神经网络,先用一个最简单的单层单点神经元,如图4-4所示。

图4-4 单层单点神经元

下面,我们用这个最简单的线性回归的例子,来说明神经网络中最重要的反向传播和梯度下降的概念、过程以及代码实现。

输入层

此神经元在输入层只接受一个输入特征,经过参数w,b的计算后,直接输出结果。这样一个简单的“网络”,只能解决简单的一元线性回归问题,而且由于是线性的,我们不需要定义激活函数,这就大大简化了程序,而且便于大家循序渐进地理解各种知识点。

严格来说输入层在神经网络中并不能称为一个层。

权重w/b

因为是一元线性问题,所以w/b都是一个标量。

输出层

输出层1个神经元,线性预测公式是:

\[z_i = x_i \cdot w + b\]

z是模型的预测输出,y是实际的样本标签值,下标 \(i\) 为样本。

损失函数

因为是线性回归问题,所以损失函数使用均方差函数。

\[loss(w,b) = \frac{1}{2} (z_i-y_i)^2\]

4.3.2 反向传播

由于我们使用了和上一节中的梯度下降法同样的数学原理,所以反向传播的算法也是一样的,细节请查看4.2.2。

计算w的梯度

\[
{\partial{loss} \over \partial{w}} = \frac{\partial{loss}}{\partial{z_i}}\frac{\partial{z_i}}{\partial{w}}=(z_i-y_i)x_i
\]

计算b的梯度

\[
\frac{\partial{loss}}{\partial{b}} = \frac{\partial{loss}}{\partial{z_i}}\frac{\partial{z_i}}{\partial{b}}=z_i-y_i
\]

为了简化问题,在本小节中,反向传播使用单样本方式,在下一小节中,我们将介绍多样本方式。

4.3.3 代码实现

其实神经网络法和梯度下降法在本质上是一样的,只不过神经网络法使用一个崭新的编程模型,即以神经元为中心的代码结构设计,这样便于以后的功能扩充。

在Python中可以使用面向对象的技术,通过创建一个类来描述神经网络的属性和行为,下面我们将会创建一个叫做NeuralNet的class,然后通过逐步向此类中添加方法,来实现神经网络的训练和推理过程。

定义类

class NeuralNet(object):
    def __init__(self, eta):
        self.eta = eta
        self.w = 0
        self.b = 0

NeuralNet类从object类派生,并具有初始化函数,其参数是eta,也就是学习率,需要调用者指定。另外两个成员变量是w和b,初始化为0。

前向计算

    def __forward(self, x):
        z = x * self.w + self.b
        return z

这是一个私有方法,所以前面有两个下划线,只在NeuralNet类中被调用,不对外公开。

反向传播

下面的代码是通过梯度下降法中的公式推导而得的,也设计成私有方法:

    def __backward(self, x,y,z):
        dz = z - y
        db = dz
        dw = x * dz
        return dw, db

dz是中间变量,避免重复计算。dz又可以写成delta_Z,是当前层神经网络的反向误差输入。

梯度更新

    def __update(self, dw, db):
        self.w = self.w - self.eta * dw
        self.b = self.b - self.eta * db

每次更新好新的w和b的值以后,直接存储在成员变量中,方便下次迭代时直接使用,不需要在全局范围当作参数内传来传去的。

训练过程

只训练一轮的算法是:



for 循环,直到所有样本数据使用完毕:

  1. 读取一个样本数据
  2. 前向计算
  3. 反向传播
  4. 更新梯度

    def train(self, dataReader):
        for i in range(dataReader.num_train):
            # get x and y value for one sample
            x,y = dataReader.GetSingleTrainSample(i)
            # get z from x,y
            z = self.__forward(x)
            # calculate gradient of w and b
            dw, db = self.__backward(x, y, z)
            # update w,b
            self.__update(dw, db)
        # end for

推理预测

    def inference(self, x):
        return self.__forward(x)

推理过程,实际上就是一个前向计算过程,我们把它单独拿出来,方便对外接口的设计,所以这个方法被设计成了公开的方法。

主程序

if __name__ == '__main__':
    # read data
    sdr = SimpleDataReader()
    sdr.ReadData()
    # create net
    eta = 0.1
    net = NeuralNet(eta)
    net.train(sdr)
    # result
    print("w=%f,b=%f" %(net.w, net.b))
    # predication
    result = net.inference(0.346)
    print("result=", result)
    ShowResult(net, sdr)

4.3.4 运行结果可视化

打印输出结果:

w=1.716290,b=3.196841
result= [3.79067723]

最终我们得到了W和B的值,对应的直线方程是\(y=1.71629x+3.196841\)。推理预测时,已知有346台服务器,先要除以1000,因为横坐标是以K(千台)服务器为单位的,代入前向计算函数,得到的结果是3.74千瓦。

结果显示函数:

def ShowResult(net, dataReader):
    ......

对于初学神经网络的人来说,可视化的训练过程及结果,可以极大地帮助理解神经网络的原理,Python的Matplotlib库提供了非常丰富的绘图功能。

在上面的函数中,先获得所有样本点数据,把它们绘制出来。然后在[0,1]之间等距设定10个点做为x值,用x值通过网络推理方法net.inference()获得每个点的y值,最后把这些点连起来,就可以画出图4-5中的拟合直线。

图4-5 拟合效果

可以看到红色直线虽然穿过了蓝色点阵,但是好像不是处于正中央的位置,应该再逆时针旋转几度才会达到最佳的位置。我们后面小节中会讲到如何提高训练结果的精度问题。

4.3.5 工作原理

就单纯地看待这个线性回归问题,其原理就是先假设样本点是呈线性分布的,注意这里的线性有可能是高维空间的,而不仅仅是二维平面上的。但是高维空间人类无法想象,所以我们不妨用二维平面上的问题来举例。

在4.2的梯度下降法中,首先假设这个问题是个线性问题,因而有了公式\(z=xw+b\),用梯度下降的方式求解最佳的\(w、b\)的值。

在本节中,用神经元的编程模型把梯度下降法包装了一下,这样就进入了神经网络的世界,从而可以有成熟的方法论可以解决更复杂的问题,比如多个神经元协同工作、多层神经网络的协同工作等等。

如图4-5所示,样本点摆在那里,位置都是固定的了,神经网络的任务就是找到一根直线(注意我们首先假设这是线性问题),让该直线穿过样本点阵,并且所有样本点到该直线的距离的平方的和最小。

可以想象成每一个样本点都有一根橡皮筋连接到直线上,连接点距离该样本点最近,所有的橡皮筋形成一个合力,不断地调整该直线的位置。该合力具备两种调节方式:

  1. 如果上方的拉力大一些,直线就会向上平移一些,这相当于调节b值;
  2. 如果侧方的拉力大一些,直线就会向侧方旋转一些,这相当于调节w值。

直到该直线处于平衡位置时,也就是线性拟合的最佳位置了。

如果样本点不是呈线性分布的,可以用直线拟合吗?

答案是“可以的”,只是最终的效果不太理想,误差可以做到在线性条件下的最小,但是误差值本身还是比较大的。比如一个半圆形的样本点阵,用直线拟合可以达到误差值最小为1.2(不妨假设这个值的单位是厘米),已经尽力了但能力有限。如果用弧线去拟合,可以达到误差值最小为0.3。

所以,当使用线性回归的效果不好时,即判断出一个问题不是线性问题时,我们会用第9章的方法来解决。

代码位置

ch04, Level3

思考和练习

  1. 请把上述代码中的dw和db也改成私有属性,然后试着运行程序。

原文地址:https://www.cnblogs.com/woodyh5/p/11994587.html

时间: 2024-10-13 21:05:17

[ch04-03] 用神经网络解决线性回归问题的相关文章

利用神经网络解决机器人动力学问题

利用神经网络解决机器人动力学问题 总览 提出了利用神经网络解决机器人动力学问题的新观念.主要介绍了神经网络相关技术背景,BP神经网络的基本原理.在Matlab中建立了一个6自由度的机器人,采用BP神经网络和径向神经网络,进行了对机器人动力学预测的仿真验证.结果表明神经网络能有效地解决该问题. 背景介绍 在开发机器人牵引技术过程中,需要对机器人进行动力学建模.而机器人动力学建模通常由牛顿欧拉法和牛顿拉格朗日法,两种方法推导过程都较为复杂,且计算量随着机器人自由度的增加而迅速增加,计算结果容易出错.

Python网络编程03/ low版解决粘包问题

目录 Python网络编程03/ low版解决粘包问题 1.操作系统的缓存区 2.基于TCP协议的socket循环通信 2.1 服务端(server) 2.2客户端(client) 3.基于TCP协议的socket链接+循环 通信 3.1服务端(server) 3.2 客户端(client) 4.基于TCP协议的socket应用实例:执行远程命令 4.1服务端(server) 4.2客户端(client) 5.粘包现象 5.1服务端(server) 5.2客户端(client) 5.3展示收发问

Tensorflow--梯度下降解决线性回归

Tensorflow一些常见操作: 代码: # -*- coding: UTF-8 -*- """ 用梯度下降的优化方法来快速解决线性回归问题 """ import numpy as np import matplotlib.pyplot as plt import tensorflow as tf try: xrange = xrange # Python 2 except: xrange = range # Python 3 # 构建数据 p

[ch05-02] 用神经网络解决多变量线性回归问题

系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力 5.2 神经网络解法 与单特征值的线性回归问题类似,多变量(多特征值)的线性回归可以被看做是一种高维空间的线性拟合.以具有两个特征的情况为例,这种线性拟合不再是用直线去拟合点,而是用平面去拟合点. 5.2.1 定义神经网络结构 我们定义一个如图5-1所示的一层的神经网络,输入层为2或者更多,反正大于2了就没区别.这个一层的神经网络的特点是: 没有中间层,只

[ch04-02] 用梯度下降法解决线性回归问题

系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力. 4.2 梯度下降法 有了上一节的最小二乘法做基准,我们这次用梯度下降法求解w和b,从而可以比较二者的结果. 4.2.1 数学原理 在下面的公式中,我们规定x是样本特征值(单特征),y是样本标签值,z是预测值,下标 \(i\) 表示其中一个样本. 预设函数(Hypothesis Function) 为一个线性函数: \[z_i = x_i \cdot w

TensorFlow 用神经网络解决非线性问题

本节涉及点: 激活函数 sigmoid 产生随机训练数据 使用随机训练数据训练 加入偏移量b加快训练过程 进阶:批量生产随机训练数据 在前面的三好学生问题中,学校改变了评三好的标准 —— 总分>= 95,即可当三好.计算总分公式不变 —— 总分 = 德*0.6+智*0.3+体*0.1 但学校没有公布这些规则,家长们希望通过神经网络计算出学校的上述规则 这个问题显然不是线性问题,也就是无法用一个类似 y = w*x + b 的公式来从输入数据获得结果 虽然总分和各项成绩是线性关系,但总分与是否评比

【神经网络】BP算法解决XOR异或问题MATLAB版

第一种 %% %用神经网络解决异或问题 clear clc close ms=4;%设置4个样本 a=[0 0;0 1;1 0;1 1];%设置输入向量 y=[0,1,1,0];%设置输出向量 n=2;%输入量的个数 m=3;%隐层量的个数 k=1;%输出层的个数 w=rand(n,m);%为输入层到隐层的权值赋初值 v=rand(m,k);%为隐层到输出层的权值赋权值 yyuzhi=rand(1,m);%为输入层到隐层的阈值赋初值 scyuzhi=rand(1,1);%为隐层到输出层的阈值赋权

(转)神经网络和深度学习简史(第一部分):从感知机到BP算法

深度|神经网络和深度学习简史(第一部分):从感知机到BP算法 2016-01-23 机器之心 来自Andrey Kurenkov 作者:Andrey Kurenkov 机器之心编译出品 参与:chenxiaoqing.范娜Fiona.杨超.微胖.汪汪.赵巍 导读:这是<神经网络和深度学习简史>第一部分.这一部分,我们会介绍1958年感知机神经网络的诞生,70年代人工智能寒冬以及1986年BP算法让神经网络再度流行起来. 深度学习掀起海啸 如今,深度学习浪潮拍打计算机语言的海岸已有好几年,但是,

Machine Learning_Ng 第四讲 多变量线性回归

在第四讲中,主要学习了多变量线性回归(Linear Regression with Multiple Variables)的多维特征.多变量梯度下降.特征缩放.特征和多项式回归以及正规方程等. # 多维特征(Multiple Features) 为房价模型增加更多的特征,如房间楼层数等,则构成了一个含有多个变量的模型. 假设$h_\theta(x)=\theta_0+\theta_1*x_1+\theta_2*x_2+-+\theta_n*x_n$, 设x_0=1,则存在$h_\theta(x)