<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>神经网络 - Google 机器学习速成课程配套中文解读 on 跟我学机器学习</title><link>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/</link><description>Recent content in 神经网络 - Google 机器学习速成课程配套中文解读 on 跟我学机器学习</description><generator>Hugo</generator><language>zh_CN</language><lastBuildDate>Fri, 30 Oct 2026 21:40:00 +0800</lastBuildDate><atom:link href="https://machinelearningwithme.com/course/google-machine-learning/neural-networks/index.xml" rel="self" type="application/rss+xml"/><item><title>深度学习神经网络：简介 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/introduction/</link><pubDate>Wed, 28 Oct 2026 19:42:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/introduction/</guid><description>&lt;h1 id="神经网络简介"&gt;神经网络：简介&lt;a class="anchor" href="#%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e7%ae%80%e4%bb%8b"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;预计整个模块学习时长：&lt;/strong&gt; 75 分钟&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;学习目标：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;解释我们为什么要构建神经网络，以及它们解决了哪些使用场景的问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;定义并说明深度神经网络架构中几个关键组件各自的作用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;节点&lt;/strong&gt;（Nodes）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隐藏层&lt;/strong&gt;（Hidden layers）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;激活函数&lt;/strong&gt;（Activation functions）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;顺着推理过程一步步走一遍，建立「神经网络是怎么做出预测」的直觉。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;借助反向传播算法，建立「神经网络是怎么被训练出来的」的高层直觉。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解释神经网络如何完成两种多类别分类：一对多（one-vs.-all）与一对一（one-vs.-one）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;blockquote class='book-hint caution'&gt;
&lt;p&gt;&lt;strong&gt;先修要求：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本模块假设你已经熟悉以下模块中介绍的概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/ml/chapter04/generalization-basics/"&gt;机器学习简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/linear-regression/"&gt;线性回归&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/logistic-regression/"&gt;逻辑回归&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/classification/"&gt;分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/numerical-data/"&gt;处理数值数据&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/categorical-data/"&gt;处理类别数据&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/"&gt;数据集、泛化与过拟合&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;h2 id="一个线性模型分不开的分类问题"&gt;一个线性模型分不开的分类问题&lt;a class="anchor" href="#%e4%b8%80%e4%b8%aa%e7%ba%bf%e6%80%a7%e6%a8%a1%e5%9e%8b%e5%88%86%e4%b8%8d%e5%bc%80%e7%9a%84%e5%88%86%e7%b1%bb%e9%97%ae%e9%a2%98"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;先回顾一个场景。在&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/categorical-data/"&gt;类别型数据&lt;/a&gt;模块的&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/categorical-data/feature-cross-exercises/"&gt;特征交叉练习&lt;/a&gt;里，我们见过这样一个分类问题：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="300" src="https://machinelearningwithme.com/images/course/nonlinear_simple.png" alt="图 1. 一张直角坐标平面，横轴标着 x₁、纵轴标着 x₂，四个象限里各撒着一团散点。右上和左下两团是蓝色实心圆点，左上和右下两团是橙色实心圆点。"/&gt; &lt;/div&gt;&lt;center&gt;图 1. 非线性分类问题&lt;/center&gt;
&lt;p&gt;从图中可以看到，这个问题是非线性的。所谓“非线性”，指的是你没法用 $b + w_1x_1 + w_2x_2$ 这种形式的模型准确预测标签，换句话说，它的「决策面」不是一条直线。&lt;/p&gt;
&lt;p&gt;不过话说回来，如果我们对特征 $x_1$ 和 $x_2$ 做一次特征交叉，两个特征之间的非线性关系就能用一个线性模型来表示了：&lt;/p&gt;
$$b + w_1x_1 + w_2x_2 + w_3x_3$$&lt;p&gt;这里 $x_3$ 就是 $x_1$ 与 $x_2$ 的特征交叉。结果是：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="300" src="https://machinelearningwithme.com/images/course/nonlinear_simple_feature_cross.png" alt="图 2. 与图 1 同一张坐标平面，但整幅图被涂上了渐变底色：右上与左下是蓝色，左上与右下是橙色，两种底色之间由一条平滑弯曲的过渡带分开。散点都画成了白色描边的空心圈。"/&gt; &lt;/div&gt;&lt;center&gt;图 2. 加上特征交叉 $x_1x_2$ 之后，线性模型学出了一条双曲形状的边界，把蓝点与橙点分开。&lt;/center&gt;
&lt;p&gt;对比一下图 1 和图 2 就会发现：坐标平面还是那张坐标平面，模型也依然是那个线性模型，变的是它的输入——多出来的 $x_3$ 那一项，正好把弯曲的边界给撑了出来。&lt;/p&gt;</description></item><item><title>神经网络：节点和隐藏层 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/nodes-hidden-layers/</link><pubDate>Thu, 29 Oct 2026 16:08:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/nodes-hidden-layers/</guid><description>&lt;h1 id="神经网络节点和隐藏层"&gt;神经网络：节点和隐藏层&lt;a class="anchor" href="#%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e8%8a%82%e7%82%b9%e5%92%8c%e9%9a%90%e8%97%8f%e5%b1%82"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;在上一节内容中我们说到了非线性问题，如果要搭出一个能学到非线性的神经网络，我们先从一个你已经很熟悉的模型结构说起——一个线性模型：&lt;/p&gt;
$$
y' = b + w_1x_1 + w_2x_2 + w_3x_3
$$&lt;p&gt;这个方程可以这样看：$x_1$、$x_2$ 和 $x_3$ 是我们的三个输入节点（蓝色），$y'$ 是输出节点（绿色）。整张网络就这么简单——一层输入，一层输出，中间没有别的。&lt;/p&gt;
&lt;div class="container lr-interactive-embed" data-interactive-embed&gt;
 &lt;iframe
 src="https://machinelearningwithme.com/course/mlcc_neural_networks_linear.html"
 title="线性模型交互练习：可播放、点选节点并调整权重与偏置"
 loading="lazy"
 style="display:block;width:100%;height:824px;border:0;background:#fff;"
 &gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="练习-1先熟练使用线性模型"&gt;练习 1：先熟练使用线性模型&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a0-1%e5%85%88%e7%86%9f%e7%bb%83%e4%bd%bf%e7%94%a8%e7%ba%bf%e6%80%a7%e6%a8%a1%e5%9e%8b"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;在上面的模型里，&lt;strong&gt;权重&lt;/strong&gt;（weight）和&lt;strong&gt;偏置&lt;/strong&gt;（bias）的值都是随机初始化的。接下来的三个任务，一边帮我们熟悉这个界面，一边摸清线性模型的门道。&lt;/p&gt;
