- 1.前言
- 2.机器学习和深度学习综述
- 关系:人工智能>机器学习>深度学习
- 机器学习:机器学习是专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构,使之不断改善自身的性能。
- 机器学习的实现:
- 归纳: 从具体案例中抽象一般规律,机器学习中的“训练”亦是如此。从一定数量的样本(已知模型输入X和模型输出Y)中,学习输出Y与输入X的关系(可以想象成是某种表达式)。
- 演绎: 从一般规律推导出具体案例的结果,机器学习中的“预测”亦是如此。基于训练得到的Y与X之间的关系,如出现新的输入XXX,计算出输出YYY。通常情况下,如果通过模型计算的输出和真实场景的输出一致,则说明模型是有效的。
- 机器学习的方法论
- 确定模型参数
- 以HHH为模型的假设,它是一个关于参数W和输入X的函数,用H(W,X) 表示。模型的优化目标是H(W,X)的输出与真实输出YYY尽量一致,两者的相差程度即是模型效果的评价函数(相差越小越好)。那么,确定参数的过程就是在已知的样本上,不断减小该评价函数(H(W,X) 和Y相差)的过程,直到学习到一个参数W,使得评价函数的取值最小。这个衡量模型预测值和真实值差距的评价函数也被称为损失函数(损失Loss)
- 模型结构介绍
- 模型假设:世界上的可能关系千千万,漫无目标的试探Y~X之间的关系显然是十分低效的。因此假设空间先圈定了一个模型能够表达的关系可能,如蓝色圆圈所示。机器还会进一步在假设圈定的圆圈内寻找最优的Y~X关系,即确定参数W。
- 评价函数:寻找最优之前,我们需要先定义什么是最优,即评价一个Y~X关系的好坏的指标。通常衡量该关系是否能很好的拟合现有观测样本,将拟合的误差最小作为优化目标。
- 优化算法:设置了评价指标后,就可以在假设圈定的范围内,将使得评价指标最优(损失函数最小/最拟合已有观测样本)的Y~X关系找出来,这个寻找的方法即为优化算法。最笨的优化算法即按照参数的可能,穷举每一个可能取值来计算损失函数,保留使得损失函数最小的参数作为最终结果。
- 机器执行学习的框架体现了其学习的本质是“参数估计”(Learning is parameter estimation)
- 深度学习
- 神经网络的基本概念
- 神经元: 神经网络中每个节点称为神经元,由两部分组成:
- 加权和:将所有输入加权求和。
- 非线性变换(**函数):加权和的结果经过一个非线性函数变换,让神经元计算具备非线性的能力。
- 多层连接: 大量这样的节点按照不同的层次排布,形成多层的结构连接起来,即称为神经网络。
- 前向计算: 从输入计算输出的过程,顺序从网络前至后。
- 计算图: 以图形化的方式展现神经网络的计算逻辑又称为计算图。我们也可以将神经网络的计算图以公式的方式表达如下:
- Y=f3(f2(f1(w1⋅x1+w2⋅x2+w3⋅x3+b)+…)…)…)
- 深度学习的发展历程
- 大数据是神经网络发展的有效前提
- 依靠硬件的发展和算法的优化
- 在深度学习兴起之前,很多领域建模的思路是投入大量精力做特征工程,将专家对某个领域的“人工”理解沉淀成特征表达,然后使用简单模型完成任务(如分类或回归)。而在数据充足的情况下,深度学习模型可以实现端到端的学习,即不需要专门做特征工程,将原始的特征输入模型中,模型可同时完成特征提取和分类任务
-
- 3.波士顿房价预测任务
- 期望构建一个基于13个因素进行房价预测的模型
- 对于预测问题,可以根据预测输出的类型是连续的实数值,还是离散的标签,区分为回归任务和分类任务。因为房价是一个连续值,所以房价预测显然是一个回归任务。
- 线性回归模型
- 模型的求解即是通过数据拟合出每个wjw_jwj和bbb。其中,wj和b分别表示该线性模型的权重和偏置。一维情况下,wj 和 b 是直线的斜率和截距。
- 线性回归模型使用均方误差作为损失函数(Loss),用以衡量预测房价和真实房价的差异
- 线性回归模型的神经网络结构
- 神经网络的标准结构中每个神经元由加权和与非线性变换构成,然后将多个神经元分层的摆放并连接形成神经网络。线性回归模型可以认为是神经网络模型的一种极简特例,是一个只有加权和、没有非线性变换的神经元(无需形成网络)
- 构建波士顿房价预测任务的神经网络模型
- 五个步骤即可完成模型的构建和训练
- 数据处理
- 数据处理包含五个部分:数据导入、数据形状变换、数据集划分、数据归一化处理和封装load data函数。数据预处理后,才能被模型调用。
- 代码读入数据
- 数据形状变换:读入的原始数据是1维的,所有数据都连在一起。因此需要我们将数据的形状进行变换,形成一个2维的矩阵,每行为一个数据样本(14个值),每个数据样本包含13个X(影响房价的特征)和一个Y(该类型房屋的均价)。
- 将数据集划分成训练集和测试集,其中训练集用于确定模型的参数,测试集用于评判模型的效果
- 数据归一化处理:对每个特征进行归一化处理,使得每个特征的取值缩放到0~1之间。这样做有两个好处:一是模型训练更高效;二是特征前的权重大小可以代表该变量对预测结果的贡献度
- 封装成load data函数
- 模型设计
- 模型设计是深度学习模型关键要素之一,也称为网络结构设计,相当于模型的假设空间,即实现模型“前向计算”(从输入到输出)的过程。如果将输入特征和输出预测值均以向量表示,输入特征x有13个分量,y有1个分量,那么参数权重的形状(shape)是13×1
- 矩阵乘法:1、当矩阵A的列数(column)等于矩阵B的行数(row)时,A与B可以相乘。2、矩阵C的行数等于矩阵A的行数,C的列数等于B的列数。3、乘积C的第m行第n列的元素等于矩阵A的第m行的元素与矩阵B的第n列对应元素乘积之和。
- forward函数(代表“前向计算”):计算预测输出的过程以“类和对象”的方式来描述,类成员变量有参数w和b,从特征和参数到输出预测值的计算过程。
- 训练配置
- 模型设计完成后,需要通过训练配置寻找模型的最优值,即通过损失函数来衡量模型的好坏。
- 通过模型计算x表示的影响因素所对应的房价应该是z, 但实际数据告诉我们房价是y。这时我们需要有某种指标来衡量预测值z跟真实值y之间的差距。对于回归问题,最常采用的衡量方法是使用均方误差作为评价模型好坏的指标,具体定义如下:
- Loss简记为: L,通常也被称作损失函数,它是衡量模型好坏的指标。在回归问题中均方误差是一种比较常见的形式,分类问题中通常会采用交叉熵作为损失函数
- 因为计算损失函数时需要把每个样本的损失函数值都考虑到,所以我们需要对单个样本的损失函数进行求和,并除以样本总数N。
- 训练过程
- 求解参数w和b的数值这个过程也称为模型训练过程。训练过程是深度学习模型的关键要素之一,其目标是让定义的损失函数Loss尽可能的小,也就是说找到一个参数解w和b使得损失函数取得极小值。
- 函数在某一点的导数就是该函数所代表的曲线在这一点上的切线斜率
- 若f(a)是函数f(x)的极大值或极小值,则a为函数f(x)的极值点,极大值点与极小值点统称为极值点
- 梯度下降法(Gradient Descent)
- 在现实中存在大量的函数正向求解容易,反向求解较难,被称为单向函数。这种函数在密码学中有大量的应用,密码锁的特点是可以迅速判断一个**是否是正确的(已知x,求y很容易),但是即使获取到密码锁系统,无法**出正确的**是什么(已知y,求x很难)
- 这种情况特别类似于一位想从山峰走到坡谷的盲人,他看不见坡谷在哪(无法逆向求解出Loss导数为0时的参数值),但可以伸脚探索身边的坡度(当前点的导数值,也称为梯度)。那么,求解Loss函数最小值可以这样实现:从当前的参数取值,一步步的按照下坡的方向下降,直到走到最低点。
- np.arange([start, ]stop, [step, ]dtype=None)
- 均方误差表现的“圆滑”的坡度有两个好处:1.曲线的最低点是可导的。2.越接近最低点,曲线的坡度逐渐放缓,有助于通过当前的梯度来判断接近最低点的程度(是否逐渐减少步长,以免错过最低点)。
- 实现梯度下降法的方案如下:
- 计算梯度
- 为了梯度计算更加简洁,引入因子1/2,定义损失函数如下:
- 其中zii是网络对第i个样本的预测值:
- 梯度的定义
- 计算出LLL对w和b的偏导数:
- 考虑只有一个样本,计算梯度
- 根据梯度的计算公式,总梯度是对每个样本对梯度贡献的平均值
- 确定损失函数更小的点
- 开始研究更新梯度的方法。首先沿着梯度的反方向移动一小步,找到下一个点P1,观察损失函数的变化。
- 相减:参数需要向梯度的反方向移动。
- eta:控制每次参数值沿着梯度反方向变动的大小,即每次移动的步长,又称为学习率。
- 特征输入归一化后,不同参数输出的Loss是一个比较规整的曲线,学习率可以设置成统一的值 ;特征输入未归一化时,不同特征对应的参数所需的步长不一致,尺度较大的参数需要大步长,尺寸较小的参数需要小步长,导致无法设置统一的学习率
- 将代码程封装成Train函数
- 训练扩展到全部参数
- 为了能给读者直观的感受,上面演示的梯度下降的过程仅包含w5w_5w5和w9w_9w9两个参数,但房价预测的完整模型,必须要对所有参数www和bbb进行求解。这需要将Network中的update和train函数进行修改。由于不再限定参与计算的参数(所有参数均参与计算),修改之后的代码反而更加简洁。实现逻辑:“前向计算输出、根据输出和真实值计算Loss、基于Loss和输入计算梯度、根据梯度更新参数值”四个部分反复执行,直到到达参数最优点。
- TransV1.py
- 随机梯度下降法( Stochastic Gradient Descent)
- 在实际问题中,数据集往往非常大,如果每次都使用全量数据进行计算,效率非常低.由于参数每次只沿着梯度反方向更新一点点,因此方向并不需要那么精确。一个合理的解决方案是每次从总的数据集中随机抽取出小部分数据来代表整体,基于这部分数据计算梯度和损失来更新参数,这种方法被称作随机梯度下降法(Stochastic Gradient Descent,SGD)
- 核心概念:
- min-batch:每次迭代时抽取出来的一批数据被称为一个min-batch。
- batch_size:一个mini-batch所包含的样本数目称为batch_size。
- epoch:当程序迭代的时候,按min-batch逐渐抽取出样本,当把整个数据集都遍历到了的时候,则完成了一轮训练,也叫一个epoch。启动训练时,可以将训练的轮数num_epochs和batch_size作为参数传入。
- 数据处理需要实现拆分数据批次和样本乱序(为了实现随机抽样的效果)两个功能
- 通过大量实验发现,模型对最后出现的数据印象更加深刻。训练数据导入后,越接近模型训练结束,最后几个批次数据对模型参数的影响越大。为了避免模型记忆影响训练效果,需要进行样本乱序操作。
- 随机梯度下降加快了训练过程,但由于每次仅基于少量样本更新参数和计算损失,所以损失下降曲线会出现震荡。
- 总结
- 构建网络,初始化参数w和b,定义预测和损失函数的计算方法。
- 随机选择初始点,建立梯度的计算方法和参数更新方式。
- 从总的数据集中抽取部分数据作为一个mini_batch,计算梯度并更新参数,不断迭代直到损失函数几乎不再下降。
- 4.飞桨开源深度学习平台介绍
- 深度学习框架优势
- 节省编写大量底层代码的精力:屏蔽底层实现,用户只需关注模型的逻辑结构。同时,深度学习工具简化了计算,降低了深度学习入门门槛。
- 省去了部署和适配环境的烦恼:具备灵活的移植性,可将代码部署到CPU/GPU/移动端上,选择具有分布式性能的深度学习工具会使模型训练更高效。
- 深度学习框架设计思路
- 飞桨开源深度学习平台全景
- 飞桨技术优势
- 5.使用飞浆重写房价预测模型
- 加载飞桨框架的相关类库
- 数据处理
- 模型设计
- 定义init函数:在类的初始化函数中声明每一层网络的实现函数。
- 定义forward函数:构建神经网络结构,实现前向计算过程,并返回预测结果
- 训练配置
- 以guard函数指定运行训练的机器资源,表明在with作用域下的程序均执行在本机的CPU资源上。dygraph.guard表示在with作用域下的程序会以飞桨动态图的模式执行(实时执行)。
- 可以发现声明模型、定义优化器等操作都在with创建的 fluid.dygraph.guard()上下文环境中进行,可以理解为with fluid.dygraph.guard()创建了飞桨动态图的工作环境,在该环境下完成模型声明、数据转换及模型训练等操作
- 声明定义好的回归模型Regressor实例,并将模型的状态设置为训练。
- 模型实例有两种状态:训练状态.train()和预测状态.eval()。训练时要执行正向计算和反向传播梯度两个过程,而预测时只需要执行正向计算。
- (1)部分高级的算子(例如Drop out和Batch Normalization,在计算机视觉的章节会详细介绍)在两个状态执行的逻辑不同。
- (2)从性能和存储空间的考虑,预测状态时更节省内存,性能更好。
- 使用load_data函数加载训练数据和测试数据。
- 设置优化算法和学习率,优化算法采用随机梯度下降SGD,学习率设置为0.01。
- 训练过程
- 内层循环: 负责整个数据集的一次遍历,采用分批次方式(batch)。假设数据集样本数量为1000,一个批次有10个样本,则遍历一次数据集的批次数量是1000/10=100,即内层循环需要执行100次。
- batch的取值会影响模型训练效果。batch过大,会增大内存消耗和计算时间,且效果并不会明显提升;batch过小,每个batch的样本数据将没有统计意义。
- 数据准备:将一个批次的数据转变成np.array和内置格式。
- 前向计算:将一个批次的样本数据灌入网络中,计算输出结果。
- 计算损失函数:以前向计算结果和真实房价作为输入,通过损失函数square_error_cost计算出损失函数值(Loss)。飞桨所有的API接口都有完整的说明和使用案例,在后续的资深教程中我们会详细介绍API的查阅方法。
- 反向传播:执行梯度反向传播backward函数,即从后到前逐层计算每一层的梯度,并根据设置的优化算法更新参数opt.minimize。
- 外层循环: 定义遍历数据集的次数,通过参数EPOCH_NUM设置。
- 保存并测试模型
- 保存:将模型当前的参数数据model.state_dict()保存到文件中(通过参数指定保存的文件名 LR_model),以备预测或校验的程序调用
- 测试:
- 1.配置模型预测的机器资源。
- 2.将训练好的模型参数加载到模型实例中。由两个语句完成,第一句是从文件中读取模型参数;第二句是将参数内容加载到模型。加载完毕后,需要将模型的状态调整为eval()(校验)。训练状态的模型需要同时支持前向计算和反向传导梯度,模型的实现较为臃肿,而校验和预测状态的模型只需要支持前向计算,模型的实现更加简单,性能更好。