<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>yzd</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://yzd11.github.io/</id>
  <link href="https://yzd11.github.io/" rel="alternate"/>
  <link href="https://yzd11.github.io/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, yzd</rights>
  <subtitle>机器学习 / 深度学习 学习笔记</subtitle>
  <title>yzd's Log Book</title>
  <updated>2026-08-22T07:24:29.543Z</updated>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<h2 id="c2L3f">Self-supervised Learning</h2><p><img src="/2024/11/20/BERT/1732095158193-234e1753-47e1-4828-8a08-cee38b18e2fe.png"></p><p>在学习$ BERT $之前我们需要先了解什么是自监督学习，之前我们已经学过了监督学习和非监督学习，但是自监督学习和这两个有所不同，具体来讲就是没有标注好的数据，但是我们将其中的一部分作为标签，另一部分作为输入数据，将输出的数据和标签进行对比，然后使其更加接近。</p><h2 id="abVMf">Masking Input</h2><p><img src="/2024/11/20/BERT/1732095401594-1ab8c1a9-02c0-494d-b3b6-f6932497b67d.png"></p><p>在$ BERT $中，我们是使用了一个$ Transformer $的$ Encoder $，然后通过随机的$ masking $一些$ tokens $可以是使用特殊的符号，也可以是换成随机的符号。由于我们本身是知道原本的数据的，因此我们可以判断输出的数据到底和之前的数据一不一样。</p><h2 id="qlCki">Next Sentence Prediction</h2><p><img src="/2024/11/20/BERT/1732095645542-128c1cd0-090b-4c52-bc54-13cad7816f1a.png"></p><p>除了屏蔽一些输入的$ tokens $，还用在预测两个句子之间有没有关系，例如选择两个随机的句子，虽然有多个输出，但是仅取$ [CLS] $对应的那个，然后通过这个判断这两个句子之间的关系。</p><p>但是从最新的文章来看这种方式似乎用处不大，可能是因为随机的句子本身就关系不大，这个训练对于$ BERT $来讲有些过于简单，因此有人提出了一个新的任务，选择两个本身有关系的句子，但是调换顺序然后再进行判断，这种方式被用在$ ALBERT $这个模型上。</p><h2 id="l6OcF">Downstream Tasks</h2><p><img src="/2024/11/20/BERT/1732095984919-703acc2f-a20f-473f-93c5-b8d7d803e37d.png"></p><p>在刚刚的介绍中似乎$ BERT $就仅仅用在预测屏蔽的输入和判断两个句子的关系，但是实际上我们仅需要使用一些有标注的数据进行微调，就可以很好的实现一些下游任务上。</p><p><img src="/2024/11/20/BERT/1732096096169-a56c1521-088d-4ac6-8dcb-3d79007854eb.png"></p><p>通常我们训练了一个模型之后可以将其应用在这些任务上，然后取平均值判断其效果。</p><p><img src="/2024/11/20/BERT/1732096275531-1443bc79-b762-41a4-979a-e6e6f8ca11b8.png"></p><p>可以看到随着时间的推进，这些任务上机器的表现已经逐渐趋近于人类，甚至高于人类。</p><h2 id="V1FME">How to use</h2><p><img src="/2024/11/20/BERT/1732096354340-5305b5a7-ba1b-4610-9089-08d0c1d0d549.png">对于怎么使用$ BERT $，使用这么一个简单的例子，输入一个句子，输出一个分类。在这其中我们通过训练好的参数初始化$ BERT $，然后使用随机的初始来初始化我们$ Linear $层，这样的效果是要比全部都随机初始化要好的。</p><p>如果具象化的来讲的化，我们可以假设$ BERT $就是一个胚胎干细胞，我们可以将其用于各种各样的任务。</p><h2 id="N1Cwr">Why does BERT work</h2><p><img src="/2024/11/20/BERT/1732096627686-7c72a087-e187-472b-a51e-02838b087d18.png"></p><p>虽然我们应该知道了怎么使用$ BERT $，但是为什么它可以有效依旧是一个很大的问题，其中的一个解释是，我们的输出是一个词的$ embedding $，也就是不同语义下的词分布在不同的位置。</p><p>例如，苹果手机中的”果”和吃苹果的”果”一定不是同一个意思，它是从这些词的上下文中学到的，类似的$ tokens $也具有更接近的$ embedding $。不过这也只是一种解释而已，$ BERT $真正的工作原理仍是一个巨大的问题。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/11/20/BERT/</id>
    <link href="https://yzd11.github.io/2024/11/20/BERT/"/>
    <published>2024-11-20T10:58:21.000Z</published>
    <summary>了解 BERT 模型</summary>
    <title>BERT</title>
    <updated>2026-08-22T07:24:29.543Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<h2 id="EON2x">引入</h2><p><img src="/2024/11/19/Self-Attention/1730626794760-70760341-8574-45b9-a3c8-f053db82a286.png"></p><p>对于一个向量的输入计算我们很容易处理，但是现在我们希望对于一个句子的多个向量进行计算，这点可以体现在文字处理上。</p><p><img src="/2024/11/19/Self-Attention/1730626868758-ccdc176b-804b-4e0d-b5ba-3892fc9534e1.png"></p><p>将每个单词都作为一个向量处理，那么一个句子就是多个长度不一的向量合在一起。</p><p><img src="/2024/11/19/Self-Attention/1730627020310-36ff30fe-0a5a-4da6-9bf5-68c229d8a23b.png"></p><p>对于多个向量的输入对应的输出可能分为三种情况，每个向量对应一个标签，全部向量对应一个标签，模型自己选择输出几个标签，今天主要处理的是第一种，即一个向量对应一个标签。</p><p><img src="/2024/11/19/Self-Attention/1730627177270-32a133c4-d835-4d7a-a71a-996b40f298cc.png"></p><p>对于多个向量要想同时考虑到，可以使用一个$ window $，但是这不是最好的，因为这个窗口的大小是不固定，无法考虑到全部的向量，对于这种情况可以使用$ Self-Attention $。</p><h2 id="C6Q8i">Self-Attention</h2><p><img src="/2024/11/19/Self-Attention/1730627369098-d43ffdd6-8146-4600-832e-f0e3e58e5959.png"></p><p>我们可以多次使用$ self-attention $，然后配合上全连接网络使用，这个也被称为自注意力机制。</p><p><img src="/2024/11/19/Self-Attention/1730627479789-d7a3b789-f0ed-42b6-b984-4da3b6cea297.png"></p><p>我们希望计算$ b^1 $的时候可以对于$ a^1 $同时考虑到$ a^2,a^3,a^4 $，因此我们需要知道他们彼此之间的关联性。</p><p><img src="/2024/11/19/Self-Attention/1730627584221-1b4f25f0-bf6d-4f64-9b1d-e1c371f9dde1.png"></p><p>也就是使用一个$ \alpha $来计算其中的关联性，对于这个$ \alpha $的计算方法有很多种，这里提到了其中两种。</p><p><img src="/2024/11/19/Self-Attention/1730627656315-4926de97-a7e6-450c-b6fd-da1af48c424e.png"></p><p>第一种是$ Dot-product $，先通过两个矩阵的变换再进行点乘，再$ self-attention $中使用的也是这个。第二种是$ Additive $，本次并没有使用。</p><p><img src="/2024/11/19/Self-Attention/1730627807219-55bc4fcc-cbd3-47df-97fb-8419c6a80c60.png"></p><p>首先使用刚才的$ Dot-product $计算$ a^1 $和它本身以及其余三个的关联性。</p><p><img src="/2024/11/19/Self-Attention/1730627886953-8355bc29-b4dd-4ca3-9d94-90cbbd5073e3.png"></p><p>接着可以对输出的结果进行$ soft-max $，并不是一定要使用$ soft-max $，也可以使用$ relu $之类的方式。</p><p><img src="/2024/11/19/Self-Attention/1730628003983-76b449d9-a72a-411c-ae24-d0bf1c7ff40e.png"></p><p>最后使用进行变化的结果和向量$ v $相乘，最后将相乘的结果加在一起就得到了$ b^1 $。</p><p><img src="/2024/11/19/Self-Attention/1730637942593-5e6d6877-69bd-483c-90e2-fa8a87cb36fb.png"></p><p>刚才介绍了怎么得到$ b^1 $的方式，现在从矩阵乘法的角度重新介绍一下，可以看到将合在一起的矩阵$ I $乘上三个不同的矩阵，就可以得到$ Q,K,V $这三个矩阵。</p><p><img src="/2024/11/19/Self-Attention/1730638095733-c78c92d4-d283-459b-b0cb-bfd93670c149.png"></p><p>使用得到的矩阵$ K $的转置和矩阵$ Q $相乘，就可以得到矩阵$ A $，通过$ soft-max $就可以得到$ {A’} $</p><p><img src="/2024/11/19/Self-Attention/1730638446918-22e10f2d-4f17-4d33-b30a-090b26fe9eac.png"></p><p>将得到的矩阵$ {A’} $和$ V $相乘就可以得到我们的输出向量$ O $，其实刚才的操作就是矩阵的相乘。</p><p><img src="/2024/11/19/Self-Attention/1730638548666-78192bb2-802c-46a6-8809-bd663117294f.png"></p><p>上图中从$ I $到$ O $的改变就是做的$ self-attention $的操作，其中就只有$ W^q,W^k,W^v $这三个矩阵参数是需要我们学习的。</p><h2 id="r6LP6">多头自注意力机制</h2><p><img src="/2024/11/19/Self-Attention/1730638668529-da28ab9b-07e1-425f-99ed-b2606da55413.png"></p><p>在计算相关性的时候可能不仅只有一种相关性，因此我们可以将$ q^i,k^i,v^i $的值都再乘不同的两个矩阵，最终可以得到两个$ b^{i,1},b^{i,2} $。</p><p><img src="/2024/11/19/Self-Attention/1730638822675-ff031db3-93cf-4783-bb62-340f3d0c31c1.png"></p><p>最后乘上一个$ W^o $的向量，可以得到一个$ b^i $的值。</p><p><img src="/2024/11/19/Self-Attention/1730638898650-584f86a7-240a-42e7-87bd-b705269243e4.png"></p><p>刚才的计算中还存在一个问题，我们没有考虑向量之间的位置关系，不同的位置的影响没有被考虑进来，为了解决这个问题，我们可以计算每个位置对应的向量，将这个向量和$ a^i $相加进行计算从而将位置的信息也考虑进来。</p><h2 id="O6qhl">CNN v.s. self-attention</h2><p><img src="/2024/11/19/Self-Attention/1730639423556-6dee23e1-22e8-4fd5-a8fe-affd10918c00.png"></p><p>$ CNN $和$ self-attention $之间有很强的相关性，我们可以认为$ CNN $就是一个简化版的$ self-attention $，区别在于$ self-attention $更加的灵活，让机器自己去学习和自己相关的$ pixel $，而不是人为的设置感受野，对于$ self-attention $进行一些限制就可以做到$ CNN $一样的事。</p><p><img src="/2024/11/19/Self-Attention/1730639590567-3ec154cd-7f6b-4149-949f-b2a1f8749511.png"></p><p>既然$ self-attention $更加的灵活，那么也就代表更加容易过拟合，因此数据量很大的时候$ self-attention $的效果是要好于$ CNN $，但数据量不足的时候$ CNN $的效果就要比$ self-attention $要好一些。</p><h2 id="iWksS">RNN v.s. self-attention</h2><p><img src="/2024/11/19/Self-Attention/1730640096581-9284fd5a-1f61-4bfa-8c3d-cd6ddd21ea4b.png"></p><p>对于$ RNN $来讲，$ self-attention $虽然也都是处理多个向量的输入的，但是它并不是同时处理的，而是从左到右，在处理左边的时候无法考虑到右边，虽然也可以通过双向的$ RNN $完善，但是它也不是并行计算，因此现在更加倾向于使用$ self-attention $。</p><p>可参照：</p><p><a href="https://blog.csdn.net/weixin_43610114/article/details/126684999">Transformer：注意力机制（attention）和自注意力机制（self-attention）的学习总结_注意力机制和自注意力机制-CSDN博客</a></p>]]>
    </content>
    <id>https://yzd11.github.io/2024/11/19/Self-Attention/</id>
    <link href="https://yzd11.github.io/2024/11/19/Self-Attention/"/>
    <published>2024-11-19T08:27:32.000Z</published>
    <summary>了解自注意力机制</summary>
    <title>Self-Attention</title>
    <updated>2026-08-22T07:24:29.546Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<p><img src="/2024/11/08/Transformer/1731059389533-85d83535-8421-4242-8f08-9842d3c998c6.png"></p><p>对于$ Transformer $来讲，其中主要分为$ Encoder $和$ Decoder $，接下来首先介绍$ Encoder $。</p><h2 id="GnX9y">Encoder</h2>$ Encoder $的主要作用是进行特征提取，这样做是因为原始输入中包含一些无用或干扰信息，这会使模型的性能和泛化性大打折扣。所以在这之前，我们通过$ Encoder $来先对数据进行一次特征提取和挖掘，比如后面会提到$ Encoder $里会有一个自注意力层，正如我们之前文章中提到，自注意力层可以挖掘输入内部元素直接的关系，这是模型直接接受原始输入很难做到。<p><img src="/2024/11/08/Transformer/1731059326404-b45ea056-7ed5-473f-b999-b6f47fa189e0.png"></p><p>$ Encoder $可以给定一排向量，输出一排同样的向量，对于这个要求$ RNN,CNN $都可以实现，而在$ Transformer $中主要使用的是$ self-attention $，但是这个模型有些复杂，接下来分步介绍这个$ Encoder $。</p><p><img src="/2024/11/08/Transformer/1731059906943-1c59ae29-dbcf-43a8-a18e-888f6838b592.png"></p><p>当向量输入之后要经过多个$ Block $，但是每个$ Block $并不是一层网络，而是一个$ self-attention $加上一个$ FC $。</p><p><img src="/2024/11/08/Transformer/1731060100178-630aa339-7d87-4307-a7cd-97e2d3503e80.png"></p><p>但是这里的$ self-attention $跟之前的有些不同，还需要加上$ residual $和$ norm $，同时在$ FC $也加上这两个操作。需要注意的是这里的是层归一化。</p><p><strong>层归一化和批量归一化：</strong></p><p>$ BatchNorm $<font style="color:rgb(77, 77, 77);">把一个</font>$ batch $<font style="color:rgb(77, 77, 77);">中同一通道的所有特征（如下图红色区域）视为一个分布（有几个通道就有几个分布），并将其标准化。这意味着:</font></p><ul><li><font style="color:rgba(0, 0, 0, 0.75);">不同图片的的同一通道的相对关系是保留的，即不同图片的同一通道的特征是可以比较的</font></li><li><font style="color:rgba(0, 0, 0, 0.75);">同一图片的不同通道的特征则是失去了可比性</font></li></ul><p><img src="/2024/11/08/Transformer/1731060919570-1b51aba2-2883-4459-a5f8-9236962b6f6d.png"></p><p>$ LayerNorm $把一个样本的所有词义向量（如下图红色部分）视为一个分布（有几个句子就有几个分布），并将其标准化。这意味着:</p><p>同一句子中词义向量（上图中的$ V1, V2, …, VL $）的相对大小是保留的，或者也可以说$ LayerNorm $不改变词义向量的方向，只改变它的模。不同句子的词义向量则是失去了可比性。</p><p>用于$ NLP $领域解释:</p><p>考虑两个句子，“教练，我想打篮球！” 和 “老板，我要一打包子。”。通过比较两个句子中 “打” 的词义我们可以发现，词义并非客观存在的，而是由上下文的语义决定的。因此进行标准化时不应该破坏同一句子中不同词义向量的可比性，而$ LayerNorm $是满足这一点的，$ BatchNorm $则是不满足这一点的。且不同句子的词义特征也不应具有可比性，$ LayerNorm $也是能够把不同句子间的可比性消除。</p><p><img src="/2024/11/08/Transformer/1731061011263-f02b248e-e763-4ce4-917f-9473009da230.png"></p><p>$ Transformer $使用$ LayerNorm $而不是$ BatchNorm $的主要原因是$ LayerNorm $更加适合处理变长的序列数据。在$ Transformer $中，由于输入序列的长度是可变的，因此每个序列的批量统计信息（如均值和方差）也是不同的。而$ BatchNorm $是基于整个批量数据来计算统计信息的，这可能导致在处理变长序列时性能下降。相比之下，$ LayerNorm $是在每个样本的维度上进行归一化的，因此不受序列长度变化的影响。</p><p>在$ Transformer $中，$ LayerNorm $通常被放置在多头注意力机制和前馈神经网络的输出之后。通过对这些层的输出进行归一化，可以使得后续层的输入保持在一个相对稳定的范围内，有助于模型的训练。</p><p><font style="color:rgba(0, 0, 0, 0.75);">简单对比如下：</font></p><p><img src="/2024/11/08/Transformer/1731061060487-41b8e494-b400-481f-9a12-479b8d421005.png"></p><p>参照于：</p><p><a href="https://blog.csdn.net/m0_48086806/article/details/132153059">【深度学习中的批量归一化BN和层归一化LN】BN层（Batch Normalization）和LN层（Layer Normalization）的区别_bn和ln-CSDN博客</a></p><p><a href="https://blog.csdn.net/weixin_44174227/article/details/141558713">Transformer 系列三：Encoder编码器和Decoder解码器_transformer编码器-CSDN博客</a></p><p><img src="/2024/11/08/Transformer/1731061315933-34118ebc-1081-4af4-a8df-ef92b8cf2787.png"></p><p>对比一下刚刚看到的模型，只是将$ Self-Attention $换成了$ Mult-Head\  Attention $，同时在输入之前加上了位置编码。</p><p>同时将全连接层换成了一个前馈神经网络，其实就是一个简单的两层全连接网络，用于进一步处理多头注意力机制的输出。这个网络首先通过一个线性变换将输入映射到一个更高维的空间中，然后通过一个非线性激活函数（如$ ReLU $）增加网络的非线性能力，最后再通过另一个线性变换将输出映射回原始维度。</p><p>在自注意力层后面增加前馈神经网络层的原因：</p><ol><li>特征提取：$ FFN $通过两层全连接层（通常是线性层），对来自自注意力层的输出进行进一步的特征提取。这有助于模型学习到更深层次的、非线性的特征表示。</li><li>增加模型容量：通过引入额外的参数和非线性激活函数，$ FFN $增加了模型的容量，使得模型能够捕捉更复杂的数据模式和关系。</li><li>与自注意力机制互补：自注意力机制擅长捕捉序列内部的长距离依赖关系，而$ FFN $则专注于在给定的表示上进行特征转换。这种组合使得$ Transformer $能够有效地处理各种语言和序列任务。</li><li>提高泛化能力：$ FFN $通过增加模型的复杂性，有助于提高模型对未见数据的泛化能力。</li></ol><p><img src="/2024/11/08/Transformer/1731061526714-74569b81-d04e-4183-a87a-88871709ef3b.png"></p><p>其实$ Encoder $的架构并不是一定要这样设计，我们可以将其中的归一化的操作提前进行，这样的效果似乎看起来更好。</p><h2 id="LIDJk">Decoder</h2><p><img src="/2024/11/08/Transformer/1731072669558-64ca169a-17df-4146-b73e-c77bf9503add.png"></p><p>我们刚才介绍了$ Encoder $，现在我们先不考虑$ Encoder $的输出怎么作为$ Decoder $的输入，现在假设已经可以传递。首先使用一个$ BEGIN $作为一个输入，同时根据这个输入得到一个输出，经过一个$ softmax $之后得到一个表，选择其中概率最大的值，将这个作为我们的预测结果，同时这个表的长度就是我们希望的词的范围大小，可能是中文的常用词，大概$ 3000,5000 $字左右，也可能是例如英文的常用词的大小。</p><p><img src="/2024/11/08/Transformer/1731072933162-e6701fa0-39a3-4f66-b8e1-ef9054503fed.png">接着使用上次的输出作为这次的输入，对于如果中间出现了错误是否会导致接下来的结果全部错误再下面会提到。</p><p><img src="/2024/11/08/Transformer/1731073263917-2c373f2e-f5fa-43d5-81c1-4437ef3d3c70.png"></p><p>这个是$ Decoder $的结构图，看起来比$ Encoder $还要复杂，但是如果把中间的部分删除，其实别的部分基本一样。</p><p><img src="/2024/11/08/Transformer/1731073335145-690059e5-a58a-4df8-b701-16ba714f9182.png"></p><p>可以看到，其余部分基本上一样，并没有什么很大的差别，只是其中的$ Multi-Head\ Attention $换成了$ Masked \  Multi-Head \ Attention $。</p><p><img src="/2024/11/08/Transformer/1731073494959-55e7c24b-fb9d-4003-8166-253112c454f6.png"></p><p>对于$ Masked \  Multi-Head \ Attention $来讲，其中的主要区别就是，当$ q^2 $是，对应的$ k $只有$ k^1,k^2 $，只可以查询到当前和再前面的值，其实从刚才的$ Decoder $的原理也可以理解，其中的$ a^1,a^2,a^3,a^4 $并不是同时出现的，因此需要使用$ Masked $的形式。</p><p><img src="/2024/11/08/Transformer/1731073768425-f6bc2f7e-ee3a-4c2e-8054-68d813d0a62b.png">刚才的$ Decoder $只有开始没有结束，为了可以让机器自己学习怎么结束，我们可以通过使用加上一个$ END $在表中的方式，其中当输出为$ END $的时候表示结束。</p><p><img src="/2024/11/08/Transformer/1731073856502-18a46e15-c71a-4a79-a87f-6b49ea3d93f4.png"></p><p>如图中所示，当输入“习”这个词的时候会输出一个$ END $表示结束。</p><p><img src="/2024/11/08/Transformer/1731074351623-4a381f46-b5cf-4310-9f39-b59bc205158f.png"></p><p>现在对刚才讲的$ Decoder $做一个总结，刚才讲的$ Decoder $全是$ AT\  Eecoder $的形式，但是还有一种$ NAT $的形式，也就是不再一个一个输入，而是采用一次性同时输入的形式，但是这样需要采用一定的措施，例如使用一个新的预测将会有几个输出，或者直接输入很多的$ BEGIN $，然后根据$ END $截断，只要$ END $前面的。</p><p><img src="/2024/11/08/Transformer/1731074750520-fa17f636-eb9f-475f-9f18-0051348173f6.png"></p><p>现在需要介绍$ Decoder $是怎么使用$ Encoder $的信息的，通过经过$ Masked \  Multi-Head \ Attention $生成的向量得到一个$ q $，然后使用这个$ q $和$ Encoder $计算得到一个$ v $作为接下来全连接层的输入。</p><p><img src="/2024/11/08/Transformer/1731074923060-1c0b588d-c98b-4f65-aa8a-6bf45e491628.png"></p><p>而且未必一定要用$ Encoder $的最后一层的输出作为输入，还可以使用别的方式进行信息的传递。</p><h2 id="IDuWG">Training</h2><p><img src="/2024/11/08/Transformer/1731075200165-d0165207-02e9-4a7a-81c6-04743ff4720e.png"></p><p>刚才介绍的都是我们已经训练好了一个模型，然后测试这个模型。但是现在要介绍的是怎么训练一个模型，首先我们需要人为的加上标签，也就是使用$ one-hot $表示，同时最小化输出和标签之间的$ cross \ entropy $，同时需要注意的是刚才提的到那个问题，如果在$ Decoder $中预测数据不正确怎么办，因此我们需要使用$ Ground\  Truth $，也就是正确的数据作为输入。</p><p><img src="/2024/11/08/Transformer/1731075824324-2a1a2748-a436-4389-a64f-8a988124ee91.png"></p><p>刚才的方法还存在一个曝光偏差($ exposure \ bias  $)，训练($ training $) 时接受的标签是真实的值($ ground\  truth\  input $)，但测试 ($ testing $) 时却接受自己前一个单元的输出($ output $)作为本单元的输入($ input $)，这两个$ setting $不一致会导致误差累积。</p><p>解决这个问题也不麻烦，只要在训练的时候在正确的标签中故意加入一些错误的数据即可。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/11/08/Transformer/</id>
    <link href="https://yzd11.github.io/2024/11/08/Transformer/"/>
    <published>2024-11-08T14:27:09.000Z</published>
    <summary>了解 Transformer</summary>
    <title>Transformer</title>
    <updated>2026-08-22T07:24:29.547Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<h2 id="XkS5Y">介绍</h2><p><img src="/2024/10/24/RNN/1729755749283-e3639f9b-1336-4ff8-8d55-ae10cf4d0ca1.png"></p><p>对用同一个词语在不同的话中可能具有完全相反的意思，但是如果还是使用之前神经网络，那么输入结果一定是相同的，为了解决这个问题，我们希望神经网络可以具有一些记忆性，这就是接下来要介绍的循环神经网络。</p><p><img src="/2024/10/24/RNN/1729755880609-8f1fd99b-6575-4de1-bbb2-5aaa49574927.png"></p><p>因此我们讲隐藏层的输出结果全部都放入到一个$ store $中进行存储，在下次输入中再取出来进行使用。</p><p><img src="/2024/10/24/RNN/1729755987478-11ab986b-3455-47ea-bd2a-4d8178e2ee68.png"></p><p>用一个例子解释，当输入为$ [1,1] $，权重为$ 1 $，无偏置的情况，第一次的输出就是$ [4,4] $，同时隐藏层的$ [2,2] $存储在$ store $中。</p><p><img src="/2024/10/24/RNN/1729756104355-dd4c44d4-6636-4f07-a46a-2de5d1b6c07d.png"></p><p>在第二次中，使用了上一次的存储值，因此就是相当于有四个输入$ 1,1,2,2 $因此最终即使输入相同，但是输出也不同。</p><p><img src="/2024/10/24/RNN/1729756230360-90c7c146-ffb7-485c-b59e-e326839979c3.png"></p><p>需要注意的是，输入的顺序不同，那么得到的结果也会有所不同。</p><p><img src="/2024/10/24/RNN/1729756288255-0f339f3f-01ad-4aaf-863c-77114805e3a7.png"></p><p>刚才讲的是$ Elman\ Network $，即存储隐藏层的数据，还可以像$ jordan\  Network $一样存储上一次的输出层的结果。</p><p><img src="/2024/10/24/RNN/1729756442678-50e1fa66-65a4-4a03-a095-2c81f55bbffa.png"></p><p>除了刚才的神经网络，还有别的变形，例如上图的双向循环神经网络。</p><h2 id="k5XBn">LSTM</h2><p><img src="/2024/10/24/RNN/1729756559765-ef7ed7b0-2443-4274-a2b9-29cd1db4d2fc.png"></p><p>除了像刚刚讲到的最基本的$ RNN $，还可以对它的存储内容进行调整。使用$ Input\ Gate $作为输入控制，判断是否可以讲结果存储$ store $中，使用$ Forget\ Gate $作为判断是否要将存储的数据清空，使用$ Output\ Gate $作为输出控制，判断别的网络是否可以使用这个存储的结果。</p><p>有一个冷知识，这个名字长短时记忆网络的断句是长 短时记忆网络，是较长的短时记忆网络，因为比最原始的$ RNN $保留的时间长一些。</p><p><img src="/2024/10/24/RNN/1729756806321-dcc62857-b052-459b-8d08-3d32a3092d94.png"></p><p>刚才提到的思路如果用数学表达的话就是，$ c’&#x3D;g(z)f(z_i)+cf\big(z_f\big) $，$ a&#x3D;h(c^{\prime})f(z_{0}) $。其中$ f $函数作为控制的阀门经常使用$ sigmod $激活函数，因为$ sigmod $的输出是在$ 0,1 $之间也就代表了允许进入多少，输出多少，保留多少。其中$ Forget\ Gata $有一点和名字不同，当$ f(z_f) $的值越大代表保留的越多，和名字的意思有些相反。</p><p><img src="/2024/10/24/RNN/1729759608131-8cbf9bfb-3e20-428f-95fc-c85a508edf3b.png"></p><p>相当于每个神经元都有了四个不同的输入，比之前的输入增加了四倍。</p><p><img src="/2024/10/24/RNN/1729759701213-b9d3e724-ed3a-45b4-95c1-9ffdbdf230ae.png"></p><p>之前讲述的$ LSTM $还不是真正的$ LSTM $，实际上的应该将上次的存储值和隐藏层输出都作为这次的输入考虑进来。</p><p><img src="/2024/10/24/RNN/1729775501942-039d7472-e7b0-4d9f-8a7b-d398250d52cb.png"></p><p>在$ RNN $中还有一个需要注意的问题就是它的梯度可能会变化的非常剧烈，如果此时的梯度较大，但是我们的学习率也比较大，很可能出现$ loss $快速增大的情况，对于这种情况可以选择在梯度达到一定值的时候将其固定。</p><p><img src="/2024/10/24/RNN/1729775674105-22032422-2b29-4878-b558-1aace1ade7cf.png"></p><p>之所以会出现这种情况是因为随着迭代相同的操作可能会执行很多次，有的时候参数的改变起不到影响，但有的时候又会造成很大的改变。</p><p><img src="/2024/10/24/RNN/1729776243637-004563bc-b9f6-4e43-82ba-0fad0f5789c3.png"></p><p>而$ LSTM $可以解决一部分的问题，也就是避免梯度消失，但无法避免梯度爆炸，这样可以将学习率设置的小一些。之所以可以是因为$ LSTM $中始终保存了之前的结果，之前的过程对现在始终有影响，甚至一开始的$ LSTM $是没有$ Forget\ Gate $这个设置的，而通常也将$ Forget\ Gate $的值设置的很大，只有少数的情况会将原来的值重置。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/24/RNN/</id>
    <link href="https://yzd11.github.io/2024/10/24/RNN/"/>
    <published>2024-10-24T13:28:27.000Z</published>
    <summary>了解循环神经网络</summary>
    <title>RNN</title>
    <updated>2026-08-22T07:24:29.544Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729081705591-33325710-f2f0-4bd5-a7cf-e07314ebe6af.png"></p><p>在选择数据时，我们可以选择一次性使用全部的数据进行训练，但是这样的计算量太大，还可以选择每次选择一个数据进行计算，但是这样容易受到噪音的干扰，因此我们希望采用一种更加折中的方式，即采用小批量随机梯度下降法。</p><p>这样既没有那么震荡，也没有那么大的计算量。</p><h2 id="MSOSW">激活函数选择</h2><h3 id="xaZzg">sigmod</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083293551-d9df5ed0-f986-4a8d-8f46-a5df1b74988d.png"></p><ul><li>梯度消失问题</li></ul><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083375965-04883ad7-6a31-432b-9777-280ce77483fb.png"></p><p>可以看到当$ x $过大或过小时，很容易造成梯度消失的问题，这不利于对于参数的调整。</p><ul><li>不关于$ 0 $对称问题</li></ul><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083448461-37e20bea-a894-46e4-843d-19c686ec43dc.png"></p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083659471-6d876ba8-ac85-4116-ad57-a36909bf7cbb.jpeg"></p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083676938-e6047976-a8fa-4f97-9438-ba6b55fa87bd.jpeg"></p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083607521-b0893af1-5a10-4ae8-b6f6-02551086c8da.jpeg"></p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083692163-861f99c0-2714-437a-baa9-30675812d032.jpeg"></p><ul><li>指数运算问题</li></ul><p>在进行指数运算时容易产生很大的计算开销。</p><h3 id="jcp7h">tanh</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729083847777-efadf0c5-ef10-4c57-8278-03bae07aad7a.png"></p><p>$ \tanh(x)&#x3D;\frac{e^x-e^{-x}}{e^x+e^{-x}} $，实际上是关于$ sigmod $函数的变型，也就是$ tanh(x)&#x3D;2sigmoid(2x)-1 $。</p><p>避免了不关于原点对称的$ zig-zag $问题，但仍存在梯度消失问题。</p><h3 id="tf51U">ReLU</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729084715218-52922c2b-8a7f-47c6-9abd-8f31bd385a3e.png"></p><p>关于$ ReLU $激活函数具有不饱和，计算快，收敛快这一系列优点，但是它仍具有不关于$ 0 $对称，并且在$ x&lt;0 $的情况下它的输出为$ 0 $。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729084952863-2a35b60e-dc8f-42e9-853f-75cf84631a91.png"></p><p>由于这个函数在$ x&lt;0 $时梯度为$ 0 $，因此会出现一种$ Dead\  ReLU $的问题，即<font style="color:rgb(51, 51, 51);">当输入为负时，梯度为0。这个神经元及之后的神经元梯度永远为0，不再对任何数据有所响应，导致相应参数永远不会被更新。</font></p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729085047797-b16efb05-dfbe-47e8-ba5c-48e3cfec47f8.png"></p><p>这种情况可能是由于初始化不好，或者学习率过大导致改变幅度过大到一个$ Dead \  ReLU $的地方再也出不去。为了解决这个问题通常加上一个偏置项在初始化中，避免开始就进入了$ Dead\  ReLU $。</p><h3 id="U9BRf">Leaky ReLU</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729085280176-245fca06-2f14-41f8-b8ec-08387528fc37.png"></p><p>对于前面的$ ReLU $的神经元梯度为$ 0 $的问题，我们可以使用$ Leaky\  ReLU $的方式。</p><h3 id="MXpbp">ELU</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729085388503-3288ce2c-66d0-410b-9cde-47642ca03158.png"></p><p>进一步使得输出接近关于$ 0 $对称，但同时指数的运算也带来了较大的运算量。</p><h3 id="AEV9z">Maxout</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729085591831-c356c660-62e4-44d8-85c7-5c84f49e8b26.png"></p><p>通过在两个神经元后面再加上一层神经元，其中有$ k $个神经元，参数个数也成$ k $倍增加。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729085923625-a38987c3-73aa-4739-a3e2-b48896596421.png"></p><p>总结一下，多使用$ ReLU $，但是要注意它的学习率，不要在中间层使用$ sigmod $函数，可能是因为计算量太大还会有$ zig-zag $问题。</p><h2 id="cOOxp">数据预处理</h2>+ 标准化处理<p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729086363022-abbf0131-ad4d-4a09-99a2-87d86429a224.png"></p><p>通过标准化，使其分布更加均匀，关于标准正态的解释可以使用中心极限定理解释，原始分布在$ n $足够大时近似为正态分布。</p><ul><li>主成分分析</li></ul><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729086453019-529a7044-ef92-4839-924c-c10cd665fc18.png"></p><p>首先通过主成分分析将数据转化在一个二维空间中，再进行标准化，这也被称为$ PCA $白化，然后将其重新变回之前所在的维度，这被称为$ ZCA $白化。</p><h2 id="N8Lvp">权重初始化</h2><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729153833137-7c830c68-0c65-4181-8b0e-ae8dc1056a44.png"></p><p>我们可能认为由于最终都有梯度下降进行迭代，那么无论怎么进行权重初始化都没有什么影响，但是实际上。如果我们给同一层的神经元一个相同的值，那么对于相同的输入，相同的权重，自然会导致相同的输出，相同的反向传播梯度，相同的更新，那么无论我们具有多少神经元本质上都是仅仅只有一个，因此权重初始化是一个很重要的问题。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729173256714-ad3d5a09-23a5-42d9-afad-7a2bd26c4d43.png"></p><p>当初始化的权重过小时，输出全部都分布在$ 0 $这个地方，那么就会导致梯度为$ 0 $。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729173323452-70250ee2-a25b-4037-97f4-4699804fd364.png"></p><p>当权重增大时，输出不全为$ 0 $，但是激活函数的导数全部为$ 0 $，那么梯度也为$ 0 $。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729173555513-eb0f3848-bc0f-46fc-a1e5-12c4911a87c2.png"></p><p>为了使得输入的方差和输出的方差相同，我们可以使用$ Xavier $的方式进行权重初始化。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729173659288-06b6b255-a811-415a-9f07-5cd4d173d6bd.png"></p><p>使用将权重的方差设置为符合$ (0,\frac{1}{d}) $的正态分布，也就可以保证输入的方差和输出的方差相同（但是上面的图我还是有些看不明白，既然保持不变那么为什么还会减小，直到最后几层才保持不变，是因为没有考虑激活函数的影响吗）</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729175652858-1291a305-e345-4cc2-9325-b3b842e1831d.png"></p><p>对于不是关于$ 0 $对称的$ ReLU $，可以使用$ Kaiming $初始化的方法。</p><h2 id="emxVG">批量归一化</h2><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729261454641-78f66195-843d-41e1-b1b1-1957ba3b42b6.png"></p><p>在进行深层的神经网络训练中，顶层的梯度很大，但是越往下层的梯度就越小，因此底层的收敛速度就很慢，因此在底层进行收敛的时候导致顶层原本学习好的数据重新学习，这无疑是低效的，因此我们希望可以每层的输出和梯度都保持在一个固定的分布。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729320742706-5518fd74-7f1d-44c5-a717-6e9a584e3df7.png"></p><p>具体的就是计算每个小批量的均值和方差，方差计算中需要加上一个$ \epsilon $，避免计算时分母为$ 0 $的情况。同时可能标准正态分布并不满足要求，因此可以使用$ \gamma,\beta $来调整方差和均值。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729321235775-1d7a856c-5f80-482a-a196-fb2940099d8e.png"></p><p>当作用在输出上时，这个批量归一化的操作需要在激活函数之前，因为如果先进行了非线性的改变在进行批量归一化，例如$ ReLU $将很多输出都设置为$ 0 $，这时的意义不是很大。</p><p>当作用在输入时，这个批量归一化对于全连接来讲就是对于每一个特征计算对应的均值和方差，对于卷积层来讲就是将每个通道维的全部像素点作为样本，因此每个通道维就是特征，计算每个通道维的均值和方差。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729321584786-9d7c178f-5f40-4b0d-8941-e3fcee4da95b.png">对于批量归一化到底是在做什么不太好判断，一开始认为是减少内部变量的转移，后来又认为是在小批量中加入噪音。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729321759318-92df4fe8-3794-402c-a89a-2a8c4f05f97b.png"></p><p>批量归一化通过固定均值和方差，然后加上可调整的偏移和缩放，这样做可以使得训练加快，但是无法改变模型的精度本身。</p><h2 id="wzYCb">优化算法</h2><h3 id="r2WAy">SGD</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729342513431-2c22c3e1-46e1-4d22-9000-303f0e29f814.png"></p><p>在开始介绍了梯度下降，随机梯度下降，小批量随机梯度下降这三种方法，但是对于这些方法来讲，除了使用全部数据的梯度下降，都存在震荡的情况。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729342632635-b3b37866-87ec-485c-ae9b-0910526aabe4.png"></p><p>更有甚者，可能会出现陷入局部最优点，鞍点的情况，对于这种情况，可以考虑加上一个动量。</p><h3 id="lpm3A">SGD+Momentum</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729342823936-9add071e-08b3-49b5-abeb-2415af93f9b5.png"></p><p>即不是仅仅使用梯度本身，而是使用一个$ v_t $，使用$ v_t&#x3D;{\beta}v_{t-1}+g_t $，这样展开的话就是一个平滑的梯度，其中的$ \beta $作为一个超参数，当批量较大时也可以设置一个较大的$ \beta $，这样可以考虑更多的数据。</p><h3 id="PNqZl">Nesterov Momentum</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729343344172-00d6faa0-ee3f-4fc4-ba0a-7b53475cc7ed.png"></p><p>刚刚使用的$ Momentum $的方法很好用，但是还可以更好的改进，尽然要使用$ v_t $，那就使用加上$ v_t $之后的梯度，向前看一步，显然使用$ a $这个梯度是要好于$ b $的。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729344781676-ed3b6333-1148-4b93-955f-0059471ef4b2.png"></p><p>图中的点标注有点错误，应该是$ X_t+1 $。</p><h3 id="cIV0b">AdaGrad</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729345008404-dc61e6f8-80cb-4666-b049-4a3b2b06ab02.png"></p><p>在$ AdaGrad $中使用了对梯度进行惩罚的方式，但是因为$ grad_squared $是一个累加和，随着这个数的越来越大在后面的更新可能会越来越慢。</p><p>$ RMSProp $ <img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729345293261-9d2f52a8-8802-4fc3-a04c-3918d6a7e0d8.png"></p><p>为了解决上面的问题，引入了一个$ decay_{rate} $进行衰减，通过这个值选择保留多少之前的$ grad_squared $。</p><h3 id="dd597">Adam</h3><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729345824803-cd08189c-7207-44a6-b64b-14fec9db535f.png"></p><p>上面的$ Momentum $考虑了之前的累加和，$ AdaGrad $即考虑了对较大的梯度进行惩罚，现在将这两种方法加在一起就有了$ Adam $优化算法。</p><p>但是这个的第一动量和第二动量在开始的时候都起不到什么作用，因此可以进行优化。</p><p><img src="/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1729346541847-5f17379f-08cc-4a73-9789-98a05a6ddc26.png"></p><p>开始的时候$ t $很小，因此$ 1\ -\ beta1\ ^{**}\ t $的值就很小，因此$ first_unbias $就很大，使得这个值在开始的时候不会不起作用，随着时间的累积，这个值和原本的$ first_moment $自然越来越接近。</p><p>上述提到的这些都是仅使用一阶导函数，还可以使用二阶导函数的牛顿法进行优化。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/</id>
    <link href="https://yzd11.github.io/2024/10/19/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/"/>
    <published>2024-10-19T14:18:19.000Z</published>
    <summary>神经网络的训练技巧</summary>
    <title>训练神经网络</title>
    <updated>2026-08-22T07:24:29.574Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="l3aVC">引入</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1722242257625-e2f82895-f1a0-4f84-a43a-d621f5b435fe.png"></p><p>我们使用一个需求预测的例子引入神经网络，再输入层中输入四个特征，接着通过激活函数在隐藏层得到三个激活值。最后将这三个输出作为输出层的输入通过逻辑回归得到一个概率预测。</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1722242621190-a72dcc70-dcfe-4f4d-af1f-e18cd3291345.png"></p><p>我们可以有多个隐藏层，同时每个隐藏层中的具体特征选择不需要我们自己考虑，但是总共的层数和每层的神经元数量需要我们选择。</p><h2 id="VyJM8">图像感知</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1722249269243-5c688f7a-7784-482e-a938-b15d75199802.png"></p><p>在第一个隐藏层中我们选择一些小的线条，在第二个中选择了眼睛或鼻子等器官，在第三个中选择了整个脸部，最终得到一个预测的可能值。对于这些隐藏层中神经元的内容我们没有指定，而是神经网络根据数据集自己训练的结果。</p><h2 id="AiN8E">神经网络中的网络层</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1722249538421-d27a9dfd-a6af-4363-8e98-f5e15cd93dbb.png"></p><p>我们将输入层成为第$ 0 $层，接着是第$ 1 $层，第$ 2 $层，第$ n $层，我们放大看第$ 1 $层。</p><p>为了区分，我们将上标作为层数标志，例如$ \vec{a}^{[1]} $表示第$ 1 $层的数据。使用下标表示第几个神经元，例如$ \vec{w}_{1}^{[1]} $表示第$ 1 $层中第一个神经元的$ \vec{w} $向量。</p><p>我们的输入向量在每个神经元中都进行一个小的逻辑回归运算得到一个概率值$ a $，结合在一起得到了一个输出向量$ \vec{a} $。同时这个向量也可以作为下一层的输入向量。</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1722250219985-45fb08ea-f3d7-4cb7-bd30-3592b98a4cb1.png"></p><p>最终我们通过输出层的一个神经元的逻辑回归运算得到一个输出值$ 0.84 $，我们可以设置一个阈值，如果大于这个值就为$ 1 $，否则为$ 0 $。</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1722250887396-4cdf7413-5771-4da5-bbaa-6d8aa5069acb.png"></p><p>其中$ a $为激活值，$ g $为激活函数$sigmoid$，$ l $为层数，$ j $代表第几个神经元，最后，$ w,b $表示权重和偏置。</p><h2 id="X8ETU">前向传播</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1722251509044-17506475-96d8-43d5-ad88-a2b9071d83d4.png"></p><p>图中从左向右依次计算激活值的过程被称为前向传播。</p><h2 id="OhQT7">优化算法</h2><p>待优化参数$ w $，损失函数$ loss $，学习率$ lr $，每次迭代一个$ batch $，$ t $表示当前$ batch $迭代的总次数：</p><ol><li>计算$ t $时刻损失函数关于当前参数的梯度$ g_{t}&#x3D;\nabla loss&#x3D;\frac{\partial loss}{\partial(w_{t})} $</li><li>计算$ t $时刻一阶动量$ m_t $和二阶动量$ V_t $</li><li>计算$ t $时刻下降梯度：$ \eta_t&#x3D;lr\cdot m_t&#x2F;\sqrt{V_t} $</li><li>计算$ t+1 $时刻参数：$ w_{t+1}&#x3D;w_t-\eta_t&#x3D;w_t-lr\cdot m_t&#x2F;\sqrt{V_t} $</li></ol><p>一阶动量：与梯度相关的函数</p><p>二阶动量：与梯度平方相关的函数</p><ul><li>SGD（随机梯度下降）</li></ul><p>$m_t&#x3D;g_t\quad V_t&#x3D;1$</p><p>$\eta_\mathrm{t}&#x3D;lr\cdot m_\mathrm{t}&#x2F;\sqrt{V_t}&#x3D;lr\cdot g_t$</p><p>$w_{t+1}&#x3D;w_t-\eta_t$</p><p>$&#x3D;w_t-lr\cdot m_t&#x2F;\sqrt{V_t}&#x3D;w_t-lr\cdot g_t$</p><p>$w_{t+1}&#x3D;w_t-lr*\frac{\partial loss}{\partial w_t}$ </p><ul><li>SGDM（含momentum的SGD），在SGD的基础上增加一阶动量</li></ul><p>$ m_t&#x3D;\beta\cdot m_{t-1}+(1-\beta)\cdot g_t \quad V_t&#x3D;1 $</p><p>$ \begin{aligned}<br>\eta_{t}&#x3D;lr\cdot m_{t}&#x2F;\sqrt{V_{t}}&#x3D;lr\cdot m_{t} \ &#x3D;lr\cdot(\beta\cdot m_{t-1}+(1-\beta)\cdot g_{t})<br>\end{aligned} $  </p><p>$w_{t+1}&#x3D;w_\mathrm{t}-\eta_\mathrm{t}$</p><p>$&#x3D;w_\mathrm{t}-lr\cdot(\beta\cdot m_{\mathrm{t-1}}+(1-\beta)\cdot g_\mathrm{t})$</p><ul><li>Adagrad，在SGD的基础上增加二阶动量</li></ul><p>$ m_{t}&#x3D;g_{t}\quad V_{t}&#x3D;\sum_{\tau&#x3D;1}^{t}g_{\tau}^{2} $</p><p>$\eta_\mathrm{t}&#x3D;lr\cdot m_t&#x2F;\left(\sqrt{V_t}\right)$</p><p>$&#x3D;lr\cdot g_t&#x2F;(\sqrt{\sum_{\tau&#x3D;1}^tg_\tau^2})$</p><p>$w_{t+1}&#x3D;w_t-\eta_t$</p><p>$&#x3D;w_t-lr\cdot g_t&#x2F;(\sqrt{\sum_{t&#x3D;1}^tg_\tau^2})$</p><ul><li>RMSProp，在SGD的基础上增加了二阶动量</li></ul><p>$ m_t&#x3D;g_t\quad V_t&#x3D;\beta\cdot V_{t-1}+(1-\beta)\cdot g_t^2 $</p><p>$\eta_t&#x3D;lr\cdot m_t&#x2F;\sqrt{V_t}$</p><p>$&#x3D;lr\cdot g_t&#x2F;(\sqrt{\beta\cdot V_{t-1}+(1-\beta)\cdot g_t^2})$</p><p>$w_{t+1}&#x3D;w_t-\eta_t$</p><p>$&#x3D;w_t-lr\cdot g_t&#x2F;(\sqrt{\beta\cdot V_{t-1}+(1-\beta)\cdot g_t^2})$</p><ul><li>Adam，同时结合SGDM一阶动量和RMSProp二阶动量</li></ul><p>$m_t&#x3D;\beta_1\cdot m_{t-1}+(1-\beta_1)\cdot g_t$</p><p>修正一阶动量的偏差：$\widehat{m_{t}}&#x3D;\frac{m_{t}}{1-\beta_{1}^{t}}$</p><p>$V_t&#x3D;\beta_2\cdot V_{step-1}+(1-\beta_2)\cdot g_t^2$</p><p>修正二阶动量的偏差：$\widehat{V_{t}}&#x3D;\frac{V_{t}}{1-{\beta_{2}}^{t}}$</p><p>$\eta_t&#x3D;lr\cdot\widehat{m}_t&#x2F;\sqrt{\widehat{V}_t}$</p><p>$&#x3D;lr\cdot\frac{m_t}{1-\beta_1^t}&#x2F;\sqrt{\frac{V_t}{1-\beta_2^t}}$</p><p>$w_{t+1}&#x3D;w_t-\eta_t$</p><p>$&#x3D;w_t-lr\cdot\frac{m_t}{1-{\beta_1}^t}&#x2F;\sqrt{\frac{V_t}{1-{\beta_2}^t}}$</p><h2 id="XC9wn">激活函数</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723017582358-91c249a8-8496-486d-9e12-41c79275ce8f.png"></p><p>我们可以看到除了我们已经学习过的线性激活函数和$ sigmod $函数，这里还有一种新的激活函数-$ ReLU $函数，也就是$ g(z)&#x3D;max(0,z) $，适用于输出都是非负数的情况。</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723018947523-626e7e37-a33c-4411-8eec-3dc6d5b93d11.png"></p><p>我们现在要学习一下为什么需要非线性的激活函数，如果我们仅仅只是使用线性的激活函数，那么无论我们的隐藏层中有多少的神经元我们也无法拟合一个非线性的目标函数。</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723019324194-02e926ec-862e-4ef9-b2f8-588b249744dd.png"></p><p>不要在隐藏层中使用线性激活函数，这样的话即使我们在输出层中使用$ sigmod $函数，我们也仅仅是实现了一个逻辑回归函数，因此我们最好是使用$ ReLU $函数。</p><h2 id="U0Lan">多分类问题</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723020029387-4499ee98-3444-45fe-bb36-eaa7fb3ea467.png"></p><p>我们不再仅仅预测一个二分类的问题，而是对多分类问题进行预测，我们使用$ Softmax $函数对线性运算的结果进行处理，使其成为一些列合为$ 1 $的值。其中的$ Softmax $为$ a_{j}&#x3D;\frac{e^{z_{j}}}{\sum_{k&#x3D;1}^{N}e^{z_{k}}}&#x3D;\mathrm{P(y&#x3D;j|\vec{x})} $</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723021305631-29a235aa-a51b-453d-b4cb-aab45f417925.png"></p><p>类比$ sigmod $的损失函数，我们可以得到$ Softmax $函数的损失函数为$ loss&#x3D;-log{a_j} \quad if ~ y&#x3D;j $</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723107620050-777b4cb1-476b-4e87-b705-77ee48028472.png"></p><p>由于$ Softmax $函数中出现了上溢和下溢的问题，我们需要使用指数归一化或者$ LSE $函数对其进行优化，因此，我们可以使用$\text{from logits&#x3D;True}$对其进行操作，使得$ Softmax $操作和交叉熵的操作放在一起进行并使用$ LSE $避免溢出问题。<br><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723109324375-d4c44b64-01df-4433-947c-ba777a4ce924.png"></p><p>同时由于我们在输出层不再进行$ Softmax $操作，因此我们最后的结果依然是具体的数值而不是概率值，因此需要在最后的结果预测时经过$ Softmax $的计算。</p><p>具体分析参照：</p><p><a href="https://blog.csdn.net/yjw123456/article/details/121869249">一文弄懂LogSumExp技巧-CSDN博客</a></p><p>关于$ Softmax $函数的由来参照:</p><p><a href="https://blog.csdn.net/yangwohenmai1/article/details/95936462">softmax函数名字的由来(代数&amp;几何原理)——softmax前世今生系列(2)_softmax的由来-CSDN博客</a></p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723109992747-692660f6-d5ce-4c49-b3e0-61409f4c195a.png"></p><p>多标签问题和多分类问题不同，多标签问题不具有排他性，可以既是car，又是bus，因此可以使用$ sigmod $激活函数，但是多分类问题时稀疏的，仅可以具有一种性质，采用$ Softmax $。</p><h2 id="ySInJ">高级优化方法</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723121395990-5e43996f-a662-49e5-b065-94651ecbe9dd.png"></p><p>我们可以看到Adam优化器的算法比我们之前的原始梯度下降算法要优秀，可以根据学习率的过大或过小自动调整。</p><h2 id="N5XNz">卷积神经网络</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723122039778-52decf09-0e9d-4ca7-a56e-530edbe6e638.png"></p><p>我们可以看到，卷积神经网络和之前学习的全连接网络的区别，我们可以调整每个卷积层的神经元的窗口大小和神经元个数。</p><h2 id="GTTaw">计算图</h2><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723799756880-bb61012d-8ff9-4e11-bbd4-b6a3300f2496.png"></p><p>对于自动求导，我们采用了三种方式，分别是符号求导，数值求导和计算图。</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723799618830-1ef7b2e2-af30-4249-a62f-901f46366404.png"></p><p>我们在这里采用了计算图的方式来进行自动求导，使用一个有向无环图进行求导。分为两步，分别是前向传播和反向传播。前向传播中我们计算数值，实际上就是为反向传播的求导过程准备数值。如图中，$ \frac{\partial z}{\partial b}&#x3D;2b $我们就用到了前向传播中的$ b $。</p><p><img src="/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1723800161864-6fd4f478-259b-4e51-bb36-391f4ed495dc.png"></p><p>反向累积中我们无论时正向传播还是反向传播，我们需要的计算都是相同的，同时由于需要保存中间变量，需要的内存会是$ O(n) $，但是对于正向累计来讲，由于每次计算一个导数都需要遍历后面的节点，因此它的时间复杂度远远大于反向累积，同时由于它不需要存储中间变量，它的空间复杂度很低。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/</id>
    <link href="https://yzd11.github.io/2024/10/19/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/"/>
    <published>2024-10-19T13:23:46.000Z</published>
    <summary>了解简单的神经网络</summary>
    <title>神经网络</title>
    <updated>2026-08-22T07:24:29.569Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<h2 id="介绍CNN"><a href="#介绍CNN" class="headerlink" title="介绍CNN"></a>介绍CNN</h2><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728910158927-03a99169-300a-483f-822d-e8a5d09597db.png"></p><p>对于卷积神经网络来讲，卷积，下采样，全连接是属于卷积神经网络最重要三个部分，接下来分别进行介绍。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728910341608-f03090b1-15c2-4bf4-8997-3708bc30cafb.png"></p><p>在之前的全连接中，在处理数据之前我们通常将全部的数据拉伸为一个直线，接着进行数据处理，但是这样的话会丢失一些空间信息。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728910997908-62bdfea4-9a1b-4082-a95f-3e174c7c394f.png"></p><p>因此，我们就需要使用这个卷积神经网络，每个卷积层跟着一个池化，最终加上全连接和输出层。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728911120044-434ef739-20f2-47fd-a6fa-77be14858565.png"></p><p>上图就是具体的卷积过程，其中$ input $中的绿色部分就是一个局部感受野，中间的$ 3\times3 $的矩阵就是一个卷积核，将这两个内容两两相乘再相加，最终得到的数据就是输出的值。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728911300869-4690ce4d-ce7b-4ed4-80fb-a1caf07825ba.png"></p><p>每个卷积核经过计算之后都会得到一个$ feature\ map $（特征图），上图中存在三个卷积核，因此得到三个$ feature\ map $，将这三个$ feature\ map $叠加在一起就是下一层的输入值。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728911551727-c479330f-d476-485c-a87e-2b3194c4f991.png"></p><p>同时需要注意的是，在计算中边缘数据的访问要少于中间数据的访问，因此我们可以通过填充数据$ 0 $来进行优化，这样也可以避免随着卷积计算得到的$ feature\ map $越来越小。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728911780453-d299978b-2654-4b09-a46f-6e3dedcbe7ee.png"></p><p>还需要注意的是，对于一个多通道的输入，对应的卷积核也要有相应的通道数，也就是对于一个三通道的输入，它的卷积核也要是三通道的。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728912019117-3dcd2d49-3ac1-4ffc-95b9-530cce6ac008.png"></p><p>对应上图，也就是第二个卷积核正在生成第二个$ feature\ map $，有多少个卷积核就生成多少个$ feature\ map $，最终将这些$ feature\ map $摞在一起。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728912152839-d5d7cddb-bbf7-41eb-8408-cccd1e1f6221.png"></p><p>这个图和上一个相同，都是对于一个多通道的输入的一个处理，还可加上一个偏置项。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728912317449-ba375d9c-5c01-4cad-b2b9-e66676f3a9d6.png"></p><p>其实每一次的卷积操作都可以看成是一个全连接的神经元。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728912394857-70e46035-a6cb-40e0-88aa-7a7bcc264ed9.png"></p><p>刚刚已经学习了卷积操作，但是还需要知道为什么需要进行卷积操作，卷积的意义就是将原图上符合卷积核特征的特征提取出来，例如上图中我们的卷积核就是一个眼睛，那么原图中眼睛的部分数值最高，</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728912850903-b7637931-fa64-4ad5-8b5a-8521f1928d93.png"></p><p>也就是得到这样的卷积输出，提取出眼睛的特征。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728912976131-684052a3-ece7-4a8a-a2e5-5ac4e2f8d1bc.png"></p><p>可以看到，有多少个卷积核那么久有多少个$ feature\ map $，那么如果具有$ 256 $个卷积核得到的$ feature\ map $就有$ 256 $，这样得到数据是很大的，因此我们可以选择其中的一部分，也就是用到了池化操作，也叫做下采样。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728913187314-a99ff174-f7bc-4d7a-b4cf-6171859bae56.png"></p><p>池化的操作有些类似于前面的卷积，但是没有卷积核，可以通过使用最大池化或者平均池化。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728913313596-097984ee-088e-43fd-9f94-acea4450a302.png"></p><p>可以看到，即使原图发生了平移，但是我们提取到的池化之后的结果确实相同的，因此池化操作是具有平移不变性的，因此在识别图片时即使发生了偏移，伸缩也不会影响。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728913442964-45ad479a-0e6d-40f3-a5c9-8ffc9671632c.png"></p><p>在池化中，除了刚刚提到的减少参数和平移不变性，还具有防止过拟合的性质，因为是提取了一个方块中最重要的信息，因此可以避免一些噪音点的干扰，可以避免过拟合。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728913567845-c90d10d7-9964-40e5-9649-dc6a6578ddf2.png"></p><p>在这幅图中最上面可以看到卷积的过程，经过卷积，池化，最终全连接并使用$ softmax $输出。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728913658853-83d250b4-f51d-4067-8487-e8d77ca476b0.png"></p><p>由于同一个卷积核在计算时是不变，因此说具有权重共享的性质。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728913836472-3c706e71-5df1-486d-9cf8-7863e41d1c8e.png"></p><p>对于如何计算一个$ feature\ map $的大小，可以通过$ (N-F)&#x2F;stride+1 $这个计算公式进行计算，同时需要避免出现步长为小数的情况。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728913967226-4e3cc4aa-bed2-4ebf-9086-cd0f8faf64ea.png"></p><p>如果算上填充$ 0 $的情况就是加上双倍的$ padding $的大小，同时计算可得，当$ p&#x3D;(F-1)&#x2F;2 $时，输入和输出的长宽相等。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728914113445-13639488-42b6-4eaa-8e32-97408e7779b1.png"></p><p>总结一下，通过上图计算我们可以得到输出的$ feature\ map $的大小和总权重的个数。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728914235025-93784183-27a2-43d5-a9e9-0c5b134ee5e7.png"></p><p>再试想一下，如果是一个$ 1\times1 $的卷积核，它具有什么作用。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728914293636-29d13708-bd80-4405-8a8a-aa634f5d171b.png"></p><p>可以看到，这个卷积核具有升维或者降维的作用，当$ n $大于$ 32 $时就是升维，相反就是降维。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728914359579-6447ed9a-7986-459e-8077-b29426facb7a.png"></p><p>对于普通的卷积神经网络，计算的运算量是一个很大的数量级，但是如果可以通过$ 1\times1 $的卷积核进行降维，可以减少参数量，同时将不同通道之间的数据进行交流，加上一层降维操作也等同于增加模型深度，提高了非线性的能力。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1728914631273-d2bd74b1-4aad-44c6-980b-f6735d3ab00e.png"></p><p>每一个卷积核也相当于一个神经元的全连接操作，其中原图上的元素相当于$ x $，卷积核上的权重相当于$ w $，一次卷积操作也相当于一个全连接操作。</p><p>对于图中的五个通道值，是五个不同的卷积核对于同一个感受野的计算值累加在一起，因此一个$ 1\times1 $的卷积核相当于对于不同通道的值穿在一起。</p><h2 id="卷积和卷积神经网络"><a href="#卷积和卷积神经网络" class="headerlink" title="卷积和卷积神经网络"></a>卷积和卷积神经网络</h2><p>首先，我们通过两个图讲述卷积的概念。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732097502213-2b02ce66-1e9c-403d-9c10-0c38d0163d67.png"></p><p>假设这是一个人吃食物的图像，横纵坐标分别代表时间和进食。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732097593746-0f3dc9af-f745-453b-b507-d86267a110c2.png"></p><p>这是一个人消化食物的图像，横纵坐标分别代表时间和剩余的食物的比例。</p><p>对于卷积的公式，$ \int_{-\infty}^{\infty}f(\tau)g(x-\tau) \mathrm{d}\tau $,其中我们使用$ f $函数表示进食，使用$ g $函数表示消化。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732097899162-328b89a1-9749-4cdc-ae00-eb7d38770b1d.png"></p><p>现在我们希望计算这个人在$ 14 $点剩余的食物，如果没有$ g $函数的话，我们仅仅需要求一个积分就行了，但是现在需要考虑到$ g $函数的影响。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732098041317-7fe62c79-4d77-49eb-9f01-b1989ff49054.png"></p><p>单个时间的话就是$ \mathrm{f(x)\cdot g(t-x)} $，但是全部加上就是$ \int_0^\mathrm{t}f(x)g(t-x)dx $。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732098201415-cec30db0-3e4d-41c0-a90e-beda2106050e.png"></p><p>可以看到每一个连线就是$ f(x) $和$ g(x) $的相乘，最后把它们全部加起来，对比真正的卷积公式就是将上下限进行了调整。</p><p>现在我们可以得到卷积的价值，就是对于一个系统，输入不稳定，输出稳定，可以使用卷积计算系统的存量。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732098408809-ce23003e-2e20-45e2-9766-0b8040b47b79.png"></p><p>关于卷积的名字，有一个解释是将刚才的函数进行了翻转，因为翻转因此叫做卷积。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732098926757-2dbe7997-7f96-424a-9a69-4817428e91e5.png"></p><p>在卷积操作上，我们类比刚才的定义，输入就是图像本身，输出是卷积核。</p><p>但是为什么卷积核可以作为函数$ g $，关于这一点可以通过上面的图像进行分析，我们可以将其看作周围点对当前点的影响，假设当前点是$ f(x,y) $，周围点是$ f(x-1,y-1) $，那么代入也就是$ f(x-1,y-1)·g(1,1) $。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732099264322-b22a0c64-a002-4e6f-8e30-3ee738f3a24b.png">将其全部展开的话，可以看到其实$ g $函数对应的就是卷积核，但是有一点别扭。</p><p><img src="/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1732099320918-a2b59c49-1112-48f2-9fe1-e86876657378.png"></p><p>将$ g $旋转$ 180 $度就是卷积核本身了，我们可以使用这个卷积核对图像进行操作。</p><p>最后卷积在$ CNN $中可以看作是一个像素的对于周围像素点的试探和选择，可以通过这个卷积核作为一个过滤器，保留下有用的信息，提取一些和卷积核更相似的信息，例如上个小节提到的提取眼睛的信息。</p><p>对于卷积的含义有以下三层：</p><ol><li>不稳定输入，稳定输出的系统中求系统存量</li><li>周围的像素点对当前像素的影响</li><li>一个像素点主动的保留周围像素点上需要的特征</li></ol>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/</id>
    <link href="https://yzd11.github.io/2024/10/14/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/"/>
    <published>2024-10-14T14:10:45.000Z</published>
    <summary>了解卷积神经网络</summary>
    <title>卷积神经网络</title>
    <updated>2026-08-22T07:24:29.550Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<p><img src="/2024/10/13/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%92%8C%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD/1728742853744-bb4783be-8349-4539-91ae-5be9f1b8dc49.png"></p><p>首先我们需要讲之前的线性函数转化为非线性函数，也就是使用$ Relu(x)&#x3D;max(0,x) $这个激活函数，多个这样的感知机加在一起，也就是我们所讲的多层感知机$ MLP $，也被叫做全连接神经网络。</p><p><img src="/2024/10/13/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%92%8C%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD/1728743147222-378043dd-8e9f-42fa-8240-f4487c3c6538.png"></p><p>正是有了激活函数，神经网络才可以拟合非线性，否则无论有多少层神经元都可以使用一个线性转换得到最后的结果，和单个线性层无区别。</p><p><img src="/2024/10/13/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%92%8C%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD/1728743551024-e1a28d22-be8e-4b9b-91e3-e1c8ed62e9e5.png"></p><p>我们通常使用的有以下几种激活函数，其中$ ReLU $最为常用，因为其结构简单，但是由于在输入为负时的结果梯度为$ 0 $，因此有了$ ELU,Leaky ReLU $作为优化。</p><p><img src="/2024/10/13/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%92%8C%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD/1728788208773-ff39c312-547e-4ada-8586-db4bf1769856.png"></p><p>在计算梯度时，需要使用计算图和反向传播，这在机器学习中也有具体解释。</p><p><img src="/2024/10/13/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%92%8C%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD/1728788251795-51fa4eb8-cd68-4798-8f62-1463bdbea8f9.png"></p><p>对于不同的操作，梯度的变换也不尽相同，例如，加法时梯度没有改变，乘法时梯度发生交换。</p><p>注意：隐含层的作用就是将输入的非线性的数据转换为线性可分的数据，因此在输出层中就不再需要使用激活函数。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/13/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%92%8C%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD/</id>
    <link href="https://yzd11.github.io/2024/10/13/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E5%92%8C%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD/"/>
    <published>2024-10-13T03:05:45.000Z</published>
    <summary>了解简单的神经网络和反向传播</summary>
    <title>神经网络和反向传播</title>
    <updated>2026-08-22T07:24:29.570Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<h2 id="wtXia">SVM分类</h2><p><img src="/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/1728738689184-62e0c89c-1af5-45bb-a127-c86b90c82e9c.png"></p><p>上一节已经介绍了线性分类器，但是我们并没有对其进行评估。现在我们需要对其进行评估，首先定义一个损失函数，接着然后对其进行优化，使其$ loss $最小化。</p><p><img src="/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/1728739289631-6716ccf4-0b02-4c26-8cce-4a43ea0bc51e.png"></p><p>首先使用$ SVM $分类，对于这个算法在这里不多介绍，具体在机器学习中详细介绍，这里直接使用它的损失函数，也就是前面提到的合页函数，但是需要注意的是，这里的损失函数并不是前面直接使用目标值和预测值的乘积，在实际应用的时候，一方面，预测值$ y $并不总是属于$ [-1,1] $，也可能属于其他的取值范围；另一方面，很多时候我们希望训练的是两个元素之间的相似关系，而非样本的类别得分，因此我们更倾向于使用二者的差值预测二者之间的相似关系。</p><p><img src="/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/1728740284653-65bb7a62-d454-40ea-9859-df5cf829de2e.png"></p><p>当我们对于猫这张图片进行计算的时候，可以看到这个损失函数的值就是$ 2.9 $</p><p><img src="/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/1728740371798-cdd26a24-192d-4fa6-9447-e48b65bb4c87.png"></p><p>可以看到即使两个$ w $的值不同，但只要是关系，那么损失值也是相同的，那么如何衡量使用合适的权重，这就需要使用正则化。</p><p><img src="/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/1728740351542-001b8849-30eb-464c-b577-84f632bbd057.png"></p><p>图中展示了我们进行使用的$ L1,L2 $正则化，以及$ Dropout $等避免过拟合的方法。</p><h2 id="EXWkB">softmax分类</h2><p><img src="/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/1728741089486-09af98f7-0a09-4dfd-bc57-7120d11c7677.png"></p><p>除了上一节的$ SVM $，对于分类问题，例如对于多分类的逻辑回归问题，我们还可以使用$ softmax $激活函数，因此可以计算出不同类型的概率，还可以使用最大似然估计求得损失函数，这一部分也是属于机器学习的内容，这里不过多阐述。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/</id>
    <link href="https://yzd11.github.io/2024/10/12/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E4%B8%8E%E4%BC%98%E5%8C%96/"/>
    <published>2024-10-12T14:14:09.000Z</published>
    <summary>了解损失函数</summary>
    <title>损失函数与优化</title>
    <updated>2026-08-22T07:24:29.560Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="深度学习" scheme="https://yzd11.github.io/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    <category term="Deep Learning" scheme="https://yzd11.github.io/tags/Deep-Learning/"/>
    <content>
      <![CDATA[<h2 id="LyDW4">K-Nearest Neighbors算法</h2><p>在$ cs231n $的课程中，首先介绍了$ k $近邻算法，但由于课件上没有介绍$ KD $树，因此采用另外一个课程的讲解。</p><p><a href="https://www.bilibili.com/video/BV1JE41147KA/?spm_id_from=333.999.0.0">第3章 k-近邻算法_哔哩哔哩_bilibili</a></p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727268386728-b08d48b9-4254-4e9d-8877-5142c1b599cf.png"></p><p>首先，$ k $近邻算法的原理就在于找到离自己最近的$ k $个点，对于分类问题，采用多数表决法，对于回归问题，计算平均值，这里有些类似于决策树。</p><p>例如对于这个图像来讲，我们选择$ k $为$ 3 $，也就是离这个点最近的三个点，其中两个红三角，一个蓝方块，因此我们将其预测为红三角。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727268580798-48405c9b-2adc-4953-9f21-56302f14e0ba.png"></p><p>对于$ k $近邻算法分为这几个步骤，可以看到我们基本上没有学习的过程，相比于之前学到的逻辑回归，我们的训练过程仅仅是将所有的数据读入，因此$ k $近邻算法也被称为是一种懒散的学习方法，基本上不学习。同时我们也看到在$ k $近邻算法中，$ k $值的选取是十分重要的，接下来我们将介绍这个部分。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727268921685-ddf63c43-6a7f-4f93-96b9-695b01d8b380.png"></p><p>可以看到，对于不同的$ k $来讲，我们随着$ k $的增大，那么这个分类也就变得更加平滑，但是同时误差也会增大，如果使用一个极端的情况，$ k $等于样本个数，那么就没有分类，样本中哪个多就属于哪个，当$ k $太小时也不好，这样虽然误差减小，但是模型会过于复杂，很容易过拟合，因此，我们需要通过交叉验证选择一个合适的超参数$ k $。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727269266237-1b2749e0-daa6-4d45-bc07-67658fb65bcf.png"></p><p>除了$ k $的值，我们还需要选择怎么衡量这个距离，其中我们经常使用曼哈顿距离和欧式距离。</p><h2 id="ASMS5">KD树  </h2><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727269386887-06a07925-be9b-4028-9749-19af5951fb7b.png"></p><p>我们刚刚的计算方法也就是暴力的计算方法，但是在这种方法下，虽然我们的训练时间很短，仅需要将全部的数据读入即可，但是在测试中，对于每个测试数据我们都需要遍历全部的数据，如果这个数据集很大的话，我们的测试时间也会变得很大，为了解决这个问题，我们可以使用数据结构中的树。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727269612937-71e0ffcc-8ed5-40cd-9d47-ab99934bcda9.png"></p><p>$ KD $树做作为一种二叉树，可以有效地划分数据集，避免对于全部的数据都进行访问。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727269702376-bd2185c3-b127-42a7-b6ca-c9d07ac7bac1.png"></p><p>首先，构建一个$ KD $树。我们先选择一个维度进行划分，我在不同的资料中找到两种划分的方式，第一种是视频中的这种方式，先选择$ x $轴，接着循环划分，如果有$ y,z $的话就一直循环，第二种是刘建平老师的博客中讲到，选择方差最大的维度作为划分，在本文中选择第一种方式，比较简单。</p><p>对于这个图，首先，我们以$ x $轴作为划分，因此，我们需要选择其中的中位数，这个例子中由于存在偶数个数，因此，我们可以选择$ (5,4) $也可以选择$ (7,2) $，我们选择较大的$ (7,2) $，接着，将$ x $轴上小于$ 7 $的$ (5,4),(4,7),(2,3) $划入左子树，将$ (9,6),(8,1) $划为右子树。接着在选择$ y $轴作为划分，最终可以得到下图。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727270228656-a27a902b-2a00-4ef1-8395-85e3f70e5850.png"></p><p>图中在第三层就划分完成了，因此，如果还有数据的话重新选择以$ x $轴划分。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727270296473-1a2c5bcb-74a8-4717-ace3-3a2ddbe9eb30.png"></p><p>现在通过构建好的$ KD $树，介绍$ KD $树搜索。</p><blockquote><p>　　当我们生成KD树以后，就可以去预测测试集里面的样本目标点了。对于一个目标点，我们首先在KD树里面找到包含目标点的叶子节点。以目标点为圆心，以目标点到叶子节点样本实例的距离为半径，得到一个超球体，最近邻的点一定在这个超球体内部。然后返回叶子节点的父节点，检查另一个子节点包含的超矩形体是否和超球体相交，如果相交就到这个子节点寻找是否有更加近的近邻,有的话就更新最近邻。如果不相交那就简单了，我们直接返回父节点的父节点，在另一个子树继续搜索最近邻。当回溯到根节点时，算法结束，此时保存的最近邻节点就是最终的最近邻。</p></blockquote><p>虽然文字描述很绕口，但实际上的思路很简单，首先我们找到一个临时的最近的节点，也就是找到一个叶子节点，类似于二分搜索树，我们根据大于小于当前节点进行划分。</p><p>如图，$ (2,4.5) $在$ x $轴上，小于$ 7 $，因此，划分到左子树，又因为在$ y $轴上大于$ 4 $，因此划分到右子树，最终到达叶子节点$ (4,7) $。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727270765981-adc1048e-964e-4e87-ab42-f208181fc369.png"></p><p>但是这仅仅是一个临时的最小值，我们可以看到$ (2,4.5) $虽然是属于$ (4,7) $所在的范围，但是由于这个范围太大，而这两个点离得并不是很近，反而是$ (2,3) $和$ (2,4.5) $离得更近一些。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727272355603-6f431ff7-ccd4-44a5-a6a6-c831c1d98fcb.png"></p><p>首先我们计算节点$ (4,7) $，可以看到，这个节点不小于我们的临时最小值，接着判断另一个兄弟节点$ (2,3) $所在的范围是否与以$ (2,4.5) $为球心，$ (2,4.5),(4,7) $之间距离为半径的超球体有相交的地方，虽然这个图我画的不是很标准，但是可以明显看到是存在一个相交的，因此我们需要将其移动到$ (2,3) $，经过计算，这个距离小于$ (4,7) $，因此将其更新为临时的最小距离，这个节点的兄弟节点已经判断过了，因此我们回到这个节点的父节点$ (5,4) $。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1727272803714-fe97f4fc-de91-40cb-a09a-b93596e9020a.png"></p><p>由于这个节点的距离不小于我们的临时最小值，因此不需要改变，同时这个新的超球体和当前节点$ (5,4) $的兄弟节点$ (9,6) $所在的范围也并不相交，因此不需要递归这个右子树，关于递归这个可以参照这篇博客的详细介绍，实际上就是重新按照第一步找到这个子树下的叶子节点。</p><p><a href="https://blog.csdn.net/u013468614/article/details/125519008">kd tree最近邻搜索算法深度解析_kdtree最近邻算法-CSDN博客</a></p><p>接着回到根节点，计算这个距离不小于临时最小距离，因此搜索结束，则$ (2,3) $为最小距离节点。</p><p>通过了解了$ KD $树搜索最小距离，在计算$ k $个值时，仅需要屏蔽已经标记的最小距离重新进行循环计算$ k $次即可，同时，如果数据量不太，我们还可以通过维护一个小根堆来遍历一个即可。在使用$ KD $树中由于我们减少对于一些无意义的遍历，缩短了测试时间，但是数据分布不是很均匀的时候，这种方法的效果就不是很好了，对于这种情况可以参照这篇博客。</p><p><a href="https://www.cnblogs.com/pinard/p/6061661.html#order=0&desc=true&!comments">K近邻法(KNN)原理小结 - 刘建平Pinard - 博客园</a></p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1728654826891-6ca71996-1b2c-4d74-a989-4397de2238b6.png"></p><p>我们虽然提到了$ KNN $算法，但是在实际的图像分类中我们并不会使用这个方法，除了这个方法在测试的时候太慢，还会出现例如上图中右侧三个图片虽然不一样，但是如果计算他们和左侧图片的$ L2 $距离却会出现一样值的结果。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1728655000280-be059524-d4f0-42e0-80a2-91c4fbf2884a.png"></p><p>同时当我们的维度提到了，需要的数据则是一个指数的增长，这些问题都导致我们在实际上并不会使用这个方法。</p><h2 id="kMeW4">线性分类器</h2>除了$ KNN $，我们还有一种分类方法，称为线性分类器，接下来从三个角度理解这个分类器。<ul><li>代数角度</li></ul><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1728655148357-d8372a78-3346-4af2-a549-9715701d28d1.png"></p><p>假设当前有一个长$ 32 $，宽$ 32 $，通道为$ 3 $的图像，将这个图像转换为一个列向量，也就是一个$ 3072\times1 $的列向量。同时我们将其分为$ 10 $类，对于每一个我们都需要$ 3072 $个权重，因此我们就得到了一个$ 10\times3072 $的矩阵，使用这个权重矩阵乘上像素值加上截距，也就得到了我们的分类结果。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1728655458901-6fca019b-9b27-4062-a5e7-f546a7b4df8a.png"></p><p>使用这个例子，我们猫的图片有四个像素点，因此就伸长为一个$ 4\times1 $的列向量，同时因为需要划分为$ 3 $类，因此需要一个$ 3\times4 $的权重矩阵，最后加上偏置即可。</p><ul><li>直观角度</li></ul><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1728655618355-94a64d85-b4d3-4c0a-ba18-19edbafe424b.png"></p><p>从直观角度上来讲就是讲训练的$ 3072 $个权重变回原本的$ 32\times32\times3 $的矩阵，可以看到对于飞机来讲蓝色像素点的占比分高，也就是讲如果有一个图片跟这个图片很接近，那么高的权重乘上高的像素自然结果也就越高，说明也就越是飞机。</p><ul><li>几何角度</li></ul><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1728655918466-e531c44b-6365-45c4-8b6c-b422a3f92005.png"></p><p>从几何上来讲，这个线性分类在一维上就是点，二维上就是直线，三维上就是面，更高维上就是超平面，例如上图中划分了$ 10 $个超平面。</p><p><img src="/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/1728656021444-bd0fb96b-d21b-4f04-801e-92149da0744a.png"></p><p>同时线性分类也具有一些问题，对于线性不可分的情况，例如图一的异或问题，图二的环状问题，我们的线性分类都是无法满足的。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/</id>
    <link href="https://yzd11.github.io/2024/10/11/%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%EF%BC%9AKNN%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB%E5%99%A8/"/>
    <published>2024-10-11T14:15:51.000Z</published>
    <summary>原始的图像分类算法</summary>
    <title>图像分类:KNN和线性分类器</title>
    <updated>2026-08-22T07:24:29.551Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<p><img src="/2024/10/11/%E6%9C%B4%E7%B4%A0%E8%B4%9D%E5%8F%B6%E6%96%AF%E5%88%86%E7%B1%BB%E5%99%A8/1728639226454-1a8bf1fa-0fb3-4d9a-ac7b-df0549f691fb.png"></p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/11/%E6%9C%B4%E7%B4%A0%E8%B4%9D%E5%8F%B6%E6%96%AF%E5%88%86%E7%B1%BB%E5%99%A8/</id>
    <link href="https://yzd11.github.io/2024/10/11/%E6%9C%B4%E7%B4%A0%E8%B4%9D%E5%8F%B6%E6%96%AF%E5%88%86%E7%B1%BB%E5%99%A8/"/>
    <published>2024-10-11T09:34:47.000Z</published>
    <summary>了解朴素贝叶斯分类器</summary>
    <title>朴素贝叶斯分类器</title>
    <updated>2026-08-22T07:24:29.563Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="ZMbnq">线性分类介绍</h2><p><img src="/2024/10/09/%E6%84%9F%E7%9F%A5%E6%9C%BA/1728483273876-2570f8e0-fc19-41e1-9d4c-0ba31513c951.png"></p><h2 id="SzUin">感知机介绍</h2><p><img src="/2024/10/09/%E6%84%9F%E7%9F%A5%E6%9C%BA/1728483833861-6dca08bf-5103-4e37-b5f0-5ba80bed2f0c.png"></p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/09/%E6%84%9F%E7%9F%A5%E6%9C%BA/</id>
    <link href="https://yzd11.github.io/2024/10/09/%E6%84%9F%E7%9F%A5%E6%9C%BA/"/>
    <published>2024-10-09T14:24:56.000Z</published>
    <summary>了解感知机算法</summary>
    <title>感知机</title>
    <updated>2026-08-22T07:24:29.558Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="RHhJ9">硬间隔SVM-模型定义（最大间隔分类器）</h2><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1727496364081-ea4f3596-5393-428c-9512-5f9c1dd44c75.png"></p><p>$ SVM $可用于处理分类问题，首先介绍硬间隔$ SVM $。</p><p>对于感知机分类来讲是存在多种分类方法的，但是这些分类中存在有的分类很容易发生变动，因此我们希望找到一个鲁棒性（稳定性）最好的一种。这里我们衡量的方法采用了硬间隔最大，首先选择在集合点中离分类超平面两侧中最近的点，这些点也被称为支持向量，相隔的距离也就是图中的$ margin(w,b) $。接着通过调整$ w,b $最大化该间隔。</p><p>其中我们处理要保证结构的最大化之外，也就是硬间隔的最大化，还要保证划分的点都是正确的，也就是$ y_{i}(w^{T}x_{i}+b) $的最小值大于$ r $，其中$ r&gt;0 $，令$ r&#x3D;1 $，将其缩放为一个固定的值，同时简化运算。</p><p>最终我们要满足在所有点都分类正确的情况下，最大化硬间隔。</p><h2 id="f3TKD">硬间隔SVM-对偶问题引出</h2><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1727499837949-28637c63-55d9-44ba-b972-cb5086ef49cb.png"></p><p>上一节介绍了硬间隔问题的数学模型，接下来对其进行一个转换，使其更加容易求解，同时可以方便使用核函数。</p><p>首先使用拉格朗日乘子，将其原本的约束条件改变为等式中的隐形条件，由于是$ min $最小化的值，因此，如果$ 1-y_{i}(W^{T}X_{i}+b)&gt;0 $的话，我们对其进行$ max $，最终的值一定是$ +\infty $，但是加上前面的$ min $也就相当于直接将其省略，仅保留了$ 1-y_{i}(W^{T}X_{i}+b)&lt;&#x3D;0 $的情况。之所以要进行$ max $也是因为这个项是一个小于等于零的数，对其最大化相当于对于$ y_{i}(W^{T}X_{i}+b) $进行最小化。在这一步中其实就是相当于将这个带约束的条件转换为无约束的隐式条件。</p><p>接着我们利用这个凸二次优化问题本身的强对偶性，将其转化为$ maxmin $问题，利用图中右侧的转化，我们可以将等式最终简化为$ \min_{\lambda}\frac{1}{2}\sum_{i&#x3D;1}^{N}\sum_{j&#x3D;1}^{N}\lambda_{i}\lambda_{j}y_{i}y_{j}x_{i}^{T}x_{j}-\sum_{i&#x3D;1}^{N}\lambda_{i} $，其中条件为$ \lambda_{i}&gt;&#x3D;0 $。关于这个条件的证明可以参照与这个视频。</p><p><a href="https://www.bilibili.com/video/BV1cZ4y147vZ?p=3&vd_source=a1e5dd0aa99678acd93e274baaf2577f">SVM支持向量机-3_哔哩哔哩_bilibili</a></p><h2 id="kwX3G">硬间隔SVM-对偶问题之KKT条件</h2><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1727503109230-bfca61da-d01f-4b8a-b93a-598bc44c3d2f.png"></p><p>我们上一节已经得到了这个问题的对偶问题，现在我们需要利用它的$ KKT $条件。</p><p>由于原问题和对偶问题之间具有对偶性是满足$ KKT $条件的充要条件，我们已经知道由于这个问题是凸二次优化问题，一定满足强对偶关系（这一点我也不会证）。</p><p>因此我们就可以利用$ KKT $的条件，因此我们就可以计算$w^*,b^*$的值。</p><p>其中$w^*$已经计算过了，而对于$b^*$就需要利用我们的$ \lambda_{i}(1-y_{i}(w^{T}x_{i}+b))&#x3D;0 $这个松弛互补条件，最终通过右下角的推导可以得到$ b^{*} $的值。</p><p>对于这个松弛互补条件，如果我们的点在$ w^{T}x_{i}+b&#x3D;\pm1 $上，那么$ 1-y_{i}(w^{T}x_{i}+b) $就等于$ 0 $,$ \lambda&gt;0 $，但是如果不再这个分界上，那么$ 1-y_{i}(w^{T}x_{i}+b) $就小于$ 0 $，那么$ \lambda&#x3D;0 $，那么对于求解$w^*,b^*$就无意义了。</p><h2 id="xchcl">软间隔SVM-模型定义</h2><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1727507725680-f7187318-ff09-4dfb-a75a-28ed5842cb52.png"></p><p>前几节中介绍了硬间隔$ SVM $，现在我们来介绍软间隔$ SVM $。</p><p>如果我们的数据中存在噪音的情况，那么我们就需要对超平面进行调整，现在我们需要这个模型可以容纳一些错误，也就是引入损失函数，现在这个函数有两种定义的方式。</p><p>如果使用数量代表，那么可以通过指示函数$ I $表示，但是由于这个函数不是连续的，因此我们在进行求导的时候很不方便，因此可以使用距离表示。</p><p>如果$ y_{i}(w^{T}x_{i}+b)&gt;&#x3D;1 $，那么$ loss&#x3D;0 $。如果$ y_{i}(w^{T}x_{i}+b)&lt;1 $，那么$ loss&#x3D;1-y_{i}(w^{T}x_{i}+b) $。也就可以写成$ loss&#x3D;max{0,1-\underbrace{y_{i}(w^{T}x_{i}+b)}_{z}} $，由于这个函数的图像类似于一个合页，因此也被称为$ hinge \quad loss $，即合页函数。</p><p>同时由于使用$ max $的表达不太方便，因此可以引入一个$ \epsilon $，因此我们的表达式也就可以写成下面的形式。</p><p>$\begin{cases}\min_{w,b}\frac{1}{2}w^Tw+C\sum_{i&#x3D;1}^N\epsilon_i \newline s.t\quad y_i(w^Tx_i+b)\geq1-\epsilon_i,\epsilon_i\geq0\end{cases}$</p><h2 id="qGg5G">核方法-背景介绍</h2><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1727511489368-623e7a94-cfe9-4e29-affa-a85b6036ab0b.png"></p><p>之前我们介绍的硬间隔是对应严格线性可分的情况，为了允许一定的错误我们引入了软间隔，但是如果当错误过多，已经是非线性可分的情况，那么我们就需要改变思路。对于感知机来讲，我们可以使用升维或者采用多层感知机，也就是神经网络来逼近任意一个线性函数，对于$ SVM $来讲我们可以也可以使用升维的方法。</p><p>可以看到在之前的对偶问题转换之后我们得到的结果中存在一个内积的情况，那么在升维之后这个内积就会变成$ \phi(x_{i})^{T}\phi(x_{j}) $的形式，对于少数的样本点进行升维的转化还可以接受，但是对于多个样本点我们很难计算升维的转换，因此我们可以使用一个核函数，不需要升维，直接计算最终的升维之后的内积。例如我们使用这个$ exp(-\frac{(x-x^{\prime})^{2}}{2\delta^{2}}) $这个核函数就可以直接计算最终的结果，而不需要进行复杂的升维，大大简化了运算的过程。</p><h2 id="pzYED">核方法-正定核（两个定义）</h2><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1728392517583-77fb6885-dce3-4e37-8cb5-c5d29f7eb534.png"></p><p>对于正定核，具有上图的两个定义，第一个表示对于一个正定核函数，通过核函数计算的值等于经过映射之后的内积的值，但是这个不利于计算，因此有第二个定义，也就是满足核函数满足对称性和正定性即可证明该核函数为正定核函数。下图给出两个性质的证明。</p><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1728395597228-16e1a64b-c2ce-4a72-9cd6-0a763935199b.png"></p><h2 id="ZkioK">补充</h2><p><img src="/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/1728395886739-29298343-2861-4061-b404-06852d7e0577.png"></p><p>对于前面的高斯核函数，我们也要注意它的$ \gamma $值，当$ \gamma $值过大时，需要两个向量之间很近，它们的相似度才不会为$ 0 $，注意，核函数本身就是计算内积，因此可以体现二者的相似度。相似度高的自然容易被分到一起，因此当$ \gamma $值过大时，仅仅相邻很近的向量会被划分为相同的，因此很容易造成过拟合。同时$ \gamma $过小的后果也就是会造成过于容易划分。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/</id>
    <link href="https://yzd11.github.io/2024/10/08/%E6%94%AF%E6%8C%81%E5%90%91%E9%87%8F%E6%9C%BA/"/>
    <published>2024-10-08T14:03:33.000Z</published>
    <summary>了解支持向量机算法</summary>
    <title>支持向量机</title>
    <updated>2026-08-22T07:24:29.562Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="强化学习" scheme="https://yzd11.github.io/categories/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
    <category term="Reinforcement Learning" scheme="https://yzd11.github.io/tags/Reinforcement-Learning/"/>
    <content>
      <![CDATA[<h2 id="xu0Pq">引入</h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726128985868-783ba096-524f-46ca-86e2-8d323f2d093d.png"></p><p>在强化学习中，不同于之前的监督学习，例如对于一个直升飞机来讲，似乎我们很难人为的评断什么是好的，什么是坏的，我们更多的是通过奖励来对其行为进行调整。</p><p>和监督学习相比较，强化学习中的标签是后给出的，与无监督学习相比，强化学习中使用了标签。</p><p>例如对于这个火星探测车，我们需要它拍摄到有价值的图片,也就是到达$ state1 $或$ state6 $，这样就可以得到奖励为$ 100 $或$ 40 $，假设我们现在处于$ 4 $这个状态，我们可以选择向左或者向右移动，最终到达奖励的位置。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726130376079-0eea49f5-0366-4fd7-b7af-686a09a69449.png"></p><p>刚才我们仅仅看到目的地的奖励，但是显然$ 100 $的距离却比$ 40 $要远，那么我们就需要把距离这个因素也计算进去。  因此我们引入了一个新的概念–<font style="background-color:#FBDE28;">折扣因子</font>$ \gamma $，在这里我们采用$ \gamma&#x3D;0.5 $的情况来进行评估。</p><p>$ Reward $<font style="background-color:#FBDE28;">奖励</font>，表示每个时刻采取动作后得到的是即时奖励</p><p>$ Return $<font style="background-color:#FBDE28;">回报</font>，表示在时刻采取某个动作后到游戏结束可以得到的总的奖励，即$ U_t&#x3D;R_t+R_{t+1}+R_{t+2}\ldots $</p><blockquote><p>“ 注意上面的$ U_t $公式中的$ reward $采用的是大写字母，因为它们表示的是随机变量，小写字母$ r_t $表示的是在时刻$ s_t $采取某个具体动作$ a_t $后得到的具体的奖励值。”</p></blockquote><p>上面给的$ U_t $计算公式是从$ t $时刻开始未来每个时刻的奖励的累加，可以看到所有时刻的$ reward $都是相同权重的。但是这样设计有一个问题，就是假如我现在给你$ 100 $和$ 1 $年后才给你$ 100 $，这两个$ 100 $显然不应该赋予相同权重，所以你经常可以看到$ return $计算时会有一个参数$ \gamma $,得到的是$ discounted \quad return $，即$ U_t&#x3D;R_t+\gamma R_{t+1}+\gamma^2R_{t+2}\ldots $</p><h2 id="kl2xD">策略</h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726131338806-0bfd8ada-e15c-4ace-a726-bd701cb119ed.png"></p><p>我们再介绍一个新的术语–<font style="background-color:#FBDE28;">策略</font>$ \pi $，我们使用$ \pi{(s)}&#x3D;a $表示在状态$ s $下采用决策$ a $，也就是表明了我们在状态$ s $下应该采用的决策。</p><h2 id="xkWyp">马尔科夫决策过程</h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726131649478-02572d0a-a510-4612-8251-bf347a232c70.png"></p><p>对用这种问题我们有一个经常使用的方法，称为<font style="background-color:#FBDE28;">马尔科夫决策过程</font>，我们对于一个状态采取一个决策，然后基于这些决策发生的变化，得到新的状态和奖励。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726145604442-dcfbef47-8a1d-4521-b65d-ff3f62166f1b.png"></p><p>我们再引入一个新的概念-<font style="background-color:#FBDE28;">动作价值函数</font>，$ Q(s,a) $表示等于回报值，如果在状态$ s $下采用一次决策$ a $，然后接下来进行最优选择。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726146024569-16db0a74-cde0-4acb-8f60-8ca9df448c92.png"></p><p>可以看到，最理想的收获值就是$ \max_{a}Q(s,a) $，在状态$ s $下最理想的决策就是可以使得$ Q $为最大值的决策。有的情况下这个函数也被写成$ Q^{*} $，实际上是一样的。</p><h2 id="apBak">贝尔曼方程</h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726236383612-d803bbb4-c840-4ddf-8c93-7357f06da0a3.png"></p><p>上一节中提到了动作价值函数，那么如何计算，这就需要用到<font style="background-color:#FBDE28;">贝尔曼方程</font>，即$ Q(s,a)&#x3D;R(s)+\gamma \max_{a’}Q(s’,a’) $。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726236581187-25cea284-f4f7-48d0-be8a-b5cc1c723385.png"></p><p>之前我们一直计算的都是最优的情况，但是实际上即使我们做出了最优的决策，但是仍存在可能事情不按照我们的决策进行，因此我们对于未来得到的回报就需要加上一个期望，表示在各种概率下的加权平均。</p><p>对于具体如何计算，可以参考这篇博客，用具体的例子展示了怎么使用贝尔曼方程列出等式并求解。</p><p><a href="https://blog.csdn.net/november_chopin/article/details/106589197">强化学习 1 —— 一文读懂马尔科夫决策过程（MDP）-CSDN博客</a></p><h2 id="aO70C">连续状态应用</h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726649653666-1d559a7e-3237-4b67-adb9-60843bebbdf3.png"></p><p>我们之前讲的全部都是在离散的状态下进行的计算，但是在现实中很多东西都不是离散的，因此我们可以使用一个向量将这些数据作为输入进行计算，例如控制一个直升机，我们就需要有$ x,y,z $三个轴，偏移方向，角速度等。</p><h2 id="MHSDP"><font style="color:rgb(0, 0, 0);">Deep Q-Network</font></h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726650010452-f655730d-7687-4781-bc16-f2226e2b601f.png"></p><p>我们通过将深度学习的神经网络引入强化学习中，通过计算不同的$ Q(s,a) $得到最优的那个。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726651251286-7f2cc463-ebda-4007-bbc9-47141c6c52fe.png"></p><p>我们将状态值和决策设置为$ x $，将计算得到的$ y $设置为标签。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726655233437-6b032134-96d7-4f52-a6c1-bc6cbbec3ded.png"></p><p>在这个算法中，首先随机初始化全部的$ Q(s,a) $函数，接着启动月球登陆器，收集信息，并将其存储在一个回放缓冲区中，接下来训练这个神经网络，我们得到一个新的$ Q_{new} $并使得这个数尽可能的靠近我们的计算值，最终将这个新的$ Q_{new} $设置为新的$ Q $。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726655717999-956d66b9-266b-435a-9d36-5f30ab727937.png"></p><p>在之前的那个网络中我们需要对于每个决策都计算一次，但是我们可以改进这个神经网络的输出层，使得这个输出层可以一次计算四个值。</p><h2 id="JJe8K">$ \epsilon $贪婪策略</h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726656032263-9db4bf2f-2158-4fc5-932a-4c836c32a109.png"></p><p>由于之前的$ Q $值都是随机初始化的，因此我们选择最大值有的时候可能会很糟糕，我们引入了一个新的策略，使用一个超参数$ \epsilon $，使得这个算法可以在探索$ （exploration） $和利用$ （exploitation） $之间进行权衡。我们有$ \epsilon $的可能性不根据最大值选择而是进行不同的尝试。</p><h2 id="KXJ98">小批量和软更新</h2><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726656450338-bd1e49c0-2408-4878-ad7b-2e0ecc72156d.png"></p><p>如果有很多的样本用例，可能是$ 10000000 $，如果一次更新那么在进行梯度下降运算的时候会很麻烦，因此，我们可以划分不同的$ mini-batch $，一次更新$ 32 $个，虽然这样看起来在趋于最小值的过程中显得十分曲折，但是最终也是会到达全局的最小值。</p><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726656683775-51684b5c-19b6-40fa-b78a-98f81f829809.png"></p><p>同时，在我们之前的更新中我们是直接将$ Q_{new} $设置为$ Q $，因此，如果我们训练的$ Q_{new} $并不是很好的话很可能使得$ Q $变得更糟糕，因此我们可以使用软更新，也就是例如上面的$ w,b $，使得新的值占的权重仅仅是一部分而不是全部。</p><h2 id="VWbHt">马尔科夫推导-白板推导版</h2><h3 id="zGvkI">背景介绍</h3><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726150873590-787a3380-d63b-4f5c-aec2-07e0026fe8ff.png"></p><h3 id="CwBPj">动态特性</h3><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726204536895-3c8db483-9bc1-470d-80a9-c042e64e309f.png"></p><h3 id="bIxaM">价值函数</h3><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726223602333-e74a970c-196f-4369-bea2-33f0f3c5f980.png"></p><h3 id="FHJoG">贝尔曼期望方程</h3><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726225565356-8535e491-af85-4123-a481-340f1c957316.png"></p><h3 id="Y4Kgw">贝尔曼最优方程</h3><p><img src="/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/1726227238694-a3ea5ec0-60eb-4912-ad22-a02ce3480e0b.png"></p>]]>
    </content>
    <id>https://yzd11.github.io/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/</id>
    <link href="https://yzd11.github.io/2024/09/18/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
    <published>2024-09-18T10:55:36.000Z</published>
    <summary>了解简单的强化学习</summary>
    <title>强化学习</title>
    <updated>2026-08-22T07:24:29.555Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="推荐系统" scheme="https://yzd11.github.io/categories/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="viaER">引入</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725878076162-33f96ebc-ca0a-4dfc-9f44-ffafb593d31f.png"></p><p>其中$ j $表示用户的编号，$ i $代表电影的编号，最终我们可以使用这个公式预测对于用户$ j $来讲电影$ i $的评分，这个算法有些类似于线性回归，都是将特征值乘上权重加上偏置。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725878289200-615b1075-3d80-4737-8e33-98985df70d58.png"></p><p>$ r(i,j) $：表示用户$ j $是否对于电影$ i $进行评分，$ 1 $代表是，$ 0 $代表否。</p><p>$ y^{(i,j)} $：表示用户$ j $对于电影$ i $的评分，如果存在的话。</p><p>$ w^{(j)},b^{(j)} $：表示对于用户$ j $的权重和偏置</p><p>$ x^{(i)} $：表示电影$ i $的特征向量</p><p>因此对于用户$ j $和电影$ i $来讲，评分为$ \mathrm{w^{(j)}\cdot x^{(i)}+b^{(j)}} $，加入$ m^{(j)} $作为对于用户$ j $评分的电影个数。</p><p>为了更好的学习$ w^{(j)},b^{(j)} $可以通过最小化代价函数进行调整。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725879353125-03f3f9ca-39e1-48bf-9d64-94e6a8bc064d.png"></p><p>这仅仅是对于用户$ j $来讲所有评分电影的参数，为了实现对于全部用户的预测，我们可以将$ m^{(j)} $这个电影个数省略，这仅仅是一个常数，不会影响$ w^{(j)},b^{(j)} $的训练。同时将全部的用户相加，我们就可以训练出全部的参数。</p><h2 id="DPnm8">协同过滤算法</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725881821862-82ece18d-3df0-4c8c-8cb5-060759a2958f.png"></p><p>我们刚刚使用了特征值，但是这些特征值的数据从何而来，我们可以对其进行学习。通过预测$ w,b $类似的算法我们可以对$ x $的值实现类似的预测。那么可能会想到既然可以通过评分对特征值进行预测，那么在之前的线性回归中为什么不这样做，其实是由于这里的评分是多个用户的评分，而在之前的传统机器学习算法中我们仅仅有一个用户，因此不可以对特征值进行学习。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725881969005-d355f68a-ca18-46e8-a9ef-74f5b548a47d.png"></p><p>为了对预测的值进行一个调整，我们可以使用类似的代价函数，只不过这次$ x $成为了参数，在正则化中也是对于$ x $的正则化实现。但是现在又存在一个问题，也就是我们的$ w,b $从何而来呢，我们会想到上一节中我们学习的$ w,b $，因此我们可以将其结合在一起，这就是我们的协同过滤算法。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725882499447-c3a627af-f5be-4798-8ac8-79d00e232ea6.png"></p><p><font style="color:rgb(25, 27, 31);background-color:#FBDE28;">协同过滤</font><font style="color:rgb(25, 27, 31);">，从字面上理解，包括协同和过滤两个操作。所谓协同就是利用群体的行为来做决策(推荐)，生物上有</font><a href="https://zhida.zhihu.com/search?q=%E5%8D%8F%E5%90%8C%E8%BF%9B%E5%8C%96&zhida_source=entity&is_preview=1"><font style="color:rgb(25, 27, 31);">协同进化</font></a><font style="color:rgb(25, 27, 31);">的说法，通过协同的作用，让群体逐步进化到更佳的状态。对于推荐系统来说，通过用户的持续协同作用，最终给用户的</font><a href="https://zhida.zhihu.com/search?q=%E6%8E%A8%E8%8D%90%E4%BC%9A&zhida_source=entity&is_preview=1"><font style="color:rgb(25, 27, 31);">推荐会</font></a><font style="color:rgb(25, 27, 31);">越来越准。而过滤，就是从可行的决策(推荐)方案(标的物)中将用户喜欢的方案(标的物)找(过滤)出来。</font></p><p>将上面两个算法和在一起，我们就可以得到协同过滤算法，也就是同时实现对于$ w,b,x $全部参数值的训练。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725882583136-b3dd6301-8bf2-4732-9193-852543b9786e.png"></p><p>对于这个代价函数的调整，我们还可以使用梯度下降算法，只不过这次的偏置项会增加一个参数$ x $。</p><h2 id="EFMt7">二进制标签</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725884205941-a67bb8ab-a6a1-4c5f-8bf7-f96f5624e3b1.png"></p><p>我们之前是对于评分进行$ 0-5 $之间的划分，现在我们不再使用这种评分而是使用$ 0,1,? $作为标签，分别代表，喜欢，不喜欢和没有被展现。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725884789070-11c2d1a1-7570-4983-8003-be7341252452.png"></p><p>关于$ 0,1,? $的选择，我们可以根据用户在浏览后是否购买，是否浏览时间超过$ 30s $，是否点击，判断用户是否喜欢。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725884931351-ef9223b9-7997-4907-b990-c0094548b14b.png"></p><p>为了实现二进制，我们可以使用之前实现的$ sigmod $函数，将其转化为概率值。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725885220021-08ce2995-4f87-44e1-9f86-e9ea85a06491.png"></p><p>最终，由于使用了$ sigmod $函数，我们无法再使用原先的代价函数，需要使用交叉熵对其计算。</p><h2 id="duUPy">均值归一化</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725886858448-dc73d0b6-b1d1-41c2-b37a-a78f7a662f29.png"></p><p>尽管之前已经实现了均值归一化，但是我们的系统仍存在一些问题，也就是对于那些几乎没有评分的用户来讲，其中平方差为$ 0 $，又由于正则化参数越小越好，最终很有可能导致$ w&#x3D;0,b&#x3D;0 $的训练结果。如果直接使用这个参数对评分进行预测的话，那么就会得到全为$ 0 $的数据，因此，为了解决这个问题，我们提出了均值归一化。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725887330179-d76f67f7-4657-4e35-9f1f-aa2fab6b6ab6.png"></p><p>首先将全部用户的评分合成为一个矩阵，接着计算每一行的均值，得到一个平均值向量$ u $，然后对于每个用户都减去这个向量$ u $，最终我们得到了新的$ y{(i,j)} $，然后再计算预测值的时候将得到的结果加上之前的均值。其实本质上相当于对于原来预测为$ 0 $的评分设置为其他用户评分的平均值，使得预测的结果更加的合理。这样就可以使得对于原来那些评分很少或没有评分的用户的预测值更加的合理。</p><p>这是对于行平均，也可以进行列平均，比如有一部之前从没有上线的电影，由于评分很少，可以使用列平均进行优化，但是这样的效果不如行平均。</p><h2 id="TUxPd">低秩矩阵分解</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725890922756-66dd9c7d-e1d5-48f3-a7a6-a9da39511682.png"></p><p>我们为了更加方便计算实现向量化，将原先的矩阵$ Y $分解为$ \theta^Tx $，这样的方式也被称为<font style="background-color:#FBDE28;">低秩矩阵分解</font>。</p><p><font style="color:rgb(25, 27, 31);">低秩矩阵分解的核心目标是将一个</font><a href="https://zhida.zhihu.com/search?q=%E9%AB%98%E7%BB%B4%E7%9F%A9%E9%98%B5&zhida_source=entity&is_preview=1"><font style="color:rgb(25, 27, 31);">高维矩阵</font></a><font style="color:rgb(25, 27, 31);"> </font>$ M $<font style="color:rgb(25, 27, 31);"> 近似分解为两个较小的矩阵</font>$ A $<font style="color:rgb(25, 27, 31);">和</font>$ B $<font style="color:rgb(25, 27, 31);"> 的乘积。在数学上，这可以表达为 </font>$ M ≈ A × B $<font style="color:rgb(25, 27, 31);">，其中</font>$ M $<font style="color:rgb(25, 27, 31);">是一个</font>$ m × n $<font style="color:rgb(25, 27, 31);">矩阵，</font>$ A $<font style="color:rgb(25, 27, 31);">是</font>$ m × k $<font style="color:rgb(25, 27, 31);">的矩阵，</font>$ B $<font style="color:rgb(25, 27, 31);"> 是</font>$ k × n $<font style="color:rgb(25, 27, 31);"> 的矩阵，而</font>$ k $<font style="color:rgb(25, 27, 31);">（秩）远小于</font>$ m $<font style="color:rgb(25, 27, 31);">和</font>$ n $<font style="color:rgb(25, 27, 31);">。这种分解的目的是减少矩阵的维度，同时保留其主要的特征和结构。</font></p><p>还有一个问题</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725891343916-320e85b6-b6db-48ad-a3ff-c1bb7f2d6bb5.png"></p><p>我们找到一个物品时，通常界面上会推荐类似的物品，为了实现找到类似的物品，我们可以利用我们已经训练好的特征。对于人们来讲，这些特征可能会很难被解释出来，但是我们可以通过计算另外一个电影的特征$ x^{(j)} $和我们已经看过的电影的特征$ x^{(i)} $进行计算，通过计算他们的$ L2 $范数从而得到其中最类似的五个电影推荐给用户。</p><h2 id="LtjlN">补充</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725891750058-301244c4-9245-4766-8a79-785848fa4da6.png"></p><ul><li>冷启动问题</li></ul><p>对于新出的电影或者新的用户，我们如果使用协同过滤算法最终的表现不是很好，即使有均值归一化的帮助。</p><ul><li>使用更多的边信息</li></ul><p>再协同过滤算法中我们仅使用了用户对于电影的评分，但是还有很多的信息，例如用户偏好，电影的主演，等等这些信息都没有被充分利用。</p><h2 id="Wu28p">基于内容过滤</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725935689547-8f54b1be-6645-4b61-ba26-9112a3dbe94f.png"></p><p>通过对比可以看到之前的协同过滤算法仅仅是通过多个用户之前的评分进行预测，而现在我们通过充分利用用户和物品的特征来进行预测，我们仍然具有不同用户的评分，但是现在基于内容过滤更加侧重于利用用户和物品的特征。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725935939290-b825c8e8-b2b8-4ee2-9d8c-06bacccd7bb3.png"></p><p>现在我们通过分析用户和电影的特征，分别得到$ x_u^{(j)} $，$ x_m^{(i)} $，这两个向量的大小可以并不相同，甚至差距很大。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725936091823-961390d3-1d00-4691-bfc6-965467e3ecd9.png"></p><p>再基于内容的过滤中不再使用偏置项，同时将$ w,x $修改为$ V_u^{(j)} $，$ V_m{(i)} $。将这两个进行点积，但是注意$ x_u^{(j)},x_m^{(i)} $的大小可以不同，但是得到的$ V_u^{(j)} $，$ V_m{(i)} $的大小一定要相同。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725937982501-323410dc-a591-4171-a7b7-46c9b80c4589.png"></p><p>为了得到$ V_u^{(j)} $，$ V_m{(i)} $，可以使用神经网络进行深度学习，然后将得到的值进行内积，同时通过$ sigmod $函数计算概率值。注意，隐藏层的神经元个数可以任意，但是输出层的神经元个数这两个神经网络一定要相同。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725938095823-92d7037c-d153-45b0-b01d-0f95c4f1aba7.png"></p><p>再计算这个神经网络的参数时，通过最小化之前的代价函数，同时进行正则化，最终得到$ V_u^{(j)} $，$ V_m{(i)} $。同时可以使用这两个参数进行相似值的寻找。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725938256152-4cfe5567-29ff-4907-9a9e-d9a34db21266.png"></p><p>我们可以使用之前提到的$ L2 $范数，进行计算找到类似的电影，这种方法可以提前计算，例如在用户访问之前提前在服务器上进行计算，当用户看完当前电影之后可以为用户提供推荐。</p><h2 id="YbQfl">大型目录推荐</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725939901725-93d6d82c-2369-4ef7-aae8-2113b543c180.png"></p><p>在我们为用户进行推荐的时候如果对每个项目都进行评估，需要的计算量一定是相当巨大的，因此可以通过先检索再评分的方式。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725940030755-6285cd8c-0b95-499e-831f-912a3a40481e.png"></p><p>在进行检索时，可以选择根据用户最近看的$ 10 $个电影进行推荐类似的电影，或者选择用户最常看的三个分类中的$ Top 10 $，或者选择用户所在地区$ Top20 $的电影。最后将这些合在一起去除重复和看过的，合成一个列表给用户。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725940228790-ea506be2-567b-4aeb-9700-324f9d3e8451.png"></p><p>在进行排名时，将刚刚得到的列表放入训练模型中，将得到的内积作为评分，为用户形成一个排名表。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725940316850-a4df9a91-4bfa-47ed-ac3d-55eba70a6828.png"></p><p>在检索中，虽然选择更多的项目数可以得到更好的表现，但是会降低推荐速度。为了分析&#x2F;优化权衡，可以通过离线学习来查看检索更多项目是否会导致更相关的推荐（即，显示给用户的项目中$ p(y) &#x3D; 1 $的概率更高）。</p><h2 id="dILnl">在线学习</h2><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725969906603-52dbb4c4-043b-40b8-a3f1-a73d4bbda57a.png"></p><p>对于一个连续变化的数据集，我们现在可以具有更好的处理方法，也就是将其中的样本仅使用一次，然后丢弃，不再使用固定的训练集。因为我们具有连续不断的数据集，因此可以随着用户的偏好进行随时的调整，这种方法也被称为在线学习。</p><p>于此对应，还有一种方法称为离线学习。</p><p>离线学习，类似于批量学习，每次训练一批数据，直至跑完整个样本，这个时候误差率可能不让你满意，把整个样本又做个上述操作，直至误差很小。离线学习是一个$ batch $训练完才更新权重，因此要求所有数据必须在每一个训练训练操作中$ batch $中都是可用的，这样不会因为个别数据的更新错误把网络带向极端。</p><p>简单的讲：</p><p><font style="background-color:#FBDE28;">在线学习</font>：一个样本训练完，直接更新权重。</p><p><font style="background-color:#FBDE28;">离线学习</font>：一个样本进入，跑完整个样本才更新权重。</p><h2 id="iUnFj">主成分分析PCA</h2><p>大多数时候我们选择的特征不仅仅是两三个，可能是$ 10,20,50,1000 $，这样的话，我们无法做到对人们展示一个二维或者三维的图像。因此我们需要讲这些大量的特征简化为两个或者三个，更好对用户展示，这种方法可以被称为$ PCA（principal components analysis） $即 主成分分析。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725972171244-5c3ee2e9-df29-4f56-b145-fd9c1a3df87f.png"></p><p>图中这种情况，我们有两个特征，一个是长度，一个是宽度，但是宽度几乎不变，但是长度变化很大，因此我们可以选择仅使用长度作为我们需要的特征。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725972512973-b9ad168c-d76d-41db-ab3e-bc91b10bbd6c.png"></p><p>但是在这个图中，车子的高度和长度都有很大的变化。因此，我们可以再加上一个轴$ z $，作为新的特征值，这样就可以使用一个特征代表之前的两个特征。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725974710530-85dee3ef-c88e-43a8-9bcd-109b92eb2168.png"></p><p>如果选择之前的$ x $轴作为新的$ z $轴，那么我们仍能在新的轴上得到很大的方差。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725974840740-b1cc5219-2e35-4709-b5db-62ca5ce7e35d.png">稍微进行一下调整，现在得到的$ z $轴上仅保留了很小的方差。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725974919755-e5a2ded1-4d68-4b2f-8c62-adf55d54eb2d.png"></p><p>在进行一次调整，我们可以得到最大的方差，那么现在的$ z $轴就可以作为我们的主成分。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725975008196-66dd52ac-a05e-41ff-b23c-6abe394ec8a2.png"></p><p>现在我们既然找到了主成分，可以讲原先两维的数据转换为一维，也就是改变基向量，将原先在$ x,y $坐标轴上斜长度为$ 1 $的向量作为新的坐标轴的基向量，也就是$ [0.71,0.71]^{T} $。接着将原先在$ x,y $上的坐标和基向量做内积，最终我们可以得到在新的轴上的新特征值$ 3.55 $。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725975349490-e4e80c6e-708a-43a5-9336-8e9e6b561c35.png"></p><p>现在我们已经得到了其中的一个基向量$ z_1 $，接着找的这个基向量的垂直向量$ z_2 $，如果是要形成一个三维的可视化图形的话，我们可以在加上一个向量$ z_3 $，垂直于前两个$ z_1,z_2 $。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725975531687-9fd53e37-a2af-4dc0-82ea-b0ceafc9df91.png"></p><p>似乎看起来$ PCA $和之前学到的线性回归很类似，但是实际上两者完全不一样，线性回归是最小化预测值和实际值之间基于$ y $轴的距离，但是$ PCA $则是最小化它们之间的垂直距离，或者说是增大他们分布的方差。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725976200966-2f85bacb-9c0c-4ff3-acd0-bc0302b7b225.png"></p><p>从直观上来看，显然我们投影的距离越短，那么两点的分布也就越远，同时也就更更好的代表原始的数据。</p><p>从数学推导上来看，参照：</p><p><a href="https://www.cnblogs.com/pinard/p/6239403.html">主成分分析（PCA）原理总结 - 刘建平Pinard - 博客园</a></p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725976366879-68909f4e-efaa-4a7a-90e2-9b712ab8cc6f.png"></p><p>那么如何将新的坐标转换为原先的基向量下的坐标，需要将新的坐标乘上新的基向量，可以得到一个近似的估计。</p><p><img src="/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/1725977097046-5cf3b6e2-4a89-4b4a-b346-0b6210a4f221.png"></p><p>$ PCA $还有别的应用在其他的方面，例如数据压缩，加速监督学习，但是现在几乎已经不用了，更多的还是用于可视化中。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/</id>
    <link href="https://yzd11.github.io/2024/09/10/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/"/>
    <published>2024-09-10T14:06:10.000Z</published>
    <summary>了解简单的推荐系统</summary>
    <title>推荐系统</title>
    <updated>2026-08-22T07:24:29.561Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="HKkCH">机器学习定义</h2><p>Field of study that gives computers that ability to learn without being explicitly programmed.</p><h2 id="o0lfv">机器学习算法</h2>+ Supervised learning<p>used most in real-wold applications</p><ul><li>Unsupervised learning</li><li>Reinforcement Learning</li></ul><h2 id="Nrvhd">监督学习 part1</h2>目的：学习输入到输出的映射的统计规律<p><img src="/2024/09/09/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%88%86%E7%B1%BB/1721359890639-6c8bc1ba-d947-4a8f-9a5f-e9db97257837.png"></p><p><strong>回归问题：房价预测</strong></p><p><img src="/2024/09/09/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%88%86%E7%B1%BB/1721362979564-11e98232-a3fa-4bcb-981a-da103cde4fd4.png"></p><p>目的：从无限多的可能输出中预测一个数字（输入和输出是连续的）</p><h2 id="AuZ3k">监督学习 Part2</h2>**分类问题：乳腺癌检查**<p><img src="/2024/09/09/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%88%86%E7%B1%BB/1721363852707-43bbdc71-89bb-40ab-a58e-87de0c30ae97.png"></p><p>目的：从少量可能的输出中预测类别（输入和输出是离散的）</p><p>区分：</p><p><img src="/2024/09/09/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%88%86%E7%B1%BB/1721364011557-e3334628-3664-47a6-9ae0-fb4d6c9936d1.png"></p><h2 id="Sn9rS">无监督学习</h2>目的：学习数据中的统计规律或潜在结构，相比较于监督学习，训练数据仅具有输入数据，没有输出数据<p><strong>聚类问题：DNA microarray</strong></p><p><img src="/2024/09/09/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%88%86%E7%B1%BB/1721366510957-850f76de-bbb3-4476-829a-adf469bdd698.png"></p><p>目的：将相似的样本分到相同的类，不相似的样本分到相同的类</p><p>除此之外，在无监督学习中还有降维问题和概率模型估计问题，异常检测问题，在接下来将详细介绍</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/09/09/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%88%86%E7%B1%BB/</id>
    <link href="https://yzd11.github.io/2024/09/09/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%88%86%E7%B1%BB/"/>
    <published>2024-09-09T11:52:43.000Z</published>
    <summary>机器学习介绍</summary>
    <title>机器学习分类</title>
    <updated>2026-08-22T07:24:29.564Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="I4uA5">异常检测算法</h2><p><img src="/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/1725539104094-aae6a8bf-ff39-423a-b48f-48640708397b.png"></p><p>第一步：</p><p>选择要检测的特征和样本数据。</p><p>第二步：</p><p>计算不同特征对应的均值和方差。</p><p>第三步：</p><p>计算每个特征的概率并进行连乘。</p><h2 id="qZ5aR">评估异常检测系统</h2><p><img src="/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/1725540019256-90737953-8134-46c4-b0e9-d474820860f4.png"></p><p>对于这个例子，我们假设一个标签对其进行判断，在训练集中仍然仅使用未标注的数据，但是在交叉验证集和测试集上加上标签并将数据集中标注为有缺陷的数据放入，虽然训练集中没有加上标签，但是我们假设他们默认都是正常的，即使其中存在有缺陷但是未被发现的也不会影响最终的模型。</p><p>因为我们的训练集仍然是无标签的，因此这仍然是无监督学习，同时如果我们事先知道的缺陷数量过少的话，可以省略测试集，将仅有的缺陷数据全部放入交叉验证集中。</p><h2 id="BfXgy">异常检测VS监督学习</h2><p><img src="/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/1725540758155-830683eb-928f-411d-b7b1-54f3ad7458f1.png"></p><p>异常检测：</p><p>有大量的正常数据，但是仅有少部分的异常数据</p><p>更倾向于应对无法预知的情况，例如飞机制造，我们无法确定未来会有什么问题，可以是发动机问题，可能是雷达问题，对于这种无法确定异常特征的情况，更适合用于异常检测，因为我们是使用正常的数据作为训练集，同时根据异常数据和正常数据的不同来确定。</p><p>监督学习：</p><p>用大量的正常数据和异常数据，可以知道经常是那些地方会出问题，例如垃圾邮件判断，我们需要的特征是基本不会改变的，与此相反，对于诈骗来讲，欺诈的方式不断的变化，我们无法固定因此更倾向使用异常检测的方式。</p><h2 id="FgVKC">特征选择</h2><p><img src="/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/1725541775240-2329f186-18a6-4a01-bdf1-5a8c171e01e0.png"></p><p>对于选择的特征来讲，可以绘制出它的分布图，然后通过分布图判断其是否符合高斯分布，如果不符合可以对其进行一些调整，例如开方，取对数等等，使其更加符合高斯分布。</p><p><img src="/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/1725541906748-023cc8d5-247a-45ff-9cb3-2dbf1b63e254.png"></p><p>如果存在交叉验证集中的数据属于异常数据，但是它的$ P $却不是很小，那么可以进行错误分析，将其被作为异常数据原因作为新的判断特征。例如一个人在进行交易的时候别的特征都很正常，但是打字的速度却非常快，那么就可以将这个特征作为新的特征。</p><p><img src="/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/1725542231311-596f5924-4451-4c9f-9ff7-97fd84f89384.png">‘</p><p>也可以将不同的特征进行组合，使得其在正常的样例中的$ P $很大，但是对于异常样例很小。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/</id>
    <link href="https://yzd11.github.io/2024/09/05/%E5%BC%82%E5%B8%B8%E6%A3%80%E6%B5%8B/"/>
    <published>2024-09-05T13:18:34.000Z</published>
    <summary>了解异常检测算法</summary>
    <title>异常检测</title>
    <updated>2026-08-22T07:24:29.553Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="gokuz">模型评估</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723807341718-347ba59b-36e7-4a1e-ab7e-b8156d75b2ef.png"></p><p>我们对于一个数据集进行划分，将其中$ 70% $的数据划分为训练集，将剩余$ 20% $的数据划分为测试集。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723807617835-0fce2e8e-1c33-4bc9-ba28-b700be808f2a.png"></p><p>对于一个线性回归模型，我们得到了这三个公式，其中$ J(\vec{w},b) $是表示代价函数，$ J_{test}(\vec{w},b) $代表测试集的误差，$ J_{train}(\vec{w},b) $代表训练集的误差。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723807826400-275630a1-e265-4c96-b6b5-ae4ea61e70f0.png"></p><p>我们可以使用$ J_{test}(\vec{w},b) $和$ J_{train}(\vec{w},b) $来衡量该模型在测试集和训练集上的表现，显然对于这个过拟合的曲线，它在训练集的表现很好，但是在测试集上的表现很糟糕。</p><h2 id="VUEmn">交叉验证</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723815245064-cda73662-b8f4-47fa-bb99-7dd754dac8fc.png"></p><p>我们前面讲到将数据集划分为训练集和测试集，训练集用于确定$ w,b $，验证集用于选择模型，确定一个合适的超参数$ d $和判断是否过拟合。但是由于测试集已经多次参与到了数据的拟合中，因此最终得到的泛化误差是过于乐观的，可能小于实际的误差值。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723815831366-4e2ec0a8-37a2-44a7-90d5-90c13907a67a.png"></p><p>我们引入了一个新的概念-交叉验证集（也称为验证集，开发集），同时对于数据集进行重新划分，我们将其中的$ 60% $作为训练集，将剩下的$ 40% $分别各分一半作为验证集和测试集。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723865380903-77320bf6-9269-439a-a2ab-df9f546b12ca.png"></p><p><font style="color:rgb(64, 64, 64);background-color:rgb(252, 252, 252);">然后在训练集上训练模型，在验证集上选择模型，最后用测试集上的误差作为泛化误差的估计。我们可以在验证集上反复尝试不同的参数组合，当找到一组满意的参数后，最后在测试集上估计模型的泛化能力。</font></p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723815986928-b0f011de-0491-41c7-835c-4a0112d1f6d0.png"></p><p>我们通过训练集训练数据，确定$ w,b $，同时使用验证集选择模型，确定超参数层数和隐藏的神经元个数以及是否过拟合，最终我们使用没有用过的测试集得到一个泛化误差。</p><h2 id="MIohY">偏差和方差</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723816836399-b0a447c9-93ed-4bfc-9c58-31f1c47a4356.png"></p><p>对于欠拟合，我们的模型在训练集和验证集上表现很糟糕，属于高偏差的情况。而对于过拟合，我们的模型在训练集上的表现很好，但是在验证集上的表现很糟糕，属于高方差。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723817100177-f3d21ecb-c7af-4203-84a1-973e0aa58740.png"></p><p>当$ J_{train} $过高，同时$ J_{train}&#x3D;J_{cv} $，那么就属于高偏差（欠拟合），当$ J_{cv}&gt;&gt;J_{train} $时，就属于高方差（过拟合）。当$ J_{train} $过高，同时$ J_{cv}&gt;&gt;J_{train} $，那么就是同时出现了高偏差和高方差，在程序中可能前半段的输入过拟合，后半段欠拟合，这种情况就会导致最终呈现高偏差和高方差。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723865578461-620b94bc-7c69-44a1-9f43-0b531f451c82.png"></p><p>我们可以看到，正则化参数$ \lambda $的大小也会影响偏差和方差的值，同时与之前的多项式系数的图像成镜像关系。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723887190890-0f4782fe-8b8a-428e-a70f-0cd10e982228.png"></p><p>我们在对训练的结果进行判断的时候要和基准线的表现相比较，将$ J_{train} $和基准线相比较，来判断是否高偏差，将$ J_{train} $和$ J_{cv} $相比较，判断是否高方差。</p><h2 id="lCymw">学习曲线</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723893902788-af3357ce-c042-4882-a1af-f93b67ef75e6.png"></p><p>对于上图的学习曲线，$ J_{cv} $是从大到小，而$ J_{train} $是从小到大，当仅有一个时是没有误差的，随着训练集样本的增加，我们的曲线的偏离也逐渐增大。同时$ J_{cv} $的值在普遍情况下都是大于$ J_{train} $的值。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723894137813-d2851223-e127-4c63-a5f0-4d21730cf452.png"></p><p>对于高偏差的情况，即使我们不断增大训练集的容量，但是我们的$ J_{cv} $和$ J_{train} $都无法降低到和人类的表现水平相同，仍远高于这个水平。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723894907701-1a95ddbf-f958-4e39-b77a-cb16db58a9fc.png"></p><p>对于高方差的情况，随着我们对于训练集容量的提高，可以看到这将有利于我们的$ J_{cv} $和$ J_{train} $达到相接近的水平。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723897566852-a55d2e63-d397-4f00-a144-ab2905ab7db2.png"></p><p>对于高偏差，我们可以使用增加特征，提高多项式的次数，减少正则化系数$ \lambda $等一系列方法。</p><p>对于高方差，我们可以增大训练集的容量，减少特征，增大正则化系数$ \lambda $等一系列方法。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723898059891-3a43357b-9652-4802-b5c2-483f0f2a80a5.png"></p><p>如果我们的模型太复杂就会导致高方差，如果太简单就会导致高偏差，为了在高偏差和高方差之间找到一个平衡点，我们可以按照这个顺序来进行调整。我们知道只要训练集的规模不算太大，那么在一个大型的神经网络上总是一个低偏差的状态，因此当我们的$ J_{train} $过大时就要增大神经网络的大小，直到可以在训练集上表现良好。接着如果在验证集上表现糟糕，那么就可以增大训练集的容量，同时回到第一步使得在训练集上表现良好，这样周而复始最终得到一个低偏差和低方差的结果。</p><p>当我们在扩大神经网络的时候只要选择了合适的正则化方法也不会导致方差的增大。</p><h2 id="f3N9o">机器学习开发的流程</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723983706369-88d3ffe6-9a33-4d0d-97b7-e6687678ef19.png"></p><p>首先选择一个合适的模型，包含一些超参数和数据集的选择。接着进行模型的训练，根据训练的结果反向调整参数，通过偏差和方差大小的判断，重新对模型进行调整。</p><h2 id="vRBQZ">误差分析</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723983975983-a3d06e41-b115-476d-bc41-d09ee535dd84.png"></p><p>我们对于验证集的$ 500 $个样例中的$ 100 $个被错误分类的样例进行分析。可以看到其中大部分都是由于医药邮件和窃取信息的邮件出现了错误分类，而对于故意的拼写错误很少，因此我们应该将中重点放在出现错误最多的地方。</p><h2 id="kUT1F">数据增强</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723985011541-ac7d1d3d-27c6-4f6c-aa6a-c56438728c08.png"></p><p>对于图像识别问题，我们可以通过将原本数据集进行扭曲和调整对比度形成新的数据。对于语音识别功能，我们可以添加一些噪音。但是如果添加一些完全随机或者没有意义的噪音对于数据的训练帮助不大。</p><h2 id="lOcaF">迁移学习</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723985167977-4a97c766-9bf1-4aea-a853-b4aac2a56a3b.png"></p><p>对于一些训练数据不够的情况，我们可以使用网上已经训练完成的模型，这被称为<font style="color:#00346B;background-color:#FBDE28;">预训练模型</font>。接着我们可以使用预先训练好的模型的参数作为初识参数，在训练的过程中进行调整，这个过程就被称为<font style="background-color:#FBDE28;">微调</font>。</p><p>对于数据量不足的情况，我们可以选择仅训练输出层，根据自己的训练集对输出层函数进行调整。</p><p>对于数据量足够的情况，我们可以选择从头开始训练全部的参数。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723986336058-f6184bdd-a07b-4655-a16d-e12a73b942eb.png"></p><p>对于迁移学习的可行性，我们参照这个四层的神经网络可以看到，第一个隐藏层是在提取一些微小的边的特征。第二层是在提取一些角落特征，第三层是在提取一些曲线特征。因此我们可以看到对于图像识别问题，前几层所提取的信息，无论是对于车辆识别还是数字识别来讲，都是类似的，我们可以仅调整最后一层的输出，使得符合我们自己训练的数据集。</p><p>同时需要注意的是，我们的输入的类型都要是相同的，对于图形处理的预处理模型我们不可以拿来进行语言模型的训练。</p><h2 id="MeBRM">机器学习项目的完整流程</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723987473893-56823fc7-061c-4839-b753-78dad9cdf28c.png"></p><p>第一步，我们需要确定我们的项目本身和我们应该做些什么。</p><p>第二步，我们应该收集数据和贴上相应的标签。</p><p>第三步，我们应该对模型进行训练，同时根据训练的结果选择是否要收集更多的数据。</p><p>第四步，我们将项目部署在服务器上，通过使用其中的数据可以优化系统性能，同时当我们的模型无法很好的工作的时候可以选择重新训练一个新的模型来替代原有的模型。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723987766728-6a759fe3-a46f-4983-98fc-366371af0672.png"></p><p>我们在进行项目的部署的时候，可以将其部署在服务器上，我们的应用程序软件可以通过调用提供的API接口使用这个模型所提供的服务。</p><h2 id="TMq86">倾斜数据集的误差指标</h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723989146602-98fcf17e-8129-4f99-b6a5-68f922357c5b.png"></p><p>对于上述这个很倾斜的数据集，由于呈现阳性的概率只有$ 0.5% $，因此一个只会打印$ print(‘’y&#x3D;0’’) $的愚蠢算法，实际上的准确率也会比我们的仅有$ 1% $错误率的算法要高，因此仅仅依靠准确率来对于这种数据集进行评估是不公平的，我们需要引入<font style="background-color:#FBDE28;">精准率</font>和<font style="background-color:#FBDE28;">召回率</font>。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723989539765-8cf982f2-d767-4278-b603-2f45b659ecbc.png"></p><p>首先绘制一个$ 2\times 2 $的矩阵，我们称之为混淆矩阵。根据这个矩阵，我们可以计算出两个值。</p><p>精准率：$ \frac{TP}{TP+FP} $，<font style="color:rgb(77, 77, 77);">这代表在你预测为真的事件中，有多少预测正确。</font></p><p>召回率：$ \frac {TP}{TP+FN} $<font style="color:rgb(77, 77, 77);">，这代表在所有真事件中，你预测正确的占多少。</font></p><p><font style="color:rgb(77, 77, 77);">高精准率代表预测为阳性的患者很大概率是真的，高召回率代表为一个称阳性的患者可以被检测到。</font></p><p><font style="color:rgb(77, 77, 77);">如此，对于之前仅预测为假的算法，它的精准率和召回率都是为</font>$ 0 $<font style="color:rgb(77, 77, 77);">。</font></p><h2 id="LDFnN"><font style="color:rgb(77, 77, 77);">精准率和召回率</font></h2><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1723990924299-60073db9-1a4e-4d8d-b9ff-3863bb5e987f.png"></p><p>对于逻辑回归问题来讲，当我们提高阈值，那么我们的精准度就会上升，但是召回率就会下降，相反，如果降低阈值，那么我们的精准度就会下降，但是召回率就会上升，因此我们需要通过手动的方式选择一个合适的阈值。</p><p><img src="/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/1724054588075-7d3e5c3e-6f25-4659-b2a9-6f7fec4cae13.png"></p><p>为了更好的权衡精准率和召回率，我们选择使用一个$ F1 $分数，而不是简单的平均数。</p><p>使用$ F1\mathrm{~score}&#x3D;\frac{1}{\frac{1}{2}{(\frac1P+\frac1R)}}&#x3D;2\frac{PR}{P+R} $，这样得到的结果更加偏向比较小的值，这也被称为调和平均数。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/</id>
    <link href="https://yzd11.github.io/2024/09/05/%E6%A8%A1%E5%9E%8B%E9%80%89%E6%8B%A9%E4%B8%8E%E8%AF%84%E4%BC%B0/"/>
    <published>2024-09-05T12:39:29.000Z</published>
    <summary>模型选择与评估的技巧</summary>
    <title>模型选择与评估</title>
    <updated>2026-08-22T07:24:29.567Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="FVGx5">什么是聚类</h2><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725412829969-2db3611a-fc00-42d4-9a5d-ae748aab46ee.png"></p><p>我们之前的训练数据都是一个特征对应一个标签，但是对于无监督学习来讲，仅需要数据本身，不需要添加标签。</p><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725412965868-50ba6b8c-2170-416f-a225-a06309ec6f39.png"></p><p>这种聚类算法可以被用于市场划分，新闻消息分组，$ DNA $检测，天文数据分析。</p><h2 id="YflyT">k-means的直观理解</h2><p>对于$ k-means $可以分为两步进行。</p><p>第一步：</p><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725413156540-a35c5226-8057-4b2d-95b0-cf253fff01d9.png"></p><p>随机选择两个点作为簇质心，接着遍历每一个点，根据距离最近的质心，分别设置为不同的簇。</p><p>第二步：</p><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725413348615-9256f3cd-91a7-4783-b948-4bf8c96d645e.png"></p><p>接着根据划分的点，计算他们的平均值，然后将之前的质心位置移动到新的平均值位置，重复第一步，最终直到计算平均值和质心的位置相同为止。</p><h2 id="prE6i">k-means算法</h2><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725439465603-90f54db4-f23a-4cd7-b94e-cb3442c1b972.png"></p><p>首先初始化$ k $个簇质心，接下来还是和之前的算法步骤相同，重复进行分配和移动质心的位置，最终使得质心保持不动。</p><p>需要注意的是一种特殊情况，如果出现了其中一个质心没有被分配到任何数据，那么也就无法进行调整，对于这种情况通常是将这个簇删除，但是如果一定要保持$ k $个簇，也可以将簇质心重新随机分配。</p><h2 id="HuriS">优化目标</h2><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725498342096-3b29a1d7-69b7-4d4b-9ce0-f0590e549863.png"></p><p>我们首先定义几个变量</p><p>$ c^{(i)} $：当前点被分配的簇的下标</p><p>$ u_k $：簇的质心</p><p>$ u_{c^{(i)}} $：当前点被分配的簇的质心</p><p>根据这些变量我们可以得到这个失真代价函数：$ J\left(c^{(1)},…,c^{(m)},\mu_1,…,\mu_K\right)&#x3D;\frac1m\sum_{i&#x3D;1}^m\left|x^{(i)}-\mu_{c^{(i)}}\right|^2 $ </p><p><strong><font style="color:rgb(0, 0, 0);">为什么迭代后误差逐渐减小：</font></strong></p><p><font style="color:rgb(0, 0, 0);">对于</font>$ u_{c^{(i)}} $<font style="color:rgb(0, 0, 0);">而言，求导后，当</font>$ u_{c^{(i)}}&#x3D;\frac{\sum{x_i}}{m} $<font style="color:rgb(0, 0, 0);">时，代价函数最小，对应第二步；</font></p><p><font style="color:rgb(0, 0, 0);">对于</font>$ x^{(i)} $<font style="color:rgb(0, 0, 0);">而言，求导后，当</font>$ x^{(i)}&#x3D;c^{(i)} $<font style="color:rgb(0, 0, 0);">时，代价函数最小，对应第一步。</font></p><p><font style="color:rgb(0, 0, 0);">因此</font>$ k-means $<font style="color:rgb(0, 0, 0);">迭代能使误差逐渐减少直到不变</font></p><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725498763758-fe3bf4c3-54c3-42ed-ad7f-a03a8c63ef2d.png"></p><p>在第一步中我们为每个点选择更近的那个簇质心，使得可以减少差值。</p><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725498855749-feefa713-ab16-4071-93e3-73c269a9a01d.png"></p><p>在第二步中我们将簇质心移动到中间点的位置，使得可以减少差值。</p><h2 id="y5Raq">初始化k-means</h2><ul><li>随机初始化</li></ul><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725499682142-cea76b54-ea25-4b01-ae93-abd580e76059.png"></p><p>由于我们之前的初始化点都是完全随机的，不同的初始化点对于算法的收敛速度有很大的影响，因此我们可以通过多次初始化得到一个最好的初始化结果。</p><p>第一步：选择$ k $个样本点作为初始化的簇质心。</p><p>第二步：运行$ k-means $算法，得到每个点分配的簇质心并计算代价函数。</p><p>第三步：通过多次循环，得到一个代价函数最小的值作为初始化的$ k-means $</p><ul><li>$ K-Means++ $</li></ul><p>$ K-Means++ $的对于初始化质心的优化策略也很简单，如下：</p><p>$ a) $  从输入的数据点集合中随机选择一个点作为第一个聚类中心$ μ_1 $<br>$ b) $ 对于数据集中的每一个点$ x_i $，计算它与已选择的聚类中心中最近$s$ 聚类中心的距离</p><p>$D(x_{i}) &#x3D; argmin||x_{i}-\mu_{r}||_{2}^{2}$ </p><p>$r &#x3D; 1,2\ldots k_{selected}$</p><p>$ c) $ 选择一个新的数据点作为新的聚类中心，选择的原则是：$ D(x) $较大的点，被选取作为聚类中心的概率较大<br>$ d) $ 重复$ b $和$ c $直到选择出$ k $个聚类质心<br>$ e) $ 利用这$ k $个质心来作为初始化质心去运行标准的$ K-Means $算法</p><h2 id="UIzB9">选择聚类数量</h2><ul><li>肘部法则</li></ul><p><img src="/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/1725527220827-68f33f45-29ff-4095-b2d8-d3acf00a5467.png"></p><p>我们可以画出关于$ k $的代价函数图像，然后选择一个最明显的拐点，由于和人的肘部很像，因此也被称为肘部法则，但是这种方法并不是非常好用，因为像右侧的图像中代价函数的下降并不是非常陡峭无法直接判断合适的$ k $值。</p><ul><li>轮廓系数法</li></ul><p><font style="color:rgb(0, 0, 0);">轮廓系数</font>$ （Silhouette Coefficient） $<font style="color:rgb(0, 0, 0);">结合了聚类的凝聚度</font>$ （Cohesion） $<font style="color:rgb(0, 0, 0);">和分离度</font>$ （Separation） $<font style="color:rgb(0, 0, 0);">，我们希望簇内更加聚合，簇间更加分散，用于评估聚类的效果。该值处于</font>$ -1\sim1 $<font style="color:rgb(0, 0, 0);">之间，值越大，表示聚类效果越好。具体计算方法如下：</font></p><ol><li><font style="color:rgb(0, 0, 0);">对于每个样本点</font>$ i $<font style="color:rgb(0, 0, 0);">，计算点</font>$ i $<font style="color:rgb(0, 0, 0);">与其同一个簇内的所有其他元素距离的平均值，记作</font>$ a(i) $<font style="color:rgb(0, 0, 0);">，用于量化簇内的凝聚度。</font></li><li><font style="color:rgb(0, 0, 0);">选取</font>$ i $<font style="color:rgb(0, 0, 0);">外的一个簇</font>$ b $<font style="color:rgb(0, 0, 0);">，计算</font>$ i $<font style="color:rgb(0, 0, 0);">与</font>$ b $<font style="color:rgb(0, 0, 0);">中所有点的平均距离，遍历所有其他簇，找到最近的这个平均距离,记作</font>$ b(i) $<font style="color:rgb(0, 0, 0);">，即为</font>$ i $<font style="color:rgb(0, 0, 0);">的邻居类，用于量化簇之间分离度。</font></li><li><font style="color:rgb(0, 0, 0);">对于样本点</font>$ i $<font style="color:rgb(0, 0, 0);">，轮廓系数</font>$s(i)&#x3D;{\frac{(b(i)-a(i))}{max{a(i),b(i)}}}$</li><li><font style="color:rgb(0, 0, 0);">计算所有</font>$ i $<font style="color:rgb(0, 0, 0);">的轮廓系数，求出平均值即为当前聚类的整体轮廓系数，度量数据聚类的紧密程度</font></li></ol><p><font style="color:rgb(0, 0, 0);">从上面的公式，不难发现若</font>$ s(i) $<font style="color:rgb(0, 0, 0);">小于</font>$ 0 $<font style="color:rgb(0, 0, 0);">，说明</font>$ i $<font style="color:rgb(0, 0, 0);">与其簇内元素的平均距离大于最近的其他簇，表示聚类效果不好。如果</font>$ a(i) $<font style="color:rgb(0, 0, 0);">趋于</font>$ 0 $<font style="color:rgb(0, 0, 0);">，或者</font>$ b(i) $<font style="color:rgb(0, 0, 0);">足够大，即</font>$ a(i)&lt;&lt;b(i) $<font style="color:rgb(0, 0, 0);">，那么</font>$ s(i) $<font style="color:rgb(0, 0, 0);">趋近与</font>$ 1 $<font style="color:rgb(0, 0, 0);">，说明聚类效果比较好。</font></p><ul><li>$ Calinski-Harabasz $<font style="color:rgb(0, 0, 0);">法</font></li></ul><p><font style="color:rgb(0, 0, 0);">                                                  </font>$ s(k)&#x3D;\frac{tr(B_k)}{tr(W_k)}\frac{m-k}{k-1} $</p><p>　其中$ m $为训练集样本数，$ k $为类别数。$ B_k $为类别之间的协方差矩阵，$ W_k $为类别内部数据的协方差矩阵。$ tr $为矩阵的迹。</p><p>$$ B_k&#x3D;\sum_{q&#x3D;1}^kn_q(c_q-c_e)(c_q-c_e)^T<br>  \newline  W_k&#x3D;\sum_{q&#x3D;1}^k\sum_{x\in C_q}(x-c_q)(x-c_q)^T $$          </p><p>其中$ c_q $表示类$ q $的中心点，$ c_e $表示数据集的中心点，$ n_q $表示类$ q $中的数据的数目，$ C_q $表示类$ q $的数据集合。</p><p>也就是说，类别内部数据的协方差越小越好，类别之间的协方差越大越好，这样的$ Calinski-Harabasz $分数会高。</p>]]>
    </content>
    <id>https://yzd11.github.io/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/</id>
    <link href="https://yzd11.github.io/2024/09/05/%E8%81%9A%E7%B1%BB%E7%AE%97%E6%B3%95/"/>
    <published>2024-09-05T11:43:12.000Z</published>
    <summary>了解聚类算法</summary>
    <title>聚类算法</title>
    <updated>2026-08-22T07:24:29.573Z</updated>
  </entry>
  <entry>
    <author>
      <name>yzd</name>
    </author>
    <category term="机器学习" scheme="https://yzd11.github.io/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <category term="Machine Learning" scheme="https://yzd11.github.io/tags/Machine-Learning/"/>
    <content>
      <![CDATA[<h2 id="j7z1U">引入</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724056656621-5243b457-9280-4eb2-92af-43b50d1eb973.png"></p><p>我们引入一个新的模型-决策树，通过这个二叉树我们可以实现对于猫的分类，从根节点出发，判断每个节点是还是否，最终我们在叶子节点得到结果。</p><h2 id="PYoeY">学习过程</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724057265159-77bde0cb-e400-4bc2-88cc-6fce126b516f.png"></p><p>第一步：决定每个节点应该使用什么特征，尽量使得分离后的纯度更大或者杂质更少。</p><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724057659778-0d3d08ff-51d5-4a87-aea1-b40b7edf66e3.png"></p><p>第二步：决定什么时候停止。可以分为以下四种情况：</p><ul><li>当一个节点的纯度达到$ 100% $</li><li>当一个节点的深度超过我们限制的最大深度</li><li>当继续分裂的提高值小于一个阈值时</li><li>当这个节点的纯度达到一个阈值时</li></ul><h2 id="Fx3Ht">信息熵</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724064847868-3690c079-85e0-49cb-b168-f0dd41679d7f.png"></p><p>为了说明纯度，我们引入了熵这个概念。当有一半为猫，一半为狗的时候显然这个的熵是最高的，也代表是最不纯的。当全部为猫，或者全部为狗的时候则代表熵是最低的，也代表是最纯的。</p><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724065163720-48762f91-e617-492c-aa8a-1d867306a310.png"></p><p>我们可以使用这个熵函数$H(p_{1})&#x3D;-p_{1}log_{2}(p_{1})-p_{0}log_{2}(p_{0})$$&#x3D;-p_1log_2(p_1)-(1-p_1)log_2(1-p_1)$,这个就是信息熵的定义，即一个系统中所有事件的信息量累积和。一个越确定的系统，那么它的信息熵自然也就越小，因此我们可以使用信息熵作为衡量纯度的标准。</p><p>关于信息熵，交叉熵的详细解释可以参照这个视频：</p><p><a href="https://www.bilibili.com/video/BV15V411W7VB/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=a1e5dd0aa99678acd93e274baaf2577f">“交叉熵”如何做损失函数？打包理解“信息量”、“比特”、“熵”、“KL散度”、“交叉熵”_哔哩哔哩_bilibili</a></p><h2 id="nPwLc">信息增益</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724071120642-b1bce5ed-b7c2-48ff-ad7d-16c1485ae1e4.png"></p><p><font style="background-color:#FBDE28;">信息增益</font>（information gain） 代表的是在一个条件下，信息复杂度（不确定性）减少的程度，也即纯度提高的程度。</p><p>我们通过计算每个分裂特征的信息增益，作为一种衡量的标准。</p><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724071349733-a28ff25c-677d-4d6b-8110-f16f5c8f908e.png"></p><p>通过$&#x3D;\mathrm{H(p_1^{root})} -\left(w^{\mathrm{left}}H\left(p_1^{\mathrm{left}}\right)+w^{\mathrm{right}}H\left(p_1^{\mathrm{right}}\right)\right)$这个公式我们可以得到每个分裂特征的信息增益。</p><h2 id="b6G5H">完整流程</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724072346381-1c3c2c13-d2b0-4060-bef0-78cf618c1b6f.png"></p><p>第一步：将所有的样本放在根节点</p><p>第二步：计算所有分裂特征的信息增益，选择其中一个最高的</p><p>第三步：通过分裂特征切割数据集，创建左右节点</p><p>第四步：直到一定条件停止分裂</p><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724072376353-a5802b56-79a6-4b00-bf1f-4eefc7922a2a.png"></p><p>首先在根节点选择的数据集是全部的样本，接着在左节点我们选择被分割的那五个作为样本数据集，在右节点选择另外五个作为数据集，其中每次选择的数据集不同。</p><p><font style="color:rgb(51, 51, 51);">根据一定的策略 , 确定哪个属性作为树根 , 然后每个子树 , 在确定剩余的哪个属性作为子树的树根 , 这是递归问题 ，就像二叉树的深度优先遍历一样。</font></p><h2 id="h9ue2"><font style="color:rgb(51, 51, 51);">独热码</font></h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724130699991-62a9351c-38d3-4d8b-ba80-ef3976e86f2e.png"></p><p>为了处理两个以上的离散特征值，我们选择了使用独热码的形式，将其中符合特征的值设置为$ 1 $，使用这种方式就可以表示$ k $个的离散特征值，接下来处理连续的特征值。</p><h2 id="gsj7r">连续特征值</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724131599524-abc87c7e-d8ee-4777-af80-38b3aeb253d0.png"></p><p>对于连续的特征值，我们可以尝试不同的阈值，分别计算对应的信息增益，最终计算出最高的那个阈值，并使用这个作为我们的分裂特征。</p><h2 id="W7W0l">回归树</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724133102976-4083d505-8f3e-4d43-b5ca-076dc1093264.png"></p><p>我们对之前的决策树进行泛化操作，使得原本仅可以判断分类的决策树也可以实现回归问题，跟决策树相同，仅仅在输出结果时将原本的分类改为分类的重量平均值，实现了对于重量的预测。</p><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724133261296-2763a68f-cc47-435f-b9ed-6acc9072e0ea.png"></p><p>在计算应该选择那个节点作为新节点时，我们不再选择使用信息熵作为需要的指标，而是使用方差，最终我们计算出减少方差最多的那个节点，将其选择为分裂节点。</p><h2 id="U412t">多决策树</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724133836073-b4c2f28f-3c57-42ed-bd6c-006a4162421c.png"></p><p>一棵树对于数据是很敏感的，我们仅仅改变其中的一个样本，我们选择的信息增益最高的分裂特征可能就会发生改变从而得到不同的左右节点，因此我们需要使用多颗决策树同时决策。</p><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724133985511-c8c7f50e-a1e7-4e14-8a20-10b673376007.png"></p><p>我们使用三颗决策树对于同一个样本进行预测，最终通过最多数的投票做出正确预测。</p><h2 id="jut8G">有放回抽样</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724134341182-a351940b-1a83-4660-bfc1-7057165c0053.png"></p><p>我们将要抽样的数据集放在一个袋子里，每次选择其中一个，然后放回继续抽取，最终我们可以得到一个跟原先数据集很相似，但是又不完全相同的新的数据集，这是构造决策树集合的关键步骤。</p><h2 id="DkvDP">随机森林</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724135272784-497c56a6-c919-4b1a-9c2f-ccf67778f353.png"></p><p>我们循环$ B $次，每次都按照之前有放回抽样的方式这样就可以构建$ B $个决策树，但是即使这样我们的根节点还是有很大的概率选择相同的分裂特征，因此我们接下来使用在每个节点随机选取属性的方式构建随即森林。这种方式也称为$ Bagged \enspace decision \enspace tree $。</p><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724135196427-0a2a2a39-f526-4d23-ae9f-8e8659816541.png"></p><ol><li><font style="color:rgb(87, 88, 99);">一个样本容量为N的样本，有放回的抽取N次，每次抽取1个，最终形成了N个样本。这选择好了的N个样本用来训练一个决策树，作为决策树根节点处的样本。</font></li><li><font style="color:rgb(87, 88, 99);">当每个样本有M个属性时，在决策树的每个节点需要分裂时，随机从这M个属性中选取出m个属性，满足条件m &lt;&lt; M。然后从这m个属性中采用某种策略（比如说信息增益）来选择1个属性作为该节点的分裂属性。</font></li><li><font style="color:rgb(87, 88, 99);">决策树形成过程中每个节点都要按照步骤2来分裂（很容易理解，如果下一次该节点选出来的那一个属性是刚刚其父节点分裂时用过的属性，则该节点已经达到了叶子节点，无须继续分裂了）。一直到不能够再分裂为止。注意整个决策树形成过程中没有进行剪枝。</font></li><li><font style="color:rgb(87, 88, 99);">按照步骤1~3建立大量的决策树，这样就构成了随机森林了。</font></li></ol><h2 id="I698f">XGBoost</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724864141732-7be43bd1-035c-4f8c-ab03-240869e161d1.png"></p><blockquote><p>目前来说，同质个体学习器的应用是最广泛的，一般我们常说的集成学习的方法都是指的同质个体学习器。而同质个体学习器使用最多的模型是CART决策树和神经网络。同质个体学习器按照个体学习器之间是否存在依赖关系可以分为两类，第一个是个体学习器之间存在强依赖关系，一系列个体学习器基本都需要串行生成，代表算法是boosting系列算法，第二个是个体学习器之间不存在强依赖关系，一系列个体学习器可以并行生成，代表算法是bagging和随机森林（Random Forest）系列算法。</p></blockquote><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724864539041-3e2d9208-fc9f-447d-a46e-350d524107bd.png"></p><p>其中$ XGBoost $就是$ boosting $系列中的一个重要算法，它通过不断的调整学习器的权重，仅使用原始的训练集，而不是生成多个训练集，同时还内置了正则化以防止过度拟合，被广泛的用于各大比赛中。</p><p>参照：</p><p><a href="https://www.cnblogs.com/pinard/p/6131423.html">集成学习原理小结 - 刘建平Pinard - 博客园</a></p><h2 id="lG2R9">决策树VS神经网络</h2><p><img src="/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/1724865121997-d43bf438-f9d2-491a-8e0f-0e9face44c01.png"></p><p>决策树：</p><ul><li>适合结构化数据，不推荐处理非结构化的图形和声音数据</li><li>训练速度快</li><li>小型决策树可以被人为解释其中每一步的作用</li></ul><p>神经网络：</p><ul><li>对于结构化和非结构化数据都工作的很好</li><li>训练速度比决策树慢</li><li>当训练数据量不足时，可以使用迁移学习</li><li>当一个系统需要多个模型同时工作时，更容易构建大型的神经网络，决策树一次只能训练一颗</li></ul>]]>
    </content>
    <id>https://yzd11.github.io/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/</id>
    <link href="https://yzd11.github.io/2024/08/29/%E5%86%B3%E7%AD%96%E6%A0%91/"/>
    <published>2024-08-28T17:20:17.000Z</published>
    <summary>了解决策树算法</summary>
    <title>决策树</title>
    <updated>2026-08-22T07:24:29.548Z</updated>
  </entry>
</feed>