&lt;p&gt;界面上的 &lt;em&gt;Activation Function&lt;/em&gt;（激活函数）下拉框，这会儿可以先放着不管——我们会在本模块后面再专门讲它。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;点一下网络上方的播放按钮（▶️），让它算出在输入 $x_1 = 1.00$、$x_2 = 2.00$、$x_3 = 3.00$ 时，输出节点的取值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;点一下输入层里的第二个节点，把它的值从 2.00 改成 2.50。注意输出节点的取值也跟着变了。选中输出节点（绿色），再看看 &lt;em&gt;Calculations&lt;/em&gt; 面板，就知道这个输出值究竟是怎么算出来的。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;关于计算的几点说明：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;界面上显示的数值，都四舍五入到了小数点后两位。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Linear()&lt;/code&gt; 函数只是把传进去的值原样返回。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;点一下输出节点（绿色），就能看到它的权重（$w_1$、$w_2$、$w_3$）和偏置（$b$）参数值。把 $w_3$ 的权重调小一点（同样注意，输出节点的取值和下方的计算过程也都跟着变了），然后再把偏置调大一点。看看这些改动最后是怎么影响模型输出的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="给网络加一层"&gt;给网络加一层&lt;a class="anchor" href="#%e7%bb%99%e7%bd%91%e7%bb%9c%e5%8a%a0%e4%b8%80%e5%b1%82"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这里先停一下，做个小结：刚才在练习 1 里调整权重和偏置，并没有改变输入与输出之间整体的数学关系——我们的模型&lt;strong&gt;仍然是一个线性模型&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;那么，如果在输入层和输出层之间再加一层呢？&lt;/p&gt;
&lt;p&gt;在神经网络的术语里，输入层与输出层之间额外加上的这些层，叫做&lt;strong&gt;隐藏层&lt;/strong&gt;（hidden layers）；而这些层里的节点，叫做&lt;strong&gt;神经元&lt;/strong&gt;（neurons）。&lt;/p&gt;
&lt;p&gt;隐藏层中每个神经元的值，计算方式和线性模型的输出完全一样：把它的各个输入（也就是上一层的神经元）分别乘上各自的权重参数，再把乘积加起来，最后加上偏置。而下一层（这里就是输出层）的神经元，则是拿隐藏层算出来的神经元值当作输入，按同样的方式计算。&lt;/p&gt;
&lt;p&gt;这个新加的隐藏层，让模型可以用&lt;strong&gt;另一组参数&lt;/strong&gt;重新组合输入数据。那么，它能帮模型学到非线性关系吗？&lt;/p&gt;
&lt;h2 id="练习-2数参数并检验非线性"&gt;练习 2：数参数并检验非线性&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a0-2%e6%95%b0%e5%8f%82%e6%95%b0%e5%b9%b6%e6%a3%80%e9%aa%8c%e9%9d%9e%e7%ba%bf%e6%80%a7"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="container lr-interactive-embed" data-interactive-embed&gt;
 &lt;iframe
 src="https://machinelearningwithme.com/course/mlcc_neural_networks_hidden_layers.html"
 title="含隐藏层的网络交互练习：可播放、点选节点并调整权重与偏置"
 loading="lazy"
 style="display:block;width:100%;height:920px;border:0;background:#fff;"
 &gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;我们已经给模型加了一个包含 4 个神经元的隐藏层。&lt;/p&gt;
