text.html 20.9 KB
Newer Older
ToTensor's avatar
ToTensor 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
 
<p class="content">机器学习模型的确立过程中有两个主要环节。</p> 
<p class="content">(1)确定选用什么类型的模型。</p> 
<p class="content">(2)确定模型的具体参数。</p> 
<p class="content">先聚焦于第一个问题。</p> 
<h3 class="thirdTitle" id="bw76"><a >3.3.1 确定线性回归模型</a></h3> 
<p class="content">对于这个案例,使用什么模型我们早就心中有数了。虽然上图中的函数直线并未精确无误地穿过每个点,但已经能够反映出特征(也就是微信公众号广告投放金额)和标签(也就是商品销售额)之间的关系,拟合程度还是挺不错的。</p> 
<p class="content">这个简单的模型就是一元线性函数(如右图所示):</p> 
<div class="pic"> 
 <img src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0106-0119.jpg"> 
 <p class="imgtitle">一元线性函数</p> 
</div> 
<p class="content"><span class="italic">y</span>=<span class="italic">ax</span>+<span class="italic">b</span></p> 
<p class="content">其中,参数<span class="italic">a</span>的数学含义是直线的斜率(陡峭程度),<span class="italic">b</span>则是截距(与<span class="italic">y</span>轴相交的位置)。</p> 
<p class="content">在机器学习中,会稍微修改一下参数的代号,把模型表述为:</p> 
<p class="content"><span class="italic">y</span>=<span class="italic">wx</span>+<span class="italic">b</span></p> 
<p class="content">此处,方程式中的<span class="italic">a</span>变成了<span class="italic">w</span>,在机器学习中,这个参数代表权重。因为在多元变量(多特征)的情况下,一个特征对应的<span class="italic">w</span>参数值越大,就表示权重越大。而参数<span class="italic">b</span>,在机器学习中称为偏置。</p> 
<p class="content">不要小看这个简单的线性函数,在后续的机器学习过程中,此函数会作为一个基本运算单元反复地发挥威力。</p> 
<p class="content_101"><img alt="" class="h-pic" src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0106-0120.jpg">咖哥发言</p> 
<p class="content">小冰提问:“咖哥,说到模型的参数,我也看过一些文档,经常听见有人说西塔、西塔(<span class="italic">θ</span>)什么的,这是怎么一回事儿?”</p> 
<p class="content">咖哥解释:“有些机器学习教程中,用<span class="italic">θ</span>(读作<span class="bold">theta</span>)表示机器学习的参数,也会使用<span class="italic">θ</span><span class="sub">0</span><span class="italic">θ</span><span class="sub">1</span>来代表此处的<span class="italic">w</span><span class="italic">b</span>,还有用其他字母表示机器学习参数的情况。我觉得此处使用<span class="italic">w</span><span class="italic">b</span>来表示这些参数会使它们的意义更清晰一些:weight是权重,bias是偏置,各取首字母。你们看其他机器学习资料的时候,要懂得<span class="italic">θ</span><span class="sub">0</span><span class="italic">θ</span><span class="sub">1</span>和这里的<span class="italic">w</span><span class="italic">b</span>其实是一回事儿。”</p> 
<h3 class="thirdTitle" id="bw77"><a >3.3.2 假设(预测)函数——h(x)</a></h3> 
<p class="content">确定以线性函数作为机器学习模型之后,我们接着介绍假设函数的概念。先来看一个与线性函数稍有差别的方程式:</p> 
<p class="content_100"><span class="italic">y'</span>=<span class="italic">wx</span>+<span class="italic">b</span></p> 
<p class="content">也可以写成:</p> 
<p class="content_100"><span class="italic">h</span><span class="italic">x</span>)=<span class="italic">wx</span>+<span class="italic">b</span></p> 
<p class="content">其中,需要注意以下两点。</p> 
<p class="content"><span class="italic">y'</span>指的是所预测出的标签,读作y帽(y-hat)或y撇。</p> 
<p class="content"><span class="italic">h</span><span class="italic">x</span>)就是机器学习所得到的函数模型,它能根据输入的特征进行标签的预测。</p> 
<p class="content">我们把它称为<span class="bold">假设函数</span>,英文是hypothesis function(所以选用首字母h作为函数符号)。</p> 
<p class="content_105">小冰疑惑了:“这不就是线性函数吗?为什么又要叫假设函数<span class="italic">h</span><span class="italic">x</span>)?”</p> 
<p class="content_105">咖哥笑答:“这的确就是线性函数。不过,机器学习的过程,是一个不断假设、探寻、优化的过程,在找到最佳的函数<span class="italic">f</span><span class="italic">x</span>)之前,现有的函数模型不一定是很准确的。它只是很多种可能的模型之中的一种—因此我们强调,假设函数得出的结果是<span class="italic">y'</span>,而不是<span class="italic">y</span>本身。所以假设函数有时也被叫作<span class="bold">预测函数</span>(predication function)。在机器学习中看到<span class="italic">h</span><span class="italic">x</span>)、<span class="italic">f</span><span class="italic">x</span>)或者<span class="italic">p</span><span class="italic">x</span>),基本上它们所要做的都是一回事,就是根据微信公众号广告投放金额<span class="italic">x</span><span class="bold">推断</span>(或预测)销售额<span class="italic">y'</span>。”</p> 
<p class="content">所以,机器学习的具体目标就是确定假设函数<span class="italic">h</span><span class="italic">x</span>)。</p> 
<p class="content">■确定<span class="italic">b</span>,也就是<span class="italic">y</span>轴截距,这里称为偏置<span class="bold"></span>有些机器学习文档中,称它为<span class="italic">w</span><span class="sub">0</span>(或<span class="italic">θ</span><span class="sub">0</span>)。</p> 
<p class="content">■确定<span class="italic">w</span>,也就是斜率,这里称为特征<span class="italic">x</span>的权重,有些机器学习文档中,称它为<span class="italic">w</span><span class="sub">1</span>(或<span class="italic">θ</span><span class="sub">1</span>)。</p> 
<p class="content">一旦找到了参数<span class="italic">w</span><span class="italic">b</span>的值,整个函数模型也就被确定了。那么这些参数<span class="italic">w</span><span class="italic">b</span>的具体值怎么得到呢?</p> 
<h3 class="thirdTitle" id="bw78"><a >3.3.3  损失(误差)函数——L(w,b)</a></h3> 
<p class="content">在继续寻找最优参数之前,需要先介绍损失和损失函数。</p> 
<p class="content">如果现在已经有了一个假设函数,就可以进行标签的预测了。那么,怎样才能够量化这个模型是不是足够好?比如,一个模型是3<span class="italic">x</span>+5,另一个是100<span class="italic">x</span>+1,怎样评估哪一个更好?</p> 
<p class="content">这里就需要引入<span class="bold">损失</span>(loss)这个概念。</p> 
<p class="content"><span class="bold">损失,是对糟糕预测的惩罚。</span>损失也就是<span class="bold">误差</span>,也称为<span class="bold">成本</span>(cost)或<span class="bold">代价</span>。名字虽多,但都是一个意思,也就是当前预测值和真实值之间的差距的体现。它是一个数值,表示对于单个样本而言模型预测的准确程度。如果模型的预测完全准确,则损失为0;如果不准确,就有损失。在机器学习中,我们追求的当然是比较小的损失。</p> 
<p class="content">不过,模型好不好还不能仅看单个样本,而是要针对所有数据样本找到一组平均损失“较小”的函数模型。样本的损失的大小,从几何意义上基本上可以理解为<span class="italic">y</span><span class="italic">y'</span>之间的几何距离。平均距离越大,说明误差越大,模型越离谱。如右图所示,左边模型所有数据点的平均损失很明显大过右边模型。</p> 
<div class="pic"> 
 <img src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0107-0121.jpg"> 
 <p class="imgtitle">左边是平均损失较大的模型,右边是平均损失较小的模型</p> 
