<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>深度学习 &#8211; Blog of Code</title>
	<atom:link href="https://www.cztcode.com/category/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.cztcode.com</link>
	<description></description>
	<lastBuildDate>Thu, 24 Aug 2023 15:06:15 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.cztcode.com/wp-content/uploads/2024/02/cropped-logo-32x32.webp</url>
	<title>深度学习 &#8211; Blog of Code</title>
	<link>https://www.cztcode.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">217219486</site>	<item>
		<title>Softmax 回归简介</title>
		<link>https://www.cztcode.com/2023/4957/</link>
					<comments>https://www.cztcode.com/2023/4957/#respond</comments>
		
		<dc:creator><![CDATA[Jellow]]></dc:creator>
		<pubDate>Thu, 24 Aug 2023 15:05:41 +0000</pubDate>
				<category><![CDATA[深度学习]]></category>
		<guid isPermaLink="false">https://www.cztcode.com/?p=4957</guid>

					<description><![CDATA[社会科学家邓肯·卢斯于1959年在*选择模型*（choice model）的理论基础上 发明的了*softmax函数*： softmax函数能够将未规范化的预测变换为非负数并且总和为1，同时让模型保持 可导的性质。

为什么叫Softmax呢？Softmax从字面上来说，可以分成soft和max两个部分。max故名思议就是最大值的意思。Softmax的核心在于soft，而soft有软的含义，与之相对的是hard硬。很多场景中需要我们找出数组所有元素中值最大的元素。

Softmax函数是一个在数学和计算机科学中常用的函数，特别是在机器学习的分类问题中。它可以把一个含任意实数的K维向量“压缩”到另一个K维实向量中，使得每一个元素的范围都在`$$(0,1)$$`之间，并且所有元素的和为1。这使得Softmax函数的输出可以被解释为概率分布。]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><h2>Softmax函数</h2>
<p>社会科学家邓肯·卢斯于1959年在<em>选择模型</em>（choice model）的理论基础上 发明的了<em>softmax函数</em>： softmax函数能够将未规范化的预测变换为非负数并且总和为1，同时让模型保持 可导的性质。</p>
<p>为什么叫Softmax呢？Softmax从字面上来说，可以分成soft和max两个部分。max故名思议就是最大值的意思。Softmax的核心在于soft，而soft有软的含义，与之相对的是hard硬。很多场景中需要我们找出数组所有元素中值最大的元素。</p>
<p>Softmax函数是一个在数学和计算机科学中常用的函数，特别是在机器学习的分类问题中。它可以把一个含任意实数的K维向量“压缩”到另一个K维实向量中，使得每一个元素的范围都在<code class="katex-inline">(0,1)</code>之间，并且所有元素的和为1。这使得Softmax函数的输出可以被解释为概率分布。</p>
<p>Softmax函数的定义如下：</p>
<p><code class="katex-inline">\text{softmax}(x)_i = \frac{e^{x_i}}{\sum_{j=1}^K e^{x_j}}</code></p>
<p>其中<code class="katex-inline">x</code>是输入向量，<code class="katex-inline">K</code>是向量的维度，<code class="katex-inline">i</code>是指定的元素索引。</p>
<p>在多分类问题中，Softmax函数常用于将模型的原始输出（通常被称为logits）转换为概率分布。这样，每个类别的概率可以直接相比较，从而选择最可能的类别。</p>
<p>例如，如果一个模型用于对数字图像进行分类，并且原始输出是<code class="katex-inline">(2.0, 1.0, 0.1)</code>，则通过Softmax函数，我们可以得到一个新的向量，如<code class="katex-inline">(0.7, 0.2, 0.1)</code>，其中每个值代表对应数字的预测概率。</p>
<h2>Softmax回归</h2>
<p>Softmax回归可以看作是一个简单的神经网络，其中没有隐藏层，直接将输入与输出层连接。虽然模型相对简单，但在一些多分类问题上表现还是不错的，特别是在类别之间的边界比较清晰的情况下。</p>
<p><img decoding="async" src="https://markdown.cztcode.com/1eabd6c5a86078811b356c098e6c4b8d.svg" alt="../_images/softmaxreg.svg" /></p>
<h2>SoftLabel</h2>
<p>SoftLabel 是一种处理标签问题的技术，通常用在机器学习的分类问题中。在传统的分类任务中，每个样本只会被分配一个确定的类别标签，比如说在一个二分类问题中，标签通常是 0 或 1。但在某些情况下，我们可能希望更灵活地表达分类的不确定性或者模糊性。</p>
<p>SoftLabel 就是这样一种技术，允许每个样本有一个属于每个类别的概率分布。例如，在一个二分类问题中，一个样本的 SoftLabel 可能是 (0.6, 0.4)，这表示该样本属于第一类的概率是 60%，属于第二类的概率是 40%。</p>
<p>这种方法有以下几个优点：</p>
<ol>
<li>
<p><strong>灵活性</strong>：SoftLabel 能更灵活地表示样本之间的不确定性和模糊性，适用于那些不容易归入单一类别的样本。</p>
</li>
<li>
<p><strong>鲁棒性</strong>：对于那些具有噪声或不准确标签的数据集，SoftLabel 可以提供一种更鲁棒的方法来表达这种不确定性。</p>
</li>
<li>
<p><strong>更好的梯度信息</strong>：在训练神经网络时，SoftLabel 可以提供更丰富的梯度信息，有助于网络的训练。</p>
</li>
<li>
<p><strong>平滑化决策边界</strong>：SoftLabel 通过允许样本具有模糊的类别分配，可以使分类器的决策边界更加平滑，从而减少过拟合现象。</p>
</li>
</ol>
<p>SoftLabel 可以与各种损失函数结合使用，如交叉熵损失。它是许多现代机器学习模型中的一个重要组成部分，尤其在处理具有模糊或不确定标签的数据时。</p>
<h2>Softmax注意事项</h2>
<p>Softmax函数虽然强大和广泛应用，但在某些情况下也存在一些限制和挑战，如：</p>
<ul>
<li><strong>数值稳定性问题</strong>：Softmax涉及指数运算，可能导致数值上溢或下溢。一些改进方法，如对输入进行缩放，可以帮助缓解这个问题。</li>
<li><strong>计算成本</strong>：对于大规模的类别集合，Softmax的计算可能相对昂贵。</li>
<li><strong>不适用于非互斥类别</strong>：如果数据可以归入多个类别，传统的Softmax可能不适用。</li>
<li><strong>可能的局部最优解</strong>：在某些情况下，Softmax可能会陷入局部最优解，不一定能找到全局最优解。</li>
</ul>
<p>虽然Softmax在许多方面表现出色，但在使用过程中需要注意一些问题。其中一个常见的挑战是数值稳定性。由于涉及指数运算，可能会出现数值上溢或下溢的情况。解决这个问题的一种方法是在计算之前对输入进行缩放。此外，Softmax可能不适用于具有大量类别或非互斥类别的场景。</p>
<h2>手动实现Softmax</h2>
<p>用Softmax实现图像分类问题</p>
<pre><code class="language-python">import torch
import torchvision
from torch.utils import data
from torchvision import transforms

lr = 0.1
w = torch.normal(0, 0.01, size=(784, 10), requires_grad=True)
b = torch.zeros(10, requires_grad=True)

def sgd(params, lr, batch_size):
    &quot;&quot;&quot;Minibatch stochastic gradient descent.&quot;&quot;&quot;
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()

def get_dataloader_workers():  # @save
    &quot;&quot;&quot;使用4个进程来读取数据&quot;&quot;&quot;
    return 4

def load_data_fashion_mnist(batch_size, resize=None):  # @save
    &quot;&quot;&quot;下载Fashion-MNIST数据集，然后将其加载到内存中&quot;&quot;&quot;
    trans = [transforms.ToTensor()]
    if resize:
        trans.insert(0, transforms.Resize(resize))
    trans = transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(
        root=&quot;../data&quot;, train=True, transform=trans, download=True
    )
    mnist_test = torchvision.datasets.FashionMNIST(
        root=&quot;../data&quot;, train=False, transform=trans, download=True
    )
    return (
        data.DataLoader(
            mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()
        ),
        data.DataLoader(
            mnist_test, batch_size, shuffle=False, num_workers=get_dataloader_workers()
        ),
    )

def softmax(X):
    X_exp = torch.exp(X)
    partition = X_exp.sum(1, keepdim=True)
    return X_exp / partition  # 这里应用了广播机制

def cross_entropy(y_hat, y):
    return -torch.log(y_hat[range(len(y_hat)), y])

def net(X):
    return softmax(torch.matmul(X.reshape((-1, w.shape[0])), w) + b)

def accuracy(y_hat, y):
    if len(y_hat.shape) &gt; 1 and y_hat.shape[1] &gt; 1:
        y_hat = y_hat.argmax(axis=1)
    cmp = y_hat.type(y.dtype) == y
    return float(cmp.type(y.dtype).sum())

def evaluate_accuracy(net, data_iter):
    if isinstance(net, torch.nn.Module):
        net.eval()
    metric = Accumulator(2)
    for X, y in data_iter:
        metric.add(accuracy(net(X), y), y.numel())
    return metric[0] / metric[1]

class Accumulator:
    &quot;&quot;&quot;在`n`个变量上累加。&quot;&quot;&quot;

    def __init__(self, n):
        self.data = [0.0] * n

    def add(self, *args):
        self.data = [a + float(b) for a, b in zip(self.data, args)]

    def reset(self):
        self.data = [0.0] * len(self.data)

    def __getitem__(self, idx):
        return self.data[idx]

def train_epoch_ch3(net, train_iter, loss, updater):
    &quot;&quot;&quot;训练模型一个迭代周期（定义见第3章）。&quot;&quot;&quot;
    # 将模型设置为训练模式
    if isinstance(net, torch.nn.Module):
        net.train()
    # 训练损失总和、训练准确率总和、范例数
    metric = Accumulator(3)
    for X, y in train_iter:
        # 计算梯度并更新参数
        # 其余代码不变
        y_hat = net(X)
        l = loss(y_hat, y)
        if isinstance(updater, torch.optim.Optimizer):
            # 使用PyTorch内置的优化器和损失函数
            updater.zero_grad()
            l.backward()
            updater.step()
            metric.add(float(l) * len(y), accuracy(y_hat, y), y.size().numel())
        else:
            # 使用定制的优化器和损失函数
            l.sum().backward()
            updater(X.shape[0])
            metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
    # 返回训练损失和训练准确率
    return metric[0] / metric[2], metric[1] / metric[2]

def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):
    &quot;&quot;&quot;训练模型（定义见第3章）。&quot;&quot;&quot;
    train_metrics = None
    test_acc = None
    for epoch in range(num_epochs):
        train_metrics = train_epoch_ch3(net, train_iter, loss, updater)
        test_acc = evaluate_accuracy(net, test_iter)
    train_loss, train_acc = train_metrics
    print(f&quot;train_loss {train_loss:f} train_acc {train_acc:f} test_acc {test_acc:f}&quot;)