&lt;p&gt;先点网络上方播放按钮（▶️），让它算出在输入 $x_1 = 1.00$、$x_2 = 2.00$、$x_3 = 3.00$ 时，4 个隐藏层节点和输出节点各自的取值。&lt;/p&gt;</description></item><item><title>神经网络：激活函数 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/activation-functions/</link><pubDate>Fri, 30 Oct 2026 10:05:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/activation-functions/</guid><description>&lt;h1 id="神经网络激活函数"&gt;神经网络：激活函数&lt;a class="anchor" href="#%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e6%bf%80%e6%b4%bb%e5%87%bd%e6%95%b0"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;在上一节的练习里我们已经试过了：光是往网络里堆隐藏层，并不足以表达出非线性。线性运算作用在线性运算上，结果仍然是线性的。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;关于这一点的实际证明过程，可以可以参见内容&lt;a href="https://machinelearningwithme.com/dl/chapter03/linear-regression-basics/"&gt;「深度学习线性回归入门：多项式回归与神经网络建模基础」&lt;/a&gt; 第3.1.5节内容。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;那么问题来了——要怎么配置一个神经网络，它才能学会取值之间的非线性关系？办法是往模型里插入一些非线性的数学运算。&lt;/p&gt;
&lt;p&gt;其实这套路子你有点眼熟。课程前面我们就在线性模型的输出上动过非线性的手脚：在&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/logistic-regression/"&gt;逻辑回归&lt;/a&gt;那一讲里，我们把线性回归模型的输出送进一个 &lt;strong&gt;sigmoid 函数&lt;/strong&gt;，让它输出 0 到 1 之间的连续值，也就是一个概率。&lt;/p&gt;
&lt;p&gt;同样的原理照样能搬到神经网络上。我们回到之前&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/neural-networks/nodes-hidden-layers/"&gt;练习 2&lt;/a&gt;里的那个模型，只不过这一次，在输出每个节点的取值之前，我们先给它套一层 sigmoid 函数：&lt;/p&gt;
&lt;div class="container lr-interactive-embed" data-interactive-embed&gt;
 &lt;iframe
 src="https://machinelearningwithme.com/course/mlcc_neural_networks_activation_functions.html"
 title="激活函数交互练习：可播放、逐步查看每个节点的计算过程"
 loading="lazy"
 style="display:block;width:100%;height:920px;border:0;background:#fff;"
 &gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;试着点一下播放按钮右边的 &lt;strong&gt;&amp;gt;|&lt;/strong&gt; 按钮，一步步走过每个节点的计算过程，再对照图形下方的 &lt;em&gt;Calculations&lt;/em&gt;（计算过程）面板，看看每个节点的取值究竟是怎么算出来的。你会发现两件事：每个节点的输出，如今都是上一层节点的线性组合再做一次 sigmoid 变换的结果；而且所有输出值都被压在 0 到 1 之间。&lt;/p&gt;