</div> 
<p class="content">因此,针对每一组不同的参数,机器都会针对样本数据集算一次平均损失。计算平均损失是每一个机器学习项目的必要环节。</p> 
<p class="content"><span class="bold">损失函数</span>(loss function)<span class="italic">L</span><span class="italic">w</span><span class="italic">b</span>)就是用来计算平均损失的。</p> 
<p class="content_101"><img alt="" class="h-pic" src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0108-0122.jpg">咖哥发言</p> 
<p class="content">有些地方把损失函数记作<span class="italic">J</span><span class="italic">θ</span>),也叫<span class="bold">代价函数</span><span class="bold">成本函数</span>(cost function)。刚才说过, <span class="italic">θ</span>就是<span class="italic">w</span><span class="italic">b</span><span class="italic">J</span><span class="italic">θ</span>)就是<span class="italic">L</span><span class="italic">w</span><span class="italic">b</span>),符号有别,但意思相同。</p> 
<p class="content">这里要强调一下:损失函数<span class="italic">L</span>是参数<span class="italic">w</span><span class="italic">b</span>的函数,不是针对<span class="italic">x</span>的函数。我们会有一种思维定势,总觉得函数一定是表示<span class="italic">x</span><span class="italic">y</span>之间的关系。现在需要大家换一个角度去思考问题,暂时忘掉<span class="italic">x</span><span class="italic">y</span>,聚焦于参数。对于一个给定的数据集来说,所有的特征和标签都是已经确定的,那么此时损失值的大小就只随着参数<span class="italic">w</span><span class="italic">b</span>而变。也就是说,现在<span class="italic">x</span><span class="italic">y</span>不再是变量,而是定值,而<span class="italic">w</span><span class="bold"></span><span class="italic">b</span><span class="bold">在损失函数中成为了变量</span></p> 
<p class="content_105">“这里有点不好理解,大家能听得懂吗?”咖哥问。</p> 
<p class="content_105">其中一位同学思考了一下,说:“大概还跟得上你的思路,接着讲吧。”</p> 
<p class="content">计算数据集的平均损失非常重要,简而言之就是:<span class="bold">如果平均损失小,参数就好;如果平均损失大,模型或者参数就还要继续调整。</span></p> 
<p class="content">这个计算当前假设函数所造成的损失的过程,就是前面提到过的<span class="bold">模型内部参数的评估</span>的过程。</p> 
<p class="content">机器学习中的损失函数很多,主要包括以下几种。</p> 
<p class="content">■用于回归的损失函数。</p> 
<p class="content">□均方误差(Mean Square Error,MSE)函数,也叫平方损失或L2损失函数。</p> 
<p class="content">□平均绝对误差(Mean Absolute Error,MAE)函数,也叫L1损失函数。</p> 
<p class="content">□平均偏差误差(mean bias error)函数。</p> 
<p class="content">■用于分类的损失函数。</p> 
<p class="content">□交叉熵损失(cross-entropy loss)函数。</p> 
<p class="content">□多分类SVM损失(hinge loss)函数。</p> 
<p class="content">一般来说,选择最常用的损失函数就可以达到评估参数的目的。下面给出线性回归模型的常用损失函数—<span class="bold">均方误差函数</span>的实现过程。</p> 
<p class="content">■首先,对于每一个样本,其预测值和真实值的差异为(<span class="italic">y</span><span class="italic">y'</span>),而<span class="italic">y'</span>=<span class="italic">wx</span>+<span class="italic">b</span>,所以损失值与参数<span class="italic">w</span><span class="italic">b</span>有关。</p> 
<p class="content">■如果将损失值(<span class="italic">y</span><span class="italic">y'</span>)夸张一下,进行平方(平方之后原来有正有负的数值就都变成正数),就变成(<span class="italic">y</span><span class="italic">y'</span><span class="super">2</span>。我们把这个值叫作单个样本的平方损失。</p> 
<p class="content">■然后,需要把所有样本(如本章示例一共记录了200周的数据,即200个样本)的平方损失都相加,即(<span class="italic">y</span><span class="italic">x</span><span class="super">(1)</span>)−<span class="italic">y'</span><span class="italic">x</span><span class="super">(1)</span>))<span class="super">2</span>+(<span class="italic">y</span><span class="italic">x</span><span class="super">(2)</span>)−<span class="italic">y'</span><span class="italic">x</span><span class="super">(2)</span>))<span class="super">2</span>+…+(<span class="italic">y</span><span class="italic">x</span><span class="super">(200)</span>))−<span class="italic">y'</span><span class="italic">x</span><span class="super">(200)</span>))<span class="super">2</span></p> 
<p class="content">写成求和的形式就是:</p> 
<div class="bodyPic_104"> 
 <img src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0108-0123.jpg"> 
