<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Ducky</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://duckywang.github.io/</id>
  <link href="https://duckywang.github.io/" rel="alternate"/>
  <link href="https://duckywang.github.io/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Ducky</rights>
  <subtitle>
    <![CDATA[Technology, Mind & Making]]>
  </subtitle>
  <title>Drafts of Reality</title>
  <updated>2023-08-12T16:00:00.000Z</updated>
  <entry>
    <author>
      <name>Ducky</name>
    </author>
    <category term="意识" scheme="https://duckywang.github.io/categories/%E6%84%8F%E8%AF%86/"/>
    <category term="随笔" scheme="https://duckywang.github.io/tags/%E9%9A%8F%E7%AC%94/"/>
    <content>
      <![CDATA[<p>宗教和科学从诞生就有着分道扬镳的发展哲学，宗教先知总是秉持的极度自洽和坚定的态度，而科学研究者则坚持怀疑批判和严谨的理论实证。但随着科技树的不断点亮，我们发现二者却又在一些问题上有些“殊途同归”，这种经常会让人陷入一种错乱：宗教和哲学解释性的话语权究竟如何，作为一个现代人该如何分辨和看待呢？</p><h2 id="宗教是实用主义的优胜劣汰"><a href="#宗教是实用主义的优胜劣汰" class="headerlink" title="宗教是实用主义的优胜劣汰"></a>宗教是实用主义的优胜劣汰</h2><p>从宗教的诞生和发展来看，他并非看起来那样‘简单’，缺少理论根据。相反，尤其是对世界上的几大宗教来说，他们是接受了最漫长和严格的‘世俗审查’，无论理论是否站得住脚，他并不需要这样的东西，他能够存在下来就说明了一切；</p><p>根本上还是，我们也很难通过实验的方法来实证宗教的“解释”，因为作为宗教很难作为一种理论被验证–不能够阐述如可操作性定义、很难明确因素变量和结果之间的关系；而只能通过世俗社会的口口相传，亲身体验以及“政治联姻”这样的方式来传播和发展。</p><p>但是不能通过实验证实并不能说明宗教没有用，恰恰很多历史悠久的宗教中存在了很多无法通过目前科学方法完全解释的“智慧”。但是并非所有都是精华，这如同科学一样，需要一些辩证的态度。</p><p>宗教没有基于普世符号和基础逻辑的标准化的教义，所以只有信徒才能更高效的吸收和接受。常见的宗教教义都是问答形式，很多人来问，由悟者或先知来回答。因此，宗教本身体现一种江湖性，或“政治性”。宗教对其所宣扬的理论表现出极大的肯定性，不容解释的自洽逻辑，如果有其他解释，可以另立门派，而非在原有教义上迭代。所以宗教虽然有如此多的分类和流派，我们却会发现很多关键且高度一致的地方，而导致他们形成差异的点，往往在一些细节的差异上，这个分类有必要吗，我觉得对于关键的问题可能没有那么重要。</p><p>另外，宗教似乎总是围绕着人来展开，很少涉及生产、制造等物质领域的知识经验，使得他相对科学在全面性上有一些空白，也是两者有明显差异的地方。</p><p>那什么时候，我们适合采取宗教的方式来解决问题呢？根据经验来看，大概是想要有“可行方法”马上解决某个问题，面临人生的困惑或痛苦，想要解惑，跳出，同时不限年龄身份，但是会讲究“机缘”。</p><h2 id="科学是怀疑、耐心且积极的现实解释者"><a href="#科学是怀疑、耐心且积极的现实解释者" class="headerlink" title="科学是怀疑、耐心且积极的现实解释者"></a>科学是怀疑、耐心且积极的现实解释者</h2><p>接受一切事实结果，尝试用一套通用的符号和逻辑体系解释事实，以解释一切为目标，在自身的基础上不断修整和发展。关于科学是什么其实本身就有相当明确的定义，这里也不赘述太多。</p><p>那么什么时候适合使用科学的方式呢？对于真的关心“为什么”的人，且有时间、耐心和一定的条件作为投入，更适合用科学的手段和方法来解决问题。为什么特别强调时间、耐心和投入，虽然科学的可操作性明显高于宗教，但是不可否认这其中的知识壁垒对一般人的局限作用，这点使得很多人理解科学由于缺乏耐心，其实也像进行某种“宗教”一样。</p><p>最重要的是，这使得其受众能够接受目前人类科学的局限性，对很多问题没有答案的结果。这点是“更迫切需要一个结果”的人难以接受的，也是科学在传播上最大的障碍–从一些比较普遍而终极的问题上看<br>“没有马上的用处”。</p><p>谈论了不同，宗教和科学也有很多反直觉的共同点。比如宗教和科学都属于“行动派”，也都通过“真实的效果”而说服他的“受众”。同时，没有所谓西方的科学，和东方的宗教之类的偏见，这二者都是人类探索宇宙空间的结晶，普遍存在于人类文明的漫长发展中，只是受到阶段性政治历史的影响，而产生了一些发展速度的不均衡。</p><p>而世界也绝非宗教和科学的二元论，对于人类的求知空间，还有很多介于二者模糊边缘的存在，比如哲学、伦理学等。</p>]]>
    </content>
    <id>https://duckywang.github.io/2023/08/13/%E9%9A%8F%E7%AC%94-%E5%AE%97%E6%95%99%E4%B8%8E%E7%A7%91%E5%AD%A6/</id>
    <link href="https://duckywang.github.io/2023/08/13/%E9%9A%8F%E7%AC%94-%E5%AE%97%E6%95%99%E4%B8%8E%E7%A7%91%E5%AD%A6/"/>
    <published>2023-08-12T16:00:00.000Z</published>
    <summary>
      <![CDATA[<p>宗教和科学从诞生就有着分道扬镳的发展哲学，宗教先知总是秉持的极度自洽和坚定的态度，而科学研究者则坚持怀疑批判和严谨的理论实证。但随着科技树的不断点亮，我们发现二者却又在一些问题上有些“殊途同归”，这种经常会让人陷入一种错乱：宗教和哲学解释性的话语权究竟如何，作为一个现代人该]]>
    </summary>
    <title>随笔-宗教与科学</title>
    <updated>2023-08-12T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ducky</name>
    </author>
    <category term="意识" scheme="https://duckywang.github.io/categories/%E6%84%8F%E8%AF%86/"/>
    <category term="脑科学" scheme="https://duckywang.github.io/tags/%E8%84%91%E7%A7%91%E5%AD%A6/"/>
    <content>
      <![CDATA[<h2 id="外侧与前方：可感知的图形界面"><a href="#外侧与前方：可感知的图形界面" class="headerlink" title="外侧与前方：可感知的图形界面"></a>外侧与前方：可感知的图形界面</h2><p>一个有趣的发现，大脑约靠近外侧和前方的部位功能越是可以感知的“图形操作界面”。这里主要就是我们所熟知的大脑皮层，负责处理所有我们能感知到的高级信息并形成决策和指令，有认知，计划，创作，欣赏，学习模仿等等这些我们非常熟悉和有知觉的行为。我们可以有意识的感知和控制。</p><h2 id="中心内核：生存系统的大管家"><a href="#中心内核：生存系统的大管家" class="headerlink" title="中心内核：生存系统的大管家"></a>中心内核：生存系统的大管家</h2><p>而越靠近中心内核和下后部，就越是承担生物本能和“底层”的结构功能，这部分包括从丘脑开始，再到下丘脑垂体，以及小脑和脑干，这部分结构通过神经递质的管理对脑神经，脊神经进行控制，能够基于意识和无意识的信息对下游神经元受体，肌肉和皮肤等身体功能结构直接产生影响，实现调控。这里主要是人类生存的必要功能的“大管家”，你不用事无巨细的和他“对齐”，他就可以妥善和摆平一切处于基本生存状态的工作。比如呼吸、血压、吞咽、体温、精细的肌肉运动，平衡，睡眠周期等基础核心功能。</p><h2 id="边缘系统：裂缝中的修补"><a href="#边缘系统：裂缝中的修补" class="headerlink" title="边缘系统：裂缝中的修补"></a>边缘系统：裂缝中的修补</h2><p>而<br>在二者的交界处，也就是大脑最深处和中心的区域（把大脑当作一个球），就是人类最区别于其他生物的复杂结构-边缘系统-人类具有最高级的边缘系统，但是这只是人类之所以是人类的特点，不一定就是完全的优点，进化总是在一些裂缝的地方修修补补。边缘系统和长短期记忆，情绪，动机等高级能力有密切的关系，包括人性的本能，母爱，性欲，战斗攻击和逃跑，以及更高级的社会化关系。</p>]]>
    </content>
    <id>https://duckywang.github.io/2023/07/29/%E9%9A%8F%E7%AC%94-%E8%84%91%E7%BB%93%E6%9E%84%E7%9A%84%E5%AE%8F%E8%A7%82%E6%84%9F%E7%9F%A5/</id>
    <link href="https://duckywang.github.io/2023/07/29/%E9%9A%8F%E7%AC%94-%E8%84%91%E7%BB%93%E6%9E%84%E7%9A%84%E5%AE%8F%E8%A7%82%E6%84%9F%E7%9F%A5/"/>
    <published>2023-07-28T16:00:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="外侧与前方：可感知的图形界面"><a href="#外侧与前方：可感知的图形界面" class="headerlink" title="外侧与前方：可感知的图形界面"></a>外侧与前方：可感知的图形界面</h2><p>一个有趣的发现，大脑约靠近外侧和前方的部位功]]>
    </summary>
    <title>脑结构的宏观感知随笔</title>
    <updated>2023-07-28T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ducky</name>
    </author>
    <category term="建模" scheme="https://duckywang.github.io/categories/%E5%BB%BA%E6%A8%A1/"/>
    <category term="BP算法" scheme="https://duckywang.github.io/tags/BP%E7%AE%97%E6%B3%95/"/>
    <content>
      <![CDATA[<h2 id="梯度下降在深度神经网络中的应用存在哪些问题"><a href="#梯度下降在深度神经网络中的应用存在哪些问题" class="headerlink" title="梯度下降在深度神经网络中的应用存在哪些问题"></a>梯度下降在深度神经网络中的应用存在哪些问题</h2><p>在基础篇中我们以线性分类器为例解释了反向传播算法的工作原理，但是在实际应用中却很少直接使用这种最原始的梯度下降反向传播算法；主要由于对于大规模的深度网络来说求解每个节点的<strong>梯度是非常大的计算量</strong>，且在<strong>更加复杂的损失函数空间中也会遇到难以逼近极值的问题</strong>；</p><h2 id="梯度的维度-计算量有多大？"><a href="#梯度的维度-计算量有多大？" class="headerlink" title="梯度的维度-计算量有多大？"></a>梯度的维度-计算量有多大？</h2><p>由于梯度下降算法中梯度的维度是和参数维度完全相同的，所以我们先来感受参数量是一个什么样的概念，我们以一个全链接网络为例；下图表示了神经网络中某一层的一个感知机的计算过程（对应图中的红色矩形部分）</p><p><img src="/images/posts/backpropagation-2/v2-5bad71914f8af2b150f1633240d1371a.webp" alt="神经网络中的感知机参数矩阵"></p><p>参数的右上角标表示这个感知机属于第几层，比如L是本层，L-1就是上一层；右下 角标表示在本层的第几个感知机（神经元&#x2F;节点）；</p><p>对于一个感知机来说，本层需要输出一个；这里的个等于上一层L-1所有神经元的加权和，具体包括对应上层每个 i 神经元的 权重 「」乘以 上层的每个「」再分别加上偏置 ，得到;</p><p>最后对这个加权和 求一个激活函数（），得到本层第 i 个神经元的输出值： 。这就是第L层第 i 个感知机的整体呈现；<br><strong>关于海量的参数量</strong>：</p><p><img src="/images/posts/backpropagation-2/v2-4b9a76942cda9d12725c88981f894204.webp" alt="神经网络中的感知机参数矩阵"></p><p>将每一个感知机的输出值看做一个变量的话，上一层有 n 个变量，那本层有 i 个变量，那本层就会有 <strong>n * i 个 参数w</strong> ; 数量等于图中两层之间的连线数，从本层的每一个节点出发分别连接上一层的每一个节点；所以参数量w的维度和相连两层的变量数（节点数）；对于输入层来说这个节点数等于一个输入sample的所有维度，而对于隐藏层的节点数来说其实就是通过交叉验证找到的最佳节点数，输出层则是要分类的情况或人为设定的值；在这种多维度的场景下，对应参数矩阵W的<strong>梯度值就会是一个雅可比矩阵</strong>（一阶导数的矩阵）；</p><p>对于多通道的图像、或one-hot特征的文本等高维度数据场景，输入层和隐藏层的节点数都是非常巨大的；比如一个1080p的RGB图片（当然实际训练不会直接用这么高像素的图片），就有两百万像素（1920 x 1080）再乘以3，我们就会得到一个输入层有600万个节点的网络，而这一层输入和隐藏层相关的参数W维度就是600w 乘以某个值；</p><h2 id="在损失函数空间中梯度下降中遇到的问题"><a href="#在损失函数空间中梯度下降中遇到的问题" class="headerlink" title="在损失函数空间中梯度下降中遇到的问题"></a>在损失函数空间中梯度下降中遇到的问题</h2><ol><li>“Z字形”下降：<br>在参数维度方向下降对应的损失函数变化水平（敏感度）不一致，某一个参数方向敏感度很高，而另一个参数方向敏感度低时，就会出现梯度在敏感度高的方向正负方向反复横跳，在敏感度低的方向缓慢前进；而真实的梯度方向很有可能是敏感度低的方向，这就导致梯度的Z字形下降，学习效率很低；这个问题在高维空间更加普遍；</li><li>困在局部“最优”：<br>局部极小值点：这个在<strong>高维空间出现的概率很低</strong>，对于一个含有一亿个参数的高维空间，要求一个点对于一亿个点都是局部极小的，向任何一个方向前进较小的一步都会损失变大，这种情况非常稀少，假设某个点在某个维度上是局部最小的概率是P，那在整个参数空间（一亿个参数）这个点是局部最小点的概率是P ^(10^8)；<br>而在<strong>低维空间</strong>这种情况就更加常见，损失函数在某个点的周围有一段凹陷，那么梯度计算周围一圈都是梯度为0，梯度下降算法在此处不执行更新，可以通过合理选择参数的初始值或者增加学习率来解决落入局部最小值的问题；</li></ol><p>鞍点：鞍点是在<strong>某些维度上的局部最小值，而在某些维度上是局部最大值</strong>；鞍点问题在高维空间更加常见，鞍点处的梯度为0，高维空间中大部分梯度为0的点几乎都是鞍点，并非局部最小值点；同样，处于鞍点会使得基于梯度下降的优化算法在此处停滞，难以从鞍点“逃离”；在高维空间中如何避免梯度落入鞍点，也是一个待解决的问题；通常我们会通过在当前维度计算梯度时参考历史梯度下降的动量信息来绕开当前梯度为0的尴尬；<br>平原区域：由于深度神经网络的参数过大，可能会存在一定的<strong>冗余性</strong>，即每个参数只贡献一点点损失函数的优化值，这就导致出现损失函数出现“平坦的地形”，在这区域内梯度接近于0，而这又恰恰处于损失函数的“高原”地带，这就会得到非常差的优化结果；<br>3. 悬崖结构<br>当损失函数呈现悬崖结构，在某处梯度非常大，使用梯度下降算法更新可能导致参数发生很大的变化，从而产生梯度爆炸现象；可以用截断的方法解决这个问题，当梯度值超过某个规定的阈值时，就进行截断，这种方法叫做梯度截断（Gradiant Clipping）<br>4. 随机性噪声影响<br>由于常规的梯度下降计算量过大，真正计算时我们通常采用随机梯度下降法，每次只对一个或者一小批的样本的损失值进行全局的梯度计算；由抽样带来随机性，通常会导致梯度收敛过程中变得曲折，增加收敛的时间；</p><h2 id="梯度下降的演化和应用策略"><a href="#梯度下降的演化和应用策略" class="headerlink" title="梯度下降的演化和应用策略"></a>梯度下降的演化和应用策略</h2><p>梯度下降的优化方向沿着几个方向分别展开：参数量、梯度方向、学习率；这些不同方向的优化方法，由于角度的正交性（独立性）往往会一起使用来优化梯度下降算法，目前最常用的就是Adam算法。下图表示了不同优化算法之间的关系。</p><p><img src="/images/posts/backpropagation-2/v2-35e5e8ab403b4a18f74d5ef4a0f2cc88.webp" alt="不同BP优化算法之间的关系"></p><h3 id="随机梯度下降"><a href="#随机梯度下降" class="headerlink" title="随机梯度下降"></a>随机梯度下降</h3><p>首先，从最朴素的减少参数量的角度看，有了<strong>随机梯度下降（SGD）</strong>，也就是每次随机挑一批数据训练（mini-batch）mini-batch梯度下降法的思想很简单，将样本总体分成多个mini-batch。例如100万的数据，分成10000份,每份包含100个数据的<a href="https://www.zhihu.com/search?q=mini-batch-1&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22:%22article%22,%22sourceId%22:%22301577420%22%7D">mini-batch-1</a>到mini-batch-10000，每次梯度下降使用其中一个mini-batch进行训练，除此之外和梯度下降法没有任何区别。这样能够明显减少计算量，同时由于数据的冗余性，减少样本量的抽样对梯度的优化几乎没有影响，因此之后所有的优化方法几乎都会叠加这个方法一起使用。</p><h3 id="牛顿法"><a href="#牛顿法" class="headerlink" title="牛顿法"></a>牛顿法</h3><p>接下来，会提到一种理论上的方法–牛顿法，这种方法可以看做是优化参数更新方向的先驱，他为我们提供一种重要思路，但是由于会面临更复杂的计算所以只是一种理论模型。我们知道，梯度计算都是损失函数对参数的一阶偏导，而牛顿法对于一阶到是否是最优的下降方向提出了质疑。梯度是损失函数L（θ）在θ_0处的<strong>一阶偏导</strong>，梯度方向只能在很小的范围成立，在更大范围内并不成立，所以就不能在这个方向上前进太多，这就<strong>限制了找到更快优化目标函数的梯度方向的速度。</strong></p><p>基于这个优化方向，牛顿法提出了对于损失函数L（θ）在θ_0处进行<strong>二阶泰勒展开得到f(θ)</strong>，针对二阶展式开来寻找优化的方向。而对于二阶泰勒展开式寻找优化方向就不再受到一阶导数小范围的限制，直接找到二阶展开的最小值（下图绿色抛物线顶点处）作为优化的值，意为二阶展开式的最小值点是当前点 θ_0 可以观测到最可能使目标函数快速下降方向。</p><p><img src="/images/posts/backpropagation-2/v2-0d0fe88a02a5324510e9327b22cc0c22.webp" alt="img"></p><p>在下图中可以看到，θ_0处的一阶梯度对应的目标函数优化值（橙色的Δy）比θ_0处的泰勒二阶展开找到的优化值更小，这也表示牛顿法可以更快的向损失函数优化的方向收敛；也可以看到二阶展开式比一阶导橙色线更接近优化方向的ground truth（灰色线）。牛顿法的迭代公式为：</p><p>其中，∇<em>f</em>(<em>x_k</em>) 是 <em>f</em>(<em>x</em>) 在点 <em>x_k</em> 处的梯度向量，∇^2<em>f</em>(<em>x_k</em>) 是<em>f</em>(<em>x</em>) 在点 <em>x_k</em> 处的 Hessian 矩阵；</p><p><img src="/images/posts/backpropagation-2/v2-27021cd97b3279e4790ae143c0b82f31.webp" alt="img"></p><p>这里非专业的同学不需要纠结Hessian矩阵。简单理解下，为什么需要hessian矩阵？① 黑塞矩阵实际上就是对于矩阵来说求解二阶偏导的工具：对点x的参数求两次偏导提供了一个精确的计算模型；② 求二次函数的最小值我们需要寻找其二阶导为0的点，偏导也是同理。</p><p><img src="/images/posts/backpropagation-2/v2-38780a61b172ccadfb0d33e12eaa1861.webp" alt="img"></p><p>因此，迭代公式中的步长 (∇^2<em>f</em>(<em>x_k</em>))^−1 · ∇<em>f</em>(<em>x_k</em>) 可以看做是一个二次函数的最小值点与当前搜索点的差值。这里的 Hessian矩阵 也被称为牛顿步长。在牛顿法中，黑塞矩阵的作用就是提供了一个精确的二次函数模型，它描述了损失函数的局部曲率，使得在曲率小的时候能够大步长更新，曲率大的时候小步长更新，这可以解决梯度下降中“Z字型”下降的问题。在这个层面上，牛顿法在当前点上不仅考虑当前坡度是否足够大，还会进一步考虑迈出这一步后的坡度如何，更具有全局观，因此比梯度下降收敛的更快。</p><blockquote><p>曲率和导数的差异：</p><p>曲率：在数学中，曲率通常被定义为曲线或曲面上某一点处的切线或切平面的<strong>弯曲程度</strong>。曲率值越大，表示该点处的曲线或曲面弯曲程度越大。可以理解为曲率是用来描述<strong>多维数据变化程度的指标</strong>；在一维数据中，曲率就等同于二阶导数。</p><p>曲率和黑塞矩阵的特征值：黑塞矩阵的特征值提供了评估函数曲线在某个点处弯曲程度和形状的重要指标</p><p>曲率可以被视为黑塞矩阵<strong>特征值的加权平均</strong>。更具体地讲，曲率的大小取决于黑塞矩阵特征值的大小及其相对比例。</p><p>在某个点处，如果所有黑塞矩阵的特征值都是正数，则函数在该点处是凸的，并且曲率在所有方向上都是正的。如果所有黑塞矩阵的特征值都是负数，则函数在该点处是凹的，并且曲率在所有方向上都是负的。如果黑塞矩阵的特征值中既有正数又有负数，则该点处可能是一个鞍点，因为曲率在不同方向上可能是正或负。</p></blockquote><p>牛顿法的简易快速理解：牛顿法的「二阶优化思路」对于某个点的目标函数通过<strong>二级泰勒展开还原</strong>附近的曲线走势，并通过Hessian矩阵工具<strong>二阶求导</strong>，尝试找到他的加速度方向，针对这个加速度来决定优化的向量；</p><p>牛顿法这么牛，为什么我们不用牛顿法呢，除了在深度神经网络中黑塞矩阵的计算是内存的不可承受之重，另外这种方式也更容易陷入“鞍点”。由于深度网络有海量的参数，对应的损失函数空间可以想象为无规则起伏的山地，就是我们常说的是一个非凸问题，因此大概率存在很多鞍点。而在鞍点附近时，黑塞矩阵的特征值在不同维度上的符号并不相同，难以收敛，因此牛顿法得到的优化方向可能会指向函数的鞍点或局部极大值点，会向着错误的方向更新。</p><p>当然，以上的这些问题也得到了一定程度的解决。比如结合随机梯度下降法（SGD），牛顿法可以通过随机性来跨越一些鞍点。同时对于黑塞矩阵计算复杂度的问题，后来的学者也提出了优化方法–一系列的拟牛顿法。旨在通近似矩阵执行参数的更新，常用的包括DFP、BFGS、L-BFGS等。拟牛顿法只需要计算一阶导数，不需要计算黑塞矩阵就能快速收敛，同时也对存储部分做了优化，因此能够被应用在更大的网络上。</p><h2 id="基于动量的优化方法：调整方向"><a href="#基于动量的优化方法：调整方向" class="headerlink" title="基于动量的优化方法：调整方向"></a>基于动量的优化方法：调整方向</h2><p>动量法是更符合直觉的一种优化方法。在物理学中，动量描述了一个物体在它的运动方向上保持运动状态的趋势，表示为物体质量和他的速度的乘积。在动量法中，我们将参数的更新看做粒子的运动，当一个单位质量的粒子从一个小坡滑下来，首先有一个初始速度v_0，由于一个持续向下的力产生了加速度（F&#x3D;ma）。小球的速度不断受到这个向下加速度影响，相比于每一个点的其他方向的梯度对速度的影响，这个向下的力产生的加速度是更大的，因此使得小球更快地落到最低处。即在每一点更新梯度时，除了当前点的梯度，还要参考（继承）历史梯度里面更有持续性、更显著的信息。比如一个小球在山坡下落的某个点遇到一个石块，但是因为受到重力产生的惯性，它不会立马沿着石块的切线方向横着走下一步，而是绕过石块继续下落，甚至有可能直接越过石块。</p><h3 id="动量法"><a href="#动量法" class="headerlink" title="动量法"></a>动量法</h3><blockquote><ol><li>：初始参数，初始速度一般为</li><li>：没有达到停止准则 do<br>​从训练集采集包含m个样本的小批量{x^i,…,x^m},对应目标为<br>​计算梯度估计：<br>​计算速度更新：<br>​参数更新：</li><li></li></ol></blockquote><p>表示待优化的目标函数，</p><p>为数据损失： ，</p><p>, 表示对损失函数求梯度，θ表示要优化的参数，包括权重W和偏置b;</p><p>这里v表示更新后的速度 ，是参数在参数空间移动的反向和速率，一般初始化为0，表示动量因子，根据经验一般设置为 0.5,0.9,0.95和0.99中的一个值，表示了前一时刻速度对当前速度的贡献，越大表示之前时刻累计的梯度对现在越大，一般初始将设置为一个较小的数值，随后慢慢变大。α则为学习率，代表当前时刻梯度对速度的影响，一般初始设置一个较大值，随后渐渐减少。和α 的这种关系，并不会每一次人工设置一个值，我们通常用「指数移动加权平均」和参数 β 来表示，这样就得到 v。</p><h3 id="如何理解指数移动加权平均"><a href="#如何理解指数移动加权平均" class="headerlink" title="如何理解指数移动加权平均"></a>如何理解指数移动加权平均</h3><p>假设存在数列</p><p>令：</p><p>. . . . . . . . .</p><p>之所以叫指数衰减，下图展示了之前不同时刻的梯度对当前时刻的权重影响值，可以看到距离越近的梯度影响越大，权重影响是呈指数衰减的。</p><p><img src="/images/posts/backpropagation-2/v2-19a1c857b18fda6f77038157436f6133.webp" alt="img"></p><p>动量法就是让梯度更新的方向不至于那么剧烈，参考下图的绿线，由于积累了历史水平方向的更新向量，减少了在敏感维度上的震动幅度，因此比普通的梯度下降在接近极值点时，更新更快，同样的迭代次数下，更划算！</p><p><img src="/images/posts/backpropagation-2/v2-892be7149286032c4281874e6f51fe25.webp" alt="绿色为动量法的下降速度方向"></p><p>而Nestrov则是在动量法的基础上，又向前卷了一步，<strong>根据历史速度信息将参数向前更新一步，在新的（参数）位置上计算梯度更新</strong>，然后再根据这个梯度和速度信息更新历史参数。实验证明，Nestrov会更快收敛。</p><blockquote><ol><li>：初始参数，初始速度一般为</li><li>：没有达到停止准则 do<br>​从训练集采集包含m个样本的小批量,对应目标为,<br>​执行临时更新  参考了速度信息，施加了速度到达新的位置<br>​计算梯度估计：<br>​计算速度更新：<br>​参数更新：</li><li></li></ol></blockquote><h2 id="自适应学习率算法：调整步伐"><a href="#自适应学习率算法：调整步伐" class="headerlink" title="自适应学习率算法：调整步伐"></a>自适应学习率算法：调整步伐</h2><p>学习率表示每次更新的幅度，在进行梯度更新时，开始需要比较大的学习率，提升学习速度，到接近极值点的地方就需要比较小的学习率来逼近，否则就会在极值点附近横跳。因此在学习率方面的优化需要一个合理的学习率随学习进行而衰减的算法， 因此又成为学习率退火；</p><p>学习率衰减策略可以分为两种：固定策略的学习率衰减和自适应学习率衰减，其中固定学习率衰减包括分段衰减、逆时衰减、指数衰减等，自适应学习率衰减包括AdaGrad、 RMSprop、 AdaDelta等。本质上都是依托一种数学表达来找到学习率衰减的方式。</p><h3 id="AdaGrad算法"><a href="#AdaGrad算法" class="headerlink" title="AdaGrad算法"></a>AdaGrad算法</h3><p>这里的ada指adaptive，就是相对于固定学习率这里会随着学习而自适应的意思。AdaGrad的思想很简单，类似于L^2正则化的思想，每一次对学习率β进行更新时，会用初始学习率α除以之前所有梯度平方的累加值；这样直接除以平方和的方式，对于出现Z字型的区域有很好的低效效果，会快速降低当前点的学习率，而对于波动比较小的维度（损失函数不敏感）学习率就会相对大一些，从这个意义上来看AdaGrad是一种对于剧烈波动维度的正则方法。</p><p>（表示逐项相乘）</p><p>但是AdaGrad方法也存在一些问题，随着迭代次数K的增加由于背上了所有的历史包袱，更新的步长越来越小。对于凸函数，Ada算法表现良好，会在局部极小点附近慢下来并最终收敛；但对于非凸函数，Ada算法可能会导致学习率过早的减少，以至于还没有达到极值点就停滞不前了。</p><h3 id="RMSProp算法"><a href="#RMSProp算法" class="headerlink" title="RMSProp算法"></a>RMSProp算法</h3><p>针对Ada存在的问题，Geoffery Hinton提出了另一种改进的自适应学习率的RMSProp算法，该方法以一种相对温和的方式调整学习率，优化了Ada过早衰减停滞的问题。总体思想是一样的，都是给初始学习率除以一个随迭代k次而变化的变量。只是将累加的梯度平方和变为历史梯度的指数衰减加权移动平均。其中，β为衰减率，一般为0.9。基于指数衰减加权的思路，给遥远的历史梯度平方很小的一个权重β^(k-1)，这样参数的学习率便不会呈现衰减的趋势，有可能变小也可能变大，始终会受到当前梯度变化的影响。RMSProp算法已经作为一种有效的优化算法用于训练深层神经网络，并被广泛使用。</p><h3 id="方法的融合：Adam方法"><a href="#方法的融合：Adam方法" class="headerlink" title="方法的融合：Adam方法"></a>方法的融合：Adam方法</h3><p>在计算考虑历史速度向量的梯度公式中有两部分，①对历史速度的参考，②对当前梯度的学习；动量法实际上是在第一部分进行修正，而学习率相关的方法则是调整对当前梯度学习比例，由于二者作用的方向并不冲突，如下图所示：</p><p>暂时无法在飞书文档外展示此内容</p><p>因此就有了Kingma D.P. 和 Ba J.提出的自适应动量估计法，Adam（Adaptive Moment Estimation）它融合了动量法和RMSPropd算法的优势，是一种非常好的优化方法，在很多网络上能得到很好的效果。</p><p>（）</p><p>要选择几个对AI发展影响最深的算法，那BP算法绝对算其中基础性，灵魂性和哲理性的存在。</p><p><strong>如果说多层网络的结构设计表现的是一种「世界观」。那么梯度下降就是一种「人生观」</strong>，这是一种<strong>在错误中学习，在迭代中进化的简单智慧</strong>。而通过梯度下降算法的不断演化的脉络，我们也看到了一条逐渐清晰的思路：如何更高效地在局部获得更加全局性信息来提高动态优化的效率，简单来说有三个方面：【提效】随机抽样减少信息量的冗余，【参考经验】参考历史和近期的重要的信息，【调整学习速度】在不同阶段调整学习内容的占比。</p><p>本文难免存在一些疏漏或不严谨的地方，但目标是希望可以让非专业的同学能够快速理解BP算法中看到的各种各样的名词，了解到它为什么是这样，是为了解决什么问题，甚至可以自己DIY新的用法。相信很多人接触深度学习都是从实用主义出发直接调pythorch，遇到优化瓶颈了在CSDN上搜一搜能用什么调参blahblah，然后就去试，效果好就是王道。当然这么做没有问题，但是这些工作人来做和机器有什么区别，属于更高智慧的直觉性经验和理解才是我们的天赋所在。</p><p>就像一个好的室内设计师，需要知道建筑哪里是承重墙，需要了解新中式和自然风格的元素差异，以及了解用户的性格和对室内环境的向往等等，以上所有信息佐之一些难以解释的随机的灵感，往往就能产生一个充满了元素混搭但却和谐而富有层次的作品。</p><p>相比模式化的套用，能够进行创造的理解才是我们学习的目的。当然这里设计师的例子也许有些过时，毕竟目前的AIGC显然已经可以80%的实现这种创造性。但是原理却不假，创造性上还有创造性，这是一条永无止尽的贪婪的生命进化之路。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p>论文：<a href="http://www.cs.utoronto.ca/~hinton/absps/naturebp.pdf">Learning representations by back-propagating errors</a> D. Rumelhart, G. Hinton, and R. Williams. <em>nature</em> <em>323 (6088): 533–536</em> (<em>1986</em>)</p><p>书：《深度学习–从神经网络到深度强化学习的演进》</p><p>视频：<a href="https://www.bilibili.com/video/BV1Zg411T71b/?spm_id_from=333.788&vd_source=6210010294dec82cce967eca4cc817f6">如何理解“梯度下降法”？什么是“反向传播”？通过一个视频，一步一步全部搞明白_哔哩哔哩_bilibili</a></p>]]>
    </content>
    <id>https://duckywang.github.io/2023/07/26/%E5%A6%82%E4%BD%95%E7%90%86%E8%A7%A3BP%E7%AE%97%E6%B3%95%EF%BC%9A%E4%BB%8E%E9%94%99%E8%AF%AF%E4%B8%AD%E5%AD%A6%E4%B9%A0%EF%BC%8C%E5%9C%A8%E4%BC%A0%E9%80%92%E4%B8%AD%E8%BF%9B%E5%8C%96(%E4%BA%8C)/</id>
    <link href="https://duckywang.github.io/2023/07/26/%E5%A6%82%E4%BD%95%E7%90%86%E8%A7%A3BP%E7%AE%97%E6%B3%95%EF%BC%9A%E4%BB%8E%E9%94%99%E8%AF%AF%E4%B8%AD%E5%AD%A6%E4%B9%A0%EF%BC%8C%E5%9C%A8%E4%BC%A0%E9%80%92%E4%B8%AD%E8%BF%9B%E5%8C%96(%E4%BA%8C)/"/>
    <published>2023-07-25T16:00:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="梯度下降在深度神经网络中的应用存在哪些问题"><a href="#梯度下降在深度神经网络中的应用存在哪些问题" class="headerlink" title="梯度下降在深度神经网络中的应用存在哪些问题"></a>梯度下降在深度神经网络中的应用存在哪些问题</]]>
    </summary>
    <title>如何理解BP算法：从错误中学习，在传递中进化(二)</title>
    <updated>2023-07-25T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ducky</name>
    </author>
    <category term="建模" scheme="https://duckywang.github.io/categories/%E5%BB%BA%E6%A8%A1/"/>
    <category term="BP算法" scheme="https://duckywang.github.io/tags/BP%E7%AE%97%E6%B3%95/"/>
    <content>
      <![CDATA[<p>这个话题我们分为两部分，在「一」中我们主要讨论基础的反向传播和梯度下降原理。</p><ul><li>初步理解：梯度和反向传播</li><li>反向传播要解决什么问题，是如何实现的</li></ul><p>在「<a href="https://zhuanlan.zhihu.com/p/634511696">二</a>」中我们将围绕梯度下降中出现的问题，对BP算法的发展演化做更具体的了解，从而对参数更新方法有更整体的了解。</p><ul><li>梯度下降中的常见问题</li><li>BP算法的演化</li></ul><h2 id="初步理解：梯度和反向传播"><a href="#初步理解：梯度和反向传播" class="headerlink" title="初步理解：梯度和反向传播"></a>初步理解：梯度和反向传播</h2><p>首先我们尝试感性地理解反向传播。</p><p>在「<a href="https://zhuanlan.zhihu.com/p/629760406">基础的深度神经网络—从多层感知机开始</a>」中了解神经网络的基本结构和特性后，很可能会好奇数据是如何在网络中流动的，这么复杂的网络是如何学习到能够适应环境的参数w？为什么一个静态的网络能够动起来学习到数据中的信息，这就不得不说到信息在神经网络中的流动的两种方向：前向传播和后向传播；</p><p>首先「正向传播」很好理解，顾名思义是指特征数据输入到网络后，数据与w和b产生计算，随着层层输出和处理，最终得到输出的结果y；而「反向传播」（BP:Backpropagation）则是把这个过程反过来，从最终的损失函数值出发，通过链式法和沿着梯度方向则将后一步的损失分摊到前一层的参数上，直到分摊到所有参数上；</p><p>为什么反向计算，就能算出合适每个神经元的参数呢？首先我们从一次正向传播的结束出发，我们得到了一个预测值和真实值的差，也就是损失函数的差；这个值可以看做是环境数据对目前神经网络学习的反馈和评估，那么我们该如何利用这个反馈来倒逼网络结构参数的优化呢？</p><p>换言之，为了下一次预测更准确，网络中的每个神经元该怎么调整？一种符合直觉的预想是根据每一个神经元对最终偏差的贡献大小进行调整：贡献大的神经元我们多调整一些，贡献少的神经元我们少调整一些；但是如何来计算每个神经元对偏差的贡献呢？</p><p>如果计算对偏差贡献实数值，是很难的；因为目前通过一次正向传播，我们只能看到一个静态的网络，每个感知机（神经元）只有一个参数和输入的x、和输出的y，我们很难说y里面有多少是贡献给了最终偏差的部分，更难计算参数w有多少贡献给了最终偏差的部分；如果解决这个问题，我们就需要引入「梯度」的概念。</p><p>当然，如果有一些微积分基础，这个问题就很好理解了，不过我们可以不管它，先尝试用我们的生活经验对梯度有一个直觉性的理解。</p><p>如果我们只有一个静态数据，但是我们却要预测一个运动物体下一秒的状态时，我们就会引入速度的概念；比如下面这个狂野的女司机，有了速度的概念，尽管你看到的是一张静止的图，但是通过画面中模糊方向的线索，你却能生出下一步运动状态如何的意识（比如轮子大概率会被逆时针旋转）。这里的”速度”实际上就是一种”梯度”，这就是对于「梯度」非常直觉性的理解了。</p><p><img src="/images/posts/backpropagation-1/v2-14f730f3eea554b7ec431ace50355a71.webp" alt="img"></p><p>一个静态视觉的例子</p><h2 id="梯度下降"><a href="#梯度下降" class="headerlink" title="梯度下降"></a>梯度下降</h2><p>感受到了梯度，比如我们知道图中方向盘逆时针方向旋转的角度代表了损失值，看起来目前我们得到一个比较大的损失值。我们如果想缩小这个损失，就要尽可能的将方向盘向逆时针方向调整，包括女司机双臂的姿势都向着反向调整，每一个细节的调整方向都是不同维度的梯度下降，最终我们就会得到一个方向盘下一秒看起来不太可能逆时针转动的图像，即根据我们的调整预期下一秒的损失值缩小了。我们继续沿着梯度下降最大的方向调整，缩小损失函数的参数优化方向，这个过程就是我们常说的通过梯度下降优化损失函数。</p><h2 id="链式法则和反向传播"><a href="#链式法则和反向传播" class="headerlink" title="链式法则和反向传播"></a>链式法则和反向传播</h2><p>回到一开始，我们是通过<strong>反向传播这样的方式实现了梯度下降的计算</strong>，你一定也会问，为什么反向计算就能够计算出梯度？<br>偏导和梯度的关系是什么呢？</p><p>偏导实际上描述了每个节点的输出值和该节点每个维度变量的关系，固定x不变，y变化，输出z也会变化；这实际上表达了损失函数变化对每个维度变量变化的敏感度（损失函数微小变化&#x2F;某个维度变量对应的微小变化），偏导就是用来准确的描述这个关系。比如这个节点上一共有x,y两个维度，那么同理z和x的偏导数也是一样。这样我们先分别对z求不同维度上自变量的偏导数。</p><p>然后把这个<strong>两个偏导数的向量相加，我们就得到了z的梯度</strong>；可以直接记住这个关系：z梯度&#x3D;∑偏导向量。</p><p><img src="/images/posts/backpropagation-1/v2-5b78be216b97da2e9bbf91e8c33df2fc.webp" alt="img"></p><p>在一个点上对不同维度求偏导的向量和就是梯度：z梯度&#x3D;∑偏导向量</p><p>当我们的任务是对全局的E 逐个节点去求偏导，将偏导数相加得到梯度做出每一节点的改进；我们似乎找到了解法，但是如何落地呢，复杂的网络是如何实现求偏导的计算呢？</p><p>我们下面以某一个神经元节点的视角来看链式法则逐层分解的过程。对于每一个感知机来说，它只需要关注上游传递下来的 E 对本节点输出的偏导（∂E&#x2F;∂z），并进行节点内局部梯度的计算（∂z&#x2F;∂x , ∂z&#x2F;∂y），就可以通过链式法则得到一个新的 E对下一个节点的偏导，如此自后向前传递，直到第一层输入的节点完成一次BP传播。网络中每个节点在进行反向传播时，都只考虑与其直接相连的节点即可，只需要求该节点的偏导向量和就可以得到该节点参数的优化方向；</p><p><img src="/../../AppData/Roaming/Typora/typora-user-images/image-20240120231017641.png" alt="image-20240120231017641"></p><p>计算图中的任意一个节点</p><h2 id="梯度更新"><a href="#梯度更新" class="headerlink" title="梯度更新"></a>梯度更新</h2><p>反向传播时计算最终损失函数（偏差的信息）对变量 a 的偏导（▽ L），将总的损失分摊到每一层的每一个神经元的参数w和b上（▽ L），根据每个参数对损失的影响大小，求出损失减少的梯度方向，相应的承担修改的责任，得到本次优化和迭代的方向，即每一次学习，每个影响点都会得到当前状态对损失函数的贡献是否正向，并会得到及时的矫正，梯度更新的通式为：W &#x3D; W - η* ▽ L</p><blockquote><p>nebula L：表示损失函数L的梯度，nebula形如▽<br>η：学习率<br>W：更新前和更新后的参数</p></blockquote><p><img src="/images/posts/backpropagation-1/v2-20be14b4c10f74cd954ac17d60930a65.webp" alt="img"></p><p>线性分类器中的反向传播和梯度更新</p><h2 id="反向传播梯度更新算法的几个特点"><a href="#反向传播梯度更新算法的几个特点" class="headerlink" title="反向传播梯度更新算法的几个特点"></a>反向传播梯度更新算法的几个特点</h2><ul><li><strong>高效性</strong>：基于链式法则的反向传播将复杂网络求梯度变成了相连节点的递归运算，每个节点只需要处理同样的局部求梯度计算，并且只关注和它最近邻的节点回传的信息，这给从硬件层面高效计算的解决方案提供了可能；</li><li><strong>可叠加性</strong>：反向传播时与A节点相连的所有节点梯度值在A处叠加，叠加值代表了A处节点对于损失函数的杠杆大小；</li><li><strong>高维度</strong>：梯度向量和原向量的维度相同，每一个节点的每一个参数都会有一个梯度，梯度向量的每个元素表示该特定元素对最终函数error的影响大小；（在进阶篇会通过网络的数学符号化表达，尝试具体的感知参数矩阵的大小；）<br>反向传播算法本质上是一个让网络结构和外界环境关联起来的反馈系统，梯度下降法是一种具体的更新策略，使用梯度信息实现参数的更新。把学习问题转化成了最优化问题，能够让每一个神经元（感知机节点）向着可能优化的方向不断变化并得到激励反馈的机制。也就是让网络动起来，让数据塑造神经网络的一种方法。需要注意的是在使用时，为了保持这种反馈链接的存在，反向传播要求神经元（节点）的激励函数可微。</li></ul>]]>
    </content>
    <id>https://duckywang.github.io/2023/07/23/%E5%A6%82%E4%BD%95%E7%90%86%E8%A7%A3BP%E7%AE%97%E6%B3%95%EF%BC%9A%E4%BB%8E%E9%94%99%E8%AF%AF%E4%B8%AD%E5%AD%A6%E4%B9%A0%EF%BC%8C%E5%9C%A8%E4%BC%A0%E9%80%92%E4%B8%AD%E8%BF%9B%E5%8C%96(%E4%B8%80)/</id>
    <link href="https://duckywang.github.io/2023/07/23/%E5%A6%82%E4%BD%95%E7%90%86%E8%A7%A3BP%E7%AE%97%E6%B3%95%EF%BC%9A%E4%BB%8E%E9%94%99%E8%AF%AF%E4%B8%AD%E5%AD%A6%E4%B9%A0%EF%BC%8C%E5%9C%A8%E4%BC%A0%E9%80%92%E4%B8%AD%E8%BF%9B%E5%8C%96(%E4%B8%80)/"/>
    <published>2023-07-22T16:00:00.000Z</published>
    <summary>
      <![CDATA[<p>这个话题我们分为两部分，在「一」中我们主要讨论基础的反向传播和梯度下降原理。</p>
<ul>
<li>初步理解：梯度和反向传播</li>
<li>反向传播要解决什么问题，是如何实现的</li>
</ul>
<p>在「<a href="https://zhuanlan.zh]]>
    </summary>
    <title>如何理解BP算法：从错误中学习，在传递中进化(一)</title>
    <updated>2023-07-22T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ducky</name>
    </author>
    <category term="建模" scheme="https://duckywang.github.io/categories/%E5%BB%BA%E6%A8%A1/"/>
    <category term="机器学习" scheme="https://duckywang.github.io/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    <content>
      <![CDATA[<h2 id="神经网络的基础结构"><a href="#神经网络的基础结构" class="headerlink" title="神经网络的基础结构"></a>神经网络的基础结构</h2><p>多层感知机，也称为MLP模型，是一种层次网络，包括了三个部分，输入层，输出层，和中间层&#x2F;隐藏层；每一层都由特定个数的节点（又可称为神经元）构成。</p><p>每一个节点上的非线性函数称为激活函数，如果缺少了激活函数，神经网络无论有多少层都失去了意义，都只能描述线性关系。</p><p>最基础的MPL是只有一个隐藏层的全链接神经网络，这是最基本的神经网络架构类型。</p><p><img src="/images/posts/mlp-basics/v2-5f7681bc15bf29574df8c33bd53051c6.webp" alt="有两个隐藏层的MLP"></p><p>在深度学习中，神经网络的结构通常包括<strong>输入层、隐藏层和输出层</strong>。其中，输入层的节点数需要与数据形状匹配，隐藏层的节点数需要根据实验和调整找到最佳的节点数，输出层的节点数通常根据任务的要求来定义。此外，<strong>激活函数</strong>也是神经网络中的重要组成部分，常见的有Sigmoid、ReLU、Tanh、Softmax等。以下是神经网络的主要结构和构造方法：</p><table><thead><tr><th>输入层</th><th>输入层的节点数需要与数据形状（维度数量）匹配，否则模型将无法接收正确形状的输入数据。对于每个输入样本，它的特征数量就对应着输入层的节点数。例如，对于图像识别问题，输入层节点数通常等于图像的分辨率乘以通道数。如果图像分辨率为28x28像素，通道数为3（RGB），则输入层的节点数为2352。对于文本处理问题，词嵌入模型通常只需要低维的输入层节点，而词袋模型或one-hot模型就需要词个数那么多的维度&#x2F;节点数了；</th></tr></thead><tbody><tr><td>隐藏层</td><td>中间层的节点数是根据训练数据和模型的复杂度来确定的，这需要进行实验和调整以找到最佳的节点数。一种常见的方法是通过交叉验证来确定中间层的节点数。交叉验证是将数据集分成若干份，其中一部分作为验证集用于验证模型的性能，其他部分作为训练集用于训练模型。然后，多次进行模型训练和验证，并记录模型在验证集上的性能，最终选择最佳的中间层节点数。</td></tr><tr><td>输出层</td><td>输出层的节点数通常根据任务的要求来定义。输出层节点数表示了模型最终需要输出的目标数量，例如分类问题可能需要输出不同类别的概率或标签，回归问题可能需要输出具体的数值等。</td></tr><tr><td>激活函数</td><td>它属于非线性函数，作用于神经元的输出，在神经网络中起到对输入信号进行加工、调整和压缩的作用，将神经元的输出值进行过滤或归一化，使之更符合网络后层的处理需求。常见的有 Sigmoid、ReLU、Tanh、 Softmax等。</td></tr></tbody></table><blockquote><p>深度神经网络的优势在于其层次性，通过多个计算层次、非线性的变换将输入信号逐步转化成更加高级、抽象和有效的特征。</p></blockquote><h2 id="神经网络的层次性"><a href="#神经网络的层次性" class="headerlink" title="神经网络的层次性"></a>神经网络的层次性</h2><p>这一结构的神奇之处在于，像很多经典的公式那样（傅里叶级数、泰勒展开…），<strong>只要隐藏层节点数足够多，就可近似任何连续函数</strong>；而这种多层的神经网络，就称之为深度神经网络。为什么深度神经网络对对数据有着<strong>极强的表征能力</strong>呢？层次性是自然界的基本法则，从微观粒子到整个宇宙，我们周围的世界就是由不同的层次构建起来的。在生物体内，不同细胞有着不同的分工，下一个环节的细胞响应并加工上一个环节细胞的信号&#x2F;分泌物；以视觉系统为例，图像信号从进入眼睛开始，需要经历6-8层信息处理过程，才能在大脑皮层形成对画面的认知和理解；</p><p>这种层次性的意义在于，<strong>下一层不必重复处理上一层的信息</strong>，可以提高效率，<strong>同时关注更高级的信息</strong>，通过叠加层次能够实现能力的跃迁，而非堆叠；当我们忽略信息或知识之间的这种层次性时，由于高层次到低层次信息牵一发而动全身的复杂性，学习难度将会大幅提高；然而，虽然听起来只是增加层次，但是在Hinton提出分层预训练的方法之前，实现多层神经网络的学习一直是非常困难的问题，这也是为什么近十几年深度神经网络才开始大放异彩的原因。</p><h2 id="激活与特征提取"><a href="#激活与特征提取" class="headerlink" title="激活与特征提取"></a>激活与特征提取</h2><p>除了多层次的特点，区别于传统机器学习模型的还有<strong>神经元的激活函数机制</strong>，这使得深度神经网络有了<strong>自动提取数据特征的能力</strong>；如果没有非线性的激活表达，那多么深的网络也形如一层；为什么激活函数有这么大的作用呢？这种非线性变换和生物大脑中神经元的激活状态具有类似性质，在生物神经元中，当神经元接收到足够多的输入信号时，才会处于兴奋状态，输出脉冲，相当于一种阈值判定机制。类似地，在深度神经网络中，激活函数也可以看作是一种阈值判断机制，只有当神经元的输入信号超过一定阈值时，才会输出非零的值。</p><p>这种 ”多层感知机+激活函数” 的结构带来的适应性优势–能够<strong>捕捉到数据之间更为复杂和高级的关系</strong>，让深度学习网络<strong>能够适应各种数据场景</strong>；因此能够在图像识别、自然语言处理、语音识别等领域中得到更好效果。</p><p>当然，由于深度学习提取特征的过程相当黑盒，通常从一个随机数开始，经过<strong>BP算法不断更新到更优</strong>。应用神经网络时，我们需要注意到最后网络参数的生成是由一定的网络超参数（人为设计）和BP反向传播算法根据输入的数据不断调优而形成的，因此神经网络除了部分超参数，很大程度是是<strong>完全黑箱的模型训练</strong>过程。这一过程一般是通过实现神经网络层次结构中不同层之间的参数学习来完成的，因此提取出的特征是由网络学得到的数据中本身就存在的抽象特征，而非用户自定义的。</p><p>尽管如此，可以通过调整神经网络的各层超参数和结构，来对特征提取的过程进行一定的定制和优化。例如，在卷积神经网络中，我们可以调整卷积核的数量、大小和步长等超参数，以及采用不同的卷积核形状、激活函数和池化方式等来定制网络的特征提取能力。此外，还可以使用迁移学习等方法，将已经训练好的神经网络模型迁移到自己的任务上，从而实现定制化的特征提取。</p><p>总结一下，深度神经网络能够通过<strong>多个计算层次、非线性的变换将输入信号逐步转化成更加高级、抽象和有效的特征</strong>；并通过<strong>梯度下降优化算法根据反馈来不断更新各层权重和偏置</strong>，从而得到更优的特征表示。</p>]]>
    </content>
    <id>https://duckywang.github.io/2023/06/23/%E5%9F%BA%E7%A1%80%E7%9A%84%E6%B7%B1%E5%BA%A6%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E2%80%94%E4%BB%8E%E5%A4%9A%E5%B1%82%E6%84%9F%E7%9F%A5%E6%9C%BA%E5%BC%80%E5%A7%8B/</id>
    <link href="https://duckywang.github.io/2023/06/23/%E5%9F%BA%E7%A1%80%E7%9A%84%E6%B7%B1%E5%BA%A6%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E2%80%94%E4%BB%8E%E5%A4%9A%E5%B1%82%E6%84%9F%E7%9F%A5%E6%9C%BA%E5%BC%80%E5%A7%8B/"/>
    <published>2023-06-22T16:00:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="神经网络的基础结构"><a href="#神经网络的基础结构" class="headerlink" title="神经网络的基础结构"></a>神经网络的基础结构</h2><p>多层感知机，也称为MLP模型，是一种层次网络，包括了三个部分，输入层，输出层，和中间]]>
    </summary>
    <title>基础的深度神经网络—从多层感知机开始</title>
    <updated>2023-06-22T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ducky</name>
    </author>
    <category term="构造" scheme="https://duckywang.github.io/categories/%E6%9E%84%E9%80%A0/"/>
    <category term="随笔" scheme="https://duckywang.github.io/tags/%E9%9A%8F%E7%AC%94/"/>
    <content>
      <![CDATA[<p>自从第一个原始部落形成，人类突破了生存这第一个门槛后，很多在生存阶段富有挑战性和冒险的事情有了路径依赖和明确的ROI，就变成了工作，这种充斥在权力金字塔和关系网络中的大大小小的分工，之所以叫它工作是因为：人类天生就不爱工作，人类爱的是一种可以获得金币和多巴胺的路径依赖。</p><h2 id="世界的游戏性本质"><a href="#世界的游戏性本质" class="headerlink" title="世界的游戏性本质"></a>世界的游戏性本质</h2><p>而那些充满变化的不确定性，挑战，得不到的可能性，或者美的感受和享受才真正可以激发人类主观上的热爱和能动性，获得新知，喜悦，荣誉，权力，这才是世界的游戏性本质。工作和职业只是效率导向流通中的间接性产物。</p><h2 id="从效率逻辑中松动"><a href="#从效率逻辑中松动" class="headerlink" title="从效率逻辑中松动"></a>从效率逻辑中松动</h2><p>总有很大一部分工作在做着间接而又间接的事情，而这正是现在一个很矛盾的现象：我们一边嫌弃这些狗屁工作，又同时担心这些工作被AI抢走。</p><p>这是因为人类游戏的精神，游戏的能力和经验，在长期的商业和效率环境下很难发育起来，总要考虑生存，效率，ROI来决定我们的行为；导致我们不得不做自己不喜欢的事情以换取报酬（再实现游戏性的追求），并且这个逻辑看起来似乎非常理所当然。然而，这并非唯一可行的逻辑，赚钱和做不喜欢的事情其实并没有必然的相关性。就像月亮其实抬头就可以看到，不需要先低头去捡六便士。</p><p>但是往往只有“游戏者”才能意识到这一点，而非打工人——农场主时代有奴隶，当今人力资源作为现代商业最宝贵的能源，可以用货币买卖。而这都是因为有大量的工作需要人来完成，以生成足够全人类消费的产品和服务。而这一条件，正在发生变化……</p><p><img src="/image-1.png" alt="linux之父自传-一切为了好玩"></p><h2 id="数字雅典与游戏的-3-0-版本"><a href="#数字雅典与游戏的-3-0-版本" class="headerlink" title="数字雅典与游戏的 3.0 版本"></a>数字雅典与游戏的 3.0 版本</h2><p>随着AI的快速发展，可预见地会接替大量的这种流通中间接性环节，我们逐渐实现在满足总商品和服务生产的同时，减少人力资源投入。（这里还会有一个比较棘手的问题，即分配机制和组织形式如何设计才能保证社会的正常运转，不至于走向贫富差距的严重失控，比如赛博朋克的设定）</p><p>总之，当有越来越多的人可以从消耗精神和意志的工作中解放出来时，人类的游戏天性会被逐步释放和发育，类似数字雅典，随着AI的发展，世界正在从效率的2.0版本进入游戏的3.0版本。那时，生活，工作和游戏的边界越来越模糊。</p><p><img src="/image.png" alt="spaceX发射场"></p>]]>
    </content>
    <id>https://duckywang.github.io/2023/04/24/%E6%B8%B8%E6%88%8F%E4%B8%8E%E5%B7%A5%E4%BD%9C/</id>
    <link href="https://duckywang.github.io/2023/04/24/%E6%B8%B8%E6%88%8F%E4%B8%8E%E5%B7%A5%E4%BD%9C/"/>
    <published>2023-04-23T16:00:00.000Z</published>
    <summary>
      <![CDATA[<p>自从第一个原始部落形成，人类突破了生存这第一个门槛后，很多在生存阶段富有挑战性和冒险的事情有了路径依赖和明确的ROI，就变成了工作，这种充斥在权力金字塔和关系网络中的大大小小的分工，之所以叫它工作是因为：人类天生就不爱工作，人类爱的是一种可以获得金币和多巴胺的路径依赖。</]]>
    </summary>
    <title>随笔-游戏与工作</title>
    <updated>2023-04-23T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ducky</name>
    </author>
    <category term="观测" scheme="https://duckywang.github.io/categories/%E8%A7%82%E6%B5%8B/"/>
    <category term="数据" scheme="https://duckywang.github.io/tags/%E6%95%B0%E6%8D%AE/"/>
    <content>
      <![CDATA[<blockquote><p>前言：对于一门复杂且快速迭代的学科，掌握知识的结构比掌握知识本身更重要，相信很多对数据科学和人工智能有兴趣的朋友一开始总免不了主动或被动的翻看各种大部头的技术书籍。由于技术书籍本身非常微观具体和颇有难度，self-learner往往容易深陷在某几个章节，要么难以持续，要么进展缓慢；倘若一开始，可以顺着一个全局的路线图来学习，本着循序渐进和有的放矢的节奏，那对于人工智能的学习理解会更加高效；</p></blockquote><p>AMAI GmbH是一家位于德国的软件公司，最近在GitHub上发布了一个名为“AI-Expert-Roadmap”的项目。该项目提供了全面的AI领域知识点，几乎涵盖了AI领域所有的内容。如果你想快速入门并成为AI领域的专家，这个路线图可能会给你带来指引。该项目上线短短几天就获得了2.1k颗星的好评。</p><p>本系列的文章将简要地叙述这个学习路线框架，由于篇幅较长建议参考右侧栏目录查看，如果感兴趣可以浏览学习<strong>项目地址</strong>：<a href="https://github.com/AMAI-GmbH/AI-Expert-Roadmap/">https://github.com/AMAI-GmbH/AI…</a></p><h2 id="导言"><a href="#导言" class="headerlink" title="导言"></a>导言</h2><p>这里并非需要严格按照路线图前进，但是需要清楚某个知识在整个框架中的哪一环节，具体对你关心的部分的影响权重如何，是否依赖其他部分的知识；清楚了这个优先级的背景知识，可以帮助我们在自学过程中减少很多焦虑或迷茫~！  </p><p><img src="/images/posts/ai-expert-roadmap/202304102301782.png" alt="要循序渐进，而非直接到深度学习"></p><h2 id="Foundamentals"><a href="#Foundamentals" class="headerlink" title="Foundamentals"></a>Foundamentals</h2><h3 id="矩阵和线性代数基础"><a href="#矩阵和线性代数基础" class="headerlink" title="矩阵和线性代数基础"></a>矩阵和线性代数基础</h3><p>在数据科学和AI领域所接触到的数据和平时我们熟悉的数据最大的区别，就是维度化和向量化，这是因为我们通常需要输入或让机器学习比较复杂的数据结构，这种结构通常就是用向量矩阵来表示的；而对于这种数据类型的计算规则就需要用到线性代数的基础知识；由于课本的线性代数知识比较复杂，建议先了解基础知识，等遇到了具体的问题再具体深入学习对应的工具；  </p><p>必须掌握的基础知识：</p><p>线性代数本质：图像或更高维数据的线性变化，可以总结为在几向量方向的拉伸、旋转；  </p><p>矩阵的运算：点积</p><h3 id="数据库基础"><a href="#数据库基础" class="headerlink" title="数据库基础"></a>数据库基础</h3><h4 id="关系型和非关系型数据："><a href="#关系型和非关系型数据：" class="headerlink" title="关系型和非关系型数据："></a><a href="https://www.dataversity.net/review-pros-cons-different-databases-relational-versus-non-relational/">关系型和非关系型数据</a>：</h4><p>关系数据库就像是一个大型的电子表格，数据存储在由行和列组成的表中，并且需要预定义表的结构和关系。(RDBMS：Relational Database Management Systems)也就是我们常说的SQL database；而非关系型数据库则更像是一个散列表或字典，它们不需要预定义固定的表结构，可以根据需要动态添加新的字段和属性。这种数据库通常适用于半结构化或非结构化数据，例如JSON或XML格式的数据。  </p><p>再举一个例子，关系型数据库就像一家传统的银行，每个客户都有自己的帐户，所有交易记录都按照特定的格式进行记录，并且需要遵守特定的规则和标准。而非关系型数据库就像一个市场摊位，各个商贩可以自由地展示和出售自己的产品，每个商贩也可以随时添加和修改自己的货品和价格。虽然市场摊位没有像银行那么严谨的规定和要求，但它具有更高的灵活性和适应性，能够更好地满足不同的需求。</p><h4 id="基础的SQL语法"><a href="#基础的SQL语法" class="headerlink" title="基础的SQL语法"></a>基础的SQL语法</h4><p>如何查询所谓的关系型数据库呢，我们可以通过数据库查询语言进行；<a href="https://en.wikipedia.org/wiki/Join_(SQL)">SQL</a>（Structured Query Language）是一种用于管理关系型数据库的标准化语言。它可以用来创建、查询、更新和删除数据库中的数据。SQL使用简单易懂的语法，允许我们通过输入各种命令来与数据库交互，比如SELECT、INSERT、UPDATE和DELETE等命令。</p><p>可以把SQL想象成一个非常强大的工具箱，里面有各种各样的工具，帮助我们对数据库进行操作。举个例子，如果我们想要从一个表中检索某些数据，我们可以使用SELECT命令。如果我们想要在表中插入新的数据，我们可以使用INSERT命令。如果我们想要更新表中的数据，我们可以使用UPDATE命令。如果我们想要删除数据，我们可以使用DELETE命令。</p><p>总之，SQL是一种重要的编程语言，它为开发人员提供了一种可靠的方式来管理和操纵数据库中的数据。</p><h4 id="NoSQL"><a href="#NoSQL" class="headerlink" title="NoSQL"></a>NoSQL</h4><p>常见的NOSQL数据库有以下几种：  </p><p>-文档型数据库：MongoDB、Couchbase、RavenDB等。  </p><p>-列族数据库：HBase、Cassandra、Scylla等。  </p><p>-键值对数据库：Redis、Memcached、Couchbase等。  </p><p>-图形数据库：Neo4j、OrientDB、Titan等。  </p><p>-对象数据库：db4o、Versant Object Database等。  </p><p>这些不同类型的NOSQL数据库适用于各种不同的应用场景和需求。例如，文档型数据库通常用于存储半结构化数据，列族数据库通常用于大规模分布式系统，键值对数据库通常用于缓存和快速查找，图形数据库通常用于复杂的网络关系图分析，而对象数据库则更适合面向对象的开发模型。</p><p>和SQL语法的关系：  </p><p>-查询语言：SQL使用结构化查询语言（Structured Query Language）作为查询语言，而NOSQL数据库则根据其特定的数据模型和用途，使用不同的查询语言或API。例如，MongoDB使用MongoDB查询语言（MQL），Cassandra使用CQL（Cassandra Query Language）等等。</p><p>-数据操作：SQL使用标准的INSERT、SELECT、UPDATE和DELETE等命令进行数据操作，而NOSQL数据库则根据其特定的数据模型和查询语言，提供不同的数据操作方式。例如，MongoDB提供了find、insert、update、remove等方法，Redis则提供了get、set、del等命令。</p><p>-索引：SQL数据库通常使用B-tree索引，而NOSQL数据库则根据其特定的数据结构和查询方式，使用不同的索引类型。例如，MongoDB使用B-tree和哈希索引，Cassandra使用SSTable索引等等。</p><h3 id="表格数据："><a href="#表格数据：" class="headerlink" title="表格数据："></a>表格数据：</h3><p>是指按照表格形式组织的数据，其中每一行表示一个记录或实例，每一列表示一个属性或特征，每个记录都有相同的数据结构。因此，表格数据可以用于存储、查询和分析非常规则化的数据集，例如订单信息、客户信息、销售报表等等。表格数据是在计算机科学和数据处理领域中最基本和最常用的类型之一，它们既易于理解又容易处理。许多数据分析工具和技术都是针对表格数据而设计的，例如SQL查询、数据透视表、图表等等。</p><h3 id="DataFrame-Series"><a href="#DataFrame-Series" class="headerlink" title="DataFrame &amp; Series"></a>DataFrame &amp; Series</h3><p>Data Frames和Series是Pandas库中常用的两种非常重要的数据结构。Pandas是一个开源的Python数据处理库，它提供了丰富、高效的数据分析工具，特别适合用于表格型或异质型数据的处理。</p><p><strong>DataFrame</strong>：DataFrame是一种二维表格型数据结构，类似于Excel表格或SQL数据库中的表。每个DataFrame对象都由行和列组成，其中每一列可以是不同的数据类型（例如整数、浮点数、字符串等等）。我们可以将DataFrame看作是由多个Series对象组成的字典，它们共享相同的行索引，但拥有不同的列索引。在Pandas中，DataFrame通常被用来存储和处理大量的结构化数据，例如时间序列数据、金融数据、人口统计数据等等。</p><p><strong>Series</strong>：Series是一种一维数组型数据结构，类似于Python中的列表（list）或Numpy中的一维数组（ndarray）。每个Series对象都由一组数据和一组与之对应的索引组成，它们可以是数字、字符串、布尔值等等。Series可以看作是DataFrame中的一列数据，也可以单独使用，通常用于存储和处理一些简单的数据集合，例如某个特定时期内的温度数据、股票价格变动数据等等。</p><h3 id="数据预加工ETL"><a href="#数据预加工ETL" class="headerlink" title="数据预加工ETL"></a>数据预加工ETL</h3><p>ETL(Extract,Transform,Load)是指从数据源中抽取（Extract）数据，经过转换（Transform）处理，最后加载（Load）到目标库中的一种数据集成方法。ETL通常用于将多个数据源中的数据进行汇聚、清洗、整合和转换，以便更好地支持数据分析、业务决策和数据挖掘等应用。</p><p>用一个比较形象的例子来介绍ETL的过程：假设你正在收集各个城市的天气信息，你需要将不同城市的气温、湿度、降雨量等数据抽取出来，并进行转换和整合，最后汇总到一个数据库中供数据分析专家使用。</p><p>-首先，你需要从各个数据源中抽取数据，例如从气象局网站上爬取每个城市的气象数据。这个过程就是Extract。</p><p>-接下来，你需要对采集到的数据进行转换，例如将不同城市的数据统一格式化，清洗掉不合法或重复的数据，计算平均温度等等。这个过程就是Transform。</p><p>-最后，你需要将处理后的数据加载到目标数据库中，例如使用SQL语句将数据插入到一个关系型数据库中，或者使用Hadoop&#x2F;Hive将数据加载到一个大数据存储中。这个过程就是Load。</p><p>通过ETL的过程，你可以将来自不同数据源的数据进行整合和处理，得到更加规范化、一致性和可靠性的数据集合。这些数据可以用于数据分析、机器学习、业务报表等各种应用场景，帮助你做出更准确、更有针对性的决策。</p><h3 id="Reporting-BI-Analytics"><a href="#Reporting-BI-Analytics" class="headerlink" title="Reporting &amp; BI &amp; Analytics"></a>Reporting &amp; BI &amp; Analytics</h3><p>Reporting、BI和Analytics是数据分析领域中的三个重要概念，都是数据分析领域中的重要概念。报表主要用于展示数据或信息，BI则注重企业数据的转换和利用，Analytics则专注于数据分析和挖掘，发现新的洞见和知识。这些概念在实际应用中有着各自不同的侧重点和目标，但却都能为企业提供更多的商业价值，它们之间有些微妙的不同点：-</p><p>-<strong>Reporting（报表）</strong>：Reporting通常是指展示数据或信息的静态或半静态的格式化文档。这些文档可以是PDF、Excel、Word等各种格式，通常用于告诉人们<strong>什么已经发生、正在发生或可能会发生</strong>。报表往往会根据用户需求生成预定的格式，并在固定时间内自动更新，例如月度财务报告、销售报告、客户报告等等。</p><p>-<strong>BI（商业智能）</strong>：BI是指通过数据挖掘、数据分析、数据可视化和其他技术手段，将企业数据转换为有价值的信息和洞见。BI旨在帮助企业做出更明智的决策，优化业务流程和提高效率。与报表不同的是，BI通常会涉及对历史数据和趋势的分析以及对未来情景的模拟和预测，同时也可以使用交互性的可视化工具，让用户能够更好地理解数据和信息。</p><p>-<strong>Analytics（分析）</strong>：Analytics通常被看作是BI的一部分，它着重于数据分析和挖掘，通过使用各种技术和工具对数据进行挖掘和解释，以发现新的信息和知识。Analytics可以帮助企业发现隐藏的模式、关联和趋势，进而提供更具体、更深入的见解，从中获得更好的商业价值。</p><h3 id="Data-Formats-常见的数据交换格式"><a href="#Data-Formats-常见的数据交换格式" class="headerlink" title="Data Formats 常见的数据交换格式"></a>Data Formats 常见的数据交换格式</h3><p>数据交换格式是指用于在不同系统之间传输和共享数据的一种标准化格式。数据交换格式通常包括了数据结构、编码规则和交换协议等多个方面，其目的是为了保证不同系统之间能够正确地解析和使用数据。  </p><p>在实际应用中，不同的系统可能会使用不同的数据格式来存储和处理数据，这就对数据的交换和共享带来了一些困难。为了解决这个问题，人们设计出了一系列标准化的数据交换格式，例如JSON、XML、CSV、Protobuf、Avro等等。这些数据交换格式具有以下特点：</p><h4 id="JSON"><a href="#JSON" class="headerlink" title="JSON"></a>JSON</h4><p>JSON（JavaScript Object Notation）：JSON是一种轻量级的数据交换格式，通常用于Web应用程序中的数据传输。JSON采用基于键值对的方式存储数据，支持多层嵌套结构，可以表示复杂的数据结构。它的语法简洁明了，易于阅读和编写，并且能够被大部分编程语言解析和生成。因此，在互联网领域，JSON已经成为了最流行的数据格式之一。</p><h4 id="XML"><a href="#XML" class="headerlink" title="XML"></a>XML</h4><p>XML（Extensible Markup Language）：XML也是一种用于数据交换的标记语言，它支持自定义标签和属性，可以表示非常复杂的数据结构。XML在Web服务、文档传输、配置文件等方面非常常见，但由于其标签比较冗长，语法相对复杂，因此在数据传输方面逐渐被JSON所取代。</p><h4 id="CSV"><a href="#CSV" class="headerlink" title="CSV"></a>CSV</h4><p>CSV（Comma-Separated Values）：CSV是一种简单的纯文本文件格式，它使用逗号或其他分隔符将数据字段分隔开，每行表示一个记录或实例。CSV最初是电子表格软件中的一种常用数据格式，但现在已经广泛应用于数据交换和数据处理领域。CSV的优点是语法简单，易于生成和解析，并且可以作为多个数据分析工具之间的通用格式进行数据转换。</p><h3 id="正则表达式RegExp"><a href="#正则表达式RegExp" class="headerlink" title="正则表达式RegExp"></a>正则表达式RegExp</h3><p>（Regular Expression），简称为Regex或RegExp，是一种用于字符串匹配和文本处理的表达式语言。它是通过定义规则来匹配和处理字符串的一种方式，可以在不知道具体字符串内容的情况下，快速地检索、替换和提取字符串。  </p><p>正则表达式通常由各种字符和特殊符号组成，这些符号代表着某些意义或规则。例如，使用字符集合[]来表示一个字符集合，使用量词符{}来表示匹配次数，使用锚点^和$来表示字符串的开头和结尾等等。正则表达式的规则非常灵活，可以根据需要自由组合和扩展，以满足不同的字符串匹配和文本处理需求。可以了解比较基础的正则语法，具体的语法也是可以等到使用时再进行学习和查询；  </p><p><img src="/images/posts/ai-expert-roadmap/202304102323252.png" alt="数据，一切的基础"></p><h3 id="Python-Programming"><a href="#Python-Programming" class="headerlink" title="Python Programming"></a>Python Programming</h3><h4 id="Python-基础"><a href="#Python-基础" class="headerlink" title="Python 基础"></a>Python 基础</h4><h5 id="Python表达式"><a href="#Python表达式" class="headerlink" title="Python表达式"></a>Python表达式</h5><p>Expressions是Python程序中的一种基本元素，它们由变量、操作符和函数组成，用于计算并返回一个值。Python表达式可以用于各种场合，例如赋值语句、条件语句、循环语句和函数调用等。Python表达式通常由以下几个部分组成：</p><p>-变量：变量是Python程序中的一个标识符，用于存储和处理数据。在表达式中，我们可以使用变量来表示一个值或对象。</p><p>-操作符：操作符是用于进行数学运算、比较和逻辑判断的符号。常见的操作符包括加号+、减号-、乘号*、除号&#x2F;、等于号&#x3D;、大于号&gt;等等。</p><p>-函数：函数是一段可重复使用的代码块，用于封装和执行特定的任务。在表达式中，我们可以使用内置函数或自定义函数来执行特定的计算和操作。  </p><p>例如，下面是一个简单的Python表达式，在这个表达式中，变量x和y分别被赋值为10和5，z被计算为(x+y)*2的结果，最终输出z的值20：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1234</span><br></pre></td></tr></table></figure><h5 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h5><p>Python中的变量（Variables）是用于存储数据值的标识符，可以通过变量名来访问和操作对应的数据。在Python中，变量不需要显式地声明，而是在第一次赋值时自动创建，并且可以随时重新赋值。</p><p>以下是一些常见的Python变量类型：</p><p>-整数：整数类型（int）用于存储整数值，例如：x &#x3D; 10</p><p>-浮点数：浮点数类型（float）用于存储实数值，例如：y &#x3D; 3.14</p><p>-布尔值：布尔类型（bool）用于存储True或False两种值，例如：z &#x3D; True</p><p>-字符串：字符串类型（str）用于存储文本，例如：name &#x3D; “Bob”</p><p>变量名必须遵循一定的命名规则，通常采用小写字母和下划线的组合，例如：my_variable、person_name等。此外，在Python中还有一些约定俗成的命名规则，例如：类名采用驼峰命名法、私有变量前面加上下划线等。</p><p>在Python中，变量的类型是动态的（Dynamic Typing），即它们的类型可以随着赋值操作而改变。例如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">12</span><br></pre></td></tr></table></figure><p>总之，Python中的变量是用于存储数据值的标识符，可以随时重新赋值，并且可以自动推导出其类型。开发者需要遵循命名规则和约定俗成的命名方式(见PEP 8)，以提高代码的可读性和可维护性。</p><h5 id="数据格式"><a href="#数据格式" class="headerlink" title="数据格式"></a>数据格式</h5><p>Data Structures  </p><p>Python中的数据结构（Data Structures）是一种用于组织和存储数据的方式，可以支持各种不同类型的数据操作。Python提供了多种内置的数据结构，包括列表、元组、字典、集合等。</p><p>以下是一些常见的Python数据结构：</p><p>-列表（List）：列表是一种有序的数据结构，可以存储任意数量的元素，并且支持动态添加、删除、修改等操作。例如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1</span><br></pre></td></tr></table></figure><p>-元组（Tuple）：元组也是一种有序的数据结构，类似于列表，但是它的元素不可修改。例如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1</span><br></pre></td></tr></table></figure><p>–字典（Dictionary）：字典是一种键值对的数据结构，可以通过键来访问对应的值，支持动态添加、删除、修改等操作。例如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1</span><br></pre></td></tr></table></figure><p>-集合（Set）：集合是一种无序的数据结构，可以存储任意数量的元素，并且自动去重。例如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1</span><br></pre></td></tr></table></figure><p>除了以上内置的数据结构之外，Python还支持其他一些高级的数据结构，例如堆（Heap）、队列（Queue）等，它们可以在不同的场景下提高代码的效率和可读性。</p><p>总之，Python中的数据结构是一种用于组织和存储数据的方式，开发者可以根据具体需求选择适合的数据结构，并且灵活地使用内置方法和操作来对其进行增删改查等操作。</p><h5 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h5><p>在Python中，函数（Function）是一种可重用的代码块，可以接受输入参数并返回输出结果。通过定义封装和调用，函数能够提高代码的可读性、可维护性和复用性，常常被用于封装特定功能和算法。  </p><p>在Python中，函数定义采用关键字def，后面跟着函数名和参数列表，参数列表中的参数可以有默认值，也可以使用带*的元组形式来接收任意数量的位置参数，或者使用带**的字典形式来接收任意数量的关键字参数。例如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1234567891011121314151617181920</span><br></pre></td></tr></table></figure><p>Python 主要的内置函数查询</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">123</span><br></pre></td></tr></table></figure><p><strong>map</strong>：主要联合其他函数使用，将函数依次作用到序列的每个元素，得到一个新的序列。  </p><p><strong>filter</strong>：是将传入的函数依次作用于每个元素，然后根据返回值是True还是False决定保留还是丢弃该元素，主要对序列的值进行过滤  </p><p><strong>sorted</strong>：sorted(iterable,key&#x3D;None, reverse&#x3D;False)接受一个key函数来实现对可迭代对象进行自定的排序  </p><p><strong>reduce</strong>：指定列表中两两相邻元素的结合条件</p><p><strong>迭代器和生成器</strong>：都是 Python 中用来处理集合对象的概念。</p><p>-迭代器是Python最强大的功能之一，是访问集合元素的一种方式。 迭代器是所有包含了__iter__() 和__next__() 方法的对象。其中__iter__() 方法返回迭代器对象本身，而__next__() 方法返回集合中的下一个元素。当没有更多元素时，该方法应该引发 StopIteration 异常。通常可以用于遍历可视化图像数据集；</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">123456</span><br></pre></td></tr></table></figure><p>以下是一些常见的数据结构，也是 Python 内置的迭代器类型：</p><p>列表（list）、元组（tuple）和集合（set）等序列类型都支持迭代器协议，因此它们可以被视为迭代器。</p><p>字典（dict）类型虽然不是序列，但也支持迭代器协议。当我们对一个字典进行迭代时，实际上是在遍历它的键。</p><p>文件（file）类型也实现了迭代器协议，每次迭代会返回文件中的下一行。</p><p>-在Python中，使用了yield的函数被称为生成器，生成器则是一种特殊的迭代器，它基于函数生成值序列。在函数内部，使用 yield 语句产生值。每次调用生成器的 next() 方法时，它会执行到 yield 语句处并返回一个值。再次调用 next() 方法时，该函数将从上次离开的地方恢复执行。和其他函数不同的是，每当程序执行完语句时，程序就会暂停执行。  </p><p>以下是一个简单的生成器示例，生成斐波那契数列：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1234567891011</span><br></pre></td></tr></table></figure><p>生成器会无限地生成斐波那契数列，但在这个例子中我们使用了一个 break 语句来限制输出的数量。每次调用 next() 方法时，该生成器函数都会在 yield 语句处暂停并返回一个值（即当前斐波那契数），直到再次被调用以产生下一个值。</p><p>除了以上特性之外，Python函数还支持闭包、装饰器等高级特性，可以实现更加灵活和高效的编程方式。</p><h5 id="包管理语言-依赖管理器"><a href="#包管理语言-依赖管理器" class="headerlink" title="包管理语言&amp;依赖管理器"></a>包管理语言&amp;依赖管理器</h5><p>包管理语言是指一种用于管理特定编程语言或平台的软件包的工具或系统。它们提供了一种简单的方式来安装、升级和删除软件包，并解决软件项目中的依赖关系。在包管理语言中，软件包通常被存储在公共或私有的存储库（如npm、NuGet、PyPI等）中，并且可以通过特定的命令行工具进行访问和管理。这些工具可以下载和安装软件包及其依赖项，同时还可以提供其他功能，例如搜索和列出可用的软件包、创建和发布软件包等。</p><p>Dependency manager（依赖管理器）是指一种工具，用于管理软件项目中的依赖关系。在软件开发中，通常需要使用许多不同的库和框架来构建一个功能完整的应用程序，这些库和框架之间可能存在复杂的依赖关系。使用依赖管理器可以自动地解决这些依赖关系，安装和升级所需的包和库，从而简化了开发者的工作流程，提高了项目的可维护性和可重用性。目前比较知名的依赖管理器有npm、pip、Maven等。</p><p>包管理器通常包含依赖管理器的功能；</p><p>Python 常见的包管理工具有：</p><p>pip：Python 的默认包管理器，可以从 PyPI（Python Package Index）上安装、升级和卸载各种 Python 包。</p><p>Anaconda：一种针对数据科学领域的 Python 发行版，内置了众多数据分析和科学计算常用的包，可以使用 conda 进行包管理。</p><p>easy_install：另一种 Python 包安装工具，与 pip 类似，但已经逐渐被取代。</p><p>virtualenv：一种 Python 虚拟环境管理工具，可以创建独立的 Python 环境，使得不同项目之间可以隔离开来并且使用不同版本的 Python 和不同的库。</p><h5 id="Codestyle"><a href="#Codestyle" class="headerlink" title="Codestyle"></a>Codestyle</h5><p>Codestyle是指编写代码时所遵守的规范和约定，它包括了代码组织、命名规则、注释风格、缩进方式、代码结构等方面的要求。能够提高代码的可读性、可维护性和可扩展性，从而降低代码出错和重构的风险。  </p><p>PEP 8：PEP 8是Python语言的官方Codestyle规范，提供了关于代码布局、注释、命名、字符串引号、缩进等方面的建议。它强调代码的可读性和一致性，并且被广泛视为Python开发中的最佳实践。  </p><p>以下是主要的规则：  </p><p>缩进：使用四个空格作为缩进，不要使用制表符。</p><p>行长：每行代码不超过 79 个字符。</p><p>函数和类命名：使用小写字母和下划线分隔单词的方式来命名函数和类，例如 my_function、my_class。</p><p>变量命名：同样使用小写字母和下划线分隔单词的方式来命名变量，例如 my_variable。</p><p>空格：在运算符前后加上一个空格，但是在括号内部不加空格。</p><p>注释：使用注释来解释代码的意图，注释应该清晰、简洁、易于理解。</p><p>导入格式：每个导入应该独占一行，并放置在文件开头。标准库模块应该先导入，然后是第三方模块，最后是本地模块。</p><p>空行：使用空行分隔函数和类定义以及函数内的逻辑块，但是不要滥用空行。</p><h4 id="常用库"><a href="#常用库" class="headerlink" title="常用库"></a>常用库</h4><h5 id="Numpy"><a href="#Numpy" class="headerlink" title="Numpy"></a>Numpy</h5><p>NumPy提供了高效的数组操作和数学函数，这使得它成为数值分析、科学计算和数据科学任务的首选库之一。它支持多维数组，包括向量、矩阵和张量，并且提供了广泛的数学函数和线性代数运算。更适合数值处理的场景。此外，NumPy还具有良好的内存管理和优化，因此在处理大型数据集时非常快速和高效。</p><h5 id="Pandas"><a href="#Pandas" class="headerlink" title="Pandas"></a>Pandas</h5><p>Pandas是一个基于NumPy构建的库，它提供了更高级别的数据结构，例如Series和DataFrame，这些结构与传统的SQL数据库表非常相似。适合各种类型的异质性数据，使用Pandas，可以轻松地读取、写入、转换和过滤数据，以及执行聚合、重塑和透视等常见操作。Pandas内置了许多强大的函数和方法，可以利用Python的灵活性和易用性来完成复杂的数据处理任务。</p><h4 id="virtual-environment"><a href="#virtual-environment" class="headerlink" title="virtual environment"></a>virtual environment</h4><p>虚拟环境是隔离的 Python 环境，在其中你可以为特定的项目安装包。这很有用，因为不同的项目可能需要相同包的不同版本，甚至不同版本的 Python 本身。通过使用虚拟环境，你可以避免包之间的冲突，并确保你的项目具有所需的依赖项。</p><p><a href="https://docs.python-guide.org/dev/virtualenvs/">Pipenv</a>是一个用于 Python 项目的虚拟环境和包管理工具。它为你的项目创建并管理虚拟环境，使你可以安装包而不影响系统上全局的 Python 安装。可以通过终端来运行；</p><h4 id="Jupyter-Notebooks-Lab"><a href="#Jupyter-Notebooks-Lab" class="headerlink" title="Jupyter Notebooks &#x2F; Lab"></a>Jupyter Notebooks &#x2F; Lab</h4><p>Jupyter Notebook 和 Jupyter Lab都是基于Web的交互式计算环境，用于创建和贡献文档，其中包括代码、方程式、可视化图标以及文字说明等元素。他们通常运行在本地计算机或远程服务器上，并且都支持多项语言，包括Python、R、Julia 等。</p><p>Jupyter Notebook 是最早的 Jupyter 项目，它通过单元格的方式组织代码和文本，并支持即时运行代码并查看输出结果。这些单元格可以随时修改、重新运行，并与其他单元格进行交互。Jupyter Notebook 还支持 Markdown 来添加富文本说明、数学公式和图像等内容。</p><p>Jupyter Lab 是 Jupyter Notebook 的下一代版本，增加了许多强大的功能和改进，例如更好的多窗口管理、扩展性和自定义界面。它还支持在同一个界面中同时打开多个文件类型（如 Notebooks、文本文件、终端等）。</p><p>总的来说，Jupyter Notebooks 和 Jupyter Lab 非常适合数据分析、科学计算和软件开发等领域，它们使得工作流程更加高效、可重复和易于分享。要在本地使用Jupyter Notebook，您需要安装<a href="https://www.anaconda.com/products/individual">Anaconda</a>或Miniconda。这些是Python发行版，包括Jupyter Notebook和其他常用数据科学工具。</p><p><img src="/images/posts/ai-expert-roadmap/202304110817096.png" alt="Python基础"></p><h3 id="Data-Sources"><a href="#Data-Sources" class="headerlink" title="Data Sources"></a>Data Sources</h3><h4 id="Data-mining"><a href="#Data-mining" class="headerlink" title="Data mining"></a>Data mining</h4><p>数据挖掘是关于如何实现（商业）问题&#x2F;目标的事情，是充分挖掘已知信息，来推测未知信息；通常在一个完整的建模分析中，数据挖掘的时间往往大于所谓的分析时间，数据质量，维度特征的重要性非常高，尤其是在机器学习中，不同特征的选取直接会对模型效果有较大影响；而在深度学习和集成学习中，由于神经网络的结构会天然对特征进行筛选，而机器往往比人类完成的会更好，因此很多场景中神经网络模型要比机器学习出色很多，这也说明了数据挖掘的重要性；</p><h4 id="Web-Scraping"><a href="#Web-Scraping" class="headerlink" title="Web Scraping"></a>Web Scraping</h4><p>爬虫：网页数据检索&#x2F;抓取</p><p>爬虫好处：  </p><p>· 能够批量且及时的更新你所关注的信息，听上去也是一种非常geek的信息获取方式，这种信息输入模型或直接提取能够发挥较大的实用价值；  </p><p>爬虫劣势：  </p><p>· 爬虫语言本身是一种相对静态获取信息的方式，因此随着要爬取对象包含JavaScript代码的多少(当网页中大量使用JavaScript时，这些JavaScript代码可以对爬虫产生很大的影响，包括页面中的内容发生改变、URL的生成发生变化、内容的异步加载等，这都可能导致爬虫难以成功地提取所需的数据)，难度会不断上升，通常需要更为复杂的工具，例如Selenium等，以便能够完全模拟浏览器的行为来获取所需的数据；  </p><p>· 随着AI的发展，AI能够自行检索网络信息，在信息处理领域人工智能的价值越来越大，因此掌握爬虫技术的性价比会越来越低；  </p><p>· 爬虫需要遵守robots.text君子协议，基本上有用的信息都反爬，所以爬虫往往需要肩负法律风险；  </p><p>· 因为网页通常是出于不断迭代中的，反爬技术也在不断更新，因此维护一段爬虫代码对精力投入的要求也是比较高的；</p><p>小结，爬虫只是一种互联网信息的获取方式，有很多获取信息的方式，需要考虑使用成本和方便程度，重要的是是否能够获取的信息，让信息为你所用；比如下一part，就会展示其实有很多组织和个人在做优质信息的处理和分享工作；如果更好地使用优质低成本的公开信息，也许更有价值；</p><h4 id="Awesome-Public-Datasets"><a href="#Awesome-Public-Datasets" class="headerlink" title="Awesome Public Datasets"></a>Awesome Public Datasets</h4><p><a href="https://github.com/awesomedata/awesome-public-datasets">分类目学科的官方数据目录</a></p><h4 id="Kaggle"><a href="#Kaggle" class="headerlink" title="Kaggle"></a>Kaggle</h4><p>Kaggle 上有很多竞赛会提供高质量且真实的数据集供大家使用学习，这里有一些使用tips~</p><ol><li>在Kaggle平台上可以找到各种主题的数据科学竞赛，包括分类、回归、聚类、自然语言处理、图像识别、时间序列预测等。寻找感兴趣的竞赛，并阅读比赛的描述、数据、评估标准等信息。</li><li>在参加比赛之前，需要先了解比赛所提供数据的格式、特点以及数据分布等情况。可以下载并分析数据，挖掘数据背后的信息。</li><li>在得到数据之后，可以根据比赛要求和自己的理解，构建和训练本地的机器学习模型，进行组合调参等优化，提高模型的预测表现。</li><li>当完成模型训练后，需要将模型提交到Kaggle竞赛平台以进行评估。提交后Kaggle平台将使用测试数据集来评估模型的性能，给出排名和评估指标。但是对于初学者，排名也许不是最重要的，而是理解不同模型方法对模型准确性的影响，不断积累对数据挖掘的模型经验才是最重要的；</li><li>参考讨论区：在参加比赛的过程中，可以参考讨论区查看其他用户的解决方案和经验，同时也可以在讨论区提出自己的问题与其他用户交流和讨论。</li></ol><p><img src="/images/posts/ai-expert-roadmap/202304151319022.png" alt="Data Sources"></p><h3 id="常见的数据挖掘方法"><a href="#常见的数据挖掘方法" class="headerlink" title="常见的数据挖掘方法"></a>常见的数据挖掘方法</h3><h4 id="PCA-主成分分析"><a href="#PCA-主成分分析" class="headerlink" title="PCA 主成分分析"></a>PCA 主成分分析</h4><p>PCA是用信息中的主要成分表示原信息的特征，是通过降维进行信息压缩（降维）的一种方式；</p><p>原理：首先去中心化，然后旋转遍历找最合适的坐标系向量（找方差最大的方向，数据分布最分散的方向）原数据在正交轴上投影的分布，方差越大，数据越分散，能够保存样本点最多特征信息的最佳坐标系–&gt;压缩后尽可能保留更多的信息量；</p><p>度量指标：这里的最佳坐标系可以理解为初始坐标系的线性变化，通常我们用协方差来度量 坐标系信息线性变换每个瞬间的离散程度；协方差表示：矩阵中的变量之间，相关性如何；xy同向变动时协方差较大，xy反方向变动时协方差为负；</p><p>迭代：由于协方差在数量大时计算相当复杂，因此在大数据量的情况下我们可以通过SVD直接计算PCA；在线性代数领域优化SVD的算法优化非常多，因此SVD在进行矩阵分解的计算有更优秀的性能；SVD的右奇异矩阵起到的作用同样是对列数即特征维度的压缩，等同于PCA的作用；</p><h4 id="Dimensionality-Numerosity-Reduction"><a href="#Dimensionality-Numerosity-Reduction" class="headerlink" title="Dimensionality &amp; Numerosity Reduction"></a>Dimensionality &amp; Numerosity Reduction</h4><p>数据归约：通过数据维度降维或样本量减少的方式，优化数据分析的一种数据挖掘技术；  </p><p>常用方法：</p><ol><li>抽样（Data Sampling）</li><li>聚类（Clustering）</li><li>汇总（Data Aggregation）</li><li>泛化（Data  Generalization）：用通用性的数据替代某些数据，使数据集仍能代表本身的重要信息；</li><li>数据压缩（Data Compression）：通常有有损压缩和无损压缩，在图像处理，视频等高维数据中比较多常见；</li></ol><p>Pros ：  </p><p>· 提升学习效率，更快；  </p><p>· 提成学习性能（准确性，降低干扰）；  </p><p>· 节省存储成本；  </p><p>· 降低数据的解释成本（减少低相关的数据）；  </p><p>Cons ：  </p><p>· 信息有损  </p><p>· 影响准确性（当不小心删减了重要信息时）  </p><p>· 提升数据的解释成本（当删减过多上下文，导致数据语境不明）  </p><p>· 计算成本：进行数据压缩同样需要大量的机器计算成本</p><h4 id="归一化-Normalization"><a href="#归一化-Normalization" class="headerlink" title="归一化 Normalization"></a>归一化 Normalization</h4><p>归一化可以尽可能地保留数据内部样本之间的分布关系，而忽略数据绝对值的信息，从而使不同数据集之间的数据有可比性，能够更公允的对齐不同数据间的情况；</p><p>常见的操作：</p><ol><li>最大-最小规范化（Min-max normalization）：将数据转换到[,1]区间内。公式为：x_norm &#x3D; (x - min(x)) &#x2F; (max(x) - min(x))</li><li>z-score标准化（Z-score normalization）：将数据通过平均数偏移和标准偏差缩放转换到标准正态分布上。公式为：x_norm &#x3D; (x - mean(x)) &#x2F; std(x)</li><li>小数定标规范化（Decimal scaling normalization）：通过缩放因子10的幂次，将数据转换为[-1,1]或[,1]区间内。公式为：x_norm &#x3D; x &#x2F; (10 ^ j)，其中j为作为缩放因子的幂次。</li><li>归一化积分值（Normalization by integral）：将数据划分为若干区间，然后将每个区间的数据值除以整个数据集的总和。公式为：x_norm &#x3D; x &#x2F; Sum(x)</li></ol><p><img src="/images/posts/ai-expert-roadmap/20230415132210.png" alt="Data Exploratory"></p><h4 id="数据清洗"><a href="#数据清洗" class="headerlink" title="数据清洗"></a>数据清洗</h4><blockquote><p>Quality data beats fancy algorithms.  </p><p>尤其是在在如今大模型、通用人工智能模型表现出如此智能化&#x2F;涌现 能力的今天，数据质量的重要性将比以往任何时候都更加重要；  </p><p>在处理和清洗数据前，搞清楚的明白你的目的，比采取任何行动都至关重要；</p></blockquote><p>一些CheatSheet：</p><ol><li>标准「数据质量」：正确&#x2F;有用性，准确性，完整性，连续性&#x2F;一致性，统一性</li></ol><p>· 数据可用性：数据格式、数据取值范围、空值检查&#x2F;补全、数据去重、枚举值梳理、外键约束（一个表的外键必须存在于另一个表的主键）交叉验证；  </p><p>· 数据格式化处理  </p><p>· 数据有用性校验（end_date&gt;start_date）  </p><p>· 量纲统一<br>2. ToDo「工作流」：数据检查、数据清洗、数据可用性处理、数据报告  </p><p>· 数据检查： 整体探查，可视化  </p><p>· 数据清洗：不相关数据删除，重复数据合并，数据类型转换，格式纠正（eg：移除不必要的空格），标准化、量纲&#x2F;范围修正（极端值剔除），归一化，空值处理（丢弃、推断补充、相似移植，标识（0&#x2F;missing），数据逻辑校验（如果指标间有计算关系可以校验）</p><blockquote><p>关于标识 Flag的处理方法的适用场景，可以参考幸存者偏差，因为很可能空值的样本本在总体中的分布式有原因的而非随机，那这种情况空值本身也是一种特征（删除和推断都会让我们丢失信息），如果被填充或者删除都会影响学习效果；  </p><p>·记录在数据清洗中的主要工作，帮助我们在需要时进行回溯或迭代；</p></blockquote>]]>
    </content>
    <id>https://duckywang.github.io/2023/02/01/%E6%95%B0%E6%8D%AE%E5%BA%94%E7%94%A8%E5%AD%A6%E4%B9%A0roadmap/</id>
    <link href="https://duckywang.github.io/2023/02/01/%E6%95%B0%E6%8D%AE%E5%BA%94%E7%94%A8%E5%AD%A6%E4%B9%A0roadmap/"/>
    <published>2023-01-31T16:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>前言：对于一门复杂且快速迭代的学科，掌握知识的结构比掌握知识本身更重要，相信很多对数据科学和人工智能有兴趣的朋友一开始总免不了主动或被动的翻看各种大部头的技术书籍。由于技术书籍本身非常微观具体和颇有难度，self-learner往往容易深陷在某几个]]>
    </summary>
    <title>Roadmap to becoming an Artificial Intelligence Expert in 2022</title>
    <updated>2023-01-31T16:00:00.000Z</updated>
  </entry>
</feed>