&lt;p&gt;在这里，sigmoid 扮演的就是神经网络的激活函数（activation function）——在神经元的输出值被送进下一层的计算之前，先对它做一次非线性的变换。&lt;/p&gt;
&lt;p&gt;加上了激活函数，再叠层才真正有意义。非线性一层压着一层，我们才有可能建模输入与预测输出之间那些非常复杂的关系。简单说，每一层实际上都在原始输入之上，学到了一个更复杂、层次更高的函数。想对这套机制再建立一些直觉，可以看看 Chris Olah 的这篇&lt;a href="https://colah.github.io/posts/2014-03-NN-Manifolds-Topology/"&gt;博客&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id="常见的激活函数"&gt;常见的激活函数&lt;a class="anchor" href="#%e5%b8%b8%e8%a7%81%e7%9a%84%e6%bf%80%e6%b4%bb%e5%87%bd%e6%95%b0"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;常用作激活函数的数学函数有三个：sigmoid、tanh 和 ReLU。&lt;/p&gt;
&lt;p&gt;前面已经讲过的 sigmoid 函数，对输入 $x$ 做如下变换，输出落在 0 到 1 之间：&lt;/p&gt;
$$
F(x)=\frac{1} {1+e^{-x}}
$$&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt; &lt;em&gt;sigmoid&lt;/em&gt; 这个词常被更宽泛地用来指代任何 S 形的曲线。而上面这个具体的函数 $F(x)=\frac{1} {1+e^{-x}}$，更准确的技术名称其实是 logistic 函数。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;这条曲线长这样：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/sigmoid.png" alt="图 4. 一张直角坐标图，横轴从 -10 标到 10，纵轴从 0.0 标到 1.0。一条蓝色 S 形曲线在左端紧贴着 y=0，从 x≈-2.5 开始缓慢抬起，在 x=0 附近穿过约 0.5，随后逐渐变平，右端无限逼近 y=1 的水平线。"/&gt; &lt;/div&gt;&lt;center&gt;图 4. sigmoid 函数的曲线图。&lt;/center&gt;
&lt;p&gt;tanh（&amp;ldquo;双曲正切&amp;quot;的缩写）把输入 $x$ 变换成 -1 到 1 之间的输出值：&lt;/p&gt;</description></item><item><title>神经网络：使用反向传播训练 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/backpropagation/</link><pubDate>Fri, 30 Oct 2026 14:45:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/backpropagation/</guid><description>&lt;h1 id="神经网络使用反向传播训练"&gt;神经网络：使用反向传播训练&lt;a class="anchor" href="#%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e4%bd%bf%e7%94%a8%e5%8f%8d%e5%90%91%e4%bc%a0%e6%92%ad%e8%ae%ad%e7%bb%83"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint tip'&gt;
&lt;p&gt;&lt;strong&gt;本页要点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反向传播&lt;/strong&gt;：神经网络最主要的训练算法，正是它让梯度下降在多层网络上成为可能，通常由机器学习库自动完成。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;梯度消失&lt;/strong&gt;：发生在底层几层的梯度变得极小、拖慢训练的时候，用 ReLU 激活函数可以缓解。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;梯度爆炸&lt;/strong&gt;：发生在权重过大、梯度大到无法收敛的时候，可以用批归一化或降低学习率来对付。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;死掉的 ReLU 单元&lt;/strong&gt;：指输出卡在 0、梯度再也流不过去的情况，降低学习率或改用 LeakyReLU 这类变体可以避免。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dropout 正则化&lt;/strong&gt;：通过训练时随机「丢掉」一部分单元的激活来防止过拟合，丢掉的比例越高，正则化越强。&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;反向传播&lt;/strong&gt;（backpropagation）是神经网络最常用的训练算法，正是它让梯度下降在多层网络上成为可能。很多机器学习代码库（比如 &lt;a href="https://keras.io/"&gt;Keras&lt;/a&gt;）都会自动完成反向传播，所以你根本不需要自己去算那些底层的东西。&lt;/p&gt;
&lt;h2 id="神经网络训练的最佳实践"&gt;神经网络训练的最佳实践&lt;a class="anchor" href="#%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e8%ae%ad%e7%bb%83%e7%9a%84%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这一节要讲的是：反向传播会在哪些地方翻车，以及最常用的一种神经网络正则化手段。&lt;/p&gt;
&lt;p&gt;对于反向传播的直观理解，可以看成是：模型先做出预测，再根据预测结果与正确答案之间的差距，逐层向后调整各个参与者的影响力（权重），从而不断减少预测误差。&lt;/p&gt;
&lt;p&gt;以教室识别树木为例：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 前向传播（做出预测）&lt;/strong&gt;：从最后一排到第一排，学生们依次传递各自对树木种类的判断，最终汇总得出预测结果。就像模型将输入数据逐层传递，最终得到预测值。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 计算误差（发现问题）&lt;/strong&gt;：老师将预测结果与正确答案进行比较，发现班级只识别对了 7 张照片中的 1 张，说明当前的判断方式存在较大偏差。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 反向传播（追溯误差）&lt;/strong&gt;：老师从最终公布答案的学生开始，逐排向后分析，判断哪些学生的意见对错误结果产生了较大影响。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 更新权重（调整影响力）&lt;/strong&gt;：老师调整不同学生的发言比重，降低不合理的影响，提升有价值的判断，让下一次预测更加准确。&lt;/p&gt;
&lt;p&gt;核心理解： 前向传播负责根据当前权重做出预测，反向传播负责计算误差如何影响各层参数的梯度，而优化器则根据梯度更新权重。通过反复迭代，模型逐渐学会更准确地预测。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;MLWM&lt;/strong&gt;: 一句话总结，通过梯度下降最小化目标函数求得参数，但使用梯度下降的前提是知道目标函数关于每个参数的梯度，而反向传播算法恰恰是求解梯度的一大利器。&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt; 反向传播算法用到了微积分里的&lt;a href="https://wikipedia.org/wiki/Gradient"&gt;梯度&lt;/a&gt;概念，靠它来调整模型权重、把损失压到最小。要理解并排查下面这些问题，通常得先有点微积分基础。&lt;/p&gt;&lt;/blockquote&gt;&lt;h3 id="梯度消失"&gt;梯度消失&lt;a class="anchor" href="#%e6%a2%af%e5%ba%a6%e6%b6%88%e5%a4%b1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;越靠近输入层的那些底层网络，它们的梯度可能会变得非常小。在&lt;strong&gt;深度网络&lt;/strong&gt;（隐藏层超过一层的网络）里，算这些梯度往往要连乘很多个很小的项。&lt;/p&gt;
&lt;p&gt;当底层那些层的梯度值趋近于 0 时，我们就说梯度「消失」了。出现梯度消失的层，训练起来会非常慢，甚至干脆完全不训练。 此时，ReLU 激活函数可以极大地帮我们避免梯度消失。&lt;/p&gt;
&lt;h3 id="梯度爆炸"&gt;梯度爆炸&lt;a class="anchor" href="#%e6%a2%af%e5%ba%a6%e7%88%86%e7%82%b8"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;反过来，如果网络里的权重非常大，底层的梯度就变成很多大项的连乘。这种情况下就可能出现&lt;strong&gt;梯度爆炸&lt;/strong&gt;：梯度大到根本没法收敛。这个时候，不妨可以试试 &lt;a href="https://machinelearningwithme.com/dl/chapter06/batch-norm/"&gt;批归一化（batch normalization）&lt;/a&gt;和降低学习率这两个方法。&lt;/p&gt;
&lt;h3 id="死掉的-relu-单元"&gt;死掉的 ReLU 单元&lt;a class="anchor" href="#%e6%ad%bb%e6%8e%89%e7%9a%84-relu-%e5%8d%95%e5%85%83"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;虽然 ReLU 激活函数能够有效缓解梯度消失的问题，不过一旦某个 ReLU 单元的加权和掉到 0 以下，那这个单元就永远失去了作用，因为此时它的输出恒为 0，对网络输出毫无贡献，反向传播时梯度也再也流不过去了。当梯度这么一断，喂给这个 ReLU 的输入就可能永远变不到足够大，导致这个加权和再也回不到 0 以上。&lt;/p&gt;
&lt;p&gt;此时，降低学习率，可以在一定程度上缓解这一问题。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt; 当然，针对这个问题，业界还设计了不少 ReLU 的变体，比如 &lt;a href="https://machinelearningwithme.com/dl/chapter03/activation-functions/"&gt;LeakyReLU&lt;/a&gt; ，可以考虑用它来当激活函数。&lt;/p&gt;</description></item><item><title>神经网络：交互式练习 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/interactive-exercises/</link><pubDate>Fri, 30 Oct 2026 18:35:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/interactive-exercises/</guid><description>&lt;h1 id="神经网络交互式练习"&gt;神经网络：交互式练习&lt;a class="anchor" href="#%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e4%ba%a4%e4%ba%92%e5%bc%8f%e7%bb%83%e4%b9%a0"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint tip'&gt;
&lt;p&gt;&lt;strong&gt;本页、节要点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;参数与超参数&lt;/strong&gt;：权重、偏置是参数，改动它们会直接改变这一次的计算结果；隐藏层层数、神经元个数、学习率、激活函数是超参数，它们决定模型学什么。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;前馈推理&lt;/strong&gt;：这个网络的计算是单向流动的，新加一层只会影响它之后的节点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ReLU 的截断性&lt;/strong&gt;：ReLU(0) 与 ReLU(-5) 的输出都是 0，所以节点值没变并不等于底层计算没变。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;损失（loss）&lt;/strong&gt;：练习 2 用测试损失与训练损失两个数字，衡量模型拟合得够不够好。&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;通过接下来的两个练习，让我们把神经网络拆开看个究竟。先看参数与超参数的改动如何影响网络的预测，再动手训练一个神经网络，让它自己学会拟合非线性数据。&lt;/p&gt;
&lt;h2 id="练习-1亲手拨一个-relu-网络"&gt;练习 1：亲手拨一个 ReLU 网络&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a0-1%e4%ba%b2%e6%89%8b%e6%8b%a8%e4%b8%80%e4%b8%aa-relu-%e7%bd%91%e7%bb%9c"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;下面的组件按这样一套配置搭好了一个神经网络：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;输入层有 3 个神经元，初始取值分别是 0.00、0.00、0.00。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;隐藏层有 4 个神经元。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;输出层有 1 个神经元。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;隐藏层的所有节点，以及输出节点，都使用 ReLU 激活函数。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;先花点时间熟悉一下网络的初始设置（注意：&lt;strong&gt;暂时不要点 ▶️ 和 &amp;gt;| 这两个按钮&lt;/strong&gt;），然后完成组件下面的两个任务。&lt;/p&gt;
&lt;div class="container lr-interactive-embed" data-interactive-embed&gt;
 &lt;iframe
 src="https://machinelearningwithme.com/course/mlcc_neural_networks_hidden_layers_relu.html"
 title="含 ReLU 激活的多层神经网络交互练习：可运行、点选节点并调整权重与偏置"
 loading="lazy"
 style="display:block;width:100%;height:920px;border:0;background:#fff;"
 &gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h3 id="任务-1输出会是正数负数还是-0"&gt;任务 1：输出会是正数、负数，还是 0？&lt;a class="anchor" href="#%e4%bb%bb%e5%8a%a1-1%e8%be%93%e5%87%ba%e4%bc%9a%e6%98%af%e6%ad%a3%e6%95%b0%e8%b4%9f%e6%95%b0%e8%bf%98%e6%98%af-0"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;神经网络的三个输入特征，取值都是 0.00。点开网络里的每个节点，看看初始化之后的参数值。在按下运行（▶️）按钮之前，先回答这个问题：&lt;/p&gt;