</div> 
<p class="content_101"><img alt="" class="h-pic" src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0109-0124.jpg">咖哥发言</p> 
<p class="content">同学们注意一下,此处公式里带小括号的上标<span class="italic">x</span><span class="super">(1)</span>,代表样本的维度索引,即整个数据集中的第几个样本。那么大家是否还记得<span class="italic">x</span><span class="sub">1</span>中的下标代表什么?那是标签的维度索引,即第几个标签。这个例子中目前只有一个标签,因此省略了下标。</p> 
<p class="content">■最后,根据样本的数量求平均值,则损失函数<span class="italic">L</span>为:</p> 
<div class="bodyPic_104"> 
 <img src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0109-0125.jpg"> 
</div> 
<p class="content">关于以上公式,说明以下几点。</p> 
<p class="content">■(<span class="italic">x</span><span class="italic">y</span>)为样本,<span class="italic">x</span>是特征(微信公众号广告投放金额),<span class="italic">y</span>是标签(销售额)。</p> 
<p class="content"><span class="italic">h</span><span class="italic">x</span>)是假设函数<span class="italic">wx</span>+<span class="italic">b</span>,也就是<span class="italic">y'</span></p> 
<p class="content"><span class="italic">D</span>指的是包含多个样本的数据集。</p> 
<p class="content"><span class="italic">N</span>指的是样本数量(此例为200)。<span class="italic">N</span>前面还有常量2,是为了在求梯度的时候,抵消二次方后产生的系数,方便后续进行计算,同时增加的这个常量并不影响梯度下降的最效结果。</p> 
<p class="content">■而<span class="italic">L</span>呢,<span class="bold">对于一个给定的训练样本集而言,它是权重</span><span class="italic">w</span><span class="bold">和偏置</span><span class="italic">b</span><span class="bold">的函数,它的大小随着</span><span class="italic">w</span><span class="bold"></span><span class="italic">b</span><span class="bold">的变化而变</span></p> 
<p class="content">下面用Python定义一个<span class="italic">MSE</span>函数,并将其封装起来,以后会调用它。</p> 
<p class="content_101"><img alt="" class="h-pic" src="http://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/b88b00f6ad14402ea66695d6809614da/figure-0109-0126.jpg">咖哥发言</p> 
<p class="content">其实,<span class="italic">MSE</span>函数也不需要我们自己写代码来实现,直接调用Python数学库函数也是可以的,但这是我们的第一个项目,多练练手吧。</p> 
<p class="content">还有一点要告诉大家的,使用<span class="italic">MSE</span>函数做损失函数的线性回归算法,有时被称为<span class="bold">最小二乘法</span></p> 
<p class="content">下面是本例的核心代码段之一:</p> 
<div class="content_106"> 
 <p class="content_105">def loss_function(X, y, weight, bias): # 手工定义一个均方误差函数</p> 
 <p class="content_121">y_hat = weight*X + bias # 这是假设函数, 其中已经应用了Python的广播功能</p> 
 <p class="content_121">loss = y_hat-y # 求出每一个y'和训练集中真实的y之间的差异</p> 
 <p class="content_121">cost = np.sum(loss**2)/2*len(X) # 这是均方误差函数的代码实现</p> 
 <p class="content_121">return cost # 返回当前模型的均方误差值</p> 