def updater(batch_size):
    return sgd([w, b], lr, batch_size)

if __name__ == &quot;__main__&quot;:
    num_epochs = 10
    train_iter, test_iter = load_data_fashion_mnist(batch_size=256)
    train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
</code></pre>
<h2>参考资料</h2>
<p><a href="https://zh.d2l.ai/chapter_linear-networks/softmax-regression.html" target="_blank" rel="noopener">https://zh.d2l.ai/chapter_linear-networks/softmax-regression.html</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cztcode.com/2023/4957/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4957</post-id>	</item>
		<item>
		<title>交叉熵损失</title>
		<link>https://www.cztcode.com/2023/4908/</link>
					<comments>https://www.cztcode.com/2023/4908/#respond</comments>
		
		<dc:creator><![CDATA[Jellow]]></dc:creator>
		<pubDate>Mon, 21 Aug 2023 11:29:15 +0000</pubDate>
				<category><![CDATA[深度学习]]></category>
		<guid isPermaLink="false">https://www.cztcode.com/?p=4908</guid>

					<description><![CDATA[熵 信息论中熵的概念首次被香农提出，目的是寻找一种高效/无损地编码信息的方法：以编码后数据的平均长度来衡量高效性，平均长度越小越高效；同时还需满足“无损”的条件，即编码后不能有原始信息的丢失。这样，香农提出了熵的定义：无损编码事件信息的最小平均编码长度。 假设一个信息事件有 N 种可能的状态，且各状态等可能性，即每种状态的可能性为 P = \frac{1}{N}。则编码该信息所需的最小编码长度可以 [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><h2>熵</h2>
<p>信息论中熵的概念首次被香农提出，目的是寻找一种高效/无损地编码信息的方法：以编码后数据的平均长度来衡量高效性，平均长度越小越高效；同时还需满足“无损”的条件，即编码后不能有原始信息的丢失。这样，香农提出了熵的定义：无损编码事件信息的最小平均编码长度。</p>
<p>假设一个信息事件有 N 种可能的状态，且各状态等可能性，即每种状态的可能性为 <code class="katex-inline">P = \frac{1}{N}</code>。则编码该信息所需的最小编码长度可以用以下数学公式表示：</p>
<p><code class="katex-inline">L = \log_2 N</code></p>
<p>比如当 N = 8 ，所以每种状态的可能性 <code class="katex-inline">\ P = \frac{1}{8} = 12.5\%</code> ，那么编码该信息所需的最小编码长度为：</p>
<p><code class="katex-inline">L = \log_2 8 = 3</code></p>
<p>也就是说，8个值需要3位来编码（例如000, 001, 010, 011, 100, 101, 110, 111）。不可以减少任何1位，也不应多于3位来编码8个可能的值。</p>
<h2>熵的公式</h2>
<p>其中<code class="katex-inline">P(i)</code> 是概率分布，最小编码长度为<code class="katex-inline">-log_2 P(i)</code> ，二者相乘即为对事件i的最小编码长度，再对所有事件求和就可以得到整个信息系统的平均最小编码长度，也就是熵。</p>
<p>对一个离散变量 i 的概率分布P(i)求熵：<br />
<code class="katex-inline">H = - \sum_{i=1}^{N} P(i) \log_2 P(i)</code></p>
<p>回到上面举的编码例子，每种状态出现的概率均为<code class="katex-inline">\ P = \frac{1}{8} = 12.5\%</code> 。对于具有  N  种等可能性状态的信息系统，每种状态的可能性为 <code class="katex-inline">P = \frac{1}{N}</code>，信息的熵（平均最小编码长度）带入公式:</p>
<p><code class="katex-inline">H = - \sum_{i=1}^{N} P \log_2 P = -N \left( \frac{1}{N} \log_2 \frac{1}{N} \right) = \log_2 N</code></p>
<p>熵用单位比特（bit）来度量，并可以理解为对信息事件的平均不确定性。当  <code class="katex-inline">N = 8</code>时，熵为：</p>
<p><code class="katex-inline">H = \log_2 8 = 3 \text{ bits}</code></p>
<p>这与前面所述的最小编码长度相匹配，正好是3位。熵在此情况下就是编码8个等可能状态所需的平均最小长度。</p>
<p>压缩（最小编码长度）与预测（概率分布）有什么关系呢？ 想象一下，我们有一个要压缩的数据流。 如果我们很容易预测下一个数据，那么这个数据就很容易压缩。 为什么呢？ 举一个极端的例子，假如数据流中的每个数据完全相同，这会是一个非常无聊的数据流。 由于它们总是相同的，我们总是知道下一个数据是什么。 所以，为了传递数据流的内容，我们不必传输任何信息。也就是说，“下一个数据是xx”这个事件毫无信息量。</p>
<p>但是，如果我们不能完全预测每一个事件，那么我们有时可能会感到“惊异”。 克劳德·香农决定用信息量<code class="katex-inline">-log_2 P(i)</code></p>
<p>来量化这种惊异程度（也就是上面的最小编码长度，信息量越大最小编码长度就越长）。 在观察一个事件i时，并赋予它主观概率<code class="katex-inline">P(i)</code> 。 当我们赋予一个事件较低的概率时，我们的惊异会更大，该事件的信息量也就更大。 </p>
<p>当然，我们可以深入探讨一下为什么使用公式 <code class="katex-inline">-\log_2 P(i)</code> 来表示信息量。</p>
<p>使用对数函数来度量信息量有以下几个理由：</p>
<ol>
<li>
<p><strong>非负性</strong>：由于 <code class="katex-inline">0 \leq P(i) \leq 1</code>，因此 <code class="katex-inline">-\log_2 P(i)</code> 总是非负的。这符合我们对信息量的直观理解，即信息量不应该是负的。</p>
</li>
<li>
<p><strong>自信息的可加性</strong>：如果事件 A 和事件 B 是独立的，那么知道 A 和 B 发生所带来的总信息应该是知道 A 发生和 B 发生所带来的信息之和。对数函数具有这个性质，即 <code class="katex-inline">\log(ab) = \log(a) + \log(b)</code>。两个独立事件的“惊奇”程度是各个事件的“惊奇”程度之和。如果你已经知道了一个事件的结果，那么这不会影响你对另一个独立事件结果的“惊奇”程度。如果你对于信息可加性还有一点疑问，十分推荐看这个讲解视频<a href="https://www.bilibili.com/video/BV15V411W7VB/?share_source=copy_web&amp;vd_source=51754dc3a590a9ea4b8dbe40d56ab09d" target="_blank" rel="noopener">&quot;交叉熵&quot;如何做损失函数？打包理解&quot;信息量&quot;、&quot;比特&quot;、&quot;熵&quot;、&quot;KL散度&quot;、&quot;交叉熵&quot;</a></p>
</li>
<li>
<p><strong>低概率事件的高信息量</strong>：使用负对数函数意味着概率较低的事件会被赋予更高的信息量。这符合我们的直观感受：罕见的事情发生时，我们获得的新信息更多。</p>
</li>
<li>
<p><strong>位的选择</strong>：使用底数 2 的对数，信息量的单位是“比特”。这是一种广泛用于计算机科学和信息理论的度量单位。</p>
</li>
</ol>
<p>因此，信息量 <code class="katex-inline">-\log_2 P(i)</code> 不仅可以量化惊异，还满足了一些与信息编码和处理相关的基本性质。</p>
<p>当我们谈到编码或压缩时，这个概念变得非常直观。如果一个事件的概率为 <code class="katex-inline">P(i) = \frac{1}{2}</code>，那么编码所需的比特数就是 1。如果一个事件的概率是 <code class="katex-inline">P(i) = \frac{1}{4}</code>，则需要 2 个比特来编码，依此类推。这正好与 <code class="katex-inline">-\log_2 P(i)</code> 的值相匹配，它给出了对事件 <code class="katex-inline">i</code> 进行编码所需的最小比特数。</p>
<p>关于位的选择还有一些历史：香农使用的是纳特而不是比特表示的信息量，也就是底数不是2而是e。</p>
<p>那为什么我们用比特来表示呢？</p>
<ol>
<li>
<p><strong>比特（bit）</strong>：比特是信息论中最常用的度量单位，表示了信息的最小单位。在二进制编码中，一个比特可以表示两个等可能的状态（例如0和1），因此对数底为2。</p>
</li>
<li>
<p><strong>纳特（nat）</strong>：纳特是以自然对数为基础的信息单位，与比特的关系由以下公式给出：<br />
<code class="katex-inline">1\text{ nat} = \frac{1}{\ln 2} \text{ bits} \approx 1.4427 \text{ bits}</code><br />
这里的 <code class="katex-inline">ln</code> 表示自然对数，即对数底为e。</p>
</li>
<li>
<p><strong>选择比特的原因</strong>：</p>
<ul>
<li><strong>直观理解</strong>：在数字计算和通信系统中，二进制编码非常普遍，所以比特作为度量单位更直观。</li>
<li><strong>历史与传统</strong>：早期的信息论研究就是基于二进制的，因此比特成为了标准单位。</li>
<li><strong>硬件实现</strong>：二进制编码与现代计算机硬件和存储系统有直接关系，因此以2为底的对数在编码和压缩算法中更具有实际意义。</li>
</ul>
</li>
</ol>
<p>总的来说，比特作为信息的度量单位与我们现代通信和计算系统的实际工作方式紧密相连，因此成为了信息量的标准度量单位。纳特则更多用于一些特殊的数学和理论分析场景。</p>
<h2>熵的估计</h2>
<p>只要我们知道了任何事件的概率分布，我们就可以计算它的熵；那如果我们不知道事件的概率分布，又想计算熵，该怎么做呢？那我们来对熵做一个估计吧，熵的估计的过程自然而然的引出了交叉熵。</p>
<p>假如我们现在需要预报东京天气，在真实天气发生之前，我们不可能知道天气的概率分布；但为了下文的讨论，我们需要假设对东京天气做一段时间的观测后，可以得到真实的概率分布P。</p>
<p>在观测之前，我们只有预估的概率分布Q，使用估计得到的概率分布可以计算估计的熵，下面我整理一下提到的几个概念：</p>
<ol>
<li>
<p><strong>真实概率分布 ( P )</strong>：这是描述天气实际情况的概率分布。对东京天气做一段时间的观测后，可以得到这个分布。</p>
</li>
<li>
<p><strong>估计的概率分布 ( Q )</strong>：这是在观测之前，基于现有信息和经验得到的天气概率分布。</p>
</li>
<li>
<p><strong>估计的熵</strong>：使用估计得到的概率分布 ( Q )，可以计算估计的熵，其公式为：<br />
<code class="katex-inline">H(Q) = -\sum_{i=1}^{N} Q(i) \log_2 Q(i)</code></p>
</li>
<li>
<p><strong>真实的熵与最小平均编码长度</strong>：如果 ( Q ) 是真实的概率分布，那么就可以使用上述公式计算编码天气信息的最小平均长度。然而，估计的概率分布 ( Q ) 与真实的概率分布 ( P ) 不同，因此会引入不确定性。</p>
<ul>
<li>计算期望的概率分布是 ( Q ) ，与真实的概率分布 ( P ) 不同。</li>
<li>计算最小编码长度的概率是 <code class="katex-inline">-logQ</code> ，与真实的最小编码长度<code class="katex-inline">-logP</code> 不同。</li>
</ul>
</li>
</ol>
<p>由于估计的概率分布 <em>Q</em> 与真实的概率分布 <em>P</em> 可能存在差异，这种不准确性可能会带来额外的“成本”。那么，如何量化这个成本，如何更准确地比较两个概率分布之间的相似性和差异性呢？这就引出了交叉熵的概念。</p>
<h2>交叉熵</h2>
<p>交叉熵（cross entropy）是一种衡量两个概率分布之间的相似性或差异性的度量。具体来说，交叉熵测量的是使用以 <em>Q</em> 为概率分布的最优编码方案来编码来自概率分布 <em>P</em> 的样本所需的平均位数。它的数学表达式为：</p>
<p><code class="katex-inline">H(P, Q) = -\sum_{i=1}^{N} P(i) \log_2 Q(i)</code></p>
<p>这里的关键思想是，交叉熵衡量了使用错误的概率分布 ( Q ) 对实际概率分布 ( P ) 进行编码所需的平均长度。也就是说，你实际上要表示的是由 ( P ) 描述的事件，但你使用 ( Q ) 来构造代码。</p>
<ul>
<li>P(i)是事件 ( i ) 的真实概率。</li>
<li><code class="katex-inline">-\log_2 Q(i)</code> 是使用概率分布 ( Q ) 编码事件 ( i ) 所需的长度。</li>
</ul>
<p>将这两者相乘并对所有事件求和，得到的是使用 ( Q ) 编码由 ( P ) 描述的事件所需的平均长度。</p>
<p>如果 ( Q ) 是完全准确的（即 ( Q = P )），那么交叉熵就等于熵。但如果 ( Q ) 不准确，交叉熵就会大于熵，反映了使用不准确的概率分布进行编码的额外“成本”。</p>
<p>对于熵值的大小有两个关键点需要理解：</p>
<ol>
<li>
<p><strong>熵的最小值取决于概率分布本身：</strong> 当一个概率分布中的事件越是确定性的，即某些事件发生的概率接近于1，其他事件的概率接近于0，那么熵会趋近于0。这是因为在这种情况下，你几乎不需要额外的信息来描述随机变量的状态，因为你可以几乎确定它会取什么值。</p>
</li>
<li>
<p><strong>对于均匀分布，熵将取最大值：</strong> 均匀分布是指所有可能的事件发生的概率都是相等的。在这种情况下，你对于随机变量的下一次取值没有任何先验知识，因此你需要更多的信息来描述它的状态。这就导致了熵取最大值，表示系统的不确定性最大。</p>
</li>
</ol>
<p>综合起来，熵作为度量随机变量不确定性的指标，其值会受到概率分布的影响。当概率分布更趋向于确定性时，熵较低；而在均匀分布中，因为所有事件发生的概率相等，所以熵取最大值，表现出系统的不确定性最大。</p>
<h2>交叉熵作为损失函数</h2>
<p>假设有两个机器学习模型对一张照片分别作出了预测：Q1和Q2。其中，Q1预测狗的概率为95%，其它动物的概率为5%平均分配；Q2预测狗的概率为60%，其它动物的概率也为40%平均分配。而第一张照片的真实标签为狗，使用one-hot编码为1,0,0,0,0。</p>
<table>
<thead>
<tr>
<th style="text-align: center;">动物</th>
<th style="text-align: center;">狗</th>
<th style="text-align: center;">猫</th>
<th style="text-align: center;">兔</th>
<th style="text-align: center;">狐狸</th>
<th style="text-align: center;">老虎</th>
<th style="text-align: center;">真实标签</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;"><strong>Q1</strong></td>
<td style="text-align: center;">95%</td>
<td style="text-align: center;">1%</td>
<td style="text-align: center;">1%</td>
<td style="text-align: center;">1%</td>
<td style="text-align: center;">1%</td>
<td style="text-align: center;">1</td>
</tr>
<tr>
<td style="text-align: center;"><strong>Q2</strong></td>
<td style="text-align: center;">60%</td>
<td style="text-align: center;">10%</td>
<td style="text-align: center;">10%</td>
<td style="text-align: center;">10%</td>
<td style="text-align: center;">10%</td>
<td style="text-align: center;">1</td>
</tr>
</tbody>
</table>
<p>其中，真实标签表示第一张照片是狗的概率为100%，这个分布是确定性分布，即熵最小值为0。</p>
<p>通过这个表格，可以更直观地看到两个模型Q1和Q2对第一张照片的预测与真实标签的比较。从中可以明显看出Q1的预测更接近真实标签。如果想进一步量化这些预测的准确性，还可以通过前面提到的交叉熵计算方法来实现。</p>
<p>对于Q1的预测，可以计算交叉熵为：<br />
<code class="katex-inline">H(P, Q1) = -\left( 1 \cdot \log_2 0.95 + 0 \cdot \log_2 0.05 + 0 \cdot \log_2 0.05 + 0 \cdot \log_2 0.05 + 0 \cdot \log_2 0.05 \right) \approx 0.074</code><br />
对于Q2的预测，可以计算交叉熵为：<br />
<code class="katex-inline">H(P, Q2) = -\left( 1 \cdot \log_2 0.6 + 0 \cdot \log_2 0.1 + 0 \cdot \log_2 0.1 + 0 \cdot \log_2 0.1 + 0 \cdot \log_2 0.1 \right) \approx 0.442</code><br />
从这个结果来看，模型Q1的预测更接近真实标签，因此交叉熵更小。这一例子清晰地展示了交叉熵如何用于比较模型预测和真实标签之间的相似性，因此可以用作分类模型的损失函数。</p>
<h2>参考资料</h2>
<ol>
<li>强推这个视频，会让你对交叉熵有更深的理解：<a href="https://www.bilibili.com/video/BV15V411W7VB/?share_source=copy_web&amp;vd_source=51754dc3a590a9ea4b8dbe40d56ab09d" target="_blank" rel="noopener">&quot;交叉熵&quot;如何做损失函数？打包理解&quot;信息量&quot;、&quot;比特&quot;、&quot;熵&quot;、&quot;KL散度&quot;、&quot;交叉熵&quot;</a></li>
<li>动手学习深度学习：<a href="https://zh.d2l.ai/chapter_linear-networks/softmax-regression.html" target="_blank" rel="noopener">https://zh.d2l.ai/chapter_linear-networks/softmax-regression.html</a></li>
<li>一文搞懂熵(Entropy),交叉熵(Cross-Entropy) &#8211; 将为帅的文章 &#8211; 知乎 <a href="https://zhuanlan.zhihu.com/p/149186719" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/149186719</a></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cztcode.com/2023/4908/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4908</post-id>	</item>
	</channel>
</rss>