&lt;p&gt;你认为最终会得到什么样的输出值：正数、负数，还是 0？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 输出为正数&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 输出为负数&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 输出为 0&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在点一下网络上方的运行（▶️）按钮，看着隐藏层和输出节点上的数值一个个被填上。你上面的答案对吗？&lt;/p&gt;

&lt;span class="subscription-widget subscription-widget--content"
 data-subscription-widget
 data-resource-id="391d6110301f4f8d"
 data-resource-text="点击查看答案及分析"
 data-resource-plan="basic"
 data-resource-color="blue"
 data-resource-align="left"
 data-resource-type="content"&gt;
 &lt;button type="button" class="subscription-btn subscription-btn--content" data-subscription-trigger data-type="content" style="font-size: 0.9em;" aria-busy="false"&gt;
 &lt;span class="subscription-btn__text"&gt;点击查看答案及分析&lt;/span&gt;
 &lt;/button&gt;
 &lt;span class="subscription-result" data-subscription-result hidden role="status" aria-live="polite"&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;script&gt;
(function () {
 var script = document.currentScript;
 var widget = script &amp;&amp; script.previousElementSibling;
 if (!widget || !widget.matches || !widget.matches('[data-subscription-widget]')) return;

 var trigger = widget.querySelector('[data-subscription-trigger]');
 var result = widget.querySelector('[data-subscription-result]');
 var icon = trigger.querySelector('.subscription-btn__icon');
 var textEl = trigger.querySelector('.subscription-btn__text');
 
 var originalIcon = icon ? icon.textContent : '';
 var originalText = textEl.textContent;
 var resourceId = widget.dataset.resourceId;
 var planHint = widget.dataset.resourcePlan || '';

 
 
 
 
 
 
 function applyContentStyle() {
 var S = window.MLWM_SUB_STYLE;
 if (S &amp;&amp; typeof S.apply === 'function') {
 S.apply(widget, widget.dataset.resourceColor, widget.dataset.resourceAlign);
 }
 }
 
 
 
 
 
 
 
 
 
 function notifyToggle(expanded) {
 document.dispatchEvent(new CustomEvent('mlwm:subscription-toggle', {
 detail: { resourceId: resourceId, expanded: !!expanded }
 }));
 }

 
 
 
 
 
 
 if (document.readyState === 'loading') {
 document.addEventListener('DOMContentLoaded', applyContentStyle, { once: true });
 } else {
 applyContentStyle();
 }

 
 
 var cached = null;
 var inflight = null;

 
 
 function resolveApiUrl(path) {
 if (window.__ML_API &amp;&amp; typeof window.__ML_API === 'function') return window.__ML_API(path);
 return path;
 }

 function isLoggedIn() {
 return document.documentElement.getAttribute('data-mlwm-auth') === 'in';
 }
 function getToken() {
 try { return localStorage.getItem('mlwm_auth_access') || ''; } catch (_) { return ''; }
 }
 function showLoginModal(opts) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openLoginModal === 'function') {
 window.MLWM_AUTH.openLoginModal(Object.assign({ mode: 'login' }, opts || {}));
 } else {
 window.location.assign('/login/');
 }
 }
 function showToast(msg, type) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.showToast === 'function') {
 window.MLWM_AUTH.showToast(msg, type || 'warning');
 }
 }
 function setBusy(busy) {
 trigger.disabled = !!busy;
 trigger.setAttribute('aria-busy', busy ? 'true' : 'false');
 textEl.textContent = busy ? '加载中...' : originalText;
 }
 function clearResult() {
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 textEl.textContent = originalText;
 trigger.style.display = '';
 }
 function setResult(html, kind) {
 applyContentStyle();
 result.hidden = false;
 result.innerHTML = html;
 result.dataset.kind = kind || 'info';
 }
 function escapeHtml(s) {
 return String(s == null ? '' : s).replace(/[&amp;&lt;&gt;"']/g, function (c) {
 return { '&amp;': '&amp;amp;', '&lt;': '&amp;lt;', '&gt;': '&amp;gt;', '"': '&amp;quot;', "'": '&amp;#39;' }[c];
 });
 }

 
 
 
 
 
 
 
 function renderMarkdown(text) {
 var src = String(text == null ? '' : text);
 if (window.MLWM_MARKED_MD &amp;&amp; typeof window.MLWM_MARKED_MD.render === 'function') {
 var html = window.MLWM_MARKED_MD.render(src);
 if (typeof html === 'string') return html;
 }
 if (typeof marked !== 'undefined' &amp;&amp; typeof marked.parse === 'function') {
 return marked.parse(src);
 }
 return escapeHtml(src);
 }

 
 function isExpanded() { return widget.classList.contains('is-expanded'); }
 function isPinned() { return widget.classList.contains('is-pinned'); }
 function pin() { widget.classList.add('is-pinned'); }
 function unpin() { widget.classList.remove('is-pinned'); }

 function renderContentBox(data) {
 var html =
 '&lt;div class="subscription-content__title"&gt;' +
 '&lt;span class="subscription-content__chevron" aria-hidden="true"&gt;&lt;/span&gt;' +
 '&lt;span class="subscription-content__title-text"&gt;' + escapeHtml(originalText) + '&lt;/span&gt;' +
 '&lt;/div&gt;' +
 '&lt;div class="subscription-content__body"&gt;' + renderMarkdown(data.body) + '&lt;/div&gt;';
 trigger.style.display = 'none';
 setResult(html, 'content');
 widget.classList.add('is-expanded');
 notifyToggle(true);
 
 
 
 if (typeof window.renderMathInElement === 'function') {
 try {
 window.renderMathInElement(result, {
 throwOnError: false,
 delimiters: [
 { left: '$$', right: '$$', display: true },
 { left: '$', right: '$', display: false },
 { left: '\\(', right: '\\)', display: false },
 { left: '\\[', right: '\\]', display: true }
 ]
 });
 } catch (_) { }
 }
 }
 function hideContentBox() {
 trigger.style.display = '';
 clearResult();
 widget.classList.remove('is-expanded');
 unpin();
 notifyToggle(false);
 }

 function renderDenied(body) {
 var detail = body.detail || {};
 
 var requiredPlan = detail.required_plan || planHint || 'pro';
 
 var currentPlan = (detail.current_plan || '').toString().trim();
 var hasCurrent = !!currentPlan;
 
 var title = hasCurrent ? '订阅等级不足' : '尚未订阅';
 
 var bodyText = hasCurrent
 ? '当前订阅为 ' + escapeHtml(currentPlan) + '，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。'
 : '当前未订阅，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。';
 
 
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 trigger.style.display = '';
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openDeniedModal === 'function') {
 window.MLWM_AUTH.openDeniedModal({
 title: title,
 body: bodyText,
 ctaText: '订阅方案',
 ctaHref: '/pricing/'
 });
 } else {
 
 window.location.assign('/pricing/');
 }
 }
 function renderDownload(data) {
 
 
 showToast('已触发下载: ' + (data.title || data.url || ''), 'success');
 var a = document.createElement('a');
 a.href = data.url;
 a.rel = 'noopener noreferrer';
 a.download = '';
 a.style.display = 'none';
 document.body.appendChild(a);
 a.click();
 document.body.removeChild(a);
 }
 function renderError(msg) {
 setResult('&lt;div class="subscription-error"&gt;' + escapeHtml(msg || '请求失败,请稍后再试') + '&lt;/div&gt;', 'error');
 }

 
 
 
 
 
 
 
 
 
 
 function fetchResource() {
 if (cached) return Promise.resolve({ ok: true, data: cached });
 if (inflight) return inflight;

 if (!isLoggedIn()) {
 return Promise.resolve({ ok: false, reason: 'not-logged-in', status: 0, body: null });
 }
 var url = resolveApiUrl('/resource/' + encodeURIComponent(resourceId));
 inflight = fetch(url, {
 method: 'GET',
 headers: { 'Authorization': 'Bearer ' + getToken() }
 })
 .then(function (r) {
 return r.json().then(function (j) { return { status: r.status, body: j }; }).catch(function () { return { status: r.status, body: null }; });
 })
 .then(function (resp) {
 if (resp.status === 401) {
 return { ok: false, reason: 'unauthorized', status: 401, body: null };
 }
 var body = resp.body;
 if (!body || typeof body !== 'object') {
 return { ok: false, reason: 'bad-response', status: resp.status, body: body };
 }
 if (body.code === 2002) {
 return { ok: false, reason: 'denied', status: resp.status, body: body };
 }
 if (body.code === 0 &amp;&amp; body.data) {
 
 if (body.data.type === 'content') {
 cached = body.data;
 return { ok: true, data: cached };
 }
 if (body.data.type === 'download' &amp;&amp; body.data.url) {
 return { ok: true, data: body.data };
 }
 }
 return { ok: false, reason: 'api-error', status: resp.status, body: body };
 })
 .catch(function () {
 return { ok: false, reason: 'network', status: 0, body: null };
 });
 
 inflight.then(function () { inflight = null; }, function () { inflight = null; });
 return inflight;
 }

 
 
 function ensureContent() {
 setBusy(true);
 return fetchResource().then(function (result) {
 setBusy(false);
 if (result.ok) {
 if (result.data.type === 'content') {
 renderContentBox(result.data);
 pin();
 return result.data;
 }
 if (result.data.type === 'download') {
 renderDownload(result.data);
 return null;
 }
 return null;
 }
 if (result.reason === 'not-logged-in') {
 showLoginModal({ bannerMessage: '请先登录后再访问资源' });
 } else if (result.reason === 'unauthorized') {
 showLoginModal({ bannerMessage: '登录已过期,请重新登录' });
 } else if (result.reason === 'denied') {
 renderDenied(result.body);
 } else if (result.reason === 'bad-response') {
 renderError('响应异常');
 } else if (result.reason === 'api-error') {
 renderError((result.body &amp;&amp; result.body.msg) || ('请求失败 (code ' + ((result.body &amp;&amp; result.body.code) || '?') + ')'));
 } else if (result.reason === 'network') {
 renderError('网络异常,请稍后再试');
 }
 return null;
 });
 }

 
 
 
 
 trigger.addEventListener('click', function (e) {
 e.stopPropagation();
 if (isExpanded()) return;
 ensureContent();
 });

 
 result.addEventListener('click', function (e) {
 var titleEl = e.target.closest('.subscription-content__title');
 if (titleEl) hideContentBox();
 });

 
 
 
 

 
 
 
 
 
 
 widget.addEventListener('mlwm:subscription-prefetch', function () {
 
 
 
 
 widget._prefetchPromise = fetchResource().then(function () {}, function () {});
 });
})();
&lt;/script&gt;