</div> 
<p class="content">其中,利用了Python的广播功能以及向量化运算。下面是代码中涉及的内容。</p> 
<p class="content">■在weight*X + bias中,<span class="italic">X</span>是一个2D张量,共200行,1列,但是此处<span class="italic">X</span>可以直接与标量weight相乘,并与标量bias相加,之后仍然得到形状为(200,1)的2D张量。在运行期间weight和bias自动复制自身,形成<span class="italic">X</span>形状匹配的张量。这就是上一课中讲过的广播。</p> 
<p class="content"><span class="italic">y_hat</span>是上面广播计算的结果,形状与标签集<span class="italic">y</span>相同。同学们如果对当前张量形状有疑惑,可以通过shape方法输出其形状。<span class="italic">y_hat</span>可以和<span class="italic">y</span>进行直接的向量化的加减运算,不需要任何for循环参与。这种向量化运算既减少了代码量,又提高了运算效率。</p> 
<p class="content">■损失函数代码中的loss或者cost,都代表当前模型的误差(或称为损失、成本) 值。</p> 
<p class="content">np.sum(loss**2)/2*len(X)是<span class="italic">MSE</span>函数的实现,其中包含以下内容。</p> 
<p class="content">■loss**2代表对误差值进行平方。</p> 
<p class="content">■sum(loss**2)是对张量所有元素求和。</p> 
<p class="content">■len(X)则返回数据集大小,例如200。</p> 
<p class="content">有了这个损失函数,我们就可以判断不同参数的优与劣了。<span class="italic">MSE</span>函数值越小越好,越大就说明误差越大。</p> 
<p class="content">下面随便设定了两组参数,看看其均方误差大小:</p> 
<div class="content_106"> 
 <p class="content_105">print ("当权重为5, 偏置为3时, 损失为:",</p> 
 <p class="content_105">loss_function(X_train, y_train, weight=5, bias=3))</p> 
 <p class="content_105">print ("当权重为100, 偏置为1时, 损失为:",</p> 
 <p class="content_105">loss_function(X_train, y_train, weight=100, bias=1))</p> 