&lt;h3 id="任务-2多插一层谁会跟着变"&gt;任务 2：多插一层，谁会跟着变？&lt;a class="anchor" href="#%e4%bb%bb%e5%8a%a1-2%e5%a4%9a%e6%8f%92%e4%b8%80%e5%b1%82%e8%b0%81%e4%bc%9a%e8%b7%9f%e7%9d%80%e5%8f%98"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在动手改网络之前，先回答这个问题：&lt;/p&gt;</description></item><item><title>神经网络：多类别分类 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/multi-class/</link><pubDate>Fri, 30 Oct 2026 21:40:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/neural-networks/multi-class/</guid><description>&lt;h1 id="神经网络多类别分类"&gt;神经网络：多类别分类&lt;a class="anchor" href="#%e7%a5%9e%e7%bb%8f%e7%bd%91%e7%bb%9c%e5%a4%9a%e7%b1%bb%e5%88%ab%e5%88%86%e7%b1%bb"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint tip'&gt;
&lt;p&gt;&lt;strong&gt;本页、节要点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多类别分类&lt;/strong&gt;：从两个以上的候选里挑出答案，而不像二元分类那样只做二选一。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;两条主要路线&lt;/strong&gt;：一对多（one-vs.-all）与一对一（one-vs.-one，后者通常就叫 softmax）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一对多&lt;/strong&gt;：用多个二元分类器，各自独立地算出每一个类别的概率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一对一（softmax）&lt;/strong&gt;：预测每个类别相对于其他所有类别的概率，softmax 保证所有概率加起来正好是 1。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;softmax 的效率&lt;/strong&gt;：类别少的时候很划算，类别一多计算成本就吃不消；候选采样是提效的替代方案。&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;前面几节我们接触过的分类模型都只做二选一，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;这封邮件是不是垃圾邮件。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这个肿瘤是恶性的还是良性的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一节要研究的是&lt;strong&gt;多类别分类模型&lt;/strong&gt;，它们可以从多个候选中挑出答案，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;这条狗是比格犬、巴吉度还是寻血猎犬？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这朵花是西伯利亚鸢尾、荷兰鸢尾、蓝旗鸢尾还是矮须鸢尾？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;那架飞机是波音 747、空客 320、波音 777，还是巴航工业 190？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这张图是苹果、熊、糖果、狗还是鸡蛋？&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;真实世界里的多类别问题，甚至可能要在数百万个类别中做选择——比如那种几乎能认出任何东西的图像多类别分类模型。&lt;/p&gt;
&lt;p&gt;本节详解多类别分类的两个主要变体：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一对多（one-vs.-all）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一对一（one-vs.-one），通常就叫 softmax&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="一对多"&gt;一对多&lt;a class="anchor" href="#%e4%b8%80%e5%af%b9%e5%a4%9a"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;一对多给出了一条把二元分类用成一连串「是 / 否」判断的路子。&lt;/p&gt;
&lt;p&gt;如果一个分类问题有 N 个可能的答案，一对多方案就是由 &lt;strong&gt;N 个彼此独立的二元分类器&lt;/strong&gt;组成——每种可能的结果配一个。训练的时候，模型依次跑过这一串二元分类器，把每一个都训练成能回答自己那个独立的问题。&lt;/p&gt;
&lt;p&gt;举个例子：拿到一张水果的图片，训练时可能会得到 4 个不同的识别器，每个都回答一个不同的是非题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;这张图是苹果吗？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这张图是橙子吗？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这张图是香蕉吗？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;这张图是葡萄吗？&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下图展示了这套做法在实践中是怎么跑起来的。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="650" src="https://machinelearningwithme.com/images/course/one_vs_all_binary_classifiers.png" alt="图 7. 一颗梨作为输入，被送进 4 个不同的二元分类器模型。第一个模型判断「苹果 / 非苹果」，给出「非苹果」；第二个模型判断「橙子 / 非橙子」，给出「非橙子」；第三个模型判断「梨 / 非梨」，给出「梨」；第四个模型判断「葡萄 / 非葡萄」，给出「非葡萄」。"/&gt; &lt;/div&gt;&lt;center&gt;图 7. 一对多：同一张图片过 4 个二元分类器&lt;/center&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt; 想知道二元分类器到底是怎么做出预测的（也就是怎么设定分类阈值，把模型输出的数值变成「正」或「负」的标签），可以看看&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/classification/"&gt;分类&lt;/a&gt;模块。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;当类别总数不多时，这套做法相当合理；但类别一多，效率就越来越差。&lt;/p&gt;
&lt;p&gt;不过我们可以用深层神经网络做出一对多得高效得多的模型：让每个输出节点代表一个不同的类别。下图就是这种做法。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="650" src="https://machinelearningwithme.com/images/course/one_vs_all_neural_net.png" alt="图 8. 一个神经网络，架构为：输入层 1 个节点，第一层隐藏层 3 个节点，第二层隐藏层 4 个节点，输出层 4 个节点。输入节点被喂入一张梨的图片。输出层施加 sigmoid 激活函数，每个输出节点表示这张图是某种指定水果的概率。输出节点 1 表示「是苹果吗？」取值 0.34，节点 2 表示「是橙子吗？」取值 0.18，节点 3 表示「是梨吗？」取值 0.84，节点 4 表示「是葡萄吗？」取值 0.07。"/&gt; &lt;/div&gt;&lt;center&gt;图 8. 用神经网络完成同一组一对多任务&lt;/center&gt;
&lt;h2 id="一对一softmax"&gt;一对一（softmax）&lt;a class="anchor" href="#%e4%b8%80%e5%af%b9%e4%b8%80softmax"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;你可能已经注意到，图 8 输出层里那些概率值加起来并不是 1.0（也就是 100%）——实际上它们加起来是 &lt;strong&gt;1.43&lt;/strong&gt;。&lt;/p&gt;</description></item></channel></rss>