</div> 
<p class="content">调用刚才定义好的损失函数,运行后结果如下:</p> 
<div class="content_126"> 
 <p class="content_109">当权重为5,偏置为3时,损失为:25.592781941560116</p> 
 <p class="content_109">当权重为100,偏置为1时,损失为:3155.918523006111</p> 
</div> 
<p class="content">因此,线性函数<span class="italic">y</span>=3<span class="italic">x</span>+5相对于线性函数<span class="italic">y</span>=100<span class="italic">x</span>+1而言是更优的模型。</p> 
<p class="content_105">同学们纷纷表示基本理解了损失函数的重要性。但小冰提出一个疑问:“这个<span class="italic">MSE</span>函数,为什么非要平方呢?<span class="italic">y</span><span class="italic">y'</span>就是预测误差,取个绝对值之后直接相加不就行了吗?”</p> 
<p class="content_105">咖哥表扬道:“好问题,这个疑惑我以前也曾经有过。均方损失函数,并不是唯一可用的损失函数。为什么这里要选用它呢?如果目的仅是计算损失,把误差的绝对值加起来取平均值就足够了(即平均绝对误差函数)。但是之所以还要平方,是为了让<span class="italic">L</span><span class="italic">w</span><span class="italic">b</span>)形成相对于<span class="italic">w</span><span class="italic">b</span>而言的凸函数,从而实现梯度下降。下面马上就要讲到这个关键之处了。”</p>