<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Sanzo Blog</title>
  
  
  <link href="https://sanzo.top/blog/atom.xml" rel="self"/>
  
  <link href="https://sanzo.top/blog/"/>
  <updated>2021-06-13T08:09:21.000Z</updated>
  <id>https://sanzo.top/blog/</id>
  
  <author>
    <name>Sanzo</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>线性代数</title>
    <link href="https://sanzo.top/blog/Blog/LinearAlgebra/"/>
    <id>https://sanzo.top/blog/Blog/LinearAlgebra/</id>
    <published>2021-06-13T09:09:21.000Z</published>
    <updated>2021-06-13T08:09:21.000Z</updated>
    
    <content type="html"><![CDATA[<p>线性代数笔记。</p><span id="more"></span><h1 id="基础知识"><a href="#基础知识" class="headerlink" title="基础知识"></a>基础知识</h1><h2 id="行列式"><a href="#行列式" class="headerlink" title="行列式"></a>行列式</h2><blockquote><p>二阶行列式</p></blockquote><p>$\begin{vmatrix} a_{11} &amp; a_{12} \\  a_{21} &amp; a_{22} \\  \end{vmatrix} &#x3D; a_{11}a_{22} - a_{12}a_{21}$</p><blockquote><p>三阶行列式</p></blockquote><div>$ \begin{vmatrix} a_{11} & a_{12} & a_{13} \\  a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{vmatrix} = a_{11}a_{22}a_{33} + a_{12}a_{23}a_{31} + a_{13}a_{21}a_{32} -a_{13}a_{22}a_{31} - a_{23}a_{32}a_{11} - a_{33}a_{12}a_{21}$</div><p><img src="/blog/img/Blog/LinearAlgebra/image-20210111133613519.png" alt="image-20210111133613519"></p><p>对于更高阶的行列式，一般将行列式转为三角形，这样只用计算对角线的乘积即可。</p><h2 id="余子式"><a href="#余子式" class="headerlink" title="余子式"></a>余子式</h2><p>$n$阶行列式，把第$a_{ij}$所在的行列删除，留下的$n-1$阶行列式称为余子式，记为$M_{ij}$。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20210111133933964.png" alt="image-20210111133933964"></p><h2 id="代数余子式"><a href="#代数余子式" class="headerlink" title="代数余子式"></a>代数余子式</h2><p>代数余子式的$A_{ij} &#x3D; -1^{i+j}M_{ij}$。</p><h2 id="伴随矩阵"><a href="#伴随矩阵" class="headerlink" title="伴随矩阵"></a>伴随矩阵</h2><p>代数余子式的转置称为伴随矩阵，只有方阵才有伴随矩阵，记为$A^*$。</p><p>伴随矩阵的性质：</p><p>$AA^* &#x3D; A^*A &#x3D; |A|E$</p><p>$A^{-1} &#x3D; \frac{1}{|A|}A^*（存在A^{-1}）$</p><p>$(A^*)^{-1}&#x3D;(A^{-1})^*&#x3D;\frac{1}{|A|}A$</p><p>$|A^*|&#x3D;|A|^{n-1}$</p><p>$(kA)^*&#x3D;k^{n-1}A^*$</p><h2 id="矩阵的逆"><a href="#矩阵的逆" class="headerlink" title="矩阵的逆"></a>矩阵的逆</h2><p>$A^{-1} &#x3D; \frac{1}{|A|}A^*（存在A^{-1}）$</p><p>$A^{-1} &#x3D; \frac{1}{|A|}A^{*}&#x3D;\frac{1}{ad-bc}\begin{bmatrix}d &amp;-b\ -c &amp; a\end{bmatrix}$</p><p>例：</p><div> $\begin{bmatrix}1&-1\\1&1 \end{bmatrix}^{-1} = \frac{1}{2}\begin{bmatrix}1&1\\-1&1 \end{bmatrix}$</div><div></div><h1 id="线性代数的本质"><a href="#线性代数的本质" class="headerlink" title="线性代数的本质"></a>线性代数的本质</h1><p><a href="https://www.bilibili.com/video/BV1ib411t7YR">b站视频链接</a></p><h2 id="什么是向量"><a href="#什么是向量" class="headerlink" title="什么是向量"></a>什么是向量</h2><p>向量对于不同的学科有不一样的定义。</p><p>物理中的向量有<strong>长度</strong>和<strong>方向</strong>决定，长度和方向不变可以随意移动，它们表示的是同一个向量。</p><p>计算机中的向量更多的是对数据的抽象，可以根据面积和价格定义一个房子$\begin{bmatrix}100m^2\\700000￥\end{bmatrix}$。</p><p>数学中的向量可以是任意东西，只要保证两个<strong>向量的相加</strong>$\vec v + \vec w$以及<strong>数字和向量相乘</strong>$2\vec v$是有意义的即可。</p><p>线性代数中的向量可以理解为一个空间中的箭头，这个箭头起点落在原点。如果空间中有许多的向量，可以点表示一个向量，即向量头的坐标。</p><blockquote><p>向量的基本运算</p></blockquote><p>向量的加法：可以理解为在坐标中两个向量的移动。</p><div>$\begin{bmatrix}   1 \\   2  \end{bmatrix} + \begin{bmatrix}   3 \\   -1  \end{bmatrix} = \begin{bmatrix}   4 \\   1  \end{bmatrix}$</div><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919202730552.png" alt="image-20200919202730552"></p><p>数字和向量相乘：可以理解为向量的缩放。</p><div>$2\begin{bmatrix}   3 \\   1  \end{bmatrix}=\begin{bmatrix}   6 \\   2  \end{bmatrix}$</div><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919202902807.png" alt="image-20200919202902807"></p><h2 id="线性组合、张成空间、基"><a href="#线性组合、张成空间、基" class="headerlink" title="线性组合、张成空间、基"></a>线性组合、张成空间、基</h2><blockquote><p>线性组合</p></blockquote><p>两个数乘向量称为两个向量的线性组合$a\vec v+ b\vec w$。</p><p>两个不共线的向量通过不同的线性组合可以得到二维平面中的所有向量。</p><p>两个共线的向量通过线程组合只能得到一个直线的所有向量。</p><p>如果两个向量都是零向量那么它只能在原点。</p><blockquote><p>张成空间</p></blockquote><p>所有可以表示给定向量线性组合的向量的集合称为给定向量的张成空间（span）。</p><p>一般来说两个向量张成空间可以是直线、平面。</p><p>三个向量张成空间可以是平面、空间。</p><p>如果多个向量，并且可以移除其中一个而不减小张成空间，那么它们是<strong>线性相关</strong>的，也可以说一个向量可以表示为其他向量的线性组合$\vec u &#x3D; a \vec v + b\vec w$。</p><p>如果所有的向量都给张成的空间增加了新的维度，它们就成为线性无关的$\vec u \neq a \vec v + b\vec w$。</p><blockquote><p>基</p></blockquote><p>向量空间的一组及是张成该空间的一个线性无关向量集。</p><h2 id="矩阵与线性变换"><a href="#矩阵与线性变换" class="headerlink" title="矩阵与线性变换"></a>矩阵与线性变换</h2><p>严格意义上来说，线性变换是将向量作为输入和输出的一类函数。</p><p>变化可以多种多样，线性变化将变化限制在一个特殊类型的变换上，可以简单的理解为网格线保持平行且等距分布。</p><p>线性变化满足一下两个性质：</p><ul><li>线性变化前后直线依旧是直线不能弯曲。</li><li>原点必须保持固定。</li></ul><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919212207688.png" alt="image-20200919212207688"></p><p>可以使用<strong>基向量来描述线性变化</strong>：</p><p>通过记录两个基向量$\hat{i}$,$\hat{j}$的变换，就可以得到其他变化后的向量。</p><p>已知向量$\vec v &#x3D; \begin{bmatrix}-1\\2\end{bmatrix}$</p><p>变换之前的$\hat i$和$\hat j$：</p><div>$$\hat{i} = \begin{bmatrix}1 \\   0  \end{bmatrix} \\  \hat{j} = \begin{bmatrix}0 \\   1  \end{bmatrix} \\\vec{v} = -1\hat{i} + 2 \hat{j} = \begin{bmatrix}-1 \\   2  \end{bmatrix}$$<div>变换之后的$\hat i$和$\hat j$：<div>$$\begin{aligned}\hat{i} = \begin{bmatrix}1 \\   -2  \end{bmatrix} \\  \hat{j} = \begin{bmatrix}3 \\   0  \end{bmatrix} \\\vec{v} = -1\hat{i} + 2 \hat{j} &= \begin{bmatrix}5 \\   2  \end{bmatrix} \\  &= -1\begin{bmatrix}1 \\   -2  \end{bmatrix}  + 2 \begin{bmatrix}3 \\  0  \end{bmatrix} \\  &= \begin{bmatrix}1 & 3 \\   -2 & 0  \end{bmatrix}  \begin{bmatrix}-1 \\   2  \end{bmatrix} \\  &= \begin{bmatrix}5 \\   2  \end{bmatrix} \\\end{aligned}$$<div>我们可以将变换后的$\hat i$和$\hat j$写成矩阵的形式：$\begin{bmatrix}1 & 3 \\   -2 & 0  \end{bmatrix}  \begin{bmatrix}-1 \\   2  \end{bmatrix}$，通过矩阵的乘法得到变化后的向量。<p><img src="/blog/img/Blog/LinearAlgebra/image-20200919214800453.png" alt="image-20200919214800453"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919214828033.png" alt="image-20200919214828033"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919214904438.png" alt="image-20200919214904438"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919214934222.png" alt="image-20200919214934222"></p><p>如果变化后的$\hat{i}$和$\hat{j}$是线性相关的，变化后向量的张量就是一维空间：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919215136876.png" alt="image-20200919215136876"></p><h2 id="矩阵乘法与线性变换复合的联系"><a href="#矩阵乘法与线性变换复合的联系" class="headerlink" title="矩阵乘法与线性变换复合的联系"></a>矩阵乘法与线性变换复合的联系</h2><blockquote><p>线性变化的复合</p></blockquote><p>如何描述<strong>先旋转再剪切</strong>的操作呢？</p><p>一个通俗的方法是首先<strong>左乘旋转矩阵</strong>然后<strong>左乘剪切矩阵</strong>。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919221913292.png" alt="image-20200919221913292"></p><p>两个矩阵的乘积需要从右向左读，类似函数的复合。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919221959763.png" alt="image-20200919221959763"></p><p>这样两个矩阵的乘积就对应了一个复合的线性变换，最终得到对应变换后的$\hat{i}$和$\hat{j}$。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919222849490.png" alt="image-20200919222849490"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919222936127.png" alt="image-20200919222936127"></p><p>这一过程具有普适性：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919223010638.png" alt="image-20200919223010638"></p><blockquote><p>矩阵乘法的顺序</p></blockquote><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919223307428.png" alt="image-20200919223307428"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919223234205.png" alt="image-20200919223234205"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919223255780.png" alt="image-20200919223255780"></p><blockquote><p>如何证明矩阵乘法的结合性？</p></blockquote><p>$(AB)C &#x3D; A(BC)$</p><p>根据线性变化我们可以得出，矩阵的乘法都是以CBA的顺序变换得到，所以他们本质上相同，通过变化的形式解释比代数计算更加容易理解。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919223807543.png" alt="image-20200919223807543"></p><h2 id="三维空间的线性变化"><a href="#三维空间的线性变化" class="headerlink" title="三维空间的线性变化"></a>三维空间的线性变化</h2><p>三维的空间变化和二维的类似。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919231921745.png" alt="image-20200919231921745"></p><p>同样跟踪基向量的变换，能很好的解释变换后的向量，同样两个矩阵相乘也是。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200919233624101.png" alt="image-20200919233624101"></p><h2 id="行列式-1"><a href="#行列式-1" class="headerlink" title="行列式"></a>行列式</h2><blockquote><p>行列式的本质</p></blockquote><p>行列式的本质是计算线性变化对空间的缩放比例，具体一点就是，测量一个给定区域面积增大或减小的比例。</p><p>单位面积的变换代表任意区域的面积变换比例。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920130814473.png" alt="image-20200920130814473"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920130933473.png" alt="image-20200920130933473"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920130915512.png" alt="image-20200920130915512"></p><p><strong>行列式的值表示缩放比例。</strong></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920131118018.png" alt="image-20200920131118018"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920131210961.png" alt="image-20200920131210961"></p><p>行列式为什么有负值呢？</p><p><img src="/blog/img/Blog/LinearAlgebra/GIF-2020-9-2013-22-08.gif"></p><p>三维空间的行列式类似，它的单位是一个单位1的立方体。</p><p>三位空间的线性变换，可以使用<strong>右手定则</strong>判断三维空间的定向。如果变换前后都可以通过右手定则得到，那么他的行列式就是正值，否则为负值。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920132802227.png" alt="image-20200920132802227"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920132900515.png" alt="image-20200920132900515"></p><blockquote><p>行列式的计算</p></blockquote><p>二阶行列式</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920133432426.png" alt="image-20200920133432426"></p><p>三阶行列式</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920133410970.png" alt="image-20200920133410970"></p><p>二阶行列式中a、d，表示横向和纵向的拉伸，b、c表示对角线的拉伸和压缩的情况。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920133555705.png" alt="image-20200920133555705"></p><h2 id="逆矩阵、列空间、秩、零空间"><a href="#逆矩阵、列空间、秩、零空间" class="headerlink" title="逆矩阵、列空间、秩、零空间"></a>逆矩阵、列空间、秩、零空间</h2><blockquote><p>线性方程组</p></blockquote><p><img src="/blog/img/Blog/LinearAlgebra/image-20200920141506454.png" alt="image-20200920141506454"></p><p>从几何的角度来思考，矩阵A表示一个线性变换，我们需要找到一个$\vec x$使得它在变换后和$\vec v$重合。</p><blockquote><p>逆矩阵</p></blockquote><p>矩阵的逆运算，记为$\vec A &#x3D; \begin{bmatrix}3&amp;1 \\0&amp;2\end{bmatrix}^{-1}$，对于线程方程$A \vec x &#x3D; \vec v $来说，找到$A^{-1}$就得到解$\vec x &#x3D; A^{-1} \vec v$。</p><div>  $A^{-1}A=\begin{bmatrix}1&0 \\   0&1  \end{bmatrix}$，什么都不做称为恒等变换。<div><blockquote><p>线性方程组的解</p></blockquote><p>对于方程组$A\vec x &#x3D; \vec v$，线性变换A存在两种情况：</p><p>$det(A) \neq0$：这时空间的维数并没有改变，有且只有一个向量经过线性变换后和$\vec v$重合。</p><p>$det(A) &#x3D;0$：空间被压缩到更低的维度，这时不存在逆变换，因为不能将一个直线解压缩为一个平面，这样就会映射多个向量。但是即使不存在逆变换，解可能仍然存在，因为目标$\vec v$刚好落在压缩后的空间上。</p><blockquote><p>秩</p></blockquote><p>秩代表变换后空间的维度。</p><p>如果线性变化后将空间压缩成一条直线，那么称这个变化的秩为1；</p><p>如果线性变化后向量落在二维平面，那么称这个变化的秩为2。</p><blockquote><p>列空间</p></blockquote><p>所有可能的<strong>输出向量</strong>$A\vec v$构成的集合，称为列空间，即所有列向量张成的空间。</p><blockquote><p>零空间（Null space）</p></blockquote><p>所有的线性变化中，零向量一定包含在列空间中，因为线性变换原点保持不动。对于非满秩的情况来说，会有一系列的向量在变换后仍为零向量。</p><p>二维空间压缩为一条直线，一条线上的向量都会落到原点。</p><p><img src="/blog/img/Blog/LinearAlgebra/GIF-2020-9-20-14-36-18.gif"></p><p>三维空间压缩为二维平面，一条线上的向量都会落到原点。</p><p><img src="/blog/img/Blog/LinearAlgebra/GIF-2020-9-20-14-40-00.gif"></p><p>三维空间压缩为一条直线，整个平面上的向量都会落到原点。</p><p><img src="/blog/img/Blog/LinearAlgebra/GIF-2020-9-20-14-43-07.gif"></p><p>当$A\vec x &#x3D; \vec v$中的$\vec v$是一个零向量，即$A\vec x &#x3D; \begin{bmatrix}0 \\0\end{bmatrix}$时，零空间就是它所有可能的解。</p><h2 id="非方阵、不同维度空间之间的线性变换"><a href="#非方阵、不同维度空间之间的线性变换" class="headerlink" title="非方阵、不同维度空间之间的线性变换"></a>非方阵、不同维度空间之间的线性变换</h2><p>不同维度的变换也是存在的。</p><p>一个$3\times2$的矩阵：$\begin{bmatrix}2&amp;0\-1&amp;1\-2&amp;1 \end{bmatrix}$它的集合意义是将一个二维空间映射到三维空间上，矩阵有两列表明输入空间有两个基向量，有三行表示每个向量在变换后用三个独立的坐标描述。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921204842378.png" alt="image-20200921204842378"></p><p>一个$2\times 3$的矩阵：$\begin{bmatrix}3&amp;1&amp;4\1&amp;5&amp;9 \end{bmatrix}$则表示将一个三维空间映射到二维空间上。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921204804360.png" alt="image-20200921204804360"></p><p>一个$1\times 2$的矩阵：$\begin{bmatrix}1&amp;2 \end{bmatrix}$表示一个二维空间映射到一维空间。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921205137915.png" alt="image-20200921205137915"></p><h2 id="点积与对偶性"><a href="#点积与对偶性" class="headerlink" title="点积与对偶性"></a>点积与对偶性</h2><blockquote><p>点积</p></blockquote><p> 对于两个维度相同的向量，他们的点积计算为：$\begin{bmatrix}1\\2\end{bmatrix}\cdot\begin{bmatrix} 3\\4\end{bmatrix}&#x3D;1\cdot3+2\cdot4&#x3D;11$。</p><p>点积的几何解释是将一个向量向一个向量投影，然后两个长度相乘，如果为负数则表示反向。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921213129723.png" alt="image-20200921213129723"></p><p>为什么点积和坐标相乘联系起来了？这和对偶性有关。</p><blockquote><p>对偶性</p></blockquote><p>对偶性的思想是：每当看到一个多维空间到数轴上的线性变换时，他都与空间中的唯一一个向量对应，也就是说使用线性变换和与这个向量点乘等价。这个向量也叫做线性变换的<strong>对偶向量</strong>。</p><p>当二维空间向一维空间映射时，如果在二维空间中等距分布的点在变换后还是等距分布的，那么这种变换就是线性的。</p><p>假设有一个线性变换A$\begin{bmatrix}1&amp;-2\end{bmatrix}$和一个向量$\vec v&#x3D;\begin{bmatrix}4\\3\end{bmatrix}$。</p><p>变换后的位置为$\begin{bmatrix}1&amp;-2\end{bmatrix}\begin{bmatrix}4\\3\end{bmatrix}&#x3D;4\cdot1+3\cdot-2&#x3D;-2$，这个变换是一个二维空间向一维空间的变化，所以变换后的结果为一个坐标值。</p><p>我们可以看到线性变换的计算过程和向量的点积相同$\begin{bmatrix}1\\-2\end{bmatrix}\cdot\begin{bmatrix}4\\3\end{bmatrix}&#x3D;4\cdot1+3\cdot-2&#x3D;-2$，所以向量和一个线性变化有着微妙的联系。</p><p>假设有一个倾斜的数轴，上面有一个单位向量$\vec v$，对于任意一个向量它在数轴上的投影都是一个数字，这表示了一个二维向量到一位空间的一种线性变换，那么如何得到这个线性变化呢？</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921215610833.png" alt="image-20200921215610833"></p><p>由之前的内容来说，我们可以观察基向量$\vec i$和$\vec j$的变化，从而得到对应的线性变化。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921215905156.png" alt="image-20200921215905156"></p><p>因为$\vec i$、$\vec j$、$\vec u$都是单位向量，根据对称性可以得到$\vec i$和$\vec j$在$\vec u$上的投影长度刚好是$\vec u$的坐标。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921220129867.png" alt="image-20200921220129867"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921220208217.png" alt="image-20200921220208217"></p><p>这样空间中的所有向量都可以通过线性变化$\begin{bmatrix}u_x&amp;u_y \end{bmatrix}$得到，而这个计算过程刚好和单位向量的点积相同。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200921220552315.png" alt="image-20200921220552315"></p><p>也就是为什么向量投影到直线的长度，刚好等于它与直线上单位向量的点积，对于非单位向量也是类似，只是将其扩大到对应倍数。</p><h2 id="叉积"><a href="#叉积" class="headerlink" title="叉积"></a>叉积</h2><p>对于两个向量所围成的面积来说，可以使用行列式计算，将两个向量看作是变换后的基向量，这样通过行列式就可以得到变换后面积缩放的比例，因为基向量的单位为1，所以就得到了对应的面积。</p><p>考虑到正向，这个面积的值存在负值，这是参照基向量$\vec i$和$\vec j$的相对位置来说的。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922102602172.png" alt="image-20200922102602172"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922102722945.png" alt="image-20200922102722945"></p><p>真正的叉积是通过两个三维向量$\vec v$和$\vec w$，生成一个新的三维向量$\vec u$，这个向量垂直于向量$\vec v$和$\vec w$所在的平面，长度等于它们围成的面积。</p><p>叉积的反向可以通过右手定则判断：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922103452143.png" alt="image-20200922103452143"></p><p>叉积的计算方法：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922103702614.png" alt="image-20200922103702614"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922103629488.png" alt="image-20200922103629488"></p><h2 id="线性代数看叉积"><a href="#线性代数看叉积" class="headerlink" title="线性代数看叉积"></a>线性代数看叉积</h2><p>参考二维向量的叉积计算：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922122052167.png" alt="image-20200922122052167"></p><p>三维的可以写成类似的形式，但是他并是真正的叉积，不过和真正的叉积已经很接近了。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922122142162.png" alt="image-20200922122142162"></p><p>我可以构造一个函数，它可以把一个三维空间映射到一维空间上。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922122515739.png" alt="image-20200922122515739"></p><p>右侧行列式是线性的，所以我们可以找到一个线性变换代替这个函数。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922122703239.png" alt="image-20200922122703239"></p><p>根据对偶性的思想，从多维空间到一维空间的线性变换，等于与对应向量的点积，这个特殊的向量$\vec p$就是我们要找的向量。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922122835340.png" alt="image-20200922122835340"></p><blockquote><p>从数值计算上:</p></blockquote><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922123007736.png" alt="image-20200922123007736"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922123018405.png" alt="image-20200922123018405"></p><p>向量$\vec p$的计算结果刚好和叉积计算的结果相同。</p><blockquote><p>从几何意义：</p></blockquote><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922122835340.png" alt="image-20200922122835340"></p><p>当向量$\vec p$和向量$\begin{bmatrix}x\y\z \end{bmatrix}$点乘时，得到一个$\begin{bmatrix}x\y\z \end{bmatrix}$与$\vec v$与$\vec w$确定的平行六面体的有向体积，什么样的向量满足这个性质呢？</p><p>点积的几何解释是，其他向量在$\vec p$上的投影的长度乘以$\vec p$的长度。</p><p>对于平行六面体的体积来说，它等于$\vec v$和$\vec w$所确定的面积乘以$\begin{bmatrix}x\y\z \end{bmatrix}$在垂线上的投影。</p><p>那么$\vec p$要想满足这一要求，那么它就刚好符合，长度等于$\vec v,\vec w$所围成的面积，且刚好垂直这个平面。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922123829003.png" alt="image-20200922123829003"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922123858594.png" alt="image-20200922123858594"></p><h2 id="基变换"><a href="#基变换" class="headerlink" title="基变换"></a>基变换</h2><p>标准坐标系的基向量为$\vec {i}: \begin{bmatrix}1\\0 \end{bmatrix}$和$\vec {j}: \begin{bmatrix}0\\1 \end{bmatrix}$，假如詹妮弗有另一个坐标系：她的基向量为$\vec i \begin{bmatrix}2\\1 \end{bmatrix}$和$\vec j \begin{bmatrix}-1\\1 \end{bmatrix}$。</p><p>对于同一个点$\begin{bmatrix}3\\2 \end{bmatrix}$来说他们所表示的形式不同，在詹妮弗的坐标系中表示为$\begin{bmatrix}\frac{5}{3}\\\frac{1}{3} \end{bmatrix}$。</p><p>从标准坐标到詹尼佛的坐标系，我能可以得到一个线性变换$A:\begin{bmatrix}2&amp;-1\\1&amp;1 \end{bmatrix}$。</p><p>如果想知道詹妮弗的坐标系中点$\begin{bmatrix}3\\2 \end{bmatrix}$在标准坐标系的位置，可以通过$\begin{bmatrix}2&amp;-1\\1&amp;1 \end{bmatrix}\begin{bmatrix}3\\2 \end{bmatrix}$得到。</p><p>如果想知道标准坐标系中点$\begin{bmatrix}3\\2 \end{bmatrix}$在詹妮弗坐标系的位置，可以通过$\begin{bmatrix}2&amp;-1\\1&amp;1 \end{bmatrix}^{-1}\begin{bmatrix}3\\2 \end{bmatrix}$得到。</p><p>具体的例子，90°旋转。</p><p>在标准坐标系可以跟踪基向量的变化来体现：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922133429853.png" alt="image-20200922133429853"></p><p>在詹妮弗的坐标系中如何表示旋转呢？首先将向量转换为标准坐标系的表示，然后左旋，最后再转换为詹妮弗的表示。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922133607455.png" alt="image-20200922133607455"></p><p>所以我们可以得到对于詹妮弗坐标系的左旋线性变化的表示：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922133725994.png" alt="image-20200922133725994"></p><p>所以表达式$A^{-1}MA$表示一种数学上的转移作用，$M$表示一种线性变换，$A$和$A^{-1}$表示坐标系的转换。</p><h2 id="特征向量与特征值"><a href="#特征向量与特征值" class="headerlink" title="特征向量与特征值"></a>特征向量与特征值</h2><p>对于一些线性变化来说，存在一些向量在变换前后留在了张成的空间里，只是拉伸或收缩了一定比例，这些向量称为特征向量，拉伸收缩的比例称为特征值。</p><p><img src="/blog/img/Blog/LinearAlgebra/GIF-2020-11-21-17-46-40.gif" alt="GIF 2020-11-21 17-46-40"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922152146060.png" alt="image-20200922152146060"></p><p>一个三维空间的旋转，如果能找到特征值为1的特征向量，那么它就是旋转轴，因为旋转并不进行缩放，且旋转轴在线性变换中保持不变。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922152945686.png" alt="image-20200922152945686"></p><blockquote><p>特征向量的求解</p></blockquote><p>特征向量的概念，等号左侧表示矩阵向量的乘积，等号右侧表示向量数乘，可以将右侧重写为某个向量的乘积，$\vec I$为单位向量。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922152931670.png" alt="image-20200922152931670"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922153357401.png" alt="image-20200922153357401"></p><p>求解等式，就是使左侧的行列式det为0，$\lambda$就是特征值。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922153527410.png" alt="image-20200922153527410"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121180605568.png" alt="image-20201121180605568"></p><p>求解$\lambda$对应的特征向量时，即求解满足$(A-\lambda I)\vec{X}&#x3D;0$的所有向量$\vec{X}$。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121181300520.png" alt="image-20201121181300520"></p><p>对应原始矩阵上所有落在$\begin{bmatrix} -1 \ 1 \end{bmatrix}$的向量被拉伸了2倍。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121181819854.png" alt="image-20201121181819854"></p><p>二维线性变换不一定存在特征向量，例如左旋90°，每个想都都发生了旋转，离开了张成空间。如果强行计算，会得到两个虚根：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922154353867.png" alt="image-20200922154353867"></p><p>剪切变换的特征向量分布在x轴：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922154541171.png" alt="image-20200922154541171"></p><p> 只有一个特征值，但是特征向量不一定只在一条直线上：</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922154704668.png" alt="image-20200922154704668"></p><blockquote><p>特征基</p></blockquote><p>一组基向量构成的集合被称为一组特征基</p><p>如果特征向量是基向量，它对应的矩阵是一个对角矩阵，矩阵的对角元是它们所属的特征值。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121182906650.png" alt="image-20201121182906650"></p><p>对角矩阵在求幂次时更方便求解，对应的幂次就是对角元的幂次。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121183110982.png" alt="image-20201121183110982"></p><p>而对于非对角矩阵的幂次求解就非常麻烦。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121183319365.png" alt="image-20201121183319365"></p><p>实际遇到对角矩阵的概率很低，但是我们可以通过基坐标变换来得到对角矩阵，前提有足够多的特征向量且可以张成整个空间，例如剪切变化就不行，应为它只有一个特征向量，无法进行坐标变换。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121184627004.png" alt="image-20201121184627004"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922155515737.png" alt="image-20200922155515737"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20201121202207724.png" alt="image-20201121202207724"></p><p>求解特征值：</p><p>$\begin{bmatrix}-\lambda&amp;1\1&amp;1-\lambda \end{bmatrix}\vec{X}&#x3D;0$</p><div>$$\begin{bmatrix}-\lambda&1\\1&1-\lambda \end{bmatrix}\vec{X}=0 \\\lambda=\frac{1+\sqrt{5}}{2},\frac{1-\sqrt{5}}{2} \\将\lambda带入求导特征向量为:\vec{v_1}=\begin{bmatrix}2\\1+\sqrt{5}\end{bmatrix},\vec{v_2}=\begin{bmatrix}2\\1-\sqrt{5}\end{bmatrix}\\所以特征基为：P = \begin{bmatrix}2&2\\1+\sqrt{5}&1-\sqrt{5}\end{bmatrix}\\P^{-1}=\frac{1}{4\sqrt{5}}\begin{bmatrix}\sqrt{5}-1&2\\\sqrt{5}+1&-2\end{bmatrix}\\构造对角矩阵：M=P^{-1}AP=\frac{1}{2}\begin{bmatrix}7+3\sqrt{5}&0\\0&7-3\sqrt{5}\end{bmatrix}\\A=PMP^{-1}\\A^{n}=PMP^{-1}PMP^{-1}...PMP^{-1}=PM^{n}P^{-1}$$<div><h2 id="抽象向量空间"><a href="#抽象向量空间" class="headerlink" title="抽象向量空间"></a>抽象向量空间</h2><p>线性的严格定义是：可加性和成比例性。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922163048868.png" alt="image-20200922163048868"></p><p>和函数的求导类似，求导具有可加性和成比例性。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922163207612.png" alt="image-20200922163207612"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922163213512.png" alt="image-20200922163213512"></p><p>对于多项式的求导，我们也可以看成是矩阵的形式，将x的不同次幂看成基函数，这和多维空间的基向量类似。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922163437035.png" alt="image-20200922163437035"></p><p>因为求导的可加性和成比例行，我们可以分别对每个基向量求导，从而得到左侧的矩阵。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922163605065.png" alt="image-20200922163605065"></p><p>数学中有很多类似向量的事物，只要处理的对象具有数乘和相加的概念，都可以运行向量的基本性质。</p><p>对于发明向量的数学家来说，他不用考虑其他所有类似的向量，他只需要给出向量数乘和加法必须遵守的规则即定理，那么所有满足这些定理的对象，就可以使用向量所拥有的性质。</p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922164358498.png" alt="image-20200922164358498"></p><p><img src="/blog/img/Blog/LinearAlgebra/image-20200922164421196.png" alt="image-20200922164421196"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;线性代数笔记。&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="linear algebra" scheme="https://sanzo.top/blog/tags/linear-algebra/"/>
    
    <category term="math" scheme="https://sanzo.top/blog/tags/math/"/>
    
  </entry>
  
  <entry>
    <title>cmake笔记</title>
    <link href="https://sanzo.top/blog/Blog/cmake/"/>
    <id>https://sanzo.top/blog/Blog/cmake/</id>
    <published>2021-07-04T14:50:47.000Z</published>
    <updated>2021-07-04T14:50:47.000Z</updated>
    
    <content type="html"><![CDATA[<p>本文的源代码：<a href="https://github.com/Sanzo00/cmake-examples">github.com&#x2F;Sanzo00&#x2F;cmake-examples</a></p><p>参考项目：<a href="https://github.com/ttroy50/cmake-examples/tree/master/">github.com&#x2F;ttroy50&#x2F;cmake-examples</a></p><p>中文学习地址：<a href="https://sfumecjf.github.io/cmake-examples-Chinese/">cmake-examples-Chinese</a></p><span id="more"></span><h2 id="basic"><a href="#basic" class="headerlink" title="basic"></a>basic</h2><h3 id="hello-cmake"><a href="#hello-cmake" class="headerlink" title="hello cmake"></a>hello cmake</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">└── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line"><span class="comment"># Set the minimum version of CMake that can be used</span></span><br><span class="line"><span class="comment"># To find the cmake version run</span></span><br><span class="line"><span class="comment"># $ cmake --version</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Set the project name</span></span><br><span class="line">project (hello_cmake)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Add an executable</span></span><br><span class="line">add_executable(hello_cmake main.cpp)</span><br><span class="line"><span class="comment"># add_executable($&#123;PROJECT_NAME&#125; main.cpp)</span></span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">message(&quot;CMAKE_SOURCE_DIR: $&#123;CMAKE_SOURCE_DIR&#125;&quot;)</span><br><span class="line">message(&quot;CMAKE_CURRENT_SOURCE_DIR: $&#123;CMAKE_CURRENT_SOURCE_DIR&#125;&quot;)</span><br><span class="line">message(&quot;PROJECT_SOURCE_DIR: $&#123;PROJECT_SOURCE_DIR&#125;&quot;)</span><br><span class="line">message(&quot;CMAKE_BINARY_DIR: $&#123;CMAKE_BINARY_DIR&#125;&quot;)</span><br><span class="line">message(&quot;CMAKE_CURRENT_BINARY_DIR: $&#123;CMAKE_CURRENT_BINARY_DIR&#125;&quot;)</span><br><span class="line">message(&quot;PROJECT_BINARY_DIR: $&#123;PROJECT_BINARY_DIR&#125;&quot;)</span><br></pre></td></tr></table></figure><table><thead><tr><th>Variable</th><th>Info</th></tr></thead><tbody><tr><td>CMAKE_SOURCE_DIR</td><td>CMakeLists.txt的根目录</td></tr><tr><td>CMAKE_CURRENT_SOURCE_DIR</td><td>当前处理CMakeLists.txt的目录</td></tr><tr><td>PROJECT_SOURCE_DIR</td><td>项目根目录</td></tr><tr><td>CMAKE_BINARY_DIR</td><td>执行cmake的目录（build）</td></tr><tr><td>CMAKE_CURRENT_BINARY_DIR</td><td>当前所在的build目录</td></tr><tr><td>PROJECT_BINARY_DIR</td><td>项目构建的目录</td></tr></tbody></table><h3 id="hello-headers"><a href="#hello-headers" class="headerlink" title="hello headers"></a>hello headers</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── include</span><br><span class="line">│   └── Hello.h</span><br><span class="line">└── src</span><br><span class="line">    ├── Hello.cpp</span><br><span class="line">    └── main.cpp</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project (hello_headers)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建SOURCES变量，保存所有的源文件</span></span><br><span class="line"><span class="built_in">set</span>(SOURCES</span><br><span class="line">  src/Hello.cpp</span><br><span class="line">  src/main.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建可执行文件</span></span><br><span class="line">add_executable(hello_headers <span class="variable">$&#123;SOURCES&#125;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定头文件</span></span><br><span class="line">target_include_directories(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  PRIVATE </span><br><span class="line">  <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/include</span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="static-library"><a href="#static-library" class="headerlink" title="static library"></a>static library</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── include</span><br><span class="line">│   └── static</span><br><span class="line">│       └── Hello.h</span><br><span class="line">└── src</span><br><span class="line">    ├── Hello.cpp</span><br><span class="line">    └── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(hello_library)</span><br><span class="line"></span><br><span class="line"><span class="comment">####################################</span></span><br><span class="line"><span class="comment"># Create a library</span></span><br><span class="line"><span class="comment">####################################</span></span><br><span class="line"></span><br><span class="line">add_library(hello_library STATIC</span><br><span class="line">  src/Hello.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">target_include_directories(hello_library</span><br><span class="line">  PUBLIC</span><br><span class="line">    <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/include</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">###################################</span></span><br><span class="line"><span class="comment"># Create an executable</span></span><br><span class="line"><span class="comment">###################################</span></span><br><span class="line"><span class="comment"># Add an executable with the above sources</span></span><br><span class="line">add_executable(hello_binary</span><br><span class="line">  src/main.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># link the new hello_library target with the hello_binary target</span></span><br><span class="line">target_link_libraries( hello_binary</span><br><span class="line">  PRIVATE</span><br><span class="line">    hello_library</span><br><span class="line">)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建静态库文件 libhello_library.a</span></span><br><span class="line">add_library(hello_library STATIC</span><br><span class="line">  src/Hello.cpp</span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="shared-library"><a href="#shared-library" class="headerlink" title="shared library"></a>shared library</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── include</span><br><span class="line">│   └── shared</span><br><span class="line">│       └── Hello.h</span><br><span class="line">└── src</span><br><span class="line">    ├── Hello.cpp</span><br><span class="line">    └── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(hello_library)</span><br><span class="line"></span><br><span class="line"><span class="comment">#######################################</span></span><br><span class="line"><span class="comment"># Create a library</span></span><br><span class="line"><span class="comment">#######################################</span></span><br><span class="line"></span><br><span class="line">add_library(hello_library SHARED</span><br><span class="line">  src/Hello.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">add_library(hello::library ALIAS hello_library)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">target_include_directories(hello_library </span><br><span class="line">  PUBLIC</span><br><span class="line">    <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/include</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#######################################</span></span><br><span class="line"><span class="comment"># Create an executable</span></span><br><span class="line"><span class="comment">#######################################</span></span><br><span class="line"></span><br><span class="line">add_executable(hello_binary</span><br><span class="line">  src/main.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">target_link_libraries(hello_binary PRIVATE</span><br><span class="line">  hello::library</span><br><span class="line">)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建动态库文件 libhello_library.so</span></span><br><span class="line">add_library(hello_library SHARED</span><br><span class="line">  src/Hello.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 对库起别名为hello:library</span></span><br><span class="line">add_library(hello::library ALIAS hello_library)</span><br></pre></td></tr></table></figure><h3 id="installing"><a href="#installing" class="headerlink" title="installing"></a>installing</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── cmake-examples.conf</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── include</span><br><span class="line">│   └── installing</span><br><span class="line">│       └── Hello.h</span><br><span class="line">├── README.adoc</span><br><span class="line">└── src</span><br><span class="line">    ├── Hello.cpp</span><br><span class="line">    └── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(cmake_install)</span><br><span class="line"></span><br><span class="line"><span class="comment">############################################</span></span><br><span class="line"><span class="comment"># Create a library</span></span><br><span class="line"><span class="comment">############################################</span></span><br><span class="line">add_library(cmake_inst SHARED</span><br><span class="line">  src/Hello.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">target_include_directories(cmake_inst</span><br><span class="line">  PUBLIC</span><br><span class="line">    <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/include</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">############################################</span></span><br><span class="line"><span class="comment"># Create an executable</span></span><br><span class="line"><span class="comment">############################################</span></span><br><span class="line">add_executable(cmake_install_bin</span><br><span class="line">  src/main.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">target_link_libraries(cmake_install_bin </span><br><span class="line">  PRIVATE</span><br><span class="line">    cmake_inst</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">############################################</span></span><br><span class="line"><span class="comment"># Install</span></span><br><span class="line"><span class="comment">############################################</span></span><br><span class="line"><span class="comment"># Binaries</span></span><br><span class="line">install(TARGETS cmake_install_bin DESTINATION bin)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Library</span></span><br><span class="line">install(TARGETS cmake_inst LIBRARY DESTINATION lib)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Header files</span></span><br><span class="line">install(DIRECTORY <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/include/ DESTINATION include)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Config</span></span><br><span class="line">install(FILES cmake.conf DESTINATION etc)</span><br><span class="line"></span><br><span class="line"><span class="comment"># set make install directory</span></span><br><span class="line"><span class="keyword">if</span>(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)</span><br><span class="line">  <span class="built_in">set</span>(CMAKE_INSTALL_PREFIX <span class="string">&quot;<span class="variable">$&#123;CMAKE_BINARY_DIR&#125;</span>/install&quot;</span> CACHE PATH <span class="string">&quot;The path to use for make install&quot;</span> FORCE)</span><br><span class="line">endif()</span><br><span class="line"></span><br><span class="line"><span class="comment"># Debug for CMAKE_INSTALL_PREFIX</span></span><br><span class="line">message(<span class="string">&quot;CMAKE_INSTALL_PREFIX: &quot;</span> <span class="variable">$&#123;CMAKE_INSTALL_PREFIX&#125;</span>)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定make instal的目录为./install</span></span><br><span class="line">cmake .. -D CMAKE_INSTALL_PREFIX=./install</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在未指定install目录时，可以在CMakeLists.txt中设置make install的目录</span></span><br><span class="line"><span class="keyword">if</span>(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)</span><br><span class="line">  <span class="built_in">set</span>(CMAKE_INSTALL_PREFIX <span class="string">&quot;<span class="variable">$&#123;CMAKE_BINARY_DIR&#125;</span>/install&quot;</span> CACHE PATH <span class="string">&quot;The path to use for make install&quot;</span> FORCE)</span><br><span class="line">endif()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在make install也可以通过DESTDIR=/tmp/stage，安装到$&#123;DESTDIR&#125;/$&#123;CMAKE_INSTALL_PREFIX&#125;</span></span><br><span class="line">make install DESTDIR=/tmp/stage</span><br><span class="line"></span><br><span class="line"><span class="comment"># Uninstall</span></span><br><span class="line"><span class="built_in">sudo</span> xargs <span class="built_in">rm</span> &lt; install_manifest.txt</span><br></pre></td></tr></table></figure><h3 id="build-type"><a href="#build-type" class="headerlink" title="build type"></a>build type</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Set a default build type if none was specified</span></span><br><span class="line"><span class="comment"># Release, Debug, MinSizeRel, RelWithDebInfo</span></span><br><span class="line"><span class="keyword">if</span>(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)</span><br><span class="line">  message(<span class="string">&quot;Setting build type to &#x27;RelWithDebInfo&#x27; as none was specified.&quot;</span>)</span><br><span class="line">  <span class="built_in">set</span>(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING <span class="string">&quot;Choose the type of build.&quot;</span> FORCE)</span><br><span class="line">  <span class="comment"># Set the possible values of build type for cmake-gui</span></span><br><span class="line">  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS <span class="string">&quot;Debug&quot;</span> <span class="string">&quot;Release&quot;</span></span><br><span class="line">    <span class="string">&quot;MinSizeRel&quot;</span> <span class="string">&quot;RelWithDebInfo&quot;</span>)</span><br><span class="line">endif()</span><br><span class="line"></span><br><span class="line">project(build_type)</span><br><span class="line"></span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  main.cpp</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>Cmake提供四种构建类型：</p><ol><li>Release，<code>-O3 -DNDEBUG</code></li><li>Debug，<code>-g</code></li><li>MinSizeRel，<code>-Os -DNDEBUG</code></li><li>RelWithDebInfo，<code>-O2 -g -DNDEBUG</code></li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 用户在cmake时指定编译类型</span></span><br><span class="line">cmake .. -DCMAKE_BUILD_TYPE=Release</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置默认的构建类型</span></span><br><span class="line"><span class="comment"># Release, Debug, MinSizeRel, RelWithDebInfo</span></span><br><span class="line"><span class="keyword">if</span>(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)</span><br><span class="line">  message(<span class="string">&quot;Setting build type to &#x27;RelWithDebInfo&#x27; as none was specified.&quot;</span>)</span><br><span class="line">  <span class="built_in">set</span>(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING <span class="string">&quot;Choose the type of build.&quot;</span> FORCE)</span><br><span class="line">  <span class="comment"># Set the possible values of build type for cmake-gui</span></span><br><span class="line">  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS <span class="string">&quot;Debug&quot;</span> <span class="string">&quot;Release&quot;</span></span><br><span class="line">    <span class="string">&quot;MinSizeRel&quot;</span> <span class="string">&quot;RelWithDebInfo&quot;</span>)</span><br><span class="line">endif()</span><br></pre></td></tr></table></figure><h3 id="compile-flags"><a href="#compile-flags" class="headerlink" title="compile flags"></a>compile flags</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.cpp</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>** argv)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">  std::cout &lt;&lt; <span class="string">&quot;Hello Compile Flags!&quot;</span> &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">// only print if compile flag set</span></span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> EX2</span></span><br><span class="line">  std::cout &lt;&lt; <span class="string">&quot;Hello Compile Flag EX2!&quot;</span> &lt;&lt; std::endl;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> EX3</span></span><br><span class="line">  std::cout &lt;&lt; <span class="string">&quot;Hello Compile Flag EX3!&quot;</span> &lt;&lt; std::endl;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(compile_flags)</span><br><span class="line"></span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  main.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Set a default C++ compile flag</span></span><br><span class="line"><span class="built_in">set</span>(CMAKE_CXX_FLAGS <span class="string">&quot;<span class="variable">$&#123;CMAKE_CXX_FLAGS&#125;</span> -DEX2&quot;</span> CACHE STRING <span class="string">&quot;Set C++ Compile Flags&quot;</span> FORCE)</span><br><span class="line"></span><br><span class="line">target_compile_definitions(<span class="variable">$&#123;PROJECT_NAME&#125;</span> PRIVATE EX3)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 为特定的可执行文件或库设置compile flags</span></span><br><span class="line">target_compile_definitions(<span class="variable">$&#123;PROJECT_NAME&#125;</span> PRIVATE EX3)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置全局的compile flags</span></span><br><span class="line"><span class="built_in">set</span>(CMAKE_CXX_FLAGS <span class="string">&quot;<span class="variable">$&#123;CMAKE_CXX_FLAGS&#125;</span> -DEX2&quot;</span> CACHE STRING <span class="string">&quot;Set C++ Compile Flags&quot;</span> FORCE)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过cmake设置</span></span><br><span class="line">cmake .. -DCMAKE_CXX_FLAGS=<span class="string">&quot;-DEX3&quot;</span></span><br></pre></td></tr></table></figure><h3 id="third-party-library"><a href="#third-party-library" class="headerlink" title="third party library"></a>third party library</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装依赖</span></span><br><span class="line"><span class="built_in">sudo</span> apt install libboost-system-dev libboost-filesystem-dev</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.cpp</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;boost/shared_ptr.hpp&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;boost/filesystem.hpp&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>** argv)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">  std::cout &lt;&lt; <span class="string">&quot;Hello Third Party Include!&quot;</span> &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// use a shared ptr</span></span><br><span class="line">  <span class="function">boost::shared_ptr&lt;<span class="type">int</span>&gt; <span class="title">isp</span><span class="params">(<span class="keyword">new</span> <span class="type">int</span>(<span class="number">4</span>))</span></span>;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// trivial use of boost filesystem</span></span><br><span class="line">  boost::filesystem::path path = <span class="string">&quot;/usr/share/cmake/modules&quot;</span>;</span><br><span class="line">  <span class="keyword">if</span> (path.<span class="built_in">is_relative</span>()) &#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Path is relative&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Path is not relative&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(third_party_library)</span><br><span class="line"></span><br><span class="line"><span class="comment"># find a boost install with the libraries filesystem and system</span></span><br><span class="line">find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)</span><br><span class="line"></span><br><span class="line"><span class="comment"># check if boost was found</span></span><br><span class="line"><span class="keyword">if</span>(Boost_FOUND)</span><br><span class="line">  message(<span class="string">&quot;boost found&quot;</span>)</span><br><span class="line"><span class="keyword">else</span>()</span><br><span class="line">  message(FATAL_ERROR <span class="string">&quot;Cannot find boost&quot;</span>)</span><br><span class="line">endif()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  main.cpp</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># link against the boost libraries</span></span><br><span class="line">target_link_libraries(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  PRIVATE</span><br><span class="line">    Boost::filesystem</span><br><span class="line">)</span><br></pre></td></tr></table></figure><blockquote><p>查找库</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># find package</span></span><br><span class="line">find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)</span><br></pre></td></tr></table></figure><p>Boost为库的名称</p><p>1.46.1是最低的版本号</p><p>REQUIRED表示这是必需的库，如果找不到报错。</p><p>COMPONENTS是要查找的库列表</p><blockquote><p>检查库是否存在</p></blockquote><p>大多数被包含的库都会设置变量<code>xxx_FOUND</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># check if boost was found</span></span><br><span class="line"><span class="keyword">if</span>(Boost_FOUND)</span><br><span class="line">  message(<span class="string">&quot;boost found&quot;</span>)</span><br><span class="line"><span class="keyword">else</span>()</span><br><span class="line">  message(FATAL_ERROR <span class="string">&quot;Cannot find boost&quot;</span>)</span><br><span class="line">endif()</span><br></pre></td></tr></table></figure><p>如果库存在，一般会设置如下参数用来定位库：</p><ul><li><code>xxx_INCLUDE_DIRS</code> - 头文件位置</li><li><code>xxx_LIBRARY</code> - 库位置</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Include the boost headers</span></span><br><span class="line">target_include_directories( third_party_include</span><br><span class="line">    PRIVATE <span class="variable">$&#123;Boost_INCLUDE_DIRS&#125;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># link against the boost libraries</span></span><br><span class="line">target_link_libraries( third_party_include</span><br><span class="line">    PRIVATE</span><br><span class="line">    <span class="variable">$&#123;Boost_SYSTEM_LIBRARY&#125;</span></span><br><span class="line">    <span class="variable">$&#123;Boost_FILESYSTEM_LIBRARY&#125;</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><blockquote><p>别名</p></blockquote><p>大多数modern CMake库包含别名，例如对于boost来说可以使用：</p><ul><li><code>Boost::boost</code> for header only libraries</li><li><code>Boost::system</code> for the boost system library.</li><li><code>Boost::filesystem</code> for filesystem library.</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">target_link_libraries( third_party_include</span><br><span class="line">PRIVATE</span><br><span class="line">Boost::filesystem</span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="compiling-with-clang"><a href="#compiling-with-clang" class="headerlink" title="compiling with clang"></a>compiling with clang</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install clang</span></span><br><span class="line"><span class="built_in">sudo</span> apt install clang</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(hello_cmake)</span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span> main.cpp)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment">###################################################</span></span><br><span class="line"><span class="comment"># Delete old build.clang directory</span></span><br><span class="line"><span class="comment">###################################################</span></span><br><span class="line">ROOT_DIR=`<span class="built_in">pwd</span>`</span><br><span class="line"><span class="comment">#dir=&quot;I-compiling-with-clang&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ -d <span class="string">&quot;<span class="variable">$ROOT_DIR</span>/build.clang&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;deleting <span class="variable">$ROOT_DIR</span>/build.clang&quot;</span></span><br><span class="line">  <span class="built_in">rm</span> -rf <span class="variable">$ROOT_DIR</span>/build.clang</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment">###################################################</span></span><br><span class="line"><span class="comment"># determine the clang binary before calling cmake</span></span><br><span class="line"><span class="comment">###################################################</span></span><br><span class="line">clang_bin=`<span class="built_in">which</span> clang`</span><br><span class="line">clang_xx_bin=`<span class="built_in">which</span> clang++`</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="variable">$clang_bin</span> ]; <span class="keyword">then</span></span><br><span class="line"><span class="comment"># 获取版本号</span></span><br><span class="line">    clang_ver=`dpkg --get-selections | grep clang | grep -v -m1 libclang | <span class="built_in">cut</span> -f1 | <span class="built_in">cut</span> -d <span class="string">&#x27;-&#x27;</span> -f2`</span><br><span class="line">    clang_bin=<span class="string">&quot;clang-<span class="variable">$clang_ver</span>&quot;</span></span><br><span class="line">    clang_xx_bin=<span class="string">&quot;clang++-<span class="variable">$clang_ver</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Will use clang [<span class="variable">$clang_bin</span>] and clang++ [<span class="variable">$clang_xx_bin</span>]&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> -p build.clang &amp;&amp; <span class="built_in">cd</span> build.clang &amp;&amp; \</span><br><span class="line">  cmake .. -DCMAKE_C_COMPILER=<span class="variable">$clang_bin</span> -DCMAKE_CXX_COMPILER=<span class="variable">$clang_xx_bin</span> &amp;&amp; make</span><br></pre></td></tr></table></figure><p>CMake的编译器选项：</p><ul><li>CMAKE_C_COMPILER - The program used to compile c code.</li><li>CMAKE_CXX_COMPILER - The program used to compile c++ code.</li><li>CMAKE_LINKER - The program used to link your binary.</li></ul><h3 id="building-with-ninja"><a href="#building-with-ninja" class="headerlink" title="building with ninja"></a>building with ninja</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br></pre></td></tr></table></figure><p>CMake包含多种生成器：<code>cmake --help</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">Generators</span><br><span class="line"></span><br><span class="line">The following generators are available on this platform (* marks default):</span><br><span class="line">* Unix Makefiles               = Generates standard UNIX makefiles.</span><br><span class="line">  Green Hills MULTI            = Generates Green Hills MULTI files</span><br><span class="line">                                 (experimental, work-in-progress).</span><br><span class="line">  Ninja                        = Generates build.ninja files.</span><br><span class="line">  Watcom WMake                 = Generates Watcom WMake makefiles.</span><br><span class="line">  CodeBlocks - Ninja           = Generates CodeBlocks project files.</span><br><span class="line">  CodeBlocks - Unix Makefiles  = Generates CodeBlocks project files.</span><br><span class="line">  CodeLite - Ninja             = Generates CodeLite project files.</span><br><span class="line">  CodeLite - Unix Makefiles    = Generates CodeLite project files.</span><br><span class="line">  Sublime Text 2 - Ninja       = Generates Sublime Text 2 project files.</span><br><span class="line">  Sublime Text 2 - Unix Makefiles</span><br><span class="line">                               = Generates Sublime Text 2 project files.</span><br><span class="line">  Kate - Ninja                 = Generates Kate project files.</span><br><span class="line">  Kate - Unix Makefiles        = Generates Kate project files.</span><br><span class="line">  Eclipse CDT4 - Ninja         = Generates Eclipse CDT 4.0 project files.</span><br><span class="line">  Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.</span><br></pre></td></tr></table></figure><p>接下来使用Ninja进行构建：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install ninja-build</span></span><br><span class="line"><span class="built_in">sudo</span> apt install ninja-build</span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> ninja.build &amp;&amp; <span class="built_in">cd</span> ninja.build</span><br><span class="line"></span><br><span class="line">cmake .. -G Ninja</span><br><span class="line"></span><br><span class="line">ninja -v</span><br></pre></td></tr></table></figure><h3 id="cpp-standard"><a href="#cpp-standard" class="headerlink" title="cpp standard"></a>cpp standard</h3><p>设置c++的编译标准。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.cpp</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>** argv)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">auto</span> message = <span class="string">&quot;Hello C++11&quot;</span>;</span><br><span class="line"></span><br><span class="line">  std::cout &lt;&lt; message &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(hello_cpp11)</span><br><span class="line"></span><br><span class="line"><span class="comment"># try conditional compilation</span></span><br><span class="line">include(CheckCXXCompilerFlag) <span class="comment"># CHECK_CXX_COMPILER_FLAG的头文件</span></span><br><span class="line">CHECK_CXX_COMPILER_FLAG(<span class="string">&quot;-std=c++11&quot;</span> COMPILER_SUPPORTS_CXX11) <span class="comment"># 尝试使用flag进行编译，并把结果保存到变量中</span></span><br><span class="line">CHECK_CXX_COMPILER_FLAG(<span class="string">&quot;-std=c++0x&quot;</span> COMPILER_SUPPORTS_CXX0X)</span><br><span class="line"></span><br><span class="line"><span class="comment"># check results and add flag</span></span><br><span class="line"><span class="keyword">if</span> (COMPILER_SUPPORTS_CXX11)</span><br><span class="line">  <span class="built_in">set</span>(CMAKE_CXX_FLAGS <span class="string">&quot;<span class="variable">$&#123;CMAKE_CXX_FLAGS&#125;</span> -std=c++11&quot;</span>)</span><br><span class="line">elseif(COMPILER_SUPPORTS_CXX0X)</span><br><span class="line">  <span class="built_in">set</span>(CMAKE_CXX_FLAGS <span class="string">&quot;<span class="variable">$&#123;CMAKE_CXX_FLAGS&#125;</span> -std=c++0x&quot;</span>)</span><br><span class="line"><span class="keyword">else</span>()</span><br><span class="line">  message(STATUS <span class="string">&quot;The compiler <span class="variable">$&#123;CMAKE_CXX_COMPILER&#125;</span> has no C++11 support. Please use a different C++ compiler.&quot;</span>)</span><br><span class="line">endif()</span><br><span class="line"></span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span> main.cpp)</span><br></pre></td></tr></table></figure><p>另外还有两种设置c++ standard的方法：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#######################################################################</span></span><br><span class="line"><span class="comment"># Using the CMAKE_CXX_STANDARD variable introduced in CMake v3.1.</span></span><br><span class="line"><span class="comment">#######################################################################</span></span><br><span class="line"><span class="built_in">set</span>(CMAKE_CXX_STANDARD 11)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#######################################################################</span></span><br><span class="line"><span class="comment"># Using the target_compile_features function introduced in CMake v3.1.</span></span><br><span class="line"><span class="comment">#######################################################################</span></span><br><span class="line"><span class="comment"># set the C++ standard to the appropriate standard for using auto</span></span><br><span class="line">target_compile_features(hello_cpp11 PUBLIC cxx_auto_type)</span><br><span class="line"></span><br><span class="line"><span class="comment"># print the list of known compile features for this version of CMake</span></span><br><span class="line">message(<span class="string">&quot;List of compile features: <span class="variable">$&#123;CMAKE_CXX_COMPILE_FEATURES&#125;</span>&quot;</span>)</span><br></pre></td></tr></table></figure><h2 id="sub-projects"><a href="#sub-projects" class="headerlink" title="sub projects"></a>sub projects</h2><ul><li>sublibrary1 - A static library</li><li>sublibrary2 - A header only library</li><li>subbinary - An executable</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── subbinary</span><br><span class="line">│   ├── CMakeLists.txt</span><br><span class="line">│   └── main.cpp</span><br><span class="line">├── sublibrary1</span><br><span class="line">│   ├── CMakeLists.txt</span><br><span class="line">│   ├── include</span><br><span class="line">│   │   └── sublib1</span><br><span class="line">│   │       └── sublib1.h</span><br><span class="line">│   └── src</span><br><span class="line">│       └── sublib1.cpp</span><br><span class="line">└── sublibrary2</span><br><span class="line">    ├── CMakeLists.txt</span><br><span class="line">    └── include</span><br><span class="line">        └── sublib2</span><br><span class="line">            └── sublib2.h</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(sub_projects)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add sub directories</span></span><br><span class="line">add_subdirectory(subbinary)</span><br><span class="line">add_subdirectory(sublibrary1)</span><br><span class="line">add_subdirectory(sublibrary2)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># sublibrary1/CMakeLists.txt</span></span><br><span class="line"><span class="comment"># set project name</span></span><br><span class="line">project(sublibrary1)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add a library with the above sources</span></span><br><span class="line">add_library(<span class="variable">$&#123;PROJECT_NAME&#125;</span> src/sublib1.cpp)</span><br><span class="line">add_library(sub::lib1 ALIAS <span class="variable">$&#123;PROJECT_NAME&#125;</span>)</span><br><span class="line"></span><br><span class="line">target_include_directories(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  PUBLIC <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/include</span><br><span class="line">)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># sublibrary2/CMakeLists.txt</span></span><br><span class="line"><span class="comment"># set the project name</span></span><br><span class="line">project(sublibrary2)</span><br><span class="line"></span><br><span class="line">add_library(<span class="variable">$&#123;PROJECT_NAME&#125;</span> INTERFACE)</span><br><span class="line">add_library(sub::lib2 ALIAS <span class="variable">$&#123;PROJECT_NAME&#125;</span>)</span><br><span class="line"></span><br><span class="line">target_include_directories(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  INTERFACE</span><br><span class="line">    <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/include</span><br><span class="line">)</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># subbinary/CMakeLists.txt</span></span><br><span class="line"><span class="comment"># set project name</span></span><br><span class="line">project(subbinary)</span><br><span class="line"></span><br><span class="line"><span class="comment"># create the executable</span></span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span> main.cpp)</span><br><span class="line"></span><br><span class="line"><span class="comment"># link the static library from sublibrary1 using it&#x27;s alias sub::lib1</span></span><br><span class="line"><span class="comment"># link the header only library from sublibrary2 using it&#x27;s alias sub::lib2</span></span><br><span class="line"><span class="comment"># this will cause the include directories for that target to be added to this project</span></span><br><span class="line">target_link_libraries(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  sub::lib1</span><br><span class="line">  sub::lib2</span><br><span class="line">)</span><br></pre></td></tr></table></figure><h2 id="code-generation"><a href="#code-generation" class="headerlink" title="code generation"></a>code generation</h2><h3 id="configure-files"><a href="#configure-files" class="headerlink" title="configure files"></a>configure files</h3><ul><li>CMakeLists.txt - Contains the CMake commands you wish to run</li><li>main.cpp - The source file with main</li><li>path.h.in - File to contain a path to the build directory</li><li>ver.h.in - File to contain the version of the project</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br><span class="line">├── path.h.in</span><br><span class="line">├── ver.h.in</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// main.cpp</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;ver.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;path.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Hello Version &quot;</span> &lt;&lt; ver &lt;&lt; <span class="string">&quot;!&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Path is &quot;</span> &lt;&lt; path &lt;&lt; std::endl;</span><br><span class="line">   <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>通过CMake的<code>configure_file()</code>自动生成代码。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line">project(cf_example)</span><br><span class="line"></span><br><span class="line"><span class="comment"># set a project version</span></span><br><span class="line"><span class="built_in">set</span>(cf_example_VERSION_MAJOR 0)</span><br><span class="line"><span class="built_in">set</span>(cf_example_VERSION_MINOR 2)</span><br><span class="line"><span class="built_in">set</span>(cf_example_VERSION_PATCH 1)</span><br><span class="line"><span class="built_in">set</span>(cf_example_VERSION <span class="string">&quot;<span class="variable">$&#123;cf_example_VERSION_MAJOR&#125;</span>.<span class="variable">$&#123;cf_example_VERSION_MINOR&#125;</span>.<span class="variable">$&#123;cf_example_VERSION_PATCH&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># call configure files on ver.h to set the version</span></span><br><span class="line"><span class="comment"># uses the standard $&#123;VARIABLE&#125; syntax in the file</span></span><br><span class="line">configure_file(ver.h.in <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/ver.h)</span><br><span class="line"></span><br><span class="line"><span class="comment"># this file can only use the @VARIABLE syntax in the file</span></span><br><span class="line">configure_file(path.h.in <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span>/path.h @ONLY)</span><br><span class="line"></span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span> main.cpp)</span><br><span class="line"></span><br><span class="line">target_include_directories(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  PRIVATE</span><br><span class="line">    <span class="variable">$&#123;PROJECT_SOURCE_DIR&#125;</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="protobuf"><a href="#protobuf" class="headerlink" title="protobuf"></a>protobuf</h3><p>protobuf是google开源的对字符串进行序列化的库，将要序列化的数据定义写在原始文件<code>.proto</code>配置文件中，protobuf将数据序列化为二进制格式，节省内存，加快了数据的传输，但是降低了可读性。</p><ul><li>AddressBook.proto - proto file from main protocol buffer <a href="https://developers.google.com/protocol-buffers/docs/cpptutorial">example</a></li><li>CMakeLists.txt - Contains the CMake commands you wish to run</li><li>main.cpp - The source file from the protobuf example.</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ tree</span><br><span class="line">.</span><br><span class="line">├── AddressBook.proto</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">├── main.cpp</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line"><span class="comment"># set cmake minimum version</span></span><br><span class="line">cmake_minimum_required(VERSION 3.5)</span><br><span class="line"></span><br><span class="line"><span class="comment"># set the project name</span></span><br><span class="line">project(protobuf_exmaple)</span><br><span class="line"></span><br><span class="line"><span class="comment"># find the protobuf compiler and libraries</span></span><br><span class="line">find_package(Protobuf REQUIRED)</span><br><span class="line"></span><br><span class="line"><span class="comment"># check if protobuf was found</span></span><br><span class="line"><span class="keyword">if</span> (PROTOBUF_FOUND)</span><br><span class="line">  message(<span class="string">&quot;protobuf found&quot;</span>)</span><br><span class="line"><span class="keyword">else</span>()</span><br><span class="line">  message(FATAL_ERROR <span class="string">&quot;Cannot find protobuf&quot;</span>)</span><br><span class="line">endif()</span><br><span class="line"></span><br><span class="line"><span class="comment"># generate the .h and .cxx files</span></span><br><span class="line">PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS AddressBook.proto)</span><br><span class="line"></span><br><span class="line"><span class="comment"># print path </span></span><br><span class="line">message(<span class="string">&quot;PROTO_SRCS = <span class="variable">$&#123;PROTO_SRCS&#125;</span>&quot;</span>)</span><br><span class="line">message(<span class="string">&quot;PROTO_HDRS = <span class="variable">$&#123;PROTO_HDRS&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># add an executable</span></span><br><span class="line">add_executable(<span class="variable">$&#123;PROJECT_NAME&#125;</span> </span><br><span class="line">  main.cpp</span><br><span class="line">  <span class="variable">$&#123;PROTO_SRCS&#125;</span></span><br><span class="line">  <span class="comment"># $&#123;PROTO_HDRS&#125;  </span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">target_include_directories(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  PUBLIC</span><br><span class="line">    <span class="variable">$&#123;PROTOBUF_INCLUDE_DIRS&#125;</span></span><br><span class="line">    <span class="variable">$&#123;CMAKE_CURRENT_BINARY_DIR&#125;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">target_link_libraries(<span class="variable">$&#123;PROJECT_NAME&#125;</span></span><br><span class="line">  PUBLIC <span class="variable">$&#123;PROTOBUF_LIBRARIES&#125;</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;本文的源代码：&lt;a href=&quot;https://github.com/Sanzo00/cmake-examples&quot;&gt;github.com&amp;#x2F;Sanzo00&amp;#x2F;cmake-examples&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;参考项目：&lt;a href=&quot;https://github.com/ttroy50/cmake-examples/tree/master/&quot;&gt;github.com&amp;#x2F;ttroy50&amp;#x2F;cmake-examples&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;中文学习地址：&lt;a href=&quot;https://sfumecjf.github.io/cmake-examples-Chinese/&quot;&gt;cmake-examples-Chinese&lt;/a&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="cmake" scheme="https://sanzo.top/blog/tags/cmake/"/>
    
  </entry>
  
  <entry>
    <title>吴恩达机器学习笔记</title>
    <link href="https://sanzo.top/blog/Blog/ML-AndrewNg/"/>
    <id>https://sanzo.top/blog/Blog/ML-AndrewNg/</id>
    <published>2022-03-27T05:02:26.000Z</published>
    <updated>2022-03-27T05:02:26.000Z</updated>
    
    <content type="html"><![CDATA[<p>机器学习劝退指南…</p><span id="more"></span><p><a href="https://www.bilibili.com/video/BV164411b7dx">吴恩达机器学习-B站视频</a></p><p><a href="https://github.com/Sanzona/ML-homework">课后作业及答案：https://github.com/Sanzona/ML-homework</a></p><p><a href="https://www.aliyundrive.com/s/841uW13SYEH">ppt和笔记下载链接: 阿里云盘</a></p><h2 id="监督学习"><a href="#监督学习" class="headerlink" title="监督学习"></a>监督学习</h2><p>监督学习是已经知道数据的label，例如预测房价问题，给出了房子的面积和价格。</p><ul><li><p>回归问题是预测连续值的输出，例如预测房价。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200922232432315.png" alt="image-20200922232432315"></p></li><li><p>分类问题是预测离散值输出，例如判断肿瘤是良性还是恶性。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200922232452094.png" alt="image-20200922232452094"></p></li></ul><h2 id="无监督学习"><a href="#无监督学习" class="headerlink" title="无监督学习"></a>无监督学习</h2><p>无监督学习是不知道数据具体的含义，比如给定一些数据但不知道它们具体的信息，对于分类问题无监督学习可以得到多个不同的聚类，从而实现预测的功能。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200922232542888.png" alt="image-20200922232542888"></p><h2 id="线性回归"><a href="#线性回归" class="headerlink" title="线性回归"></a>线性回归</h2><p><img src="/blog/img/Blog/ml-andrew/image-20200925221455511.png" alt="image-20200925221455511"></p><p>线性回归是拟合一条线，将训练数据尽可能分布到线上。另外还有多变量的线性回归称为多元线性回归。</p><h3 id="代价函数"><a href="#代价函数" class="headerlink" title="代价函数"></a>代价函数</h3><p>cost function，一般使用最小均方差来评估参数的好坏。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200925222847271.png" alt="image-20200925222847271"></p><p><img src="/blog/img/Blog/ml-andrew/image-20200925225215790.png" alt="image-20200925225215790"></p><p><img src="/blog/img/Blog/ml-andrew/image-20200925230206340.png" alt="image-20200925230206340"></p><p><img src="/blog/img/Blog/ml-andrew/image-20200925230227443.png" alt="image-20200925230227443"></p><h3 id="梯度下降"><a href="#梯度下降" class="headerlink" title="梯度下降"></a>梯度下降</h3><p>梯度下降，首先为每个参数赋一个初值，通过代价函数的梯度，然后不断地调整参数，最终得到一个局部最优解。初值的不同可能会得到两个不同的结果，即梯度下降不一定得到全局最优解。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926193450504.png" alt="image-20200926193450504"></p><p>梯度下降在具体的执行时，每一次更新需要同时更新所有的参数。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926193952535.png" alt="image-20200926193952535"></p><p>梯度下降公式中有两个部分，学习率和偏导数。</p><p>偏导数，用来计算当前参数对应代价函数的斜率，导数为正则$\theta$减小，导数为负则$\theta$增大，通过这样的方式可以使整体向$\theta&#x3D;0$收敛。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926195243593.png" alt="image-20200926195243593"></p><p>$\alpha$用来描述学习率，即每次参数更新的步长。$\alpha$的大小不好确定，如果太小则需要很多步才能收敛，如果太大最后可能不会收敛甚至可能发散。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926195756443.png" alt="image-20200926195756443"></p><p>当$\theta$处于局部最优解时，$\theta$的值将不再更新，因为偏导为0。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926195859632.png" alt="image-20200926195859632"></p><p>这也说明了如果学习率$\alpha$不改变，参数也可能收敛，假设偏导$&gt; 0$，因为偏导一直在向在减小，所以每次的步长也会慢慢减小，所以$\alpha$不需要额外的减小。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926200328203.png" alt="image-20200926200328203"></p><p><strong>单元梯度下降</strong></p><p>梯度下降每次更新的都需要进行偏导计算，这个偏导对应线性回归的代价函数。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926202751517.png" alt="image-20200926202751517"></p><p>对代价函数求导的结果为：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926202845222.png" alt="image-20200926202845222"></p><p>梯度下降的过程容易出现局部最优解：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926193450504.png" alt="image-20200926193450504"></p><p>但是线性回归的代价函数，往往是一个凸函数。它总能收敛到全局最优。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926203154017.png" alt="image-20200926203154017"></p><p>梯度下降过程的动图展示：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926203154027.gif"></p><p><strong>多元梯度下降</strong></p><p>通常问题都会涉及到多个变量，例如房屋价格预测就包括，面积、房间个数、楼层、价格等</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927122907240.png" alt="image-20200927122907240"></p><p>因此代价函数就不再只包含一个变量，为了统一可以对常量引入变量$x_0&#x3D;1$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927122848759.png" alt="image-20200927122848759"></p><p>虽然参数的个数增多，但是对每个参数求偏导时和单个参数类似。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927123117176.png" alt="image-20200927123117176"></p><h3 id="特征缩放"><a href="#特征缩放" class="headerlink" title="特征缩放"></a>特征缩放</h3><p>多个变量的度量不同，数字之间相差的大小也不同，如果可以将所有的特征变量缩放到大致相同范围，这样会减少梯度算法的迭代。</p><p>特征缩放不一定非要落到[-1，1]之间，只要数据足够接近就可以。</p><p>$X_i &#x3D; \frac{X_i-\mu}{\sigma}$，$\mu$表示平均值，$\sigma$表示标准差。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927122159371.png" alt="image-20200927122159371"></p><p><img src="/blog/img/Blog/ml-andrew/image-20200927122356465.png" alt="image-20200927122356465"></p><p><img src="/blog/img/Blog/ml-andrew/image-20200927122645246.png" alt="image-20200927122645246"></p><p><strong>缩放后的还原</strong></p><p>经过线性回归得到的参数$\theta’$，对应着缩放后的数据，如何得到缩放前的参数$\theta$？</p><div>$$\begin{aligned}不缩放，回归方程为y&=\theta_0+x_1\theta_1+x_2\theta_2+\cdots+x_n\theta_n\\缩放，回归方程为y'&=\theta_0'+x_1'\theta_1'+x_2'\theta_2'+\cdots+x_n'\theta_n'\\\because y'&=\frac{y'-\mu_y}{\sigma_y}，x_i'=\frac{x_i-\mu_i}{\sigma_i}\\\therefore \frac{y-\mu_y}{\sigma_y}&=\theta_0'+x_1'\theta_1'+x_2'\theta_2'+\cdots+x_n'\theta_n'\\&=\theta_0'+\frac{x_1-\mu_1}{\sigma_1}\theta_1'+\frac{x_2-\mu_2}{\sigma_2}\theta_2'+\cdots+\frac{x_n-\mu_n}{\sigma_n}\theta_n'\\\therefore y&=[(\theta_0' - \sum_{i=1}^{n}\frac{\mu_i\theta_i'}{\sigma_i})\sigma_y+\mu_y]+x_1\frac{\theta_1'\sigma_y}{\sigma_1}+x_2\frac{\theta_2'\sigma_y}{\sigma_2}+\cdots +x_n\frac{\theta_n'\sigma_y}{\sigma_n}\\&\therefore \left\{ \begin{matrix}(\theta_0' - \sum_{i=1}^{n}\frac{\mu_i\theta_i'}{\sigma_i})\sigma_y+\mu_y &(i=0)\\\frac{\theta_i'\sigma_y}{\sigma_i} &(i\ne 0)\\\end{matrix} \right.\end{aligned}$$</div><h3 id="学习率"><a href="#学习率" class="headerlink" title="学习率"></a>学习率</h3><p>学习率$\alpha$的大小会影响梯度算法的执行，太大可能会导致算法不收敛，太小会增加迭代的次数。</p><p>可以画出每次迭代的$J(\theta)$的变化，来判断当前算法执行的情况，然后选择合适的学习率。（调参开始…）</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927124215044.png" alt="image-20200927124215044"></p><p><img src="/blog/img/Blog/ml-andrew/image-20200927124314735.png" alt="image-20200927124314735"></p><p><strong>Batch梯度下降</strong>：每一步梯度下降，都需要遍历整个训练集样本。</p><h2 id="矩阵和向量"><a href="#矩阵和向量" class="headerlink" title="矩阵和向量"></a>矩阵和向量</h2><p>一些数学计算转化为矩阵的形式，可以简化代码书写、提高效率、代码更容易理解。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926215031531.png" alt="image-20200926215031531"></p><p><img src="/blog/img/Blog/ml-andrew/image-20200926223409425.png" alt="image-20200926223409425"></p><p><strong>矩阵乘法不满足交换律：</strong></p><p><img src="/blog/img/Blog/ml-andrew/image-20200926225453052.png" alt="image-20200926225453052"></p><p><strong>矩阵乘法满足结合律</strong>：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926225542850.png" alt="image-20200926225542850"></p><p><strong>单位矩阵</strong>：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926225634974.png" alt="image-20200926225634974"></p><p><strong>矩阵的逆</strong>：</p><ul><li>首先是方阵</li><li>不是所有的矩阵都有逆</li></ul><p><img src="/blog/img/Blog/ml-andrew/image-20200926225331312.png" alt="image-20200926225331312"></p><p><strong>转置矩阵</strong>：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200926225407464.png" alt="image-20200926225407464"></p><h2 id="正则方程"><a href="#正则方程" class="headerlink" title="正则方程"></a>正则方程</h2><p>偏导等于0对应线性方程的最小值：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927173714299.png" alt="image-20200927173714299"></p><p>利用线性代数的方法直接求解$\theta$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927173747699.png" alt="image-20200927173747699"></p><p>$\theta$的推导可以根据等式$X\theta&#x3D;y$得到，$X^TX$的目的是将矩阵转化为方阵，因为求矩阵的逆的前提是方阵。</p><p>矩阵可能存在 不可逆的情况，这时可是删除一些不必要的特征，或使用正则化。</p><p>梯度下降和正则方程的优缺点：</p><p><img src="/blog/img/Blog/ml-andrew/image-20200927174320125.png" alt="image-20200927174320125"></p><h2 id="逻辑回归"><a href="#逻辑回归" class="headerlink" title="逻辑回归"></a>逻辑回归</h2><p>Logistic Regression</p><p>逻辑回归用于解决分类的问题，如果使用线性回归可能会造成很大的误差；假如样本的标签值为0、1，线性回归输出值是连续的存在&gt;1和小于0的情况，不符合实际。</p><p>如果对于一个均匀的数据，使用线性回归，选取0.5作为分界线，可能会得到一个比较准确的模型，但是如果数据不太均匀就会存在很大的误差。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002134249446.png" alt="image-20201002134249446"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201002134545596.png" alt="image-20201002134545596"></p><h3 id="激活函数"><a href="#激活函数" class="headerlink" title="激活函数"></a>激活函数</h3><p><a href="https://github.com/Sanzona/files/blob/master/py/sigmoid.py">sigmoid.py</a></p><p><img src="/blog/img/Blog/ml-andrew/image-20201002142636471.png" alt="image-20201002142636471"></p><p>激活函数的y值分布在[0,1]内，对于分类问题，我们可以使用激活函数的值来表示满足特征的概率。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002144146860.png" alt="image-20201002144146860"></p><h3 id="决策界限"><a href="#决策界限" class="headerlink" title="决策界限"></a>决策界限</h3><p>决策边界是假设函数的一个属性，取决于函数的参数，而不是数据集。</p><p>假设以x&#x3D;0，y&#x3D;0.5作为判断的界限，当$\theta^Tx &gt;&#x3D;0.5$，预测$y&#x3D;1$；$\theta^Tx &lt;0.5$，预测$y&#x3D;0$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002151014707.png" alt="image-20201002151014707">                </p><p><img src="/blog/img/Blog/ml-andrew/image-20201002151544351.png" alt="image-20201002151544351"></p><p>[代码示例](<a href="https://github.com/Sanzona/ML-homework/blob/main/ex2-logistic">https://github.com/Sanzona/ML-homework/blob/main/ex2-logistic</a> regression&#x2F;ex2-regularized logistic regression.ipynb)</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002151951691.png" alt="image-20201002151951691"></p><p><a href="https://github.com/Sanzona/ML-homework/blob/main/ex2-logistic%20regression/ex2-regularized%20logistic%20regression.ipynb">代码示例</a></p><h3 id="代价函数-1"><a href="#代价函数-1" class="headerlink" title="代价函数"></a>代价函数</h3><p>对于函数$f(x)&#x3D;\frac{1}{1+e^{-x}}$，如果使用类似线性回归的代价函数$\Sigma(h(x)-y)^2$，将得到一个非凸函数，这样就不能使用梯度下降的方法求解全局最优解。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002155109200.png" alt="image-20201002155109200"></p><p>逻辑回归一般使用<strong>对数函数</strong>作为代价函数：</p><p>首先对于分类函数来说，他的输出值范围为[0,1]，得到的对数图像如下：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002155225235.png" alt="image-20201002155225235"></p><p>当评估模型参数对y&#x3D;1（恶性肿瘤）进行预测的好坏时，如果实际为恶性，预测值也为1（恶性），此时的代价为0；如果实际为恶性，预测为0（良性），此时的代价为$+\infty$，这时代价函数就很好的评估了参数$\theta$的表现。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002160155129.png" alt="image-20201002160155129"></p><p>同样对于y&#x3D;0（良性肿瘤）的代价函数为：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002160126721.png" alt="image-20201002160126721"></p><p>y的取值只有0、1，可以将上面两个函数合成一个，评估当前参数的$J(\theta)$为：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002193349426.png" alt="image-20201002193349426"></p><h3 id="梯度下降-1"><a href="#梯度下降-1" class="headerlink" title="梯度下降"></a>梯度下降</h3><p>在确定代价函数之后的任务是，如何最小化代价函数，因为代价函数是凸的，所以可以使用梯度下降求解。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002193549679.png" alt="image-20201002193549679"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201002193728758.png" alt="image-20201002193728758"></p><p>虽然求偏导之后，$\theta$更新的形式和线性回归类似，但是他们本质不同，因为$h_\theta(x)$完全不一样。</p><p><a href="https://www.cnblogs.com/zhongmiaozhimen/p/6155093.html">具体的偏导推导过程</a>：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002193927240.png" alt="image-20201002193927240"></p><h3 id="多元分类"><a href="#多元分类" class="headerlink" title="多元分类"></a>多元分类</h3><p><img src="/blog/img/Blog/ml-andrew/image-20201002200132671.png" alt="image-20201002200132671"></p><p>对每个特征单独训练，在做预测的时候，取三个分类器结果最大的。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002200303264.png" alt="image-20201002200303264"></p><h2 id="过拟合"><a href="#过拟合" class="headerlink" title="过拟合"></a>过拟合</h2><p>存在多个特征，但是数据很少，或者模型函数不合理，都会出现过拟合的现象。过拟合可能对样本数能够很好的解释，但是无法正确的预测新数据。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002211447558.png" alt="image-20201002211447558"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201002211511303.png" alt="image-20201002211511303"></p><h2 id="正则化"><a href="#正则化" class="headerlink" title="正则化"></a>正则化</h2><p>解决过拟合的方法：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201002211815208.png" alt="image-20201002211815208"></p><p>正则化处理过拟合问题：</p><p>在代价函数中加入正则项，通过lambda的来平衡拟合程度和参数的大小，$\theta$约大越容易出现过拟合的现象。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201009160444537.png" alt="image-20201009160444537"></p><p>如果lambda过大，导致$\theta \approx 0$，那么最终只剩下下$\theta_0$，图像将变成一个直线。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201009160357606.png" alt="image-20201009160357606"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201028164800636.png" alt="image-20201028164800636"></p><h2 id="模型评估"><a href="#模型评估" class="headerlink" title="模型评估"></a>模型评估</h2><h3 id="训练、测试集"><a href="#训练、测试集" class="headerlink" title="训练、测试集"></a>训练、测试集</h3><p>将数据集分为训练集和测试集，训练集得到参数$\theta$，然后使用测试集的数据对参数$\theta$进行评估，即计算误差。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017130647268.png" alt="image-20201017130647268"></p><p>线性回归问题的评估：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017130713921.png" alt="image-20201017130713921"></p><p>逻辑回归问题的评估：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017130740110.png" alt="image-20201017130740110"></p><h3 id="训练、验证、测试集"><a href="#训练、验证、测试集" class="headerlink" title="训练、验证、测试集"></a>训练、验证、测试集</h3><p>首先用训练集得到一个最优的参数$\theta$，然后用测试集进行评估误差。通过这样的方式可以在众多模型中选择一个理想的模型。</p><p>但是这样做并不能评估模型的<strong>泛化能力</strong>，通过测试集评估选择的模型，可能刚好适合测试集的数据，并不能说明它对其他数据的预测能力，这时就引入了验证集。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017131449719.png" alt="image-20201017131449719"></p><p>将数据集分为：训练集、验证集、测试集。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017131519699.png" alt="image-20201017131519699"></p><p>对于每个集合都可以计算相应的误差。</p><p> <img src="/blog/img/Blog/ml-andrew/image-20201017131609332.png" alt="image-20201017131609332"></p><p>这样在选择模型的时候，可以先使用测试集得到每个模型的$\theta$，然后使用验证集评估得到误差最小的模型，最后使用测试集评估他的泛化能力。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017131812807.png" alt="image-20201017131812807"></p><h3 id="偏差、方差"><a href="#偏差、方差" class="headerlink" title="偏差、方差"></a>偏差、方差</h3><p>当多项式次数增大时，训练集的误差慢慢减小，因为多项式次数越高，图像拟合的就越准确。但是验证集不同，它的趋势是先减少后增大，这分别对应着欠拟合和过拟合。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017131855857.png" alt="image-20201017131855857"></p><p>那么我们可以根据误差的不同表现来区分偏差和方差。</p><p>高偏差：训练误差和验证误差都很大。</p><p>高方差：训练误差小，验证误差大。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017132221852.png" alt="image-20201017132221852"></p><h3 id="正则化-1"><a href="#正则化-1" class="headerlink" title="正则化"></a>正则化</h3><p>通过引入$\lambda$来平衡多形式的权重。</p><p>当$\lambda$太大，参数$\theta \approx0$，模型近似直线，即欠拟合。当$\lambda$太小，就会出现过拟合。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017140626985.png" alt="image-20201017140626985"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201017140936964.png" alt="image-20201017140936964"></p><h3 id="学习曲线"><a href="#学习曲线" class="headerlink" title="学习曲线"></a>学习曲线</h3><p>随着数据量的增加，$J_{train}(\theta)$的误差慢慢增大，因为数据越少，模型越容易拟合；$J_{cv}(\theta)$慢慢减少，因为数据越多，模型越精准，所以误差减小。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017142111611.png" alt="image-20201017142111611"></p><p>高偏差的模型的学习曲线：</p><p>因为参数很少，数据很多，所以随着数据的增多高偏差的模型的$J_{train}(\theta)$和$J_{cv}(\theta)$很接近。这时选择增加数据就不是很好的选择了，可以尝试增加数据的特征。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017142532611.png" alt="image-20201017142532611"></p><p>高方差的模型的学习曲线：</p><p>高方差的特点是训练误差和验证误差之间有很大的差距，这时可以选择增加数据，随着图像右移可以看出训练误差和验证误差会慢慢接近。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201017142556080.png" alt="image-20201017142556080"></p><h3 id="如何抉择"><a href="#如何抉择" class="headerlink" title="如何抉择"></a>如何抉择</h3><p><img src="/blog/img/Blog/ml-andrew/image-20201017143417016.png" alt="image-20201017143417016"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201017143728141.png" alt="image-20201017143728141"></p><h3 id="查准率、召回率"><a href="#查准率、召回率" class="headerlink" title="查准率、召回率"></a>查准率、召回率</h3><p>例如对癌症的预测，相对于样本数据真实得癌症的人非常少，大概只有0.5%的概率，这样的问题称为偏斜类，一个类中的样本数比另一个类多得多。</p><p>对于偏斜类的问题，如何评估模型的精准度呢？可能一个只输出y&#x3D;1的函数都比你的模型准确。</p><p>这里引入了查准率和召回率，对于稀有的样本有：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019123538038.png" alt="image-20201019123538038"></p><p>通常如果阈值设置的比较高，那么对应的查准率高、召回率低；相反如果阈值设置的低，那么查准率低、召回率高。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019123701192.png" alt="image-20201019123701192"></p><h3 id="F1-score"><a href="#F1-score" class="headerlink" title="F1 score"></a>F1 score</h3><p>如何比较权衡不同的算法呢？</p><p>这里使用的$F_1 score$，即调和平均数（倒数的平均数）来衡量。</p><p>$F_1 score$会比较照顾数值小的一方，如果PR都为0，$F_1 score&#x3D;0$；如果PR都为1，$F_1 score&#x3D;1$</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019123950436.png" alt="image-20201019123950436"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201019124139908.png" alt="image-20201019124139908"></p><h2 id="神经网络"><a href="#神经网络" class="headerlink" title="神经网络"></a>神经网络</h2><p>大多数的机器学习所涉及到的特征非常多，对于非线性分类问题，往往需要构造多项式来表示数据之间的关系，多项式的组成方式千变万化，这对计算带来一定困扰。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201015221136066.png" alt="image-20201015221136066"></p><p>大脑中的神经元结构：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201015221446454.png" alt="image-20201015221446454"></p><p>机器学习中的神经网络一般包括三部分，输入层，隐藏层，输出层。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201015221559627.png" alt="image-20201015221559627"></p><p>数据从输入层开始，通过激活函数前向传播到第一隐藏层，经过多个隐藏层，最后到达输出层，神经网络表示复杂的逻辑关系，主要是对隐藏层的构造。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201015221627962.png" alt="image-20201015221627962"></p><h3 id="逻辑运算"><a href="#逻辑运算" class="headerlink" title="逻辑运算"></a>逻辑运算</h3><p><img src="/blog/img/Blog/ml-andrew/image-20201015221807035.png" alt="image-20201015221807035"></p><p>如上为一个XNOR的分类问题，$xnor&#x3D;(x_1 &amp; x_2) or (\bar{x_1} &amp; \bar{x_2})$，我们可以搭建出每种逻辑运算的神经网络，最终整合得到XNOR的神经网络模型。</p><p><strong>AND运算</strong></p><p><img src="/blog/img/Blog/ml-andrew/image-20201015221951588.png" alt="image-20201015221951588"></p><p><strong>OR运算</strong></p><p><img src="/blog/img/Blog/ml-andrew/image-20201015222018533.png" alt="image-20201015222018533"></p><p><strong>NOT运算</strong></p><p><img src="/blog/img/Blog/ml-andrew/image-20201015222132014.png" alt="image-20201015222132014"></p><p><strong>XNOR运算</strong></p><p>$xnor&#x3D;(x_1 &amp; x_2) or (\bar{x_1} &amp; \bar{x_2})$</p><p><img src="/blog/img/Blog/ml-andrew/image-20201015222208813.png" alt="image-20201015222208813"></p><h3 id="多元分类-1"><a href="#多元分类-1" class="headerlink" title="多元分类"></a>多元分类</h3><p>通过构建神经网络，每种输出就对应一个分类器。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201015222645344.png" alt="image-20201015222645344"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201015222753618.png" alt="image-20201015222753618"></p><h3 id="代价函数-2"><a href="#代价函数-2" class="headerlink" title="代价函数"></a>代价函数</h3><p><img src="/blog/img/Blog/ml-andrew/image-20201029103442247.png" alt="image-20201029103442247"></p><p>K表示输出层的单元数目，L为神经网络的层数。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201029103800511.png" alt="image-20201029103800511"></p><h3 id="前向传播"><a href="#前向传播" class="headerlink" title="前向传播"></a>前向传播</h3><p><img src="/blog/img/Blog/ml-andrew/image-20201016153630528.png" alt="image-20201016153630528"></p><h3 id="反向传播"><a href="#反向传播" class="headerlink" title="反向传播"></a>反向传播</h3><p><img src="/blog/img/Blog/ml-andrew/image-20201016153534741.png" alt="image-20201016153534741"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201016153516048.png" alt="image-20201016153516048"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201016153457879.png" alt="image-20201016153457879"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201016153704540.png" alt="image-20201016153704540"></p><h3 id="随机初始化"><a href="#随机初始化" class="headerlink" title="随机初始化"></a>随机初始化</h3><p>在对神经网络进行训练时，theta的取值要随机取值，如果都赋值为0，就会使得每一层的输出值、误差相同，从而存在大量冗余。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201109212012819.png" alt="image-20201109212012819"></p><h3 id="梯度检测"><a href="#梯度检测" class="headerlink" title="梯度检测"></a>梯度检测</h3><p>在实现反向传播算法时，如何确保梯度计算正确呢？</p><p>在数学上可以使用拉格朗日中值定理来近似的表示曲线上某一点的导数，梯度检测正是使用的这种思想。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201106223535108.png" alt="image-20201106223535108"></p><p>梯度检测的使用，可以对每个参数单独进行验证。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201106223800987.png" alt="image-20201106223800987"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201106223848817.png" alt="image-20201106223848817"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201109210603659.png" alt="image-20201109210603659"></p><p>假设通过中值定理得到的梯度为approx_grad，经过反向传播得到的梯度为grad，如果满足以下等式，则说明反向传播得到的梯度精度还行。</p><div>$$diff = \frac{||approx\_grad-grad||}{||approx\_grad+grad|||} < 10e^{-9}$$</div><p>梯度计算正确的情况下，当算法进行学习的时候要关闭梯度检测，因为它非常耗时。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201106223929987.png" alt="image-20201106223929987"></p><h2 id="支持向量机"><a href="#支持向量机" class="headerlink" title="支持向量机"></a>支持向量机</h2><p>逻辑回归模型的图像是一个曲线或复杂的曲线，SVM使用简单函数来近似这个曲线。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019172254573.png" alt="image-20201019172254573"></p><h3 id="代价函数-3"><a href="#代价函数-3" class="headerlink" title="代价函数"></a>代价函数</h3><p>支持向量机在逻辑回归的基础上简化了代价函数，逻辑回归使用正则项来权衡$\theta$的大小，以此解决过拟合的问题。SVM也是类似，它是在代价函数上添加系数C，效果等价。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019172318776.png" alt="image-20201019172318776"></p><h3 id="最大边界"><a href="#最大边界" class="headerlink" title="最大边界"></a>最大边界</h3><p>SVM又叫做最大边界分类问题，观察代价函数可以得到：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019172946034.png" alt="image-20201019172946034"></p><p>最小化代价函数，就是让左侧代价函数的和尽可能等于0，即对应$\theta^Tx$，另外还有右侧的$\theta^2$的和最小，即向量的模尽可能小。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019174929240.png" alt="image-20201019174929240"></p><p>分类问题的界限有多种可能，SVM对于如下二分类的问题，往往会得到黑色的那条分界线，这条线恰好对应着最大的边界，因此也叫做最大边界分类问题。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019174955408.png" alt="image-20201019174955408"></p><p>代价函数中的C决定了边界的划分，如果C很大对应逻辑回归的$\lambda$很小，模型过拟合，这样就会的到紫色的分界线，通过C的取值，我们可以决定边界的划分。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019175227034.png" alt="image-20201019175227034"></p><h3 id="证明"><a href="#证明" class="headerlink" title="证明"></a>证明</h3><p>向量的内积，等价于投影长度的乘积。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019175359969.png" alt="image-20201019175359969"></p><p>因此$\theta^Tx$可以写为$p||\theta||$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019175637627.png" alt="image-20201019175637627"></p><p>对于左侧的$\theta$，每个x向量在$\theta$上的投影距离很小，要满足条件那么$||\theta||$就要增大，这样最小化代价函数的值就不是最优的，可能发生过拟合，所以SVM会得到类似右侧的边界，这样$||\theta||$尽可能小些，因为投影距离都比左侧的要大，这也是最大边界的原因。</p><h2 id="核函数"><a href="#核函数" class="headerlink" title="核函数"></a>核函数</h2><p>对于一个非线性决策边界问题，我们可能使用高阶的函数进行拟合，但是是否存在比当前特征刚好的表达形式呢？</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019200045497.png" alt="image-20201019200045497"></p><p>我们可以将每种特征表示为$f_i$，使用<strong>高斯核函数</strong>来做相似度分析。</p><p>随机选择三个点作为标记，通过核函数可以得到x对应的新特征。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019200231780.png" alt="image-20201019200231780"></p><p>使用高斯函数的特点：如果相似度很高，即对应的欧几里得距离$\approx 0$对应$f_i&#x3D;1$，相反如果相似度低对应$f_i\approx 0$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019200525243.png" alt="image-20201019200525243"></p><p>假设我们已经训练好参数$\theta$，那么就可以通过$\theta^Tf \ge 0$来进行预测，即对应红色的决策边界。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019200718526.png" alt="image-20201019200718526"></p><p>可以直接将训练集中的$x^{(i)}$作为核函数中的$l^{(i)}$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201117170117585.png" alt="image-20201117170117585"></p><p>这样对于训练中的数据$x^{(i)}$，都可以得到对应的$f^{(i)}$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201117170327476.png" alt="image-20201117170327476"></p><p>SVM在使用核函数的时候，对应代价函数就可以替换为：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019201016956.png" alt="image-20201019201016956"></p><p>和SVM中的参数C一样，核函数的$\sigma^2$决定了拟合的程度。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201019201757549.png" alt="image-20201019201757549"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201019200547974.png" alt="image-20201019200547974"></p><h2 id="k均值"><a href="#k均值" class="headerlink" title="k均值"></a>k均值</h2><p>对于没有标签的数据来说，首先根据划分聚类的个数，随机设置聚类中心的位置，然后遍历所有的数据，把每个数据分配到离它最近的坐标，对于同一个簇的数据计算它们坐标的中心位置，并设置为新的聚类中心，以此不断的迭代。</p><p><img src="/blog/img/Blog/ml-andrew/GIF-2020-10-20-17-46-05.gif" alt="image-20201020174043879"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201020174734697.png" alt="image-20201020174734697"></p><p>k均值的目标函数是所有点到它所属聚类中心的距离和。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201020174835196.png" alt="image-20201020174835196"></p><p><strong>随机初始化</strong>，当聚类数量很少时，如果初始化的位置不够好，会得到一个局部最优解，解决方案是多次随机初始化，从而得到一个全局最优解。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201020194148820.png" alt="image-20201020194148820"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201020194208879.png" alt="image-20201020194208879"></p><p><strong>聚类数量的选择</strong>，得到聚类数量和代价的图像，根据肘部原则选取（一般不用）；或者根据k均值聚类的目的来做判断，比如做衣服尺寸的聚类分析，根据市场需求，3个聚类or5个聚类更适合市场营销等等。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201020195028492.png" alt="image-20201020195028492"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201020195102677.png" alt="image-20201020195102677"></p><h2 id="主成分分析-PCA"><a href="#主成分分析-PCA" class="headerlink" title="主成分分析(PCA)"></a>主成分分析(PCA)</h2><p><img src="/blog/img/Blog/ml-andrew/image-20201120230001261.png" alt="image-20201120230001261"></p><p>主成分分析(PCA)是一种数据压缩的算法，他将数据压缩到k维度，并使得所有数据投影到新维度的距离最小。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021093606393.png" alt="image-20201021093606393"></p><p>PCA不是线性回归，一个是投影距离，一个是点与直线上点的距离。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021093750890.png" alt="image-20201021093750890"></p><p>PCA执行过程，首先对数据进行均值归一化，然后计算协方差，最后得到一个k维的矩阵。</p><p>首先对数据进行均值归一化，然后确定要压缩的目标维度，即对应向量的个数，PCA的目标是使得所有数据距离新维度的距离最小。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201120232141453.png" alt="image-20201120232141453"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201120232417568.png" alt="image-20201120232417568"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021095651432.png" alt="image-20201021095651432"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021095815835.png" alt="image-20201021095815835"></p><p>如何确定维度K？</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021100643103.png" alt="image-20201021100643103"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021100650094.png" alt="image-20201021100650094"></p><p>如何得到压缩直线的近似坐标？</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021100903151.png" alt="image-20201021100903151"></p><h2 id="异常检测"><a href="#异常检测" class="headerlink" title="异常检测"></a>异常检测</h2><h3 id="高斯分布"><a href="#高斯分布" class="headerlink" title="高斯分布"></a>高斯分布</h3><p>可以使用<strong>高斯分布</strong>来进行异常检测。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021134842347.png" alt="image-20201021134842347"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021134859966.png" alt="image-20201021134859966"></p><p>计算m个数据集在每一个维度上的$\mu$和$\sigma^2$，然后根据$p(x)$得到一个概率$\epsilon$，根据概率的大小来定义是否为异常行为。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021160740256.png" alt="image-20201021160740256"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021160747899.png" alt="image-20201021160747899"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021160805733.png" alt="image-20201021160805733"></p><h3 id="多变量高斯分布"><a href="#多变量高斯分布" class="headerlink" title="多变量高斯分布"></a>多变量高斯分布</h3><p>异常检测算法，往往是把$\mu$附近的数据认为是高频率出现的，表现在图像上类似一个圆形。在一些情况下数据并不是规则分布，单变量的高斯分布不能体现拟合椭圆形状。</p><p> <img src="/blog/img/Blog/ml-andrew/image-20201021164402680.png" alt="image-20201021164402680"></p><p>多变量高斯分布引入了协方差矩阵，通过修改矩阵的值来改变高斯分布的情况。</p><p>$\Sigma$可以理解为每个特征的缩放比例，这样就可以拟合更多的数据分布。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021164622303.png" alt="image-20201021164622303"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021164636889.png" alt="image-20201021164636889"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021164653817.png" alt="image-20201021164653817"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021164707257.png" alt="image-20201021164707257"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021164803037.png" alt="image-20201021164803037"></p><p>传统的高斯分布实际上是多变量高斯分布的特殊形式，对应矩阵在非对角线上的数为0。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021164928186.png" alt="image-20201021164928186"></p><p>传统的模型需要手动构造异常特征的组合，多变量可以自动的捕捉。不过多变量的计算复杂度高一些。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021165004871.png" alt="image-20201021165004871"></p><h2 id="推荐系统"><a href="#推荐系统" class="headerlink" title="推荐系统"></a>推荐系统</h2><h3 id="内容推荐算法"><a href="#内容推荐算法" class="headerlink" title="内容推荐算法"></a>内容推荐算法</h3><p>例如一个电影推荐系统，一共有n个用户，m个电影，每部电影都有一定的特征，例如爱情片的比例、动作片的比例。n个用户对看过的电影进行评分，推荐系统做的给用户推荐新电影，预测用户对新电影的评分？</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021200557627.png" alt="image-20201021200557627"></p><p>可以使用线性回归的方法进行训练，得到用户对于特征的参数$\theta$，之后就可以根据$\theta^TX$对电影进行打分。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021201023606.png" alt="image-20201021201023606"></p><p>优化目标函数为：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021201101616.png" alt="image-20201021201101616"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021201152542.png" alt="image-20201021201152542"></p><h3 id="协同过滤"><a href="#协同过滤" class="headerlink" title="协同过滤"></a>协同过滤</h3><p>collaborative filtering，用于特征学习，自己学习得到数据的特征值。</p><p>我们无法得到每部电影中不同特征的比例，例如电影中爱情和动作的比例？除非人工审核每一部电影，但是太耗时。</p><p>这里有一个思路，首先用户根据自己的喜好对特征打分，通过计算可以大致确定已经打过分的电影它的特征值，根据已经确定的特征值，又可以计算出每个用户对这部电影的评分。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021201340270.png" alt="image-20201021201340270"></p><p>先有鸡还是先有蛋…</p><p>根据特征向量$X$可以通过线性回归得到用户的$\theta$向量，通过用户提供的$\theta$向量可以估计每部电影的特征数值。这就有点像鸡和蛋的问题。</p><p>我们可以随机选取$\theta$向量计算得到特征数值，然后再通过线性回归去更新$\theta$，这样不停的迭代直到最后的收敛。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021202054835.png" alt="image-20201021202054835"></p><p>我们也可以将两种函数合并为一个目标函数：</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021202948381.png" alt="image-20201021202948381"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021203015763.png" alt="image-20201021203015763"></p><h3 id="低秩矩阵分解"><a href="#低秩矩阵分解" class="headerlink" title="低秩矩阵分解"></a>低秩矩阵分解</h3><p>可以把n个用户对m部电影的评分结果表示为$m\times n$的矩阵。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021203534096.png" alt="image-20201021203534096"></p><p>这个矩阵可以表示为$X\theta^T$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021203614025.png" alt="image-20201021203614025"></p><p>通过特征值之间的偏差，我们可以找到类型相近的电影。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021203650048.png" alt="image-20201021203650048"></p><h3 id="均值规范化"><a href="#均值规范化" class="headerlink" title="均值规范化"></a>均值规范化</h3><p>之前无论是参数$\theta$还是特征$X$，都基于每个用户都对多个电影进行的评分，每部电影也被多个用户评分。对于新用户，他可能还没有对任何一部电影进行评分，一种思路就是把所有用户对每部电影的评分的均值作为新用户的初始评分。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021204015593.png" alt="image-20201021204015593"></p><h2 id="随机梯度下降"><a href="#随机梯度下降" class="headerlink" title="随机梯度下降"></a>随机梯度下降</h2><p>Stochastic gradient descent</p><p>随机梯度下降算法对每个数据分开处理，对一个数据更新所有的参数。</p><p>梯度下降算法是在每次更新参数的时候，需要计算所有数据。</p><p>对比下来SGD的速度要快一些，不过收敛性可能没GD好。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021225514894.png" alt="image-20201021225514894"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021225802565.png" alt="image-20201021225802565"></p><p>如何判断SGD的收敛？</p><p>首先定义cost函数，然后每隔1000次迭代画出cost的图像，根据均值来判断。</p><p>如果噪声太多图像上下震荡，可以选择更多的迭代次数。</p><p>如果随着迭代次数cost增加，那么选择更小的$\alpha$。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021230250625.png" alt="image-20201021230250625"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021230648977.png" alt="image-20201021230648977"></p><p>SGD一般不能得到全局最优，他会一直在最优值附近徘徊。</p><p>学习率的大小一般保持不变，一个思路是可以动态的改变学习率$\alpha$的大小来提高准确度，比如随着迭代次数的增加慢慢减小$\alpha$的值。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021230901609.png" alt="image-20201021230901609"></p><h2 id="Mini-Batch"><a href="#Mini-Batch" class="headerlink" title="Mini-Batch"></a>Mini-Batch</h2><p>Mini-Batch gradient descent</p><p>将数据分为多份，对每一份执行GD，相当于GD和SGD的综合。</p><p>b可以取[10,100]。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021230101676.png" alt="image-20201021230101676"></p><h2 id="Map-reduce"><a href="#Map-reduce" class="headerlink" title="Map-reduce"></a>Map-reduce</h2><p>Map-reduce and data parallelism。</p><p>Map-reduce利用了线性回归求和运算的特性，将GD对整个数据的求和处理，分摊到多个服务器上执行，最后各个服务器把结果汇总到一起进行合并。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021231524731.png" alt="image-20201021231524731"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201021231829330.png" alt="image-20201021231829330"></p><p>逻辑回归也可以这样搞。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201021231921203.png" alt="image-20201021231921203"></p><h2 id="OCR"><a href="#OCR" class="headerlink" title="OCR"></a>OCR</h2><h3 id="pipeline"><a href="#pipeline" class="headerlink" title="pipeline"></a>pipeline</h3><p><img src="/blog/img/Blog/ml-andrew/image-20201022150326345.png" alt="image-20201022150326345"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201022150336290.png" alt="image-20201022150336290"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201022150639975.png" alt="image-20201022150639975"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201022150659195.png" alt="image-20201022150659195"></p><h3 id="滑动窗口"><a href="#滑动窗口" class="headerlink" title="滑动窗口"></a>滑动窗口</h3><p><img src="/blog/img/Blog/ml-andrew/GIF-2020-10-22-15-05-26.gif" alt="GIF 2020-10-22 15-05-26"></p><h3 id="获取数据"><a href="#获取数据" class="headerlink" title="获取数据"></a>获取数据</h3><p>下载字体，然后将它们放到一个随机北京图片上。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201022150833190.png" alt="image-20201022150833190"></p><p>对图像进行人工扭曲</p><p><img src="/blog/img/Blog/ml-andrew/image-20201022150910402.png" alt="image-20201022150910402"></p><p>对语音文本加入不同的背景干扰。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201022150949080.png" alt="image-20201022150949080"></p><p>首先确保算法已经有很低的偏差，整体的模型ok，然后在考虑加数据，否则只是徒劳。</p><p>然后考虑加数据的人工和时间成本。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201022151143779.png" alt="image-20201022151143779"></p><h2 id="上限分析"><a href="#上限分析" class="headerlink" title="上限分析"></a>上限分析</h2><p>对多个模块进行分析，让其中一个模块达到100%的准确率，然后判断它能提高整个系统多少准确率。</p><p><img src="/blog/img/Blog/ml-andrew/image-20201022151317349.png" alt="image-20201022151317349"></p><p><img src="/blog/img/Blog/ml-andrew/image-20201022151401539.png" alt="image-20201022151401539"></p><h2 id="课后作业"><a href="#课后作业" class="headerlink" title="课后作业"></a>课后作业</h2><p>作业地址：<a href="https://github.com/Sanzona/ML-homework">https://github.com/Sanzona/ML-homework</a></p><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;机器学习劝退指南…&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="ML" scheme="https://sanzo.top/blog/tags/ML/"/>
    
  </entry>
  
  <entry>
    <title>VSCode插件: Continue</title>
    <link href="https://sanzo.top/blog/Blog/continue/"/>
    <id>https://sanzo.top/blog/Blog/continue/</id>
    <published>2024-04-02T11:23:09.000Z</published>
    <updated>2024-04-02T11:23:09.000Z</updated>
    
    <content type="html"><![CDATA[<p>让大模型帮你写代码：<a href="https://ollama.com/download">Ollama</a> + <a href="https://github.com/continuedev/continue">Continue</a>。</p><span id="more"></span><h2 id="Ollama"><a href="#Ollama" class="headerlink" title="Ollama"></a>Ollama</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -fsSL https://ollama.com/install.sh | sh</span><br></pre></td></tr></table></figure><p>我是在服务器上安装的，为了支持远程访问，需要修改下配置文件。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> vim  /etc/systemd/system/ollama.service</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">[Unit]</span><br><span class="line">Description=Ollama Service</span><br><span class="line">After=network-online.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">ExecStart=/usr/local/bin/ollama serve</span><br><span class="line">User=root</span><br><span class="line">Group=root</span><br><span class="line">Restart=always</span><br><span class="line">RestartSec=3</span><br><span class="line">Environment=<span class="string">&quot;OLLAMA_MODELS=your_model_path/ollama/models&quot;</span></span><br><span class="line"><span class="comment"># 添加下面两行</span></span><br><span class="line">Environment=<span class="string">&quot;OLLAMA_HOST=0.0.0.0&quot;</span></span><br><span class="line">Environment=<span class="string">&quot;OLLAMA_ORIGINS=*&quot;</span></span><br><span class="line">Environment=<span class="string">&quot;CUDA_VISIBLE_DEVICES=0,1,2&quot;</span></span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=default.target</span><br></pre></td></tr></table></figure><p>ollama所有可用模型：<a href="https://ollama.com/library">https://ollama.com/library</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重启服务</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl daemon-reload</span><br><span class="line"><span class="built_in">sudo</span> systemctl restart ollama</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载模型</span></span><br><span class="line">ollama run codellama:13b</span><br></pre></td></tr></table></figure><p>同时部署多个模型 <strong>[可选]</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 默认端口为11434， 这里额外部署一个11435的服务</span></span><br><span class="line">OLLAMA_HOST=0.0.0.0:11435 ollama serve</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载模型</span></span><br><span class="line">OLLAMA_HOST=127.0.0.1:11435 ollama pull codellama:13b</span><br><span class="line"></span><br><span class="line"><span class="comment"># 测试</span></span><br><span class="line">curl -X POST http://127.0.0.1:11435/api/generate -d <span class="string">&#x27;&#123;</span></span><br><span class="line"><span class="string">  &quot;model&quot;: &quot;codellama:13b&quot;,</span></span><br><span class="line"><span class="string">  &quot;prompt&quot;: &quot;Write me a function that outputs the fibonacci sequence&quot;</span></span><br><span class="line"><span class="string">&#125;&#x27;</span></span><br></pre></td></tr></table></figure><h2 id="Continue"><a href="#Continue" class="headerlink" title="Continue"></a>Continue</h2><ol><li><p>在vscode的插件库上安装Continue插件。</p></li><li><p>在<code>config.json</code>中添加模型配置文件。</p><p>如果使用本地模型，可以注释掉<code>&quot;apiBase&quot;: &quot;http://your_server_ip:11435&quot;</code>，如果使用的是默认的ollama服务，端口<code>11435</code> 改为 <code>11434</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;models&quot;</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;Codellama 7b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;codellama:7b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://your_server_ip:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;Codellama 13b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;codellama:13b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://your_server_ip:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;Codellama 34b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;codellama:34b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://your_server_ip:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;StarCoder2 3b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;starcoder2:3b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://node1:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;StarCoder2 7b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;starcoder2:7b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://node1:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;starcoder2:15b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;starcoder2:15b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://node1:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;Llama2 7b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;llama2:7b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://your_server_ip:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;Llama2 13b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;llama2:13b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://your_server_ip:11435&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;title&quot;</span>: <span class="string">&quot;Llama2 70b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;provider&quot;</span>: <span class="string">&quot;ollama&quot;</span>,</span><br><span class="line">      <span class="string">&quot;model&quot;</span>: <span class="string">&quot;llama2:70b&quot;</span>,</span><br><span class="line">      <span class="string">&quot;apiBase&quot;</span>: <span class="string">&quot;http://your_server_ip:11435&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">  ],</span><br></pre></td></tr></table></figure></li></ol><h2 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h2><ol><li><p><code>Ctrl + L</code>选中代码，弹出聊天窗口，可以直接询问LLM，例如编写单元测试，检查bug。</p><p><img src="/blog/img/continue/image-20240402195031626.png" alt="image-20240402195237473"></p></li><li><p><code>Ctrl + I</code>插入代码，弹出<code>prompt</code>输入框，根据需求生成代码。</p><p><img src="/blog/img/continue/image-20240402195237473.png" alt="image-20240402195237473"></p></li></ol><p><img src="/blog/img/continue/image-20240402195249229.png" alt="image-20240402195249229"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;让大模型帮你写代码：&lt;a href=&quot;https://ollama.com/download&quot;&gt;Ollama&lt;/a&gt; + &lt;a href=&quot;https://github.com/continuedev/continue&quot;&gt;Continue&lt;/a&gt;。&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="continue" scheme="https://sanzo.top/blog/tags/continue/"/>
    
    <category term="ollama" scheme="https://sanzo.top/blog/tags/ollama/"/>
    
  </entry>
  
  <entry>
    <title>使用Docker封印EasyConnect</title>
    <link href="https://sanzo.top/blog/Blog/easyconnect/"/>
    <id>https://sanzo.top/blog/Blog/easyconnect/</id>
    <published>2024-10-03T02:40:48.000Z</published>
    <updated>2024-10-03T02:40:48.000Z</updated>
    
    <content type="html"><![CDATA[<p>…</p><span id="more"></span><blockquote><p>EasyConnect的毒瘤行为</p></blockquote><ul><li>代理所有系统流量</li><li>安装自己的 CA 根证书</li><li>开机自启进程（EasyMonitor）：root 帐号启动，理论可以监听电脑所有行为，无法关闭，否则不能使用vpn服务。</li></ul><h2 id="清除EasyConnect-macOS"><a href="#清除EasyConnect-macOS" class="headerlink" title="清除EasyConnect (macOS)"></a>清除EasyConnect (macOS)</h2><ol><li><p>使用 <code>sudo su</code> 获取管理员权限；</p></li><li><p>删除</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">rm</span> /Library/LaunchDaemons/com.sangfor.EasyMonitor.plist</span><br><span class="line"><span class="built_in">rm</span> /Library/LaunchAgents/com.sangfor.ECAgentProxy.plist</span><br></pre></td></tr></table></figure></li><li><p>重新启动 Mac；</p></li><li><p>打开钥匙串，删除系统钥匙串-系统-证书下面的证书（关键词 sangfor）。</p></li></ol><blockquote><p>注意一定要 <em>先重启Mac再删除证书</em> ，因为在后台的 EasyMonitor 进程会在证书被删除后自动导入。</p></blockquote><h2 id="方案1-使用脚本管理"><a href="#方案1-使用脚本管理" class="headerlink" title="方案1: 使用脚本管理"></a>方案1: 使用脚本管理</h2><p>如果想继续使用EasyConnect在本地进行VPN服务，可以使用下面两个脚本：</p><p><strong>startEasyConnect.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#! /bin/bash</span></span><br><span class="line"></span><br><span class="line">/Applications/EasyConnect.app/Contents/Resources/bin/EasyMonitor &gt; /dev/null 2&gt;&amp;1 &amp;</span><br><span class="line">/Applications/EasyConnect.app/Contents/MacOS/EasyConnect &gt; /dev/null 2&gt;&amp;1 &amp;</span><br></pre></td></tr></table></figure><p><strong>killEasyMonitor.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#! /bin/bash</span></span><br><span class="line"></span><br><span class="line">pkill EasyMonitor</span><br><span class="line">pkill ECAgent</span><br><span class="line">pkill ECAgentProxy</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">chmod</span> +x startEasyConnect.sh</span><br><span class="line"><span class="built_in">chmod</span> +x killEasyMonitor.sh</span><br></pre></td></tr></table></figure><h2 id="方案2-使用Docker管理-推荐"><a href="#方案2-使用Docker管理-推荐" class="headerlink" title="方案2: 使用Docker管理(推荐)"></a>方案2: 使用Docker管理(推荐)</h2><blockquote><p>开启docker服务</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p ~/.config/ecdata</span><br><span class="line"></span><br><span class="line">docker run \</span><br><span class="line">    --device /dev/net/tun \</span><br><span class="line">    --cap-add NET_ADMIN \</span><br><span class="line">    -d \</span><br><span class="line">    --restart always \</span><br><span class="line">    -e PASSWORD=ecconnect \</span><br><span class="line">    -e URLWIN=1 \</span><br><span class="line">    -v ~/.config/ecdata:/root \</span><br><span class="line">    -p 5901:5901 \</span><br><span class="line">    -p 1080:1080 \</span><br><span class="line">    -p 8888:8888 \</span><br><span class="line">    hagb/docker-easyconnect:7.6.7</span><br></pre></td></tr></table></figure><blockquote><p>使用RealVNC连接</p></blockquote><p>ip: <code>127.0.0.1:5901</code>, passed: <code>ecconnect</code>.</p><p><img src="/blog/img/Blog/easyconnect/image-20241003110329733.png" alt="image-20241003110329733"></p><img src="../../img/Blog/easyconnect/image-20241003110527080.png" alt="image-20241003110527080" style="zoom:67%;" /><blockquote><p>Clash代理配置</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">- name: <span class="string">&#x27;NEU-campus#🏫&#x27;</span></span><br><span class="line">  <span class="built_in">type</span>: http</span><br><span class="line">  port: 8888</span><br><span class="line">  <span class="comment"># type: socks5</span></span><br><span class="line">  <span class="comment"># port: 1080</span></span><br><span class="line">  server: 127.0.0.1</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">- IP-CIDR,118.202.20.98/32,NEU-campus#🏫</span><br><span class="line">- IP-CIDR,210.30.200.57/32,NEU-campus#🏫</span><br><span class="line">- IP-CIDR,219.216.64.197/32,NEU-campus#🏫</span><br><span class="line">- IP-CIDR,202.118.8.24/32,NEU-campus#🏫</span><br><span class="line"><span class="comment"># - DOMAIN-SUFFIX,neu.edu.cn,NEU-campus#🏫</span></span><br></pre></td></tr></table></figure><blockquote><p>ssh代理配置</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Host node1-jump</span><br><span class="line">    HostName your_server_ip  <span class="comment"># 目标服务器主机名</span></span><br><span class="line">    User your_user_name</span><br><span class="line">    ProxyCommand connect -H 127.0.0.1:8888 %h %p</span><br><span class="line"></span><br><span class="line">Host node2-jump</span><br><span class="line">    HostName your_server_ip  <span class="comment"># 目标服务器主机名</span></span><br><span class="line">    User yuanh</span><br><span class="line">    ProxyCommand connect -H 127.0.0.1:8888 %h %p</span><br><span class="line"></span><br><span class="line"><span class="comment"># then use `ssh node2-jump` to connect the node2 server.</span></span><br></pre></td></tr></table></figure><blockquote><p>Reference</p></blockquote><p><a href="https://vccv.cc/article/docker-easyconnect.html">解决EasyConnect的毒瘤行为</a></p><p><a href="https://jortana.top/2021/07/13/%E7%94%A8docker%E5%B0%81%E5%8D%B0EasyConnect%E5%B9%B6%E8%BF%9E%E6%8E%A5%E8%BF%9C%E7%A8%8B%E6%A1%8C%E9%9D%A2%E5%92%8C%E6%95%B0%E6%8D%AE%E5%BA%93/">用docker封印EasyConnect并连接远程桌面和数据库</a></p><p><a href="https://blog.ning.moe/posts/fuck-easyconnect/">封印 Easyconnect</a></p><p><a href="https://taoshu.in/easyconnect-in-docker.html#google_vignette">使用 Docker 封印 EasyConnect</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;…&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="vpn" scheme="https://sanzo.top/blog/tags/vpn/"/>
    
    <category term="EasyConnect" scheme="https://sanzo.top/blog/tags/EasyConnect/"/>
    
    <category term="school" scheme="https://sanzo.top/blog/tags/school/"/>
    
  </entry>
  
  <entry>
    <title>git笔记</title>
    <link href="https://sanzo.top/blog/Blog/git/"/>
    <id>https://sanzo.top/blog/Blog/git/</id>
    <published>2021-07-10T16:10:10.000Z</published>
    <updated>2023-01-12T02:10:10.000Z</updated>
    
    <content type="html"><![CDATA[<p>git迷路指南</p><span id="more"></span><h2 id="Commit格式"><a href="#Commit格式" class="headerlink" title="Commit格式"></a>Commit格式</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">feat: 新增 feature</span><br><span class="line">fix: 修复 bug</span><br><span class="line">docs: 仅仅修改了文档，比如 README, CHANGELOG, CONTRIBUTE等等</span><br><span class="line">style: 仅仅修改了空格、格式缩进、逗号等等，不改变代码逻辑</span><br><span class="line">refactor: 代码重构，没有加新功能或者修复 bug</span><br><span class="line">perf: 优化相关，比如提升性能、体验</span><br><span class="line"><span class="built_in">test</span>: 测试用例，包括单元测试、集成测试等</span><br><span class="line">chore: 改变构建流程、或者增加依赖库、工具等</span><br><span class="line">revert: 回滚到上一个版本</span><br></pre></td></tr></table></figure><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><p><a href="https://missing.csail.mit.edu/2020/version-control/">Version Control（Git）</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看<span class="built_in">hash</span>对应的文件内容</span></span><br><span class="line">git cat-file -p &lt;hash&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">以graph的格式展示<span class="built_in">log</span>信息</span></span><br><span class="line">git log --all --graph --decorate</span><br><span class="line">git log --all --graph --decorate --oneline</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看文件的修改</span></span><br><span class="line">git diff &lt;filename&gt;</span><br><span class="line">git diff master &lt;filename&gt;</span><br><span class="line">git diff &lt;branch&gt; &lt;branch&gt; &lt;filename&gt;</span><br><span class="line">git diff &lt;hash&gt; &lt;hash&gt; &lt;filename&gt;</span><br><span class="line">git diff --cached</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">切换分支</span></span><br><span class="line">git checkout &lt;branch&gt;</span><br><span class="line">git checkout -b &lt;branch&gt; # 新建分支并切换</span><br><span class="line">git checkout &lt;filenam&gt; # 丢弃修改</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">分支合并</span></span><br><span class="line">git merge &lt;branch&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除分支</span></span><br><span class="line">git branch -d &lt;branch&gt;</span><br><span class="line">git push origin --delete &lt;branch&gt;</span><br><span class="line">git push origin :&lt;branch&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置upstream</span></span><br><span class="line">git branch --set-upstream-to=origin/master</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">同步</span></span><br><span class="line">git remote add &lt;name&gt; &lt;url&gt;</span><br><span class="line">git push &lt;name&gt; &lt;local branch&gt;:&lt;remote branch&gt;</span><br><span class="line">git pull &lt;name&gt; &lt;remote branch&gt;:&lt;local branch&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">仅选择需要add的行</span></span><br><span class="line">git add -p &lt;filename&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看修改情况</span></span><br><span class="line">git blame &lt;filename&gt; # 查看修改对应的id</span><br><span class="line">git show &lt;hash&gt; # 查看commit信息</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">临时保存</span></span><br><span class="line">git stash</span><br><span class="line">git stash --include-untracked</span><br><span class="line">git stash list</span><br><span class="line">git stash show -p stash@&#123;0&#125;</span><br><span class="line">git stash drop stash@&#123;0&#125;</span><br><span class="line">git stash pop</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">fork后的同步</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置upstream</span></span><br><span class="line">git remote add upstream https://github.com/xxx/xxx.git</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">同步原仓库的更新</span></span><br><span class="line">git fetch upstream</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">合并</span></span><br><span class="line">git checkout master</span><br><span class="line">git merge upstream/master</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">submodule</span> </span><br><span class="line">git submodule update --init --recursive</span><br><span class="line">git submodule add your_repository.git</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">将其他分支的commit迁移到目标分支</span></span><br><span class="line">git checkout &lt;target-branch&gt;</span><br><span class="line">git cherry-pick &lt;commit-hash&gt;</span><br></pre></td></tr></table></figure><h2 id="工作流"><a href="#工作流" class="headerlink" title="工作流"></a>工作流</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建本地分支</span></span><br><span class="line">git checkout -b my-feature</span><br><span class="line"></span><br><span class="line"><span class="comment"># 同步到remote</span></span><br><span class="line">git push origin my-feature</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将remote main的分支同步到本地分支</span></span><br><span class="line">git checkout main</span><br><span class="line">git pull origin main</span><br><span class="line">git checkout my-feature</span><br><span class="line">git rebase main</span><br><span class="line">git push -f origin my-feature</span><br><span class="line"></span><br><span class="line"><span class="comment"># main合并pull request (squash and merge)</span></span><br><span class="line">git checkout main</span><br><span class="line">git merge --squash my-feature</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除分支</span></span><br><span class="line">git checkout main</span><br><span class="line">git branch -d my-feature</span><br><span class="line">git push origin --delete my-feature</span><br></pre></td></tr></table></figure><p><a href="http://rogerdudler.github.io/git-guide/index.zh.html">git-简明指南</a></p><h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2><ul><li><p>配置用户信息</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name <span class="string">&quot;Sanzo00&quot;</span></span><br><span class="line">git config --global user.email <span class="string">&quot;arrangeman@163.com&quot;</span></span><br></pre></td></tr></table></figure></li><li><p>生成ssh-key</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -C <span class="string">&quot;arrangeman@163.com&quot;</span></span><br></pre></td></tr></table></figure><p>将生成的公钥文件<code>~/.ssh/id_rsa.pub</code>添加到Github上。</p></li></ul><h2 id="版本回退"><a href="#版本回退" class="headerlink" title="版本回退"></a>版本回退</h2><ol><li><p>修改文件后提交修改到版本库</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br><span class="line">git commit -m <span class="string">&quot;xxx&quot;</span></span><br></pre></td></tr></table></figure></li><li><p>查看历史版本</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">log</span> <span class="comment"># 显示最近到最远的提交</span></span><br><span class="line">git reflog <span class="comment"># 显示所有执行过的命令</span></span><br></pre></td></tr></table></figure></li><li><p>回退到历史版本</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 回到上一个版本</span></span><br><span class="line">git reset --hard HEAD^</span><br><span class="line"></span><br><span class="line"><span class="comment"># 回到上上一个版本</span></span><br><span class="line">git reset --hard HEAD^^</span><br><span class="line"></span><br><span class="line"><span class="comment"># 回到上一个版本 (同上)</span></span><br><span class="line">git reset --hard HEAD~1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 回到制定版本</span></span><br><span class="line">git reset --hard commit_id</span><br></pre></td></tr></table></figure></li></ol><h2 id="工作区和暂存区"><a href="#工作区和暂存区" class="headerlink" title="工作区和暂存区"></a>工作区和暂存区</h2><ol><li><p>工作区: 存放项目的目录</p></li><li><p>暂存区</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 将文件的修改添加到暂存区中</span></span><br><span class="line">git add <span class="string">&quot;file&quot;</span></span><br><span class="line"><span class="comment"># 把暂存区的修改提交到分支</span></span><br><span class="line">git commit</span><br></pre></td></tr></table></figure></li></ol><h2 id="撤销修改"><a href="#撤销修改" class="headerlink" title="撤销修改"></a>撤销修改</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 本地修改没有git add到暂存区, 回退到上一个git add或git commit</span></span><br><span class="line">git checkout -- &lt;file&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 本地修改已经git add到暂存区, 撤销本次git add, 同时撤销本次修改</span></span><br><span class="line">git reset HEAD &lt;file&gt;</span><br><span class="line">git checkout -- &lt;file&gt;</span><br></pre></td></tr></table></figure><h2 id="删除文件"><a href="#删除文件" class="headerlink" title="删除文件"></a>删除文件</h2><ol><li><p>准备工作</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在工作区新建test文件</span></span><br><span class="line"><span class="built_in">touch</span> <span class="built_in">test</span></span><br><span class="line"><span class="comment"># 添加到暂存区</span></span><br><span class="line">git add <span class="built_in">test</span></span><br><span class="line"><span class="comment"># 提交到分支</span></span><br><span class="line">git commit -m <span class="string">&quot;add test&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在本地删除test</span></span><br><span class="line"><span class="built_in">rm</span> <span class="built_in">test</span></span><br><span class="line"><span class="comment"># 工作区和版本库不一致</span></span><br><span class="line">git status</span><br></pre></td></tr></table></figure></li><li><p>确定删除文件test</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">rm</span> <span class="built_in">test</span></span><br><span class="line"><span class="comment"># git add test 等价</span></span><br><span class="line">git commit -m <span class="string">&quot;remove test&quot;</span></span><br></pre></td></tr></table></figure></li><li><p>恢复工作区文件(误删)</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git checkout -- &lt;file&gt;</span><br></pre></td></tr></table></figure></li><li><p>只删除记录中的文件，本地不删除</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">rm</span> --cached &lt;file&gt;</span><br></pre></td></tr></table></figure></li></ol><h2 id="远程仓库"><a href="#远程仓库" class="headerlink" title="远程仓库"></a>远程仓库</h2><ol><li><p>添加远程库</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 初始化本地目录为git仓库</span></span><br><span class="line">git init</span><br><span class="line"><span class="comment"># 关联一个远程库</span></span><br><span class="line">git remote add origin git@github.com:your_name/repo_name.git</span><br><span class="line">git push --set-upstream origin master</span><br><span class="line"><span class="comment"># 本地同步远程仓库</span></span><br><span class="line">git pull origin master</span><br><span class="line"><span class="comment"># 提交到远程仓库</span></span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure></li><li><p>修改远程目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote set-url origin git@github.com:your_name/repo_name.git</span><br></pre></td></tr></table></figure></li><li><p>克隆远程库</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> git@github.com:your_name/repo_name.git</span><br></pre></td></tr></table></figure></li></ol><h2 id="本地仓库"><a href="#本地仓库" class="headerlink" title="本地仓库"></a>本地仓库</h2><p>本地仓库可以用于本地端的同步，例如将本地文件定时同步到硬盘这样的场景。</p><p>比如本地的文件夹为<code>files</code>。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">将文件夹初始化为git目录。</span></span><br><span class="line">git init</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">导出 files.git 目录</span></span><br><span class="line">git clone --bare files files.git</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">把 files.git 放到硬盘中。</span></span><br><span class="line">scp -r files.git /media/sanzo/path/</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加远程目录</span></span><br><span class="line">git remote add origin g/media/sanzo/path/files.git</span><br><span class="line">git push --set-upstream origin master</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">同步</span></span><br><span class="line">git push</span><br></pre></td></tr></table></figure><h2 id="创建与合并分支"><a href="#创建与合并分支" class="headerlink" title="创建与合并分支"></a>创建与合并分支</h2><ol><li><p>创建新分支</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建dev分支</span></span><br><span class="line">git branch dev</span><br><span class="line"><span class="comment"># 切换分支</span></span><br><span class="line">git checkout dev</span><br><span class="line"><span class="comment"># 查看当前分支</span></span><br><span class="line">git branch</span><br><span class="line"><span class="comment"># 查看所有分支</span></span><br><span class="line">git branch -a</span><br></pre></td></tr></table></figure></li><li><p>合并分支</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 切换到主分支, 切换前要git commit</span></span><br><span class="line">git checkout master</span><br><span class="line"><span class="comment"># 合并dev到当前分支</span></span><br><span class="line">git merge dev</span><br><span class="line"><span class="comment"># 删除dev分支</span></span><br><span class="line">git branch -d dev</span><br></pre></td></tr></table></figure></li></ol><h2 id="解决冲突"><a href="#解决冲突" class="headerlink" title="解决冲突"></a>解决冲突</h2><p>当master和dev同时修改文件, 在git merge时会出现冲突, 需要手动解决冲突, 重新提交.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看冲突信息</span></span><br><span class="line">git status</span><br><span class="line"><span class="comment"># 打开冲突文件</span></span><br><span class="line">&lt;&lt;&lt;&lt;&lt;&lt;&lt; <span class="string">HEAD</span></span><br><span class="line"><span class="string">5</span></span><br><span class="line"><span class="string">=======</span></span><br><span class="line"><span class="string">five</span></span><br><span class="line"><span class="string">&gt;&gt;&gt;&gt;&gt;&gt;&gt; dev</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># &lt;&lt;&lt;&lt;&lt;&lt;&lt;, =======, &gt;&gt;&gt;&gt;&gt;&gt;&gt;表示不同的分支, 手动修改之后重新提交</span></span><br><span class="line"><span class="string">git add &lt;file&gt;</span></span><br><span class="line"><span class="string">git commit -m &quot;conflict fixed&quot;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">#删除dev分支</span></span><br><span class="line"><span class="string">git　branch -d dev</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">#查看分支合并图</span></span><br><span class="line"><span class="string">git log --graph</span></span><br></pre></td></tr></table></figure><h2 id="分支管理"><a href="#分支管理" class="headerlink" title="分支管理"></a>分支管理</h2><figure class="highlight plaintext"><figcaption><span>merge```, 在处理合并时如果可以, ```git```会使用```Fast forward```模式, 删除分支后会丢掉分支信息</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">```no-ff```强制禁止```Fast forward```, 在合并的时候多出一个```commit```记录, 保存分支信息</span><br><span class="line"></span><br><span class="line">```bash</span><br><span class="line"># 不使用 Fast forward模式合并分支</span><br><span class="line">git merge --no-ff -m &quot;merge with no-ff&quot; dev</span><br><span class="line"># 查看分区合并</span><br><span class="line">git log --graph --pretty=oneline --abbrev-commit</span><br></pre></td></tr></table></figure><h2 id="Bug分支"><a href="#Bug分支" class="headerlink" title="Bug分支"></a>Bug分支</h2><p>当dev分支的工作未完成, 你需要紧急修复buf, 这时可以把当前分支暂时储存起来. 完成其他工作之后, 可以恢复现场继续工作.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 储存现场</span></span><br><span class="line">git stash</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在master下新建分支并切换</span></span><br><span class="line">git chekcout master</span><br><span class="line">git checkout -b &lt;branch&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 完成工作后提交</span></span><br><span class="line">git add &lt;file&gt;</span><br><span class="line">git commit -m <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 回到之前分支</span></span><br><span class="line">git checkout &lt;branch&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看保存的工作现场</span></span><br><span class="line">git stash list</span><br><span class="line"></span><br><span class="line"><span class="comment"># 恢复现场</span></span><br><span class="line"><span class="comment">## 1.恢复并删除 </span></span><br><span class="line">git stash pop</span><br><span class="line"></span><br><span class="line"><span class="comment">## 2.恢复, 删除</span></span><br><span class="line">git stash apply stash@&#123;0&#125;</span><br><span class="line">git stash drop stash@&#123;0&#125;</span><br></pre></td></tr></table></figure><p>在上面bug分支修复的错误, 在当前dev上同样也存在问题, 可以使用<code>cherry-pick</code>复制一个<code>commit</code>, 同事<code>git</code>会新创建一个<code>commit</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git cherry-pick commit_id</span><br></pre></td></tr></table></figure><p>更简单的, 可以先用<code>git stash</code>报工作现场储存起来, 然后在当前分支修复<code>bug</code> 之后恢复现场继续工作.</p><h2 id="Feature分支"><a href="#Feature分支" class="headerlink" title="Feature分支"></a>Feature分支</h2><p>当需要添加新功能时, 可以创建feature分支, 测试完成之后, 再合并到当前分支.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建feature分支</span></span><br><span class="line">git checkout -b feature</span><br><span class="line"></span><br><span class="line"><span class="comment">#删除没有合并的分支</span></span><br><span class="line">git branch -D feature</span><br></pre></td></tr></table></figure><h2 id="多人协作"><a href="#多人协作" class="headerlink" title="多人协作"></a>多人协作</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看远程仓库</span></span><br><span class="line">git remote</span><br><span class="line">git remote -v</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将本地master分支推送到远程库</span></span><br><span class="line">git push origin master</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将远程库的dev分支创建到本地</span></span><br><span class="line">git checkout -b dev origin/dev</span><br><span class="line"></span><br><span class="line"><span class="comment"># 多人向dev合并, 会出现冲突</span></span><br><span class="line"><span class="comment"># 将远程库dev分支, 同步到本地</span></span><br><span class="line">git pull</span><br><span class="line"><span class="comment"># git pull失败, 没有和远程库链接</span></span><br><span class="line">git branch --set-upstream-to =origin/dev dev</span><br><span class="line"><span class="comment"># git pull之后, 手动解决冲突, 然后上传</span></span><br></pre></td></tr></table></figure><h2 id="Rebase"><a href="#Rebase" class="headerlink" title="Rebase"></a>Rebase</h2><p>多次本地提交或从远端pull下来之后, 本地的版本库会同时有多个commit, 通过–graph查看会觉得混乱, 可以使用rebase, 将多个commit合并成一个, 使得分支变得顺滑~.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 合并commit</span></span><br><span class="line">git rebase</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果出现冲突, 需要解决冲突之后重新git rebase</span></span><br><span class="line">git add .</span><br><span class="line">git rebase --<span class="built_in">continue</span></span><br></pre></td></tr></table></figure><h2 id="gitignore"><a href="#gitignore" class="headerlink" title=".gitignore"></a>.gitignore</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 忽略特殊文件</span></span><br><span class="line">.gitignore</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看file文件是否被ignore</span></span><br><span class="line">git check-ignore -v &lt;file&gt;</span><br></pre></td></tr></table></figure><h2 id="git服务器"><a href="#git服务器" class="headerlink" title="git服务器"></a>git服务器</h2><blockquote><p>安装git</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt install git</span><br></pre></td></tr></table></figure><blockquote><p>新建git用户</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> adduser git</span><br></pre></td></tr></table></figure><blockquote><p>公钥登录</p></blockquote><p>将设备的<code>id_rsa.pub</code>文件导入到服务器的<code>home/git/.ssh/authorized_keys</code>中。</p><p>如果本地的用户名和服务器的用户名不一致，需要配置<code>/home/user/.ssh/config</code>文件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Host server <span class="comment"># 别名</span></span><br><span class="line">    HostName 192.168.1.101 <span class="comment"># 服务器ip</span></span><br><span class="line">    User git<span class="comment"># 用户名</span></span><br></pre></td></tr></table></figure><blockquote><p>初始化</p></blockquote><p>选定服务器的<code>/srv/git/</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 新建目录作为git的工作目录</span></span><br><span class="line"><span class="built_in">mkdir</span> /srv/git</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改目录分组(必须)</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chown</span> -R git:git /srv/git</span><br></pre></td></tr></table></figure><blockquote><p>禁用shell登录</p></blockquote><p>编辑<code>/etc/passwd</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git:x:1002:1002:,,,:/home/git:/bin/bash</span><br></pre></td></tr></table></figure><p>改为：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git:x:1002:1002:,,,:/home/git:/usr/bin/git-shell</span><br></pre></td></tr></table></figure><blockquote><p>新建仓库</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> git init --bare /srv/git/sample.git</span><br></pre></td></tr></table></figure><p>也可以将本地的git项目上传到服务器：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 首先将本地的项目导出为.git目录</span></span><br><span class="line">git <span class="built_in">clone</span> --bare project project.git</span><br><span class="line"><span class="comment"># 相当于直接复制.git目录</span></span><br><span class="line"><span class="built_in">cp</span> -Rf project/.git project.git</span><br><span class="line"></span><br><span class="line"><span class="comment"># 上传到服务器</span></span><br><span class="line">scp -r project.git git@server:/srv/git</span><br></pre></td></tr></table></figure><blockquote><p>克隆项目</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> git@server:/srv/git/sample.git</span><br><span class="line">git <span class="built_in">clone</span> git@server:/srv/git/project.git</span><br></pre></td></tr></table></figure><h2 id="空分支"><a href="#空分支" class="headerlink" title="空分支"></a>空分支</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建空分支 empty</span></span><br><span class="line">git checkout --orphan empty</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除当前目录文件</span></span><br><span class="line">git <span class="built_in">rm</span> -rf .</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提交分支</span></span><br><span class="line"><span class="built_in">touch</span> README.md</span><br><span class="line">git add README.md</span><br><span class="line">git commit -m <span class="string">&quot;new branch&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看所有分支</span></span><br><span class="line">git branch -a</span><br></pre></td></tr></table></figure><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;git迷路指南&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="git" scheme="https://sanzo.top/blog/tags/git/"/>
    
  </entry>
  
  <entry>
    <title>Jump the Wall</title>
    <link href="https://sanzo.top/blog/Blog/jump-the-wall/"/>
    <id>https://sanzo.top/blog/Blog/jump-the-wall/</id>
    <published>2022-05-19T03:13:08.000Z</published>
    <updated>2022-05-19T03:13:08.000Z</updated>
    
    <content type="html"><![CDATA[<p>科学上网</p><span id="more"></span><hr><h2 id="V2ray"><a href="#V2ray" class="headerlink" title="V2ray"></a>V2ray</h2><h3 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h3><p>测试ip：<a href="https://ping.chinaz.com/">ping.chinaz.com</a></p><p>证书申请：<a href="https://freessl.cn/">https://freessl.cn/</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#X-ui面板安装</span></span><br><span class="line">bash &lt;(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ufw开启端口</span></span><br><span class="line">ufw allow 40000:60000/tcp</span><br><span class="line">ufw allow 40000:60000/udp</span><br></pre></td></tr></table></figure><h3 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h3><p>Android，linux，macOS 安装包：<a href="https://github.com/v2fly/v2ray-core/releases">https://github.com/v2fly/v2ray-core/releases</a></p><p>v2ray客户端配置文件：<a href="https://github.com/Sanzo00/files/blob/master/other/v2ray.json">https://github.com/Sanzo00/files/blob/master/other/v2ray.json</a></p><p>linux端下载v2ray安装包之后，可以选择安装到本地或者直接运行可执行文件。</p><blockquote><p>安装到本地</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">wget https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh</span><br><span class="line"><span class="comment"># 自动选择安装包</span></span><br><span class="line"><span class="built_in">sudo</span> bash install-release.sh</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定安装包</span></span><br><span class="line"><span class="built_in">sudo</span> bash install-release.sh --<span class="built_in">local</span> ./v2ray-linux-64.zip</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将配置文件拷贝到 /usr/local/etc/v2ray/config.json</span></span><br></pre></td></tr></table></figure><blockquote><p>直接运行可执行文件</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">nohup</span> ./v2ray run config.json &gt; v2ray.log 2&gt;&amp;1 &amp;</span><br></pre></td></tr></table></figure><h2 id="Clash"><a href="#Clash" class="headerlink" title="Clash"></a>Clash</h2><blockquote><p>开源桌面应用</p></blockquote><p>Mac：<a href="https://github.com/yichengchen/clashX">ClashX</a></p><p>Windows：<a href="https://github.com/Fndroid/clash_for_windows_pkg/releases">ClashForWindows</a></p><p>Android：<a href="https://github.com/Kr328/ClashForAndroid">ClashForAndroid</a></p><blockquote><p>服务器配置</p></blockquote><p>下载对应系统的可执行文件：<a href="https://github.com/Dreamacro/clash/releases">Dreamacro&#x2F;clash  release</a></p><p>V2ray to Clash节点转换工具：<a href="https://v2rayse.com/node-convert">v2rayse.com&#x2F;node-convert</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ~/software</span><br><span class="line"><span class="built_in">mkdir</span> clash &amp;&amp; <span class="built_in">cd</span> clash</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载软件包</span></span><br><span class="line">wget https://github.com/Dreamacro/clash/releases/download/v1.13.0/clash-linux-amd64-v1.13.0.gz</span><br><span class="line"></span><br><span class="line"><span class="comment"># 解压并添加权限</span></span><br><span class="line">gunzip clash-linux-amd64-v1.13.0.gz</span><br><span class="line"><span class="built_in">mv</span> clash-linux-amd64-v1.13.0 clash</span><br><span class="line"><span class="built_in">chmod</span> +x clash</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载Country.mmdb</span></span><br><span class="line">wget https://github.com/Dreamacro/maxmind-geoip/releases/download/20230312/Country.mmdb</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置clash配置文件</span></span><br><span class="line">vim config.yaml</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>创建systemd配置文件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> vim /etc/systemd/system/clash.service</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=Clash daemon, A rule-based proxy <span class="keyword">in</span> Go.</span><br><span class="line">After=network.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=simple</span><br><span class="line">Restart=always</span><br><span class="line">ExecStart=/home/sanzo/software/clash/clash -d /home/sanzo/software/clash/</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br></pre></td></tr></table></figure><p><code>/home/sanzo/software/clash/clash</code> is you clash executable file</p><p><code>/home/sanzo/software/clash/</code> is your clash config directory</p><p>使用systemctl控制clash的运行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> clash</span><br><span class="line"><span class="built_in">sudo</span> systemctl status clash</span><br><span class="line"><span class="built_in">sudo</span> systemctl start clash</span><br><span class="line"><span class="built_in">sudo</span> systemctl restart clash</span><br><span class="line"><span class="built_in">sudo</span> systemctl stop clash</span><br></pre></td></tr></table></figure><p>网络测试</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget google.com</span><br></pre></td></tr></table></figure><h2 id="设置终端代理"><a href="#设置终端代理" class="headerlink" title="设置终端代理"></a>设置终端代理</h2><h3 id="终端代理"><a href="#终端代理" class="headerlink" title="终端代理"></a>终端代理</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">vim ~/.bashrc</span><br><span class="line"></span><br><span class="line"><span class="built_in">export</span> ALL_PROXY=<span class="string">&quot;socks5://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> all_proxy=<span class="string">&quot;socks5://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> http_proxy=<span class="string">&quot;http://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> https_proxy=<span class="string">&quot;http://127.0.0.1:7890&quot;</span></span><br></pre></td></tr></table></figure><h3 id="git代理"><a href="#git代理" class="headerlink" title="git代理"></a>git代理</h3><blockquote><p>对http和https代理</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># http and https</span></span><br><span class="line">git config --global http.proxy http://127.0.0.1:7890</span><br><span class="line">git config --global https.proxy https://127.0.0.1:7890</span><br><span class="line"></span><br><span class="line"><span class="comment"># socks5</span></span><br><span class="line">git config --global http.proxy socks5://127.0.0.1:7890</span><br><span class="line">git config --global https.proxy socks5://127.0.0.1:7890</span><br><span class="line"></span><br><span class="line"><span class="comment"># unset</span></span><br><span class="line">git config --global --<span class="built_in">unset</span> http.proxy</span><br><span class="line">git config --global --<span class="built_in">unset</span> https.proxy</span><br></pre></td></tr></table></figure><blockquote><p>对ssh代理：</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt install connect-proxy</span><br><span class="line"><span class="comment"># (or) https://github.com/larryhou/connect-proxy</span></span><br><span class="line">vim ~/.ssh/config</span><br><span class="line"></span><br><span class="line"><span class="comment"># socks5</span></span><br><span class="line">Host github.com</span><br><span class="line">User git</span><br><span class="line">ProxyCommand connect -S 127.0.0.1:7890 %h %p</span><br><span class="line"></span><br><span class="line"><span class="comment"># http || https</span></span><br><span class="line">Host github.com</span><br><span class="line">User git</span><br><span class="line">ProxyCommand connect -H 127.0.0.1:7890 %h %p</span><br></pre></td></tr></table></figure><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;科学上网&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="v2ray" scheme="https://sanzo.top/blog/tags/v2ray/"/>
    
  </entry>
  
  <entry>
    <title>Linux常用命令</title>
    <link href="https://sanzo.top/blog/Blog/linux-command/"/>
    <id>https://sanzo.top/blog/Blog/linux-command/</id>
    <published>2021-06-17T07:54:40.000Z</published>
    <updated>2021-06-17T07:54:40.000Z</updated>
    
    <content type="html"><![CDATA[<p>Linux common commands.</p><span id="more"></span><hr><h2 id="用户管理"><a href="#用户管理" class="headerlink" title="用户管理"></a>用户管理</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建用户sanzo，指定home目录和登陆的shell</span></span><br><span class="line">useradd -d /home/sanzo -s /bin/bash -m sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置登录密码</span></span><br><span class="line">passwd sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加sudo组</span></span><br><span class="line">usermod -a -G <span class="built_in">sudo</span> sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除用户</span></span><br><span class="line"><span class="built_in">sudo</span> userdel -r <span class="built_in">test</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># append ssh key to remote host</span></span><br><span class="line"><span class="built_in">cat</span> .ssh/id_ras.pub | ssh user@hostname <span class="string">&quot;cat &gt;&gt; ~/.ssh/authorized_keys&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># check group</span></span><br><span class="line">getent group groupname</span><br><span class="line"></span><br><span class="line"><span class="comment"># delete group of username</span></span><br><span class="line"><span class="built_in">sudo</span> deluser username groupname</span><br></pre></td></tr></table></figure><h2 id="进程管理"><a href="#进程管理" class="headerlink" title="进程管理"></a>进程管理</h2><h3 id="后台执行"><a href="#后台执行" class="headerlink" title="后台执行"></a>后台执行</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看后台任务</span></span><br><span class="line"><span class="built_in">jobs</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 前台执行任务</span></span><br><span class="line"><span class="built_in">fg</span> %np<span class="string">&#x27;s</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># 继续在后台执行挂起的任务</span></span><br><span class="line"><span class="string">bg %n</span></span><br><span class="line"><span class="string"> </span></span><br><span class="line"><span class="string"># 挂起任务</span></span><br><span class="line"><span class="string">ctrl+z</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># 杀掉后台任务</span></span><br><span class="line"><span class="string">kill %n</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># 从当前shell移除</span></span><br><span class="line"><span class="string">disown -h %1</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># 后台执行</span></span><br><span class="line"><span class="string">nohup ./xx.exe &gt; log 2&gt;&amp;1 &amp;</span></span><br></pre></td></tr></table></figure><h3 id="查找-终止进程"><a href="#查找-终止进程" class="headerlink" title="查找&#x2F;终止进程"></a>查找&#x2F;终止进程</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看占用端口的PID</span></span><br><span class="line">lsof -i:port</span><br><span class="line">netstat -tunpl | grep port</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查找指定名称的进程</span></span><br><span class="line">ps -ef | grep xxx</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取指定名称进程的pid</span></span><br><span class="line">ps -ef | grep free | grep -v grep | awk <span class="string">&#x27;&#123;print $2&#125;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看指定进程的开始和执行的时间</span></span><br><span class="line">ps -eo pid,lstart,etime | grep pid</span><br><span class="line"></span><br><span class="line"><span class="comment"># 终止进程</span></span><br><span class="line">ps -ef | grep free | grep -v grep | awk <span class="string">&#x27;&#123;print $2&#125;&#x27;</span> | xargs <span class="built_in">kill</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 终止所有指定名称的进程</span></span><br><span class="line">killall xxx</span><br></pre></td></tr></table></figure><p>终止指定名称的进程：<a href="https://github.com/Sanzo00/files/blob/master/shell/kill.sh">kill.sh</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># check input args</span></span><br><span class="line"><span class="keyword">if</span> [ <span class="variable">$#</span> -ne 1 ]; <span class="keyword">then</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;Usage: ./<span class="variable">$0</span> xxx&quot;</span></span><br><span class="line">  <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;kill all <span class="variable">$1</span>*&quot;</span></span><br><span class="line"></span><br><span class="line">ps -ef | grep <span class="variable">$1</span> | grep -v grep | grep -v kill.sh</span><br><span class="line"></span><br><span class="line">pids=$(ps -ef | grep <span class="variable">$1</span> | grep -v grep | grep -v kill.sh | awk <span class="string">&#x27;&#123;print $2&#125;&#x27;</span>)</span><br><span class="line"><span class="comment">#echo &quot;pids:&quot;</span></span><br><span class="line"><span class="comment">#echo $pids</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">test</span> -z <span class="variable">$pids</span>; <span class="keyword">then</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$1</span> is alread killed!&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">  <span class="keyword">for</span> pid <span class="keyword">in</span> <span class="variable">$pids</span></span><br><span class="line">  <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;kill <span class="variable">$pid</span>&quot;</span></span><br><span class="line">    <span class="built_in">kill</span> -9 <span class="variable">$pid</span></span><br><span class="line">  <span class="keyword">done</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><h3 id="wc"><a href="#wc" class="headerlink" title="wc"></a>wc</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看文件的行数</span></span><br><span class="line"><span class="built_in">wc</span> -l data.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看./xx目录下.h文件的行数</span></span><br><span class="line">find ./xx -name <span class="string">&quot;*.h&quot;</span> | xargs <span class="built_in">wc</span> -l</span><br></pre></td></tr></table></figure><h3 id="date"><a href="#date" class="headerlink" title="date"></a>date</h3>  <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 日期</span></span><br><span class="line"><span class="built_in">date</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 格式化显示</span></span><br><span class="line"><span class="built_in">date</span> +%Y-%m-%d</span><br><span class="line"><span class="built_in">date</span> +%H:%m</span><br></pre></td></tr></table></figure><h3 id="cal"><a href="#cal" class="headerlink" title="cal"></a>cal</h3>  <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 显示本月的日历</span></span><br><span class="line">$ cal</span><br><span class="line"></span><br><span class="line"><span class="comment"># 显示2020年的日历</span></span><br><span class="line">$ cal 2020</span><br><span class="line"></span><br><span class="line"><span class="comment"># 显示2020年5月的日历</span></span><br><span class="line">$ cal 5 2020</span><br></pre></td></tr></table></figure><h3 id="ssh"><a href="#ssh" class="headerlink" title="ssh"></a>ssh</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 将远端服务器10.1.1.1的8888端口映射到本地的8888端口</span></span><br><span class="line">ssh -L8888:localhost:8888 root@10.1.1.1</span><br></pre></td></tr></table></figure><h3 id="head-tail"><a href="#head-tail" class="headerlink" title="head&#x2F;tail"></a>head&#x2F;tail</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 前1000行</span></span><br><span class="line"><span class="built_in">head</span> -n 1000 input.txt &gt; output.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 后1000行</span></span><br><span class="line"><span class="built_in">tail</span> -n 1000 input.txt &gt; output.txt</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第6-10行</span></span><br><span class="line"> <span class="built_in">head</span> -n 10 input.txt | <span class="built_in">tail</span> -n 5</span><br></pre></td></tr></table></figure><h3 id="grep"><a href="#grep" class="headerlink" title="grep"></a>grep</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查找当前目录下所有包含&#x27;void main()&#x27;的文件</span></span><br><span class="line">grep -rn <span class="string">&quot;void main()&quot;</span>  ./</span><br></pre></td></tr></table></figure><h3 id="gzip"><a href="#gzip" class="headerlink" title="gzip"></a>gzip</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 解压到DIR目录</span></span><br><span class="line">gzip xxx.gz -d DIR</span><br></pre></td></tr></table></figure><h3 id="tar"><a href="#tar" class="headerlink" title="tar"></a>tar</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 解压到DIR目录</span></span><br><span class="line">tar -xzvf xx.tar.gz -C DIR</span><br></pre></td></tr></table></figure><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;Linux common commands.&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="command" scheme="https://sanzo.top/blog/tags/command/"/>
    
    <category term="linux" scheme="https://sanzo.top/blog/tags/linux/"/>
    
  </entry>
  
  <entry>
    <title>LLM推理服务论文</title>
    <link href="https://sanzo.top/blog/Blog/llm_inference/"/>
    <id>https://sanzo.top/blog/Blog/llm_inference/</id>
    <published>2024-09-19T08:38:06.000Z</published>
    <updated>2025-09-03T08:38:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>记录一些LLM推理优化相关的论文</p><span id="more"></span><h2 id="FlashAttention"><a href="#FlashAttention" class="headerlink" title="FlashAttention"></a>FlashAttention</h2><h2 id="PageAttention"><a href="#PageAttention" class="headerlink" title="PageAttention"></a>PageAttention</h2><h2 id="RadixAttention"><a href="#RadixAttention" class="headerlink" title="RadixAttention"></a>RadixAttention</h2><h2 id="RingAttention"><a href="#RingAttention" class="headerlink" title="RingAttention"></a>RingAttention</h2><h2 id="RAGCache-Arxiv24"><a href="#RAGCache-Arxiv24" class="headerlink" title="RAGCache [Arxiv24]"></a>RAGCache [Arxiv24]</h2><h2 id="Cache-Craft-SIGMOD25"><a href="#Cache-Craft-SIGMOD25" class="headerlink" title="Cache-Craft [SIGMOD25]"></a>Cache-Craft [SIGMOD25]</h2><h2 id="CacheBlend-EuroSys25"><a href="#CacheBlend-EuroSys25" class="headerlink" title="CacheBlend [EuroSys25]"></a>CacheBlend [EuroSys25]</h2><h2 id="Superposition-ICLR24"><a href="#Superposition-ICLR24" class="headerlink" title="Superposition [ICLR24]"></a>Superposition [ICLR24]</h2><h2 id="AquaPipe-SIGMOD25"><a href="#AquaPipe-SIGMOD25" class="headerlink" title="AquaPipe [SIGMOD25]"></a>AquaPipe [SIGMOD25]</h2><p>AquaPipe: A Quality-Aware Pipeline for Knowledge Retrieval and Large Language Models <a href="https://dl.acm.org/doi/10.1145/3709661">[paper]</a> </p><h2 id="Similarity-based-Retrieval"><a href="#Similarity-based-Retrieval" class="headerlink" title="Similarity-based Retrieval"></a>Similarity-based Retrieval</h2><h3 id="RetrievalAttention-Arxiv24"><a href="#RetrievalAttention-Arxiv24" class="headerlink" title="RetrievalAttention [Arxiv24]"></a>RetrievalAttention [Arxiv24]</h3><p>RetrievalAttention: Accelerating Long-Context LLM Inference via Vector Retrieval <a href="https://arxiv.org/abs/2409.10516">[paper]</a> <a href="https://github.com/microsoft/RetrievalAttention">[code]</a> </p><h3 id="RetroInfer-Arxiv25"><a href="#RetroInfer-Arxiv25" class="headerlink" title="RetroInfer [Arxiv25]"></a>RetroInfer [Arxiv25]</h3><p>RetroInfer: A Vector-Storage Approach for Scalable Long-Context LLM Inference <a href="https://arxiv.org/abs/2505.02922">[paper]</a> [[code] <a href="https://komorebi660.github.io/">[author]</a></p><h3 id="PQCache-SIGMOD25"><a href="#PQCache-SIGMOD25" class="headerlink" title="PQCache [SIGMOD25]"></a>PQCache [SIGMOD25]</h3><p>PQCache: Product Quantization-based KVCache for Long Context LLM Inference <a href="https://arxiv.org/abs/2407.12820">[paper]</a> <a href="https://github.com/HugoZHL/PQCache">[code]</a></p><p>PQCache解决的LLM在long context下的推理效率问题。</p><p>长上下文推理对显存需求带来了挑战，如何在有限的显存空间实现高效的推理，同时保存高的输出质量，是一个被广泛关注的问题。</p><p>一个符合直觉的方法：selective attention，通过选择部分token进行注意力计算，显著降低了对内存和计算的需求。</p><p>现有selective attention方法可以分为：KV Cache dropping (Scissorhands, StreamingLLM [ICLR24], H2O [NIPS23])，KV Cache offloading (InfLLM [arxiv24] SparQAttention) 两类。</p><p>如下图所示，PQCache发现selective attention的执行和传统信息检索的Product Quantization的过程很像。</p><p>在LLM的注意力计算过程中，向量Q和所有的K进行相似度计算，然后经过softmax并与V加权求和得到输出X。</p><p>Q和K的相似度计算和信息检索中根据用户问题检索相似的top-k个向量的过程基本一致。</p><p><img src="/blog/img/Blog/llm-inference/image-20250628201826548.png" alt="Information retrieval vs. LLM inference with seletive attention"></p><p>本文选择了开销比较低的Product Quantization来管理KV Cache。</p><p>PQ的索引构建和搜索过程如下图所示。</p><blockquote><p>PQ Construction：</p></blockquote><ol><li>将每个KV Cache向量划分为m个子向量。</li><li>对所有KV Cache的每个子向量进行聚类，生成$2^b$个质心。</li><li>原来KV Cache向量对应的m个子向量编码为距离最近的质心id。</li></ol><blockquote><p>PQ Searching:</p></blockquote><ol><li>查询Q向量同样被划分为M个子向量。</li><li>每个子向量和对应的空间中$2^b$个向量计算相似度。</li><li>根据相似度计算原始向量与Q的相似性得分，选取TopK得分的向量。</li></ol><p><img src="/blog/img/Blog/llm-inference/image-20250628202224666.png" alt="PQ construction and serarching"></p><p>PQCache的整体执行流程如下图所示：</p><ol><li>在Prefilling阶段，正常计算得到每个输入token的KV Cache，并异步的卸载到CPU。</li><li>CPU收到KV Cache之后，构建PQ用于后续检索。</li><li>在Decoding阶段，加载Centroids和PQ Codes，并计算TopK K向量。</li><li>根据计算的TopK向量，加载对应KV向量，并在GPU执行注意力计算。</li></ol><p>在实现中，PQCache的KV Cache包含三种：initial tokens，middle tokens，and local tokens.</p><p>StreamingLLM中发现attention sink的现象，即initial tokens受到更多的注意力关注，对模型的回答质量有很大的影响。</p><p>local tokens表示最近计算的token。middle tokens表示历史KV Cache保存在CPU中。</p><p>PQCache将initial和local tokens保存在GPU，并维护一个窗口，超过窗口的local token被卸载到CPU。</p><p><img src="/blog/img/Blog/llm-inference/image-20250628202419202.png" alt="Overview of PQCache"></p><p><img src="/blog/img/Blog/llm-inference/image-20250628212757321.png" alt="PQCache v.s. sequential scheduling."></p><h2 id="Apt-Serve-SIGMOD25"><a href="#Apt-Serve-SIGMOD25" class="headerlink" title="Apt-Serve [SIGMOD25]"></a>Apt-Serve [SIGMOD25]</h2><p>Apt-Serve: Adaptive Request Scheduling on Hybrid Cache for Scalable LLM Inference Serving <a href="https://github.com/eddiegaoo/Apt-Serve">[code]</a> <a href="https://arxiv.org/pdf/2504.07494">[paper]</a></p><h2 id="Scheduling"><a href="#Scheduling" class="headerlink" title="Scheduling"></a>Scheduling</h2><h3 id="Parrot-OSDI24"><a href="#Parrot-OSDI24" class="headerlink" title="Parrot [OSDI24]"></a>Parrot [OSDI24]</h3><p>Parrot: Efficient Serving of LLM-based Applications with Semantic Variable. <a href="https://www.usenix.org/system/files/osdi24-lin-chaofan.pdf">[pdf]</a> <a href="https://github.com/microsoft/ParrotServe">[code]</a> <a href="https://chaofanlin.com/">[author]</a></p><p>Parrot这篇论文的主要贡献是提出了<strong>一个全新的推理workload：LLM Applications</strong>。</p><p>LLM Application是使用LLM来完成特定的任务（摘要，搜索，代码助手等），在一个应用中通常包含多个LLM请求。</p><img src="../../img/Blog/llm-inference/image-20240919165055080.png" alt="LLM Application的工作流程" style="zoom:50%;" /><p>以往推理优化系统是<strong>request-centric</strong>，即对用户的应用是透明的，“一视同仁”的处理用户的请求，缺少<strong>application-level</strong>的信息。</p><p>在LLM Application中，请求具有以下特点：</p><ol><li>多个连续的LLM请求可能存在<strong>依赖关系</strong>。</li><li>即使在单个应用中，LLM请求可能具有不同的<strong>调度偏好</strong>。</li><li>LLM的请求之前存在大量的<strong>相似性</strong>。</li></ol><img src="../../img/Blog/llm-inference/image-20240919170523984.png" alt="多智能体应用中LLM请求的通信流程" style="zoom:50%;" /><p>由于缺少application-level的信息，现有的推理优化主要有两个问题：</p><ol><li>网络通信开销。</li><li>任务调度等待开销。</li></ol><p><img src="/blog/img/Blog/llm-inference/image-20240919165122842.png" alt="现有推理服务 vs. Parrot推理服务"></p><img src="../../img/Blog/llm-inference/image-20240919165139641.png" alt="Parrot的系统架构图" style="zoom:50%;" /><p>Parrot设计了一个Semantic Variables的编程抽象，用来将用户的执行逻辑暴露给推理服务端。</p><p>基于这个Semantic Variables可以获取到应用内的LLM请求的调用依赖关系，进而做一些系统上的优化，包括DAG-based analysis，Performance Objective Deduction，Application-Centric Scheduling等。</p><img src="../../img/Blog/llm-inference/image-20240919171157542.png" alt="使用Parrot写的代码例子" style="zoom:50%;" /><h3 id="Preble-ICLR25"><a href="#Preble-ICLR25" class="headerlink" title="Preble [ICLR25]"></a>Preble [ICLR25]</h3><p>Preble: Efficient Distributed Prompt Scheduling for LLM Serving <a href="https://arxiv.org/pdf/2407.00023">[paper]</a>  <a href="https://github.com/WukLab/preble">[code]</a></p><p>现有推理系统的目标是充分利用GPU的计算资源，在调度请求时忽略了promt的共享前缀，因此存在冗余的计算开销。此外，简单的将共享前缀请求分配到同一个实例，会造成负载的不均衡。</p><p>Preble针对分布式推理场景，提出了一个prompt-aware的请求调度方法。</p><p>Preble首先对LLM workload进行分析，有以下4个观察：</p><ul><li><strong>Prompt 的长度远大于 Output</strong>：在真实 workload 中，Prompt 比 Output 长 4–2494 倍。</li><li><strong>Prompt 高度共享</strong>：85%–97% 的前缀可被复用。</li><li><strong>共享序列频繁复用</strong>：常见前缀平均被 8.6–126 个请求使用，但不同 workload 差异明显。</li><li><strong>请求模式极端不均</strong>：请求到达间隔从微秒到数百秒不等，系统需同时处理高并发和稀疏请求。</li></ul><p>Preble包含以下设计：</p><ul><li>globa-local两层的调度机制，global调度将请求分配到对应的实例，local调度负责在实例内部迭代的调度请求。</li><li>global调度策略如下：<ul><li>如果缓存命中的token数量大于未命中，将请求分配到具有最长共享前缀的实例。如果有多个实例满足，则优先分配到负载最少的实例。</li><li>如果缓存命中token数量小于未命中，将请求分配到最小cost的实例，cost计算逻辑如下：<ul><li>实例的负载，计算一定时间窗口内，所有请求的计算负载，包括prefill和decode，根据长度计算。</li><li>驱逐开销，插入新请求可能要驱逐一些节点，计算被驱逐节点的开销。</li><li>请求的prefill开销，prefill未命中token的计算开销。</li></ul></li></ul></li><li>为了缓解实例之间的负载不均衡问题，preble采用了负载调整方法：<ul><li>如果实例之间的负载超过一定阈值，负载大的请求调度到负载小的实例上。</li><li>将频繁复用的前缀复制到多个机器，减轻单个实例的过载问题。</li></ul></li><li>global根据prefill和decode的负载，优先将请求分配到decode重的实例。</li><li>为了保证调度的公平，local调度根据cache token的数量对请求划分多个组，每次按比例的从每个组选择请求，cache命中多的组多选。</li></ul><p><img src="/blog/img/Blog/llm-inference/image-20250903100918962.png" alt="preble architecture."></p><h3 id="TaiChi-Arxiv25"><a href="#TaiChi-Arxiv25" class="headerlink" title="TaiChi [Arxiv25]"></a>TaiChi [Arxiv25]</h3><p>Prefill-Decode Aggregation or Disaggregation? Unifying Both for Goodput-Optimized LLM Serving <a href="https://www.arxiv.org/abs/2508.01989">[paper]</a></p><p>本文对PD-aggregation和PD-disaggregation进行了详细的总结对比，并提出了一个PD-aggregation和PD-disaggregationd的混合推理方法，以实现LLM推理 Goodput的最大化。</p><blockquote><p>Motivation</p></blockquote><p>PD-aggregation和PD-disaggregation适应不同的SLO，无法适用于TTFT和TPOT均衡的SLO。</p><ul><li>PD-aggregation适合“TTFT严格，TPOT宽松”的SLO。在PD-aggregation中，所有实例参与prefill，因此可以实现较低的TTFT表现；但是由于prefill和decode相互干扰导致TPOT较高。</li><li>PD-disaggregation适合“TPOP严格，TTFT宽松”的SLO。在PD-disaggregation中，prefill和decode有不同的实例单独服务，decode不再受prefill的影响，因此TPOT较低；但是由于只有部分实例参与prefill，因此TTFT较高；</li></ul><blockquote><p>Observation</p></blockquote><ul><li>PD-aggregation的高TPOT来自prefill的干扰：compute-bound linear operations（矩阵乘），其中TPOT与干扰的密度呈线性关系。（干扰密度&#x3D;prefill tokens &#x2F; output tokens）。在PD-aggregation中，chunk size是个关键参数，减少chunk size可以减轻prefill和decode的干扰，从而降低TPOT；但同时增加了prefill迭代的次数从而增加了TTFT。（section 2.3）</li><li>PD-disaggregation的高TTFT来自于请求的等待开销（同时包括prefill和decode的等待开销）。当调整PD的实例比例，TTFT随着P的下降后上升。这是因为增加P实例可以同时处理更多的prefiil任务，但随着D数量的减少，使得decode任务的排队时间大大上升，进而导致整体的TTFT延迟升高。（section 2.3.2）</li><li>通过调度资源可以实现TTFT和TPOT延迟的转移，例如，在PD-aggregation中，增加chunk size可以将TTFT的延迟转移到TPOT上，因为增加chunk size可以为prefill提供更多的空间，代价是增加了TPOT的延迟。同样，在PD-disaggregation中，增加更多的decode实例，可以将TPOT的延迟转移到TTFT上。(section 2.4)</li></ul><blockquote><p>Challenge</p></blockquote><ul><li><p>现有LLM推理服务在PD-aggregation和PD-disagregation中二选一，虽然可以通过增加chunk size和调整PD实例数量来实现延迟转移，但是不够灵活，不支持request-level 延迟转移。（2.5 Challenge 1）</p></li><li><p>request-level的TPOT降级同时受到批处理和输出token长度不确定的影响。增加chunk size虽然可以将TTFT延迟转移到TPOT，但是可能导致同一批次一些decode请求的TPOT超过SLO；短输出长度的请求更容易受到PD干扰（output tokens是干扰密度的分母，对干扰更加敏感）。（2.5 Challenge 2）</p></li><li><p>request-level的TTFT的降级需求不直接，需要同时考虑执行时间和排队时间。prefill的长度比较分散（2k-16k不等），对于短请求的TTFT容忍度更高可以被优先降级。然而如果请求排队时间过长，那么他降级的空间就会大幅减少。（2.5 Challenge 3）</p></li></ul><blockquote><p>Design</p></blockquote><ul><li>TaiChi将实例划分为两部分：P-heavy（大chunk size）和D-heavy（小chunk size），每个实例都有一个控制chunk size的slider（$S_P$, $S_D$），通过调节slider可以动态的切换到PD-aggregation（$S_P$&#x3D;$S_D$&#x3D;chunk size）和PD-disaggregation（$S_D$排除prefill，$S_P$&#x3D;maxinum）。其外，TaiChi通过来调节P-heavy和D-heavy的比例（$R_{PD}$）以适应不同的SLO。</li><li>提出Flowing Decode Scheduling来实现request-level TPOT降级（Challenge 2），核心思想是在P-heavy和D-heavy之间动态的迁移需要降级的请求。首先，Decode任务优先分配到D-heavy实例，这样可以防止短输出的请求放到P-heavy超过SLO。当内存占用超过一定阈值，选择当前输出长度最长的请求进行降级（长度越长对TPOT相对更加不敏感）。</li><li>TPOT-aware Decode Backflow，TaiChi会监控从D-heavy迁移到P-heavy的请求，如果他们的TPOT超过一定的阈值（$\alpha \times$ SLO），则将这些请求重新迁移到D-heavy。Backflow这个方法是一个保障策略，如果backflow发生的比较频繁，说明当前的D-heavy过载，最好的方法通过调整$R_{PD}$来增加D-heavy的实例。</li><li>Length-aware Prefill Scheduling，核心思想是优先将短提示词调度到D-heavy，使得P-heavy具有更多的资源处理SLO更加严格的长提示词。</li></ul><p><img src="/blog/img/Blog/llm-inference/image-20250904175536385.png" alt="The system overview of TaiChi."></p><h2 id="Agent"><a href="#Agent" class="headerlink" title="Agent"></a>Agent</h2><h3 id="Ayo-ASPLOS25"><a href="#Ayo-ASPLOS25" class="headerlink" title="Ayo [ASPLOS25]"></a>Ayo [ASPLOS25]</h3><p>Towards End-to-End Optimization of LLM-based  Applications with Ayo <a href="https://arxiv.org/pdf/2407.00326">[paper]</a> <a href="https://github.com/NetX-lab/Ayo">[code]</a> <a href="https://txxx926.github.io/">[author]</a></p><p>这篇工作关注LLM应用的端到端性能优化。首先提出了primitive-level dataflow graph对请求的工作流进行抽象。然后基于这个dataflow graph进行细粒度的调度和优化，例如并行化和流水线。与现有系统相比实现2.09X的加速。</p><blockquote><p>背景和动机</p></blockquote><p>我们与LLM交互发生了变化，从最初的chatbot到现在利用LLM完成复杂任务（例如：RAG，Agent等）。</p><p><img src="/blog/img/Blog/llm-inference/image-20251009165020869.png" alt="常见的LLM应用执行流程。"></p><p>在LLM应用中，非LLM操作（例如：数据检索，网络搜索，调用API，索引构建等）占据了大部分执行时间。这对LLM的推理加速提出了新的需求。</p><p><img src="/blog/img/Blog/llm-inference/image-20251009164727239.png" alt="LLM应用每个模块的执行时间。"></p><p>首先，现有LLM应用开发框架（Langchain，LLamaindex）以模块为粒度顺序调度，忽略了模块之间的依赖和计算特点，从而限制了对复杂工作流的优化。</p><p><img src="/blog/img/Blog/llm-inference/image-20251009165335996.png" alt="Workflow expression and execution comparison of existing schemes and Ayo. a) module-level workflow b) primitive-based dataflow graph in Ayo. c) Execution graph after optimization in Ayo."></p><p>其次，面向request-level优化的推理后端与用户感知的application-leve的性能之间的不匹配。</p><p>例如，在对文档进行embedding，当bs&#x3D;4时每个embedding latency最低，但是bs&#x3D;16整体embedding module的latency最低；在对tree-based的文档进行总结时，由于后端不感知前端执行的依赖，固定bs和顺序调度是次优的。</p><p><img src="/blog/img/Blog/llm-inference/image-20251009165347980.png" alt="Comparison between request-level and application-level scheduling and execution."></p><p><img src="/blog/img/Blog/llm-inference/image-20251009170908821.png" alt="System Overview of Ayo."></p><p><img src="/blog/img/Blog/llm-inference/image-20251009170809916.png" alt="Illustrative optimized e-graph of a query for advanced RAG-based document QA with a refine synthesis mode."></p><h2 id="KV-Cache-Offloading"><a href="#KV-Cache-Offloading" class="headerlink" title="KV Cache Offloading"></a>KV Cache Offloading</h2><h3 id="CacheAttention-ATC24"><a href="#CacheAttention-ATC24" class="headerlink" title="CacheAttention [ATC24]"></a>CacheAttention [ATC24]</h3><p>Cost-efficient large language model serving for multi-turn conversations with CachedAttention <a href="https://arxiv.org/pdf/2403.19708">[paper]</a> <a href="https://csbingao.github.io/">[author]</a></p><h3 id="FlashGen-ASPLOS25"><a href="#FlashGen-ASPLOS25" class="headerlink" title="FlashGen [ASPLOS25]"></a>FlashGen [ASPLOS25]</h3><p>Accelerating LLM Serving for Multi-turn Dialogues  with Efficient Resource Management <a href="https://dl.acm.org/doi/pdf/10.1145/3676641.3716245">[paper]</a> </p><p>这片论文探讨了LLM推理服务在多轮对话场景下对计算和存储资源管理。</p><p>看完最大的收获是：本文讨论了队头阻塞导致的GPU内存资源利用率低的问题，虽然解决方法比较简单，但是确实没有在其他论文看到过；</p><p>本文的写作也值得学习，问题motivate的很清晰（分层缓存和请求调度问题），技术（Flash-Cache，Flash-Sched）也和两个问题一一对应。</p><blockquote><p>动机</p></blockquote><p>多轮对话也属于long-context 问题， 随着对话轮数的增加，prompt的长度显著上升，即prompt amplification problem。有限的GPU内存无法缓存所有对话的KV Cache，因此需要利用host memory，Disk来缓解KV Cache的存储压力。</p><p>此外，现有LLM推理服务采用FCFS来调度请求，当GPU剩余显存无法满足队首请求的需求，所有请求将被搁置，即使队列中有其他短请求可以执行。这就是队头阻塞导致的GPU资源利用低的问题。</p><blockquote><p>解决方案</p></blockquote><ol><li><p>FlashGen-Cache：多层存储kv cache。</p><p>这里主要讨论了GPU和host memory，GPU和Disk之间的KV Cache保存和加载的问题。</p><p>核心的思路就是尽可能overlap计算和传输（overlap不了的话，就构造一些计算任务来overlap），以及采用proactive（inclusive）来主动备份KV Cache（GPU&#x3D;&gt;CPU, CPU&#x3D;&gt;Disk），利用host momory作为GPU和Disk的中转站（请求到达的时候，就主动的从Disk加载KV Cache到中转站）减少Disk数据加载延迟。</p><p>这些也是比较常用的方法，例如在RAGCache，CacheAttention也有类似的讨论。</p></li><li><p>FlashGen-Sched：通过请求重排序来高效利用GPU资源。</p><p>如下图所示，由于队头阻塞导致资源利用率低的问题，其中GPU的内存利用率平均为88%。</p><p><img src="/blog/img/Blog/llm-inference/image-20251015083922269.png" alt="Figure 7. GPU (2 x A100-80GB) memory utilization while serving an OPT 30B model with the ShareGPT dataset"></p><p>解决队头阻塞问题的方法比较直观：当发生队头阻塞的时候，贪心的执行下一个显存需求足够的请求。，当显存空间足够执行队头长请求（有其他请求完成），被提前调度的请求所占用的显存空间会被立即回收，用来执行队头长请求，防止Starvation问题。</p></li></ol><blockquote><p>经验</p></blockquote><ol><li><p>为什么在缓存历史KV Cache不能高效利用GPU内存？</p><ul><li><p>高请求负载下意味着更高的内存争用。</p></li><li><p>在多轮对话场景下（或者用户和agent交互下），用户会花一些时间用来理解输出和输入下一个问题。这对利用GPU缓存的时间局部性带来了挑战。</p></li></ul></li><li><p>在实验中作者模拟了用户交互的时间，即在两个对话中间插入间隔时间。根据[1]，人类一分钟可以阅读300个单词，来估算每个token的时间 $1minute&#x2F;300words&#x3D;200ms$，间隔时间当前prompt长度+上一个输出token数量之和，然后乘以200ms。</p></li></ol><p>[1] Keith Rayner. 1978. Eye Movements in Reading and Information Processing.</p><h3 id="Strata-Arxiv25"><a href="#Strata-Arxiv25" class="headerlink" title="Strata [Arxiv25]"></a>Strata [Arxiv25]</h3><p>Strata: Hierarchical Context Caching for Long Context Language Model Serving <a href="https://arxiv.org/pdf/2508.18572">[paper]</a> <a href="https://github.com/xiezhq-hermann">[author]</a></p><p>这篇工作应该是作者在SGLang中实现分层KV Cache形成的一篇工作，<a href="https://github.com/sgl-project/sglang/pull/2693">[sglang issue #2693]</a>。</p><p>本文讨论了一个比较有意思的问题：LLM推理服务的“Delay Hit”问题，即多个请求具有相同的前缀，如果把这些请求打包在一起调度，会导致冗余计算。这个点在我之前的代码中也遇到过，和作者解决思路差不多，就是优先处理其中一个请求，推迟后续请求的调度。</p><blockquote><p>背景</p></blockquote><p>用户的请求通常具有相同的前缀（例如system promt，hot retrieve in RAG等）。利用这一特点，通过缓存请求的KV Cache我们可以有效减少冗余KV Cache计算。一方面随着模型上下文窗口的增加，每个请求的KV Cache越来越大，另一方面GPU有限的内存无法存储所有用户的请求。因此将KV Cache从GPU offload 到host momory和Disk是long-context LLM推理的普遍的做法。</p><blockquote><p>动机</p></blockquote><p>本文探讨了在offloading KV Cahce场景下的两个问题：</p><ol><li><p>KV Cache传输的带宽利用低。</p><p>为了解决LLM推理过程中内存碎片的问题， vLLM提出了分页管理KV Cache的技术，这也成了现有LLM推理框架的默认设置。为了保证内存的利用率和缓存命中率，页面大小通常比较小，例如TensorRT-LLM的 <code>page size =32</code>， vllm的 <code>page size = 16</code> ，SGLang的 <code>page size = 1</code>。然而这种小的page size对传输并不友好。</p><p>作者测试了不同通信带宽下，从CPU到GPU加载KV Cache的延迟和带宽利用率。可以看到，在PCIe 5.0上带宽利用率仅为22%。在更高的互连带宽下，例如Grace-Hopper下，带宽利用率低于5%。</p><p><img src="/blog/img/Blog/llm-inference/image-20251014104905600.png" alt="Latency and bandwidth utilization of loading KV caches of 8192 tokens (using page size 32) of Llama-3.1-8B from CPU to GPU on different platforms."></p><p>作者在分析传输带宽问题的思路可以借鉴下：首先根据李特尔法则（Little‘s Law），系统在稳定状态下的平均并发数量为 $C&#x3D;\lambda \cdot L$，其中$\lambda$表示请求到达速率，$L$表示每个请求的平均延迟。此时吞吐量$X&#x3D;\lambda \cdot S$，其中$S$表示每个请求的平均数据大小。合并上面两个公式， $X&#x3D;C\cdot S&#x2F;L$，因此增大并行I&#x2F;O请求数量，使用更大的块大小和降低每次操作的延迟（使用更快的存储介质）可以提高系统的吞吐量。</p></li><li><p>KV Cache延迟命中问题</p><p>在计算机网络缓存中，延迟命中（delay hit phenomenon）是指：当一个请求发生cache miss时，请求从后端服务加载对象。如果在这个缓存miss还没完成时，又有多个请求访问同一个对象，这些请求不能立即命中，只能排队等待第一个miss被填充。</p><p>在LLM推理中也存在相同的问题，例如，在高并发的请求中，多个请求具有相同的前缀，当这些请求被打包为一个batch时，就会存在冗余计算。一些推理框架（SGLang，NanoFlow）采用异步调度batch的方法，即推对一个batch请求计算的同时，异步的构建下一个batch，来减少调度对推理性能的影响。在这种情况下， 如果下个batch和上个batch存在前缀共享，那么延迟命中的问题就会被进一步放大。</p></li></ol><blockquote><p>解决方案</p></blockquote><ol><li><p>GPU-assisted I&#x2F;O实现高效的读写</p><p>GPU辅助I&#x2F;O具有以下好处：1）GPU具有大量线程，可以同时发出大量读写操作来打满带宽；2）GPU-assisted I&#x2F;O的读写粒度通常为128字节，比较适合单个page（千字节）的传输。3）利用轻量级I&#x2F;O内核来实现灵活的内存layout转换。</p><p>然而，使用GPU-assisted I&#x2F;O会和计算任务（prefill，decode）抢计算资源。作者对比了使用不同数量的block来做I&#x2F;O kernel下系统的吞吐变化。发现当block &#x3D; 1或2时，对计算的影响是可以接受的（5%）。因此对于从CPU加载KV Cache使用block &#x3D; 2（critical path），GPU写CPU使用block &#x3D; 1（non-critical path）。</p><p><img src="/blog/img/Blog/llm-inference/image-20251014104836885.png" alt="Performance interference vs. resources allocated to the KV-cache I/O kernel. Measurement on concurrently running Strata ’s I/O kernel with a prefill pass (batch of two requests with 4k input each) and a decode pass (batch of 16 requests with 4k input each), respectively."></p></li><li><p>Cache Aware Scheduling</p><ul><li><p>Deferral on Delay Hit：通过为请求进行标记来缓解“延迟命中”的问题。节点状态分为<code>in-queue</code>和<code>in-flight</code>。被调度的请求涉及的token首先被标记为<code>in-queue</code>，后续命中<code>in-queue</code>的请求将被推迟。当请求执行的时候，节点状态从<code>in-queue</code>切换到<code>in-flight</code>。作者设置阈值，只有超过一定数量的节点被命中（100个），才会被推迟调度。</p><p>如图所示，A1和A0具有相同的前缀，A0被调度的时候，前缀节点被标记为 <code>in-queue</code>，因此A1会被延迟调度。</p></li><li><p>Balance Batch Formation：当调度的请求都需要从CPU加载KV Cache会引发loading stall（例如，同时调度C和D0）。此外将具有相同前缀的请求打包在一个batch中可以减少内存占用和冗余计算，本文将这种请求称为”bundle hit”。</p><p>balance batch通过设置阈值（load&#x2F;compute &#x3D; 100）来对请求进行调度，当加入请求满足loading bound限制，将被添加到batch中，随后对所有候选请求执行bundle hit检测，将具有相同前缀的请求加入到batch中。如果请求超过loading bound将被放到一个低优先级的队列，当调度完成之后，batch没有被填满再将这些loading比较重的请求放入队列中。</p></li><li><p>Hide Loading Stall with Bubble Filing：但不可避免发生loading stall时，本文通过将loading和decoding overlap来尽可能隐藏loading的开销。</p></li></ul><p><img src="/blog/img/Blog/llm-inference/image-20251014105731387.png" alt="Figure 7. Scheduling Policies of Strata, where orange blocks indicate prefill batches experiencing cache miss, green indicates cache hit on device, purple indicates cache hit on host memory, blue indicates data transfer, and the one decoding batch is colored in gray."></p></li></ol><p>​</p><h2 id="Sparse-Attention-Long-context"><a href="#Sparse-Attention-Long-context" class="headerlink" title="Sparse Attention&#x2F;Long context"></a>Sparse Attention&#x2F;Long context</h2><h3 id="LM-infinite"><a href="#LM-infinite" class="headerlink" title="LM-infinite"></a>LM-infinite</h3><h3 id="Longformer-Arxiv20"><a href="#Longformer-Arxiv20" class="headerlink" title="Longformer [Arxiv20]"></a>Longformer [Arxiv20]</h3><h3 id="StreamingLLM-ICLR24"><a href="#StreamingLLM-ICLR24" class="headerlink" title="StreamingLLM [ICLR24]"></a>StreamingLLM [ICLR24]</h3><p>Efficient Streaming Language Models with Attention Sinks <a href="https://github.com/mit-han-lab/streaming-llm">[code]</a>  <a href="https://arxiv.org/abs/2309.17453">[paper]</a></p><blockquote><p>解决的问题</p></blockquote><p>LLM在长上下文的效率和效益的问题：</p><ol><li>长上下文的计算和内存开销大。</li><li>LLM在上下文长度超过预训练长度时，生成质量差。</li></ol><blockquote><p>核心idea</p></blockquote><p><img src="/blog/img/Blog/llm-inference/image-20250615205757413.png" alt="图1:对比4中不同的注意力计算方法"></p><ol><li><strong>Dense Attention</strong>：计算复杂度高，当上下文长度超过预训练长度，模型表现差。</li><li><strong>Window Attention</strong>：计算复杂度低，当上下文长度超过缓存长度（initial token）被驱逐时，模型表现差。</li><li><strong>Sliding Window w&#x2F; Re-computation</strong>：计算复杂度中等，通过重新计算，保留了initial token的影响，模型表现良好。</li><li><strong>StreamingLLM</strong>：在<strong>Window Attention</strong>的基础上，引入了对initial token的注意力计算，兼顾推理速度和模型生成质量。</li></ol><p>Streamllm的方法主要来自于一个观察：</p><p><strong>”Attention sink“</strong>：作者发现LLM对初始token的注意力关注较高。</p><p><img src="/blog/img/Blog/llm-inference/image-20250615205218195.png" alt="图2显示了 Llama-2-7B 在处理多个短句时的平均注意力模式。从可视化结果来看，前两层主要呈现局部注意力，偏向关注临近的 token；而从第2层起，模型普遍对句首 token 表现出异常高的关注度。这种现象说明了高层注意力容易集中在起始位置，可能引发注意力偏置问题（attention sink）。"></p><p>作者对<strong>Attention sink</strong>给了一个解释：</p><p>LLM的注意力计算，保证所有token的注意力之和为1，即使当前token只需要根据自己就可以推测出下一个token，由于softmax的设计，还是需要将一些注意力分散到其他token上去。</p><p>由于LLM的自回归特性，开始的token可以被后面所有tokne注意力到，因此LLM对initial token的关注更高，进而在训练的过程中，赋予inital token特殊的含义。</p><blockquote><p>细节</p></blockquote><ol><li><p>按照在cache中的位置，重新分配token的位置信息，以保成相对位置的正确性。</p><p>如下图所示，当生成 token 9的时候，每个token的位置为[0, 1, 2, 3, 4, 5, 6, 7]而不是[0, 1, 2, 3, 6, 7, 8, 9]。</p><p><img src="/blog/img/Blog/llm-inference/image-20250615213712847.png" alt="图3：StreamingLLM的的KV Cache"></p></li><li><p>key tensor的缓存和使用</p><ul><li><p>对于RoPE，在应用 rotray 变化前缓存 key tensor，在加载的时候对其rotray。</p></li><li><p>对于ALiBi，在注意力分数上添加一个linear bias。</p></li></ul></li></ol><h2 id="Training"><a href="#Training" class="headerlink" title="Training"></a>Training</h2><h3 id="MEMO-SIGMOD25"><a href="#MEMO-SIGMOD25" class="headerlink" title="MEMO [SIGMOD25]"></a>MEMO [SIGMOD25]</h3><p>MEMO: Fine-grained Tensor Management For Ultra-long Context LLM Training <a href="https://arxiv.org/pdf/2407.12117v3">[paper]</a></p><h3 id="Malleus-SIGMOD25"><a href="#Malleus-SIGMOD25" class="headerlink" title="Malleus [SIGMOD25]"></a>Malleus [SIGMOD25]</h3><p>Malleus: Straggler-Resilient Hybrid Parallel Training of Large-scale Models via Malleable Data and Model Parallelization <a href="https://arxiv.org/pdf/2410.13333">[paper]</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;记录一些LLM推理优化相关的论文&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="LLM" scheme="https://sanzo.top/blog/tags/LLM/"/>
    
    <category term="Inference" scheme="https://sanzo.top/blog/tags/Inference/"/>
    
  </entry>
  
  <entry>
    <title>python环境配置</title>
    <link href="https://sanzo.top/blog/Blog/python-env/"/>
    <id>https://sanzo.top/blog/Blog/python-env/</id>
    <published>2021-06-25T03:37:14.000Z</published>
    <updated>2021-06-25T03:37:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>python相关环境配置：Miniconda，PyTroch，Jupyter， venv。</p><span id="more"></span><h2 id="Miniconda"><a href="#Miniconda" class="headerlink" title="Miniconda"></a>Miniconda</h2><p>Miniconda是一个轻量级的Conda包管理器</p><h3 id="安装包"><a href="#安装包" class="headerlink" title="安装包"></a>安装包</h3><p>所有安装包：<a href="https://repo.anaconda.com/miniconda/">repo.anaconda.com&#x2F;miniconda</a></p><p>Linux: <a href="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh">python3.8 Miniconda3 Linux 64-bit</a></p><p>​<a href="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86.sh">python3.7 Miniconda3 Linux 32-bit</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 以前的版本没有ssh问题</span></span><br><span class="line">wget https://repo.anaconda.com/miniconda/Miniconda3-4.7.12.1-Linux-x86_64.sh</span><br></pre></td></tr></table></figure><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><p>初始化终端：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">~/miniconda3/bin/conda init</span><br></pre></td></tr></table></figure><p>如果失败可以手动添加<code>bin</code>目录。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;export PATH=\$PATH:/home/pi/miniconda3/bin&quot;</span> &gt;&gt; .bashrc</span><br></pre></td></tr></table></figure><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><blockquote><p>新建环境</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 新建名称为test的环境</span></span><br><span class="line">conda create --name <span class="built_in">test</span> python=3.8 -y</span><br><span class="line"></span><br><span class="line"><span class="comment"># arm只能创建python=3.4的环境</span></span><br><span class="line">conda create -n <span class="built_in">test</span> python=3.4 -y</span><br></pre></td></tr></table></figure><blockquote><p>查看所有的环境</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda <span class="built_in">env</span> list</span><br></pre></td></tr></table></figure><blockquote><p>使用环境</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 激活环境</span></span><br><span class="line">conda activate <span class="built_in">test</span></span><br><span class="line"><span class="built_in">source</span> activate <span class="built_in">test</span> <span class="comment"># arm</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 退出当前环境</span></span><br><span class="line">conda deactivate</span><br><span class="line"><span class="built_in">source</span> deactivate <span class="comment"># arm</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除环境</span></span><br><span class="line">conda remove -n test1 --all</span><br></pre></td></tr></table></figure><h3 id="rpi"><a href="#rpi" class="headerlink" title="rpi"></a>rpi</h3><p>armv7l: <a href="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-armv7l.sh">miniconda3-latest-linux-armv7l.sh</a></p><p><a href="https://github.com/jjhelmus/berryconda/releases/download/v2.0.0/Berryconda3-2.0.0-Linux-armv7l.sh">Berryconda3-2.0.0-Linux-armv7l.sh</a></p><p>arm版本的miniconda最高只能安装<code>python3.4</code>，如果需要安装更高版本的<code>python</code>，需要第三方conda，这里使用的是 <a href="https://github.com/jjhelmus/berryconda">berryconda</a>，目前最高支持到<code>python3.6</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">conda config --add channels rpi</span><br><span class="line"></span><br><span class="line">conda create --name <span class="built_in">test</span> python=3.6 -y</span><br></pre></td></tr></table></figure><h2 id="venv"><a href="#venv" class="headerlink" title="venv"></a>venv</h2><p>python自带的虚拟环境模块</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 新建</span></span><br><span class="line">python -m venv /path/venv_name</span><br><span class="line"></span><br><span class="line"><span class="comment"># 激活</span></span><br><span class="line"><span class="built_in">source</span> /path/venv_name/bin/activate</span><br><span class="line"></span><br><span class="line"><span class="comment"># 退出</span></span><br><span class="line">deactivate</span><br></pre></td></tr></table></figure><p><a href="https://www.python.org/ftp/python/3.8.5/Python-3.8.5.tgz">https://www.python.org/ftp/python/3.8.5/Python-3.8.5.tgz</a></p><h2 id="Pytorch"><a href="#Pytorch" class="headerlink" title="Pytorch"></a>Pytorch</h2><p>old version lib torch: <a href="https://github.com/pytorch/pytorch/issues/40961">https://github.com/pytorch/pytorch/issues/40961</a></p><p><a href="https://pytorch.org/get-started/locally/">Pytorch</a>，选择对应cuda版本。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">torch.version # PyTorch version</span><br><span class="line">torch.cuda.is_available()</span><br><span class="line">torch.version.cuda # Corresponding CUDA version</span><br><span class="line">torch.backends.cudnn.version() # Corresponding cuDNN version</span><br><span class="line">torch.cuda.get_device_name(0) # GPU type</span><br></pre></td></tr></table></figure><h3 id="build"><a href="#build" class="headerlink" title="build"></a>build</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install pytorch and dependences</span></span><br><span class="line">git <span class="built_in">clone</span> --depth 1 --recurse-submodule https://github.com/pytorch/pytorch.git</span><br><span class="line">conda create -y --name pytorch-build python=3.8</span><br><span class="line">conda activate pytorch-build</span><br><span class="line">conda install -y astunparse numpy ninja pyyaml mkl mkl-include setuptools cmake cffi typing_extensions future six requests dataclasses pkg-config libuv</span><br><span class="line"></span><br><span class="line"><span class="comment"># arm64</span></span><br><span class="line"><span class="built_in">mkdir</span> pytorch-build-arm64</span><br><span class="line"><span class="built_in">cd</span> pytorch-build-arm64</span><br><span class="line">cmake -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_OSX_ARCHITECTURES=arm64 DCMAKE_OSX_DEPLOYMENT_TARGET=12.10 -DUSE_MKLDNN=OFF -DUSE_QNNPACK=OFF -DUSE_PYTORCH_QNNPACK=OFF -DBUILD_TEST=OFF -DUSE_NNPACK=OFF -DCMAKE_BUILD_TYPE:STRING=Release -DPYTHON_EXECUTABLE:PATH=`<span class="built_in">which</span> python3` -DCMAKE_INSTALL_PREFIX:PATH=../pytorch-install-arm64 ../pytorch</span><br><span class="line">cmake --build . --target install</span><br><span class="line"><span class="built_in">cd</span> ..</span><br><span class="line"></span><br><span class="line"><span class="comment"># x86_64</span></span><br><span class="line"><span class="built_in">mkdir</span> pytorch-build-x86_64</span><br><span class="line"><span class="built_in">cd</span> pytorch-build-x86_64</span><br><span class="line">cmake -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=12.10 -DUSE_MKLDNN=OFF -DUSE_QNNPACK=OFF -DUSE_PYTORCH_QNNPACK=OFF -DBUILD_TEST=OFF -DUSE_NNPACK=OFF -DCMAKE_BUILD_TYPE:STRING=Release -DPYTHON_EXECUTABLE:PATH=`<span class="built_in">which</span> python3` -DCMAKE_INSTALL_PREFIX:PATH=../pytorch-install-x86_64 ../pytorch</span><br><span class="line">cmake --build . --target install</span><br><span class="line"><span class="built_in">cd</span> ..</span><br></pre></td></tr></table></figure><h3 id="test"><a href="#test" class="headerlink" title="test"></a>test</h3><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># CMakeLists.txt</span></span><br><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.0</span> FATAL_ERROR)</span><br><span class="line"><span class="keyword">project</span>(example-app)</span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span>(Torch_DIR /Users/sanzo/Software/pytorch-<span class="keyword">install</span>-arm64)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_PREFIX_PATH <span class="string">&quot;/Users/sanzo/Software/pytorch-install-arm64/share/cmake/Torch&quot;</span>)</span><br><span class="line"><span class="keyword">find_package</span>(Torch REQUIRED)</span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_FLAGS <span class="string">&quot;$&#123;CMAKE_CXX_FLAGS&#125; $&#123;TORCH_CXX_FLAGS&#125;&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">add_executable</span>(example-app example-app.cpp)</span><br><span class="line"><span class="keyword">target_link_libraries</span>(example-app <span class="string">&quot;$&#123;TORCH_LIBRARIES&#125;&quot;</span>)</span><br><span class="line"><span class="keyword">set_property</span>(<span class="keyword">TARGET</span> example-app PROPERTY CXX_STANDARD <span class="number">14</span>)</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;torch/torch.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  std::cout &lt;&lt; <span class="string">&quot;PyTorch version: &quot;</span></span><br><span class="line">    &lt;&lt; TORCH_VERSION_MAJOR &lt;&lt; <span class="string">&quot;.&quot;</span></span><br><span class="line">    &lt;&lt; TORCH_VERSION_MINOR &lt;&lt; <span class="string">&quot;.&quot;</span></span><br><span class="line">    &lt;&lt; TORCH_VERSION_PATCH &lt;&lt; std::endl;</span><br><span class="line">  torch::Tensor tensor = torch::<span class="built_in">rand</span>(&#123;<span class="number">2</span>, <span class="number">3</span>&#125;);</span><br><span class="line">  std::cout &lt;&lt; tensor &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> 0.0598  0.7058  0.0322</span></span><br><span class="line"><span class="comment"> 0.2230  0.4112  0.9342</span></span><br><span class="line"><span class="comment">[ CPUFloatType&#123;2,3&#125; ]</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><blockquote><p>references</p></blockquote><p>old version lib torch: <a href="https://github.com/pytorch/pytorch/issues/40961">https://github.com/pytorch/pytorch/issues/40961</a></p><p><a href="https://dev-discuss.pytorch.org/t/universal-binaries-for-libtorch-mac/229">https://dev-discuss.pytorch.org/t/universal-binaries-for-libtorch-mac/229</a></p><p><a href="https://github.com/pytorch/pytorch/issues/63558">https://github.com/pytorch/pytorch/issues/63558</a></p><h2 id="jupyter-notebook"><a href="#jupyter-notebook" class="headerlink" title="jupyter notebook"></a>jupyter notebook</h2><h3 id="ipykernel"><a href="#ipykernel" class="headerlink" title="ipykernel"></a>ipykernel</h3><p>通过ipykernel管理jupyter notebook的内核。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 激活环境</span></span><br><span class="line">activate env_name</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装ipykernel</span></span><br><span class="line">pip install ipykernel</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加kernel</span></span><br><span class="line">python -m ipykernel install --name env_name</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除内核</span></span><br><span class="line">jupyter kernelspec remove kernelname</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看所有内核</span></span><br><span class="line">jupyter kernelspec list</span><br></pre></td></tr></table></figure><h3 id="远程访问"><a href="#远程访问" class="headerlink" title="远程访问"></a>远程访问</h3><p>生成密钥</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 通过ipython生成密码</span></span><br><span class="line">ipython</span><br><span class="line"></span><br><span class="line">In [1]: from notebook.auth import passwd</span><br><span class="line">In [2]: passwd()</span><br><span class="line">Enter password: </span><br><span class="line">Verify password: </span><br><span class="line">Out[3]: <span class="string">&#x27;xxxxxxxxxxxxxxxxxxxxxx&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成配置文件，并添加如下配置</span></span><br><span class="line">jupyter notebook --generate-config</span><br><span class="line"></span><br><span class="line">c.NotebookApp.ip=<span class="string">&#x27;0.0.0.0&#x27;</span></span><br><span class="line">c.NotebookApp.password = u<span class="string">&#x27;xxxxxxxxxxxxxxxxxxxxxx&#x27;</span></span><br><span class="line">c.NotebookApp.open_browser = False</span><br><span class="line">c.NotebookApp.port =8888</span><br></pre></td></tr></table></figure><p>然后就可以通过<code>https://ip:8888</code>远程访问<code>jupyter notebook</code></p><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;python相关环境配置：Miniconda，PyTroch，Jupyter， venv。&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="python" scheme="https://sanzo.top/blog/tags/python/"/>
    
    <category term="miniconda" scheme="https://sanzo.top/blog/tags/miniconda/"/>
    
    <category term="venv" scheme="https://sanzo.top/blog/tags/venv/"/>
    
    <category term="pytorch" scheme="https://sanzo.top/blog/tags/pytorch/"/>
    
    <category term="setup" scheme="https://sanzo.top/blog/tags/setup/"/>
    
  </entry>
  
  <entry>
    <title>RAG介绍</title>
    <link href="https://sanzo.top/blog/Blog/rag/"/>
    <id>https://sanzo.top/blog/Blog/rag/</id>
    <published>2024-02-28T00:06:50.000Z</published>
    <updated>2025-06-01T07:06:50.000Z</updated>
    
    <content type="html"><![CDATA[<p>RAG是什么？目前的研究现状如何？</p><span id="more"></span><h2 id="RAG介绍"><a href="#RAG介绍" class="headerlink" title="RAG介绍"></a>RAG介绍</h2><blockquote><p>什么是LLM？</p></blockquote><p>大语言模型（Large Language Model，LLM）是基于海量数据集进行预训练的超大规模的深度学习模型。OpenAI发布的ChatGPT使人们意识到，具有<strong>足够的训练数据</strong>和<strong>巨大的参数</strong>的神经网络模型可以捕获人类语言的大部分语法和语义。得益于与LLM出色的语言理解能力，LLM被广泛的应用于各种下游任务，例如文案写作，知识问答，文本分类，代码生成，文本生成等。虽然LLM在很多领域具有出色的表现，但是它面临诸如<strong>幻觉</strong>，<strong>过时的知识</strong>，<strong>缺乏可解释性</strong>等挑战。</p><p><img src="/blog/img/Blog/rag/image-20240909144939668.png" alt="图1：RAG执行流程 （from RAGCache paper）"></p><blockquote><p>RAG的执行流程</p></blockquote><p>检索增强生成（Retrieval Augmented Generation，RAG）包含检索和生成两部分。如图1所示，在处理用户请求之前，RAG系统首先对外部数据（文档，语音，视频等非结构化数据）进行预处理（生成向量等），并存储到知识数据库中以供后续检索使用。当接收到用户的请求时，RAG系统首先从知识数据库中检索与问题相关的知识，然后将检索得到的知识和用户的问题一起输入到LLM，生成最终的答案。通过外挂知识库的方法，RAG一定程度缓解了LLM的幻觉，时效性差，和不可解释等问题。</p><p>目前的RAG形态主要分为VectorRAG和GraphRAG两种。</p><blockquote><p>VectorRAG</p></blockquote><p><img src="/blog/img/Blog/rag/image-20240225165419089.png" alt="图2: VectorRAG"></p><p><strong>VectorRAG使用向量来组织外部的知识</strong>。如图2所示，VectorRAG首先将文档划分为多个文本块（chunk）。每个文本块通过嵌入模型得到对应的向量表示，然后存储到向量数据库中。对于用的的请求，VectorRAG对用户的问题生成嵌入向量。然后，从向量数据库检索与问题嵌入向量相似的向量并返回对应的文本块。</p><p>VectorRAG的优点是：（1）检索速度快。（2）丰富的上下文语义信息。</p><p>VectorRAG的缺点是：（1）由于信息分散导致的检索不完整性。（2）由于语义导致的不准确性。</p><p>举个具体的例子，例如我们基于《乔布斯自传》来回答用户的问题。与用户问题相关的文本块可能有30个，而且它们分散的存储在书中的不同位置。此时，如果只取top K个片段很难得到这种分散，细粒度的完整信息。而且这种方法容易一楼相互关联的文本块，从而导致检索信息的不完整。</p><p>另外，基于嵌入的语义搜索存在不准确的问题，例如“保温杯”和“保温大棚”，这两个关键词在语义空间上存在很大的相似性，然而在真实的场景中，我们并不希望这种通用语义下的相关性出现，进而作为错误的上下文而引入”幻觉“。</p><blockquote><p>GraphRAG</p></blockquote><p><strong>&#x3D;&#x3D;重新整理&#x3D;&#x3D;</strong></p><p>GraphRAG是一种使用知识图谱（Knowledge Graph，KG）来组织外部数据的RAG。与向量RAG相比，GraphRAG具有更加细粒度的知识形式，而且，通过在图上查询目标实体的多跳邻居，可以查询相互关联的信息，即使他们不在同一个文本块内部。</p><p><img src="/blog/img/Blog/rag/image-20240228095958676.png" alt="图3: GraphRAG"></p><p>GraphRAG的执行过程可以简单概括为以下三步：</p><ul><li>从问题中提取实体</li><li>从知识图谱中检索得到子图</li><li>根据子图构造上下文</li></ul><p><img src="/blog/img/Blog/rag/image-20240226142933094.png" alt="图4: Graph + VectorRAG (siwei.io/graph-rag)"></p><p>图3是Graph和Vector联合RAG的流程图。首先对外部的文档构建索引（向量索引和KG索引），用户后续的数据检索。当用户提交一个问题的查询时，首先通过嵌入模型对用户的问题生成向量表示，然后分别从向量数据库中检索语义相关的文本块；从知识图谱数据库中检索相关的实体，然后遍历得到实体相关的查询子图。最后将向量检索得到的文本块和知识图谱检索得到的查询子图，联合问题一起输入到LLM生成问题的回答。</p><p>GraphRAG可以看作是对已有方法的额外扩展。通过将知识图谱引入到RAG中，GraphRAG可以利用现有或者新建的知识图谱，提取细粒度，领域特定且相互关联的知识。</p><h2 id="研究现状"><a href="#研究现状" class="headerlink" title="研究现状"></a>研究现状</h2><h3 id="Iterative-RAG"><a href="#Iterative-RAG" class="headerlink" title="Iterative RAG"></a>Iterative RAG</h3><h4 id="IR-COT-ACL-‘23"><a href="#IR-COT-ACL-‘23" class="headerlink" title="IR-COT [ACL ‘23]"></a>IR-COT [ACL ‘23]</h4><p>Interleaving Retrieval with Chain-of-Thought Reasoning for Knowledge-Intensive Multi-Step Questions <a href="https://arxiv.org/pdf/2212.10509">[paper]</a> <a href="https://github.com/stonybrooknlp/ircot">[code]</a></p><blockquote><p>解决的问题</p></blockquote><p>One-step  retrieve-and-read 的方法不适用于multi-step QA。</p><p>检索和生成是互补的。检索可以为生成提供支撑材料。而生成的中间信息又能反过来指导后续检索。</p><p>举个例子：</p><p>问题是：“哪个国家是电话发明者的出生地？”</p><ol><li><p>需要先找出“电话的发明者是谁”，答案是<strong>亚历山大·格雷厄姆·贝尔</strong>。这一步中，问题和答案在词汇上有明显关联。</p></li><li><p>要找的是“贝尔出生在哪个国家”。但原始问题里并没有提到“贝尔”这个词，所以这一步所需的信息与原问题<strong>没有直接的词汇或语义联系</strong>。</p></li></ol><p>因此，如果不先完成第一步推理，就无法找到第二步的支持证据。</p><blockquote><p>核心idea</p></blockquote><ol><li>生成 &#x3D; LLM(问题，历史所有检索文档)</li><li>根据上一步的生成内容，来检索文档</li></ol><blockquote><p>执行流程</p></blockquote><p><img src="/blog/img/Blog/rag/image-20250601195541379.png" alt="IRCoT执行流程"></p><h4 id="Iter-RetGen-EMNLP-‘23"><a href="#Iter-RetGen-EMNLP-‘23" class="headerlink" title="Iter-RetGen [EMNLP ‘23]"></a>Iter-RetGen [EMNLP ‘23]</h4><p>Enhancing Retrieval-Augmented Large Language Models with Iterative Retrieval-Generation Synergy <a href="https://arxiv.org/pdf/2305.15294">[paper]</a> </p><blockquote><p>解决的问题</p></blockquote><ul><li>生成只针对当前检索的内容，无法感知所有的检索知识。</li><li>多轮检索增加了检索和生成的开销。</li></ul><blockquote><p>核心idea</p></blockquote><p>将检索和生成有机的结合起来，前面生成的答案辅助后面的检索。</p><ul><li>检索增强生成。</li><li>生成增强检索，训练检索器，利用上一轮的生成内容提高检索精度。</li></ul><blockquote><p>执行流程</p></blockquote><p>给定问题Q。</p><ol><li>将上一轮的生成内容和问题Q结合起来，检索得到文档D。</li><li>根据文档D生成回答。</li><li>重复1，2</li></ol><p><img src="/blog/img/Blog/rag/image-20250601151828281.png" alt="Iter-RetGen执行流程"></p><h4 id="Self-RAG-ICLR-‘24"><a href="#Self-RAG-ICLR-‘24" class="headerlink" title="Self-RAG [ICLR ‘24]"></a>Self-RAG [ICLR ‘24]</h4><p>Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection <a href="https://openreview.net/forum?id=hSyW5go0v8">[paper]</a>  <a href="https://github.com/AkariAsai/self-rag">[code]</a></p><blockquote><p>解决的问题</p></blockquote><ul><li>没有考虑是否需要检索，只是漫无目的的检索或固定数量的检索。</li><li>大量不相关和容复的检索内容，导致低质量的生成。</li></ul><blockquote><p>核心idea</p></blockquote><p>训练LM生成特殊reflection token，来决定是否需要检索，以及判断生成内容的相关性。</p><blockquote><p>执行流程</p></blockquote><p>给定问题Q。</p><ol><li>首先判断是否执行检索，需要则生成retrieval token。</li><li>并行的执行检索，并为每个文档生成输出。</li><li>生成critique token，评估相关性，选择最相关的文档。</li><li>重复以上步骤</li></ol><p><img src="/blog/img/Blog/rag/image-20250601154008636.png" alt="Self-RAG执行流程"></p><h4 id="ReSP-WWW-‘25"><a href="#ReSP-WWW-‘25" class="headerlink" title="ReSP [WWW ‘25]"></a>ReSP [WWW ‘25]</h4><p>Retrieve, Summarize, Plan: Advancing Multi-hop Question Answering with an Iterative Approach <a href="https://dl.acm.org/doi/pdf/10.1145/3701716.3716889">[paper]</a> </p><blockquote><p>解决的问题</p></blockquote><p>现有iterative RAG在处理multi-hop QA存在的问题：</p><ul><li>过长的上下文引入噪声，使得关键信息被忽视。</li><li>缺少记录模型推理的路径，存在redundant planning。<ul><li>over-planning：已经能回答正确答案，还继续执行检索和生成。</li><li>repetitive-planning：对相同子问题的重复处理。</li></ul></li></ul><blockquote><p>核心Idea</p></blockquote><ul><li>引入Reasoner来决定是否继续进行检索</li><li>使用memory记录历史检索生成结果<ul><li>Global Evidence Memory（防止over-palnning）。</li><li>Local Pathway Memory，记录每一步的检索和生成过程（防止repetitive-planning）。</li></ul></li></ul><blockquote><p>执行流程</p></blockquote><p>给定用户的问题Q：</p><ol><li>Reasoner结合历史产生的Memory来判断是否继续检索。<ul><li>不需要检索，通过Generator生成最终答案。</li><li>需要继续检索，则生成子问题执行后续操作。</li></ul></li><li>根据子问题检索top-k文档。</li><li>使用summarier更新global memory，local memory。</li></ol><p><img src="/blog/img/Blog/rag/image-20250601150330636.png" alt="ReSP框架图"></p><h3 id="Graph-RAG"><a href="#Graph-RAG" class="headerlink" title="Graph RAG"></a>Graph RAG</h3><h4 id="GraphRAG-arxiv-‘24"><a href="#GraphRAG-arxiv-‘24" class="headerlink" title="GraphRAG [arxiv ‘24]"></a>GraphRAG [arxiv ‘24]</h4><p>From Local to Global: A Graph RAG Approach to Query-Focused Summarization <a href="https://arxiv.org/pdf/2404.16130">[paper]</a> <a href="https://github.com/microsoft/graphrag">[code]</a></p><blockquote><p>解决的问题</p></blockquote><blockquote><p>核心Idea</p></blockquote><blockquote><p>执行流程</p></blockquote><h4 id="KAG"><a href="#KAG" class="headerlink" title="KAG []"></a>KAG []</h4><p>KAG: Boosting LLMs in Professional Domains via Knowledge Augmented Generation <a href="https://arxiv.org/pdf/2409.13731">[paper]</a> <a href="https://github.com/OpenSPG/KAG">[code]</a></p><blockquote><p>解决的问题</p></blockquote><blockquote><p>核心Idea</p></blockquote><blockquote><p>执行流程</p></blockquote><h4 id="LightRAG"><a href="#LightRAG" class="headerlink" title="LightRAG []"></a>LightRAG []</h4><p>LightRAG: Simple and Fast Retrieval-Augmented Generation <a href="https://arxiv.org/pdf/2410.05779">[paper]</a> <a href="https://github.com/HKUDS/LightRAG">[code]</a></p><blockquote><p>解决的问题</p></blockquote><blockquote><p>核心Idea</p></blockquote><blockquote><p>执行流程</p></blockquote><h3 id="Memory-RAG"><a href="#Memory-RAG" class="headerlink" title="Memory RAG"></a>Memory RAG</h3><h4 id="MemoryBank-AAAI-‘24"><a href="#MemoryBank-AAAI-‘24" class="headerlink" title="MemoryBank [AAAI ‘24]"></a>MemoryBank [AAAI ‘24]</h4><p>MemoryBank: Enhancing Large Language Models with Long-Term Memory <a href="https://arxiv.org/abs/2305.10250">[paper]</a> <a href="https://github.com/zhongwanjun/MemoryBank-SiliconFriend">[code]</a></p><blockquote><p>解决的问题</p></blockquote><p>为LLM提供记忆功能，捕捉用户画像，根据用户个性化需求提供更好的回复。</p><blockquote><p>核心idea</p></blockquote><p>MemoryBank分为三个模块：</p><ol><li>MemoryStorage：存储用户的历史聊天记录，并使用LLM为每个对话生成分层摘要，得到对话的概括和用户全局的画像。</li><li>MemoryRetrieval：使用向量检索相关的记忆。</li><li>MemoryUpdating：参考记忆遗忘曲线来模拟人类记忆，来遗忘在过去很长一段时间内都没有被访问的记忆，让AI回答的更加自然。</li></ol><p><img src="/blog/Users/sanzo/Desktop/blog/source/img/Blog/rag/image-20250620085024322.png" alt="Overview of MemoryBank"></p><h4 id="Mem0"><a href="#Mem0" class="headerlink" title="Mem0"></a>Mem0</h4><p>Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory <a href="https://github.com/mem0ai/mem0">[code]</a> <a href="https://arxiv.org/pdf/2504.19413">[paper]</a></p><h4 id="A-MEM-Arxiv’-25"><a href="#A-MEM-Arxiv’-25" class="headerlink" title="A-MEM [Arxiv’ 25]"></a>A-MEM [Arxiv’ 25]</h4><p>A-MEM: Agentic Memory for LLM Agents <a href="https://arxiv.org/abs/2502.12110">[paper]</a> <a href="https://github.com/agiresearch/A-mem">[code]</a></p><blockquote><p>解决的问题</p></blockquote><p>Agent需要访问用户历史信息来提供更精确的回答。</p><p>现有Agent Memory System在管理记忆依赖于固定的格式，无法应对具有复杂交互逻辑，以及知识动态更新的Agent workflow。</p><blockquote><p>核心Idea</p></blockquote><p>借鉴Zettelkasten笔记方法，通过创建原子笔记的方法记录新加入的信息，支持动态的创建知识链接，以及更新历史知识。</p><p>Node Construction：为新加入的知识生成笔记，包括：时间戳，关键词，标签等属性。</p><p>Link Generation：首先基于相似性检索top-k个笔记，然后使用LLM判断是否创建知识链接。</p><p>Memory Evolution：使用LLM判断需要更新相似的历史知识。</p><blockquote><p>局限性</p></blockquote><ul><li>性能依赖于LLM</li><li>没有考虑多模态知识</li></ul><p><img src="/blog/Users/sanzo/Desktop/blog/source/img/Blog/rag/image-20250620114717792.png" alt="Overview of A-MEM"></p><h4 id="Zep-Arxiv-‘25"><a href="#Zep-Arxiv-‘25" class="headerlink" title="Zep [Arxiv ‘25]"></a>Zep [Arxiv ‘25]</h4><p>Zep: A Temporal Knowledge Graph Architecture for Agent Memory <a href="https://arxiv.org/abs/2501.13956">[paper] </a> <a href="https://github.com/getzep/graphiti">[code]</a></p><blockquote><p>解决的问题</p></blockquote><blockquote><p>核心Idea</p></blockquote><blockquote><p>执行流程</p></blockquote><h4 id="DeepNote"><a href="#DeepNote" class="headerlink" title="DeepNote []"></a>DeepNote []</h4><p>DeepNote: Note-Centric Deep Retrieval-Augmented Generation <a href="https://arxiv.org/abs/2410.08821">[paper]</a> <a href="https://github.com/thunlp/DeepNote">[code]</a></p><blockquote><p>解决的问题</p></blockquote><blockquote><p>核心Idea</p></blockquote><blockquote><p>执行流程</p></blockquote><h3 id="Other"><a href="#Other" class="headerlink" title="Other"></a>Other</h3><h4 id="OP-RAG-arixv-‘24"><a href="#OP-RAG-arixv-‘24" class="headerlink" title="OP-RAG [arixv ‘24]"></a>OP-RAG [arixv ‘24]</h4><p><a href="https://arxiv.org/pdf/2409.01666">paper</a></p><p>这篇论文讨论了RAG在Long-context LLM下是否还是有必要存在的问题？</p><p>结论是：Long-context LLM可能会导致对相关信息的关注减少，从而可能降低问答任务中的答案质量。因此RAG还是有必要存在的，通过使用RAG可以有效的输入文本的长度，同时可以获取更高的准确率。</p><p>在上下文限制的LLM中，使用RAG可以有效的减少输入大模型的文本长度，然后模型回答的准确率就取决于检索的性能。最近出现了很多Long-context的LLM模型，例如GPT-4o，Claudi-3.5，Llama3.1，Phi-3，Mistral-Large2具有128K的上下文长度，Gemini-1.5-pro甚至达到了1M的上下文窗口大小。因此这里有个问题：在Long-context LLM下，是否还有必要使用RAG？</p><p><img src="/blog/img/Blog/rag/image-20240909152853006.png" alt="RAG在不同上下文长度下的表现"></p><p>作者通过实验，对比了RAG在不同上下问长度下的性能。实验结果表明：<strong>随着上下文的增加，RAG性能先上升后下降。</strong>这是因为更多的上下文可能有更大的机会覆盖相关的块。然而，随着上下文长度进一步增加，答案质量会下降，因为更多不相关的块被用作干扰。</p><p>另外本文提出了一种保留检索文档原始顺序的方法，order-preserve RAG (OP-RAG)，通过实验发现可以有效的提高准确率。（没有提供insight和分析）。</p><h3 id="Evaluation"><a href="#Evaluation" class="headerlink" title="Evaluation"></a>Evaluation</h3><h4 id="RGB-AAAI’24"><a href="#RGB-AAAI’24" class="headerlink" title="RGB [AAAI’24]"></a>RGB [AAAI’24]</h4><p><a href="https://arxiv.org/pdf/2309.01431.pdf">paper</a>  <a href="https://github.com/chen700564/RGB">code</a></p><p>RGB是针对QA场景下的RAG benchmark工作，主要贡献如下：</p><ol><li>构建了一个中英文的RAG benchmark。</li><li>从以下四个方面对RAG进行了评估，分析总结了LLM和RAG的局限性和缺点。<ul><li>Noise Robustness，表示LLM可以从噪声文档中提取有用的信息。其中噪声文档，是语文题相关但是不包含答案相关的信息。</li><li>Negative Rejection，表示如果检索的文档不包含与答案相关的信息，LLM应该拒绝回答。</li><li>information Integration，表示LMM是否可以回答需要整合多个文档信息的复杂问题。</li><li>Counterfactual Robustness，表示当LLM通过prompt警告检索的信息可能包含事实错误的信息时，LLM可以识别文档中的事实错误。</li></ul></li></ol><blockquote><p>数据集构造</p></blockquote><ol><li><p>QA instances generation，收集最新的新闻文章，然后使用ChatGPT对每个文章生成 (events, questions, and answers)。通过人工检查答案的正确性，并过滤掉一些无法从搜索引擎检索得到的数据。</p></li><li><p>Retrieve using search engine，对于每个问题，使用Google的API获取10个相关的网页，然后提取出相关的文档快。每个文档快包含300个token，使用<code>dense retrieval model</code>(<a href="https://huggingface.co/moka-ai/m3e-base">m3e-base</a>，<a href="https://huggingface.co/sentence-transformers/all-mpnet-base-v2">all-mpnet-base-v2</a>) 选择top-30的文本块。这些文本被分为positive documents and negative documents。</p></li><li><p>Testbeds construction for each ability</p><ul><li><p>noise robustness，根据比例采样不同数量的negative documents。</p></li><li><p>negative rejection，只从negative documents中采样外部文档。</p></li><li><p>information integration，对问题进行expanding或者rewriting，使得问题的答案包含多个文档的信息。</p><p>例如：”Who won the MVP of Super Bowl 2023?” can be rewrite as “Who won the MVPs of Super Bowl 2022 and 2023?”</p></li><li><p>counterfactual robustness，利用LLM内部的知识生成问题的答案，然后检索出相关的文档，手动修改文档中的信息。</p></li></ul></li></ol><img src="../../img/Blog/rag/image-20240310162733217.png" alt="RGB的数据构造过程" style="zoom:50%;" /><blockquote><p>评估的metrics</p></blockquote><ol><li>Accuracy ，用来评估noise robustness and information integration。生成的回答是否和标准答案一样。</li><li>Rejection rate，评估negative rejection。当只提供negative documents，LLM应该输出”I can not answer the question because of the insufficient information in documents.”。</li><li>Error detection rate，评估counterfactual robustness。当提供的文档包含错误的事实，LLM应该输出”There are factual errors in the provided documents.“。</li><li>Error correction rate，评估LLM在识别出检索文档的事实错误后，是否可以回答出正确的答案。</li></ol><blockquote><p>实验结果</p></blockquote><ol><li>RAG的性能随着噪声比例上升严重下降。存在以下问题：<ul><li>Long-distance information</li><li>Evidence uncertainty</li><li>Concept confusion.</li></ul></li><li>RAG很容易受到噪音信息的干扰，Negative Rejection很低。</li><li>RAG在information  integration上表现不佳，存在以下问提：<ul><li>Merging Error，成功识别了两个问题，但是在合并答案出错。</li><li>Ignoring Error，没有正确识别两个问题，只回答了一个答案。</li><li>Misalignment Error，两个问题的答案混淆。</li></ul></li><li>RAG基本没有识别事实错误的能力，因为这个RAG的基本假设冲突（模型缺乏信息，从外部检索相关信息），现有的LLM缺乏对错误信息的识别能力，严重依赖检索的信息。</li></ol><h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ol><li><p><a href="https://arxiv.org/abs/2312.10997">Retrieval-Augmented Generation for Large Language Models: A Survey</a></p></li><li><p><a href="https://colab.research.google.com/drive/1tLjOg2ZQuIClfuWrAC2LdiZHCov8oUbs?usp=sharing#scrollTo=Q4QMkKKTumXn">Graph_RAG_LlamaIndex_Workshop.ipynb</a></p><ul><li><p>KG gets Fine-grained Segmentation of info. with the nature of interconnection&#x2F;global-context-retained, it helps when retriving spread yet important knowledge pieces.</p></li><li><p>Hallucination due to w&#x2F; relationship in literal&#x2F;common sense, but should not be connected in domain Knowledge</p></li></ul></li><li><p><a href="https://siwei.io/graph-enabled-llama-index/kg_and_vector_RAG.html">Custom Index combining KG Index and VectorStore Index</a></p><ul><li>Not all cases are advantageous, many other questions do not contain small-grained pieces of knowledges in chunks. In these cases, the extra Knowledge Graph retriever may not that helpful.</li></ul></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;RAG是什么？目前的研究现状如何？&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="RAG" scheme="https://sanzo.top/blog/tags/RAG/"/>
    
  </entry>
  
  <entry>
    <title>树莓派小车</title>
    <link href="https://sanzo.top/blog/Blog/raspi-car/"/>
    <id>https://sanzo.top/blog/Blog/raspi-car/</id>
    <published>2021-07-07T14:24:52.000Z</published>
    <updated>2021-07-07T14:24:52.000Z</updated>
    
    <content type="html"><![CDATA[<p>树莓派防吃灰玩具</p><span id="more"></span><p>代码地址：<a href="https://github.com/Sanzo00/pi-car">github.com&#x2F;Sanzo00&#x2F;pi-car</a></p><p>树莓派配置：<a href="https://sanzo.top/blog/Blog/raspi-setup">sanzo.top&#x2F;blog&#x2F;Blog&#x2F;raspi-setup</a></p><p><img src="/blog/img/Blog/raspi-car/car.jpg"></p><h2 id="功能展示"><a href="#功能展示" class="headerlink" title="功能展示"></a>功能展示</h2><h3 id="远程控制小车"><a href="#远程控制小车" class="headerlink" title="远程控制小车"></a>远程控制小车</h3><p><img src="/blog/img/Blog/raspi-car/remote-control-car.gif"></p><h3 id="PWM变速"><a href="#PWM变速" class="headerlink" title="PWM变速"></a>PWM变速</h3><p>小车在低电压情况下跑的比较慢，因此增加变速的功能。</p><p><img src="/blog/img/Blog/raspi-car/pwm-speed-control.png"></p><h3 id="超声波自动避障"><a href="#超声波自动避障" class="headerlink" title="超声波自动避障"></a>超声波自动避障</h3><p>这里使用超声波测距模块（HC-SR04）实现距离检测，在此基础上实现一个简单的自动避障逻辑。</p><p><img src="/blog/img/Blog/raspi-car/auto-direction.gif"></p><h2 id="GPIO"><a href="#GPIO" class="headerlink" title="GPIO"></a>GPIO</h2><p><img src="/blog/img/Blog/raspi-car/image-20201206142156793.png" alt="image-20201206142156793"></p><p><img src="/blog/img/Blog/raspi-car/image-20201206142137327.png" alt="image-20201206142137327"></p><h3 id="pinout"><a href="#pinout" class="headerlink" title="pinout"></a>pinout</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt install python3-gpiozero</span><br><span class="line">pinout</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/raspi-car/image-20201206142521859.png" alt="image-20201206142521859"></p><h3 id="gpio-readall"><a href="#gpio-readall" class="headerlink" title="gpio readall"></a>gpio readall</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wget https://project-downloads.drogon.net/wiringpi-latest.deb</span><br><span class="line">sudo dpkg -i wiringpi-latest.deb</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/raspi-car/image-20201206144158864.png" alt="image-20201206144158864"></p><h2 id="材料与安装"><a href="#材料与安装" class="headerlink" title="材料与安装"></a>材料与安装</h2><table><thead><tr><th>名称</th><th>数量</th><th>规格</th></tr></thead><tbody><tr><td>树莓派4B</td><td>1</td><td>4G</td></tr><tr><td>L298N电机驱动模块</td><td>1</td><td></td></tr><tr><td>直流减速电机</td><td>4</td><td>工作电压：3-6V，减速比：1:48</td></tr><tr><td>神火18650</td><td>2</td><td>3.7V</td></tr><tr><td>充电宝</td><td>1</td><td>5V3A</td></tr><tr><td>HC-SR04</td><td>1</td><td>2cm-400cm</td></tr></tbody></table><h3 id="L298N"><a href="#L298N" class="headerlink" title="L298N"></a>L298N</h3><p><img src="/blog/img/Blog/raspi-car/image-20210820111534273.png" alt="image-20210820111534273"></p><p><img src="/blog/img/Blog/raspi-car/image-20201206145217171.png" alt="image-20201206145217171"></p><blockquote><p>接线</p></blockquote><p>这里使用树莓派的GPIO的BCM编号。</p><p>IN1、IN2、IN3、IN4分别接到树莓派的5、6、13、19上。</p><p>ENA、ENB接到树莓派的20、21。</p><h3 id="HC-SR04"><a href="#HC-SR04" class="headerlink" title="HC-SR04"></a>HC-SR04</h3><p><img src="/blog/img/Blog/raspi-car/image-20210820110650933.png" alt="image-20210820110650933"></p><blockquote><p>测距原理</p></blockquote><p>将Trig置为高电平10us，HC-SR04发送8个40khz的方波，并检测是否有信号返回，此时Echo为高电平，若有信号返回，Echo自动置为低电平，Echo高电平持续的时间既是超声波从发射到返回的时间，最后利用声波公式计算距离$dis &#x3D; \frac{time\space \times \space 340m&#x2F;s}{2}$。</p><blockquote><p>接线</p></blockquote><p>VCC接树莓派或L298N的5V电源。</p><p>GND接树莓派GND。</p><p>Echo、Trig接树莓派GPIO 14、15。</p><h3 id="电源"><a href="#电源" class="headerlink" title="电源"></a>电源</h3><p>树莓派和L298N都单独供电，树莓派使用的是5V3A的充电宝供电，L298N使用电池盒供电。</p><p>电池盒的正极和负极，分别接到L298N的+12V、GND。</p><p>因为都是单独供电，所以将L298N的GND和树莓派的GND相互连接，这样方便同步逻辑信号。</p><p>HC-SR04使用树莓派的5V电源。</p><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;树莓派防吃灰玩具&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="pi" scheme="https://sanzo.top/blog/tags/pi/"/>
    
    <category term="RaspberryPi" scheme="https://sanzo.top/blog/tags/RaspberryPi/"/>
    
    <category term="car" scheme="https://sanzo.top/blog/tags/car/"/>
    
  </entry>
  
  <entry>
    <title>树莓派配置</title>
    <link href="https://sanzo.top/blog/Blog/raspi-setup/"/>
    <id>https://sanzo.top/blog/Blog/raspi-setup/</id>
    <published>2021-06-13T07:47:44.000Z</published>
    <updated>2021-06-13T07:47:44.000Z</updated>
    
    <content type="html"><![CDATA[<p>树莓派新机配置</p><span id="more"></span><hr><h2 id="镜像"><a href="#镜像" class="headerlink" title="镜像"></a>镜像</h2><p>Ubuntu：<a href="https://ubuntu.com/download/raspberry-pi">https://ubuntu.com/download/raspberry-pi</a></p><p>Pi OS：<a href="https://www.raspberrypi.com/software/operating-systems">https://www.raspberrypi.com/software/operating-systems</a></p><p>balena：<a href="https://www.balena.io/etcher">https://www.balena.io/etcher</a></p><h2 id="更新源"><a href="#更新源" class="headerlink" title="更新源"></a>更新源</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> vim /etc/apt/sources.list</span><br><span class="line"></span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contrib rpi</span><br><span class="line">deb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contrib rpi</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> vim /etc/apt/sources.list.d/raspi.list</span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui</span><br></pre></td></tr></table></figure><h2 id="修改时区"><a href="#修改时区" class="headerlink" title="修改时区"></a>修改时区</h2><p>Asia &#x3D;&gt; Shanghai</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> dpkg-reconfigure tzdata</span><br></pre></td></tr></table></figure><h2 id="vim配置"><a href="#vim配置" class="headerlink" title="vim配置"></a>vim配置</h2><p><a href="http://sanzo.top/Default/vim">http://sanzo.top/Default/vim</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">set</span> expandtab</span><br><span class="line"><span class="built_in">set</span> softtabstop=2</span><br><span class="line"><span class="built_in">set</span> autoindent</span><br><span class="line"><span class="built_in">set</span> tabstop=2</span><br><span class="line"><span class="built_in">set</span> shiftwidth=2</span><br><span class="line"><span class="built_in">set</span> nu</span><br><span class="line">syntax on</span><br><span class="line"></span><br><span class="line">noremap H ^</span><br><span class="line">noremap L $</span><br><span class="line">noremap J G</span><br><span class="line">noremap K gg</span><br><span class="line">nnoremap &lt; &lt;&lt;</span><br><span class="line"><span class="string">nnoremap &gt; &gt;&gt;</span></span><br></pre></td></tr></table></figure><h2 id="静态IP"><a href="#静态IP" class="headerlink" title="静态IP"></a>静态IP</h2><p><code>sudo nano /etc/dhcpcd.conf</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">interface eth0</span><br><span class="line">static ip_address=192.168.31.240/24</span><br><span class="line">static routers=192.168.31.1</span><br><span class="line">static domain_name_servers=192.168.31.1</span><br><span class="line"></span><br><span class="line">interface wlan0</span><br><span class="line">static ip_address=192.168.31.242/24</span><br><span class="line">static routers=192.168.31.1</span><br><span class="line">static domain_name_servers=192.168.31.1</span><br></pre></td></tr></table></figure><p><code>sudo reboot</code></p><h2 id="安装包"><a href="#安装包" class="headerlink" title="安装包"></a>安装包</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt install -y lrzsz git proxychains libboost-all-dev samba samba-common aria2 cmake</span><br></pre></td></tr></table></figure><h2 id="proxychains"><a href="#proxychains" class="headerlink" title="proxychains"></a>proxychains</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> vim /etc/proxychains.conf </span><br><span class="line">最后一行改为对应自己的端口</span><br><span class="line"><span class="comment"># socks5    127.0.0.1 9050</span></span><br><span class="line">socks5    127.0.0.1 10800</span><br></pre></td></tr></table></figure><h2 id="v2ray"><a href="#v2ray" class="headerlink" title="v2ray"></a>v2ray</h2><p><a href="https://github.com/v2fly/v2ray-core/releases/">v2ray下载地址安装包</a></p><p><a href="https://github.com/Sanzo00/files/blob/master/other/v2ray.json">config.json格式</a></p><p>脚本下载：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># auto install</span></span><br><span class="line">wget https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh</span><br><span class="line"><span class="built_in">sudo</span> bash install-release.sh </span><br><span class="line"><span class="comment"># sudo bash install-release.sh --local v2ray-linux-64.zip</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> vim /usr/local/etc/v2ray/config.json</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动服务</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> v2ray</span><br><span class="line"><span class="built_in">sudo</span> systemctl start v2ray</span><br></pre></td></tr></table></figure><p>安装包下载：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">unzip v2ray-linux-arm64-v8a.zip</span><br><span class="line"></span><br><span class="line"><span class="comment"># sudo vim /usr/lib/systemd/system/v2ray.service</span></span><br><span class="line">[Unit]</span><br><span class="line">Description=V2Ray Service</span><br><span class="line">Documentation=https://www.v2fly.org/</span><br><span class="line">After=network.target nss-lookup.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">User=nobody</span><br><span class="line">CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE</span><br><span class="line">AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE</span><br><span class="line">NoNewPrivileges=<span class="literal">true</span></span><br><span class="line">ExecStart=/home/ubuntu/software/v2ray/v2ray run -config /home/ubuntu/software/v2ray/config.json</span><br><span class="line">Restart=on-failure</span><br><span class="line">RestartPreventExitStatus=23</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动服务</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl daemon-reload</span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> v2ray</span><br><span class="line"><span class="built_in">sudo</span> systemctl start v2ray</span><br></pre></td></tr></table></figure><p>终端代理设置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> ALL_PROXY=<span class="string">&quot;socks5://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> all_proxy=<span class="string">&quot;socks5://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> http_proxy=<span class="string">&quot;http://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> https_proxy=<span class="string">&quot;http://127.0.0.1:7890&quot;</span></span><br></pre></td></tr></table></figure><h2 id="zsh"><a href="#zsh" class="headerlink" title="zsh"></a>zsh</h2><p><a href="https://sanzo.top/Linux/zsh/">https://sanzo.top/Linux/zsh/</a></p><h2 id="git"><a href="#git" class="headerlink" title="git"></a>git</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 设置账号信息</span></span><br><span class="line">git config --global user.email <span class="string">&quot;arrangeman@163.com&quot;</span></span><br><span class="line">git config --global user.name <span class="string">&quot;Sanzo00&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成公钥和私钥</span></span><br><span class="line">ssh-keygen -t rsa -C <span class="string">&quot;your_email@example.com&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 将公钥放到github中</span></span><br><span class="line">vim .ssh/id_rsa.pub </span><br></pre></td></tr></table></figure><h2 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install</span></span><br><span class="line">curl -fsSL get.docker.com -o get-docker.sh</span><br><span class="line"><span class="built_in">sudo</span> sh get-docker.sh --mirror Aliyun</span><br><span class="line"></span><br><span class="line"><span class="comment"># docker setup</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> docker</span><br><span class="line"><span class="built_in">sudo</span> systemctl start docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># add $USER to docker groups</span></span><br><span class="line"><span class="built_in">sudo</span> groupadd docker</span><br><span class="line"><span class="built_in">sudo</span> usermod -aG docker <span class="variable">$USER</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># test docker</span></span><br><span class="line">docker run --<span class="built_in">rm</span> hello-world</span><br></pre></td></tr></table></figure><blockquote><p>support ipv6</p></blockquote><p><a href="https://www.rectcircle.cn/posts/docker-ipv6/#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BD%91%E7%BB%9C%E6%94%AF%E6%8C%81-ipv6">https://www.rectcircle.cn/posts/docker-ipv6/#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BD%91%E7%BB%9C%E6%94%AF%E6%8C%81-ipv6</a></p><p><strong>方法1:</strong> </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># test ipv6 address</span></span><br><span class="line">docker <span class="built_in">exec</span> -it qbittorrent ifconfig</span><br><span class="line"></span><br><span class="line"><span class="comment"># ipv6 support</span></span><br><span class="line"><span class="built_in">sudo</span> vim /etc/docker/daemon.json</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;experimental&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="string">&quot;ip6tables&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="string">&quot;ipv6&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="string">&quot;fixed-cidr-v6&quot;</span>: <span class="string">&quot;2001:db8:1::/64&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># restart</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl reload docker &amp;&amp; <span class="built_in">sudo</span> systemctl restart docker</span><br></pre></td></tr></table></figure><p>方法2: </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># start ipv6 nat</span></span><br><span class="line">docker run -d --name ipv6nat --privileged --network host --restart always -v /var/run/docker.sock:/var/run/docker.sock:ro -v /lib/modules:/lib/modules:ro robbertkl/ipv6nat</span><br><span class="line"></span><br><span class="line"><span class="comment"># create ipv6 network</span></span><br><span class="line">docker network create my-net-ipv6 --ipv6 --subnet=<span class="string">&quot;fd00:1::1/80&quot;</span> --gateway=<span class="string">&quot;fd00:1::1&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># run docker image with --network my-net-ipv6</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="打印机"><a href="#打印机" class="headerlink" title="打印机"></a>打印机</h2><h3 id="docker安装"><a href="#docker安装" class="headerlink" title="docker安装"></a>docker安装</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># docker install</span></span><br><span class="line"><span class="comment"># https://yeasy.gitbook.io/docker_practice/install/raspberry-pi</span></span><br><span class="line">docker pull tigerj/cups-airprint</span><br><span class="line"></span><br><span class="line">docker run -d --restart=always --name=cups --net=host -v /var/run/dbus:/var/run/dbus --device /dev/bus -e CUPSADMIN=<span class="string">&quot;ubuntu&quot;</span> -e CUPSPASSWORD=<span class="string">&quot;ubuntu@print&quot;</span> tigerj/cups-airprint</span><br></pre></td></tr></table></figure><h3 id="手动安装"><a href="#手动安装" class="headerlink" title="手动安装"></a>手动安装</h3><blockquote><p>安装CUPS</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装CUPS</span></span><br><span class="line"><span class="built_in">sudo</span> proxychains apt install cups</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改配置文件</span></span><br><span class="line"><span class="built_in">sudo</span> vim /etc/cups/cupsd.conf</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/raspi-setup/print2.png"></p><p><img src="/blog/img/Blog/raspi-setup/print1.png"></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重启服务</span></span><br><span class="line"><span class="built_in">sudo</span> service cups restart</span><br></pre></td></tr></table></figure><blockquote><p>安装打印机驱动</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 下载安装打印机驱动</span></span><br><span class="line">wget -O foo2zjs.tar.gz http://foo2zjs.rkkda.com/foo2zjs.tar.gz</span><br><span class="line"></span><br><span class="line">tar -xzvf foo2zjs.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> foo2zjs</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装ghostscript依赖</span></span><br><span class="line"><span class="built_in">sudo</span> apt install ghostscript</span><br><span class="line"><span class="built_in">sudo</span> apt install dc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 编译</span></span><br><span class="line">make -j10</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装</span></span><br><span class="line"><span class="built_in">sudo</span> make install</span><br></pre></td></tr></table></figure><p>浏览器访问cups的配置页面<a href="http://192.168.31.240:631/">http://192.168.31.240:631</a>，添加对应的打印机。</p><p>记得要连接上打印机，而且要用root账号登录。</p><p><img src="/blog/img/Blog/raspi-setup/print6.png"></p><p><img src="/blog/img/Blog/raspi-setup/print7.png"></p><p><img src="/blog/img/Blog/raspi-setup/print8.png"></p><blockquote><p>Windows添加打印机</p></blockquote><p><img src="/blog/img/Blog/raspi-setup/print4.png"></p><p><a href="https://192.168.31.240:631/printers/HP_LaserJet_M1005">https://192.168.31.240:631/printers/HP_LaserJet_M1005</a></p><p><img src="/blog/img/Blog/raspi-setup/print5.png"></p><p>mac：<a href="https://support.apple.com/kb/DL1888?viewlocale=en_US&locale=en_US">https://support.apple.com/kb/DL1888?viewlocale=en_US&amp;locale=en_US</a></p><h2 id="挂载硬盘"><a href="#挂载硬盘" class="headerlink" title="挂载硬盘"></a>挂载硬盘</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看所用分区</span></span><br><span class="line"><span class="built_in">sudo</span> fdisk -l</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改配置文件</span></span><br><span class="line"><span class="built_in">sudo</span> vim /etc/fstab</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在末尾添加</span></span><br><span class="line">/dev/sda1 /home/pi/sanzo ntfs defaults 0 0</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建对应文件夹</span></span><br><span class="line"><span class="built_in">mkdir</span> /home/pi/sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重新挂载</span></span><br><span class="line"><span class="built_in">sudo</span> mount -a</span><br></pre></td></tr></table></figure><h2 id="Samba"><a href="#Samba" class="headerlink" title="Samba"></a>Samba</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装samba</span></span><br><span class="line"><span class="built_in">sudo</span> apt install samba samba-common</span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> vim /etc/samba/smb.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 需要账号的登录文件夹</span></span><br><span class="line">[share]</span><br><span class="line">comment = share</span><br><span class="line"><span class="comment"># 注意读写权限, 需要在对应位置创建文佳夹</span></span><br><span class="line">path = /home/pi/sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许游客访问</span></span><br><span class="line">public = no</span><br><span class="line"></span><br><span class="line"><span class="comment"># 可查看</span></span><br><span class="line">browseable = <span class="built_in">yes</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许登录的用户</span></span><br><span class="line">valid <span class="built_in">users</span> = root, pi</span><br><span class="line"></span><br><span class="line"><span class="comment"># 所用用户可写</span></span><br><span class="line"><span class="comment">#writable = yes</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许个别用户可写</span></span><br><span class="line">write list = root,pi</span><br><span class="line"><span class="comment"># 如果writable和write list同时存在，则以writable为准</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 不需要账号登录的文件夹</span></span><br><span class="line">[public]</span><br><span class="line">comment = public</span><br><span class="line"><span class="comment"># 注意读写权限, 需要在对应位置创建文佳夹</span></span><br><span class="line">path = /home/pi/sanzo/public</span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许游客访问</span></span><br><span class="line">public = <span class="built_in">yes</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 可查看</span></span><br><span class="line">browseable = <span class="built_in">yes</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 所用用户可写</span></span><br><span class="line">writable = <span class="built_in">yes</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许个别用户可写</span></span><br><span class="line"><span class="comment"># write list = test</span></span><br><span class="line"><span class="comment"># 如果writable和write list同时存在，则以writable为准</span></span><br></pre></td></tr></table></figure><p>配置用户和密码</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建密码文件</span></span><br><span class="line"><span class="comment">#sudo bash -c &quot;cat /etc/passwd |mksmbpasswd &gt; /etc/samba/smbpasswd&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动加密口令</span></span><br><span class="line"><span class="comment">#sudo vim /etc/samba/smb.conf</span></span><br><span class="line"><span class="comment">#encrypt passwords = yes</span></span><br><span class="line"><span class="comment">#smb passwd file = /etc/samba/smbpasswd</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改密码文件的权限</span></span><br><span class="line"><span class="comment">#sudo chmod 600 /etc/samba/smbpasswd</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 为用户设置samba口令</span></span><br><span class="line"><span class="built_in">sudo</span> smbpasswd -a pi</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启服务</span></span><br><span class="line"><span class="built_in">sudo</span> service smbd restart</span><br></pre></td></tr></table></figure><p>在我的电脑地址栏输入\192.168.31.240登录即可</p><p>清除windows下的net缓冲</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看</span></span><br><span class="line">net use</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除对应的缓冲</span></span><br><span class="line">net use \\192.168.31.240\share /d</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>若清除缓存后依然自动登录，则需要进入控制面板→用户账户→选择当前账户→管理你的凭据→Windows凭据→删除</p><h2 id="qBittorrent"><a href="#qBittorrent" class="headerlink" title="qBittorrent"></a>qBittorrent</h2><p><a href="https://hub.docker.com/r/linuxserver/qbittorrent">https://hub.docker.com/r/linuxserver/qbittorrent</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># download image</span></span><br><span class="line">docker pull linuxserver/qbittorrent:latest</span><br><span class="line"></span><br><span class="line"><span class="comment"># run image</span></span><br><span class="line">docker run -d \</span><br><span class="line">  --name=qbittorrent \</span><br><span class="line">  -e PUID=1000 \</span><br><span class="line">  -e PGID=1000 \</span><br><span class="line">  -e TZ=Etc/UTC \</span><br><span class="line">  -e WEBUI_PORT=18000 \</span><br><span class="line">  -p 18000:18000 \</span><br><span class="line">  -p 46881:46881 \</span><br><span class="line">  -p 46881:46881/udp \</span><br><span class="line">  -v /home/sanzo/disk/data/qbittorrent-config:/config \</span><br><span class="line">  -v /home/sanzo/disk/data/private/qbittorrent:/downloads \</span><br><span class="line">  --restart unless-stopped \</span><br><span class="line">  linuxserver/qbittorrent:latest</span><br></pre></td></tr></table></figure><p>在使用内网穿透访问局域网的qbittorrent服务时，需要取消勾选<code>设置</code>&#x3D;&gt;<code>Web UI</code>&#x3D;&gt;<code>启动Host header属性验证</code>。</p><h2 id="WebDAV"><a href="#WebDAV" class="headerlink" title="WebDAV"></a>WebDAV</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">docker pull bytemark/webdav</span><br><span class="line"></span><br><span class="line">docker run --restart always \</span><br><span class="line">-v local-dir:/var/lib/dav/data \ </span><br><span class="line">    -e AUTH_TYPE=Digest -e USERNAME=User -e PASSWORD=PASSWRD \</span><br><span class="line">    --publish port:80 --name webdav \</span><br><span class="line">    -e LOCATION=/webdav -d bytemark/webdav</span><br></pre></td></tr></table></figure><blockquote><p>中文乱码</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="built_in">exec</span> -it webdav /bin/bash</span><br><span class="line"></span><br><span class="line">vi conf/conf-enabled/dav.conf</span><br><span class="line"></span><br><span class="line">DavLockDB <span class="string">&quot;/var/lib/dav/DavLock&quot;</span></span><br><span class="line">Alias /webdav /var/lib/dav/data/</span><br><span class="line">&lt;Directory <span class="string">&quot;/var/lib/dav/data/&quot;</span>&gt;</span><br><span class="line">  Dav On</span><br><span class="line">  Options Indexes FollowSymLinks</span><br><span class="line">  <span class="comment">####### add this line (start)</span></span><br><span class="line">  IndexOptions Charset=utf-8</span><br><span class="line">  <span class="comment">##################### (end)</span></span><br><span class="line">  AuthType Digest</span><br><span class="line">  AuthName <span class="string">&quot;WebDAV&quot;</span></span><br><span class="line">  AuthUserFile <span class="string">&quot;/user.passwd&quot;</span></span><br></pre></td></tr></table></figure><blockquote><p>添加用户</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">htdigest /user.passwd <span class="string">&quot;WebDAV&quot;</span> user</span><br></pre></td></tr></table></figure><h2 id="frp内网穿透"><a href="#frp内网穿透" class="headerlink" title="frp内网穿透"></a>frp内网穿透</h2><h3 id="frps"><a href="#frps" class="headerlink" title="frps"></a>frps</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># configuration of frps</span></span><br><span class="line">vim /root/sanzo/frp/frps.toml</span><br><span class="line"></span><br><span class="line">[common]</span><br><span class="line">bind_port = 60000</span><br><span class="line">vhost_http_port = 60080</span><br><span class="line">vhost_https_port = 60443</span><br><span class="line">dashboard_addr = 0.0.0.0</span><br><span class="line">dashboard_port = 60001</span><br><span class="line">dashboard_user = YOUR_NAME</span><br><span class="line">dashboard_pwd = YOUR_PASSWD</span><br><span class="line">token = YOUR_TOKEN</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install image</span></span><br><span class="line">docker pull snowdreamtech/frps</span><br><span class="line"></span><br><span class="line"><span class="comment"># run image</span></span><br><span class="line">docker run --restart=always --net host -d -v /root/sanzo/frp/frps.toml:/etc/frp/frps.toml^C-name frps snowdreamtech/frps</span><br><span class="line"></span><br><span class="line"><span class="comment"># access frps vis this link</span></span><br><span class="line">YOUR_IP:60001</span><br></pre></td></tr></table></figure><h3 id="frpc"><a href="#frpc" class="headerlink" title="frpc"></a>frpc</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># configuration of frpc</span></span><br><span class="line">vim /home/sanzo/software/frpc/frpc.toml</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">[common]</span><br><span class="line">server_addr = SERVER_IP</span><br><span class="line">server_port = 60000</span><br><span class="line">token = SERVER_TOKEN</span><br><span class="line"></span><br><span class="line">http_proxy = http://127.0.0.1:7890</span><br><span class="line">https_proxy = https://127.0.0.1:7890</span><br><span class="line"></span><br><span class="line">[ssh]</span><br><span class="line"><span class="built_in">type</span> = tcp</span><br><span class="line">local_ip = 127.0.0.1</span><br><span class="line">local_port = 22</span><br><span class="line">remote_port = SERVER_PORT</span><br><span class="line"></span><br><span class="line">[qbt]</span><br><span class="line"><span class="built_in">type</span> = tcp</span><br><span class="line">local_ip = 127.0.0.1</span><br><span class="line">local_port = 18000</span><br><span class="line">remote_port = SERVER_PORT</span><br><span class="line"></span><br><span class="line">[pi-dashboard]</span><br><span class="line"><span class="built_in">type</span> = tcp</span><br><span class="line">local_ip = 127.0.0.1</span><br><span class="line">local_port = 80</span><br><span class="line">remote_port = SERVER_PORT</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install image</span></span><br><span class="line">docker pull snowdreamtech/frpc</span><br><span class="line"></span><br><span class="line"><span class="comment"># run image</span></span><br><span class="line">docker run --restart=always --network host -d -v /home/sanzo/software/frpc/frpc.toml:/etc/frp/frpc.toml --name frpc snowdreamtech/frpc</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Aria2"><a href="#Aria2" class="headerlink" title="Aria2"></a>Aria2</h2><p>海盗湾：<a href="https://thepiratebay.org/index.html">https://thepiratebay.org/index.html</a></p><p>1337X：<a href="https://1337x.to/">https://1337x.to/</a></p><p>LIMETORRENTS：<a href="https://www.limetorrents.pro/">https://www.limetorrents.pro/</a></p><p>TORLOCK：<a href="https://www.torlock.com/">https://www.torlock.com/</a></p><p>ZOOQLE：<a href="https://zooqle.com/">https://zooqle.com/</a></p><p>YTS：<a href="https://yts.mx/">https://yts.mx/</a></p><p>RARBG：<a href="https://rarbg.to/">https://rarbg.to/</a></p><blockquote><p>使用容器</p></blockquote><p><a href="https://hub.docker.com/r/p3terx/aria2-pro">https://hub.docker.com/r/p3terx/aria2-pro</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> aria2-pro &amp;&amp; <span class="built_in">cd</span> aria2-pro</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载配置文件</span></span><br><span class="line">wget git.io/aria2-pro.yml</span><br><span class="line"></span><br><span class="line"><span class="comment"># 运行</span></span><br><span class="line">docker-compose -f aria2-pro.yml up -d</span><br></pre></td></tr></table></figure><blockquote><p>手动安装</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt install -y aria2 </span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建文件夹和文件</span></span><br><span class="line"><span class="built_in">mkdir</span> .aria2</span><br><span class="line"><span class="built_in">touch</span> .aria2/aria2.session</span><br><span class="line">vim .aria2/aria2.config</span><br><span class="line"></span><br><span class="line"><span class="comment"># 测试运行 </span></span><br><span class="line">aria2c --conf-path=/home/pi/.aria2/aria2.config</span><br></pre></td></tr></table></figure><p>设置开机自启</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重新载入服务，并设置开机启动</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl daemon-reload</span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> aria</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看aria服务状态</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl status aria</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动，停止，重启aria服务</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl（start、stop、restart） aria</span><br></pre></td></tr></table></figure><p>AriaNg <a href="http://ariang.mayswind.net/latest">http://ariang.mayswind.net/latest</a></p><h2 id="仪表盘"><a href="#仪表盘" class="headerlink" title="仪表盘"></a>仪表盘</h2><h3 id="docker"><a href="#docker" class="headerlink" title="docker"></a>docker</h3><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">https://hub.docker.com/r/ecat/docker-pi-dashboard</span><br></pre></td></tr></table></figure><h3 id="手动安装-1"><a href="#手动安装-1" class="headerlink" title="手动安装"></a>手动安装</h3><blockquote><p>安装软件包</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get install nginx php7.3-fpm php7.3-cli php7.3-curl php7.3-gd php7.3-cgi</span><br></pre></td></tr></table></figure><blockquote><p>开启系统服务</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> service nginx restart</span><br><span class="line"><span class="built_in">sudo</span> service php7.3-fpm restart</span><br></pre></td></tr></table></figure><p>浏览器访问<code>http://树莓派ip</code></p><p><img src="/blog/img/Blog/raspi-setup/image-20201227233013606.png" alt="image-20201227233013606"></p><blockquote><p>修改配置文件</p></blockquote><p><code>sudo vim /etc/nginx/sites-available/default</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">location / &#123;</span><br><span class="line"><span class="comment"># First attempt to serve request as file, then</span></span><br><span class="line"><span class="comment"># as directory, then fall back to displaying a 404.</span></span><br><span class="line">try_files <span class="variable">$uri</span> <span class="variable">$uri</span>/ =404;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>替换为</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">location / &#123;</span><br><span class="line">index  index.html index.htm index.php default.html default.htm default.php;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line">location ~\.php$ &#123;</span><br><span class="line">fastcgi_pass unix:/run/php/php7.3-fpm.sock;</span><br><span class="line"><span class="comment"># fastcgi_pass 127.0.0.1:9000;</span></span><br><span class="line">fastcgi_param SCRIPT_FILENAME $document_root<span class="variable">$fastcgi_script_name</span>;</span><br><span class="line">include fastcgi_params;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/raspi-setup/image-20201227233506067.png" alt="image-20201227233506067"></p><p>重启服务<code>sudo service nginx restart</code></p><blockquote><p>部署项目</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> git <span class="built_in">clone</span> https://github.com/nxez/pi-dashboard.git /var/www/html/pi-dashboard</span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chown</span> -R www-data /var/www/html/pi-dashboard</span><br></pre></td></tr></table></figure><p>浏览器访问<code>http://树莓派ip/pi-dashboard</code></p><p><img src="/blog/img/Blog/raspi-setup/image-20201227234232789.png" alt="image-20201227234232789"></p><h2 id="VNC"><a href="#VNC" class="headerlink" title="VNC"></a>VNC</h2><blockquote><p>开启VNC服务</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> raspi-config</span><br></pre></td></tr></table></figure><p>选择Interface Options &#x3D;&gt; VNC，开启VNC服务。</p><blockquote><p>下载VNC客户端</p></blockquote><p>下载地址：<a href="https://www.realvnc.com/en/connect/download/viewer/">realvnc</a></p><blockquote><p>修改分辨率</p></blockquote><p>如果VNC不能正常访问，可以通过修改树莓派分辨率解决。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> raspi-config</span><br></pre></td></tr></table></figure><p>选择Display Options &#x3D;&gt; Resolution &#x3D;&gt; Mode4，接着重启机器即可。</p><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;树莓派新机配置&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="v2ray" scheme="https://sanzo.top/blog/tags/v2ray/"/>
    
    <category term="RaspberryPi" scheme="https://sanzo.top/blog/tags/RaspberryPi/"/>
    
    <category term="samba" scheme="https://sanzo.top/blog/tags/samba/"/>
    
  </entry>
  
  <entry>
    <title>ubuntu配置</title>
    <link href="https://sanzo.top/blog/Blog/ubuntu-setup/"/>
    <id>https://sanzo.top/blog/Blog/ubuntu-setup/</id>
    <published>2021-10-08T01:52:47.000Z</published>
    <updated>2021-10-08T01:52:47.000Z</updated>
    
    <content type="html"><![CDATA[<p>ubuntu常用设置.</p><span id="more"></span><h2 id="vim"><a href="#vim" class="headerlink" title="vim"></a>vim</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install vim</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加配置文件</span></span><br><span class="line">vim ~/.vimrc</span><br><span class="line"></span><br><span class="line">&quot;set paste</span><br><span class="line">&quot;set nopaste</span><br><span class="line">set expandtab</span><br><span class="line">set softtabstop=2</span><br><span class="line">set autoindent</span><br><span class="line">set tabstop=2</span><br><span class="line">set shiftwidth=2</span><br><span class="line">set nu</span><br><span class="line">syntax on</span><br><span class="line">set mouse=a &quot;支持鼠标滑轮</span><br><span class="line">set mouse=v &quot;支持鼠标选中复制</span><br><span class="line">&quot;set viminfo=&#x27;1000,&lt;500</span><br></pre></td></tr></table></figure><h2 id="用户"><a href="#用户" class="headerlink" title="用户"></a>用户</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建用户sanzo，指定home目录和登陆的shell</span></span><br><span class="line">useradd -d /home/sanzo -s /bin/bash -m sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置登录密码</span></span><br><span class="line">passwd sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加sudo组</span></span><br><span class="line">usermod -a -G <span class="built_in">sudo</span> sanzo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除用户</span></span><br><span class="line"><span class="built_in">sudo</span> userdel -r <span class="built_in">test</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># append ssh key to remote host</span></span><br><span class="line"><span class="built_in">cat</span> .ssh/id_ras.pub | ssh user@hostname <span class="string">&quot;cat &gt;&gt; ~/.ssh/authorized_keys&quot;</span></span><br></pre></td></tr></table></figure><h2 id="代理"><a href="#代理" class="headerlink" title="代理"></a>代理</h2><blockquote><p>配置v2ray</p></blockquote><p><a href="https://github.com/v2fly/v2ray-core/releases">v2ray-core&#x2F;releases</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mkdir v2ray &amp;&amp; cd v2ray</span><br><span class="line">wget https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh</span><br><span class="line">sudo bash install-release.sh --local ./v2ray-linux-64.zip</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">local</span> user run</span></span><br><span class="line">nohup ./v2ray run config.json &gt; v2ray.log 2&gt;&amp;1 &amp;</span><br></pre></td></tr></table></figure><p><a href="https://github.com/Sanzo00/files/blob/master/other/v2ray.json">v2ray config.json配置</a></p><p><img src="/blog/img/Blog/linux/image-20211008182055367.png" alt="image-20211008182055367"></p><blockquote><p>proxychains</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install proxychains</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改配置文件</span></span><br><span class="line">sudo vim /etc/proxychains.conf </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">最后一行改为对应自己的端口</span></span><br><span class="line">socks5    127.0.0.1 10800</span><br></pre></td></tr></table></figure><blockquote><p>apt代理</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo vim /etc/apt/apt.conf.d/proxy.conf</span><br><span class="line">Acquire::http::Proxy &quot;socks5h://127.0.0.1:10800&quot;;</span><br><span class="line">Acquire::https::Proxy &quot;socks5h://127.0.0.1:10800&quot;;</span><br></pre></td></tr></table></figure><blockquote><p>bash代理</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">vim ~/.bashrc</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">vim ~/.zshrc</span></span><br><span class="line"></span><br><span class="line">export ALL_PROXY=&quot;socks5://127.0.0.1:10800&quot;</span><br><span class="line">export all_proxy=&quot;socks5://127.0.0.1:10800&quot;</span><br><span class="line">export http_proxy=&quot;http://127.0.0.1:10801&quot;</span><br><span class="line">export https_proxy=&quot;https://127.0.0.1:10801&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">export</span> https_proxy=<span class="string">&quot;http://127.0.0.1:10801&quot;</span> <span class="comment"># for conda http error</span></span></span><br></pre></td></tr></table></figure><p>在setting中设置了http，apt和bash应该可以不用再设置了，以防万一可以加上。</p><h2 id="git"><a href="#git" class="headerlink" title="git"></a>git</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install git</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">环境配置</span></span><br><span class="line">git config --global user.email &quot;arrangeman@163.com&quot;</span><br><span class="line">git config --global user.name &quot;Sanzo00&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成公钥和私钥</span></span><br><span class="line">ssh-keygen -t rsa -C &quot;your_email@example.com&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">将公钥放到github中</span></span><br><span class="line">cat ~/.ssh/id_rsa.pub </span><br></pre></td></tr></table></figure><blockquote><p>代理</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># http and https</span></span><br><span class="line">git config --global http.proxy http://127.0.0.1:10801</span><br><span class="line">git config --global https.proxy https://127.0.0.1:10801</span><br><span class="line"><span class="comment"># socks5</span></span><br><span class="line">git config --global http.proxy socks5://127.0.0.1:10800</span><br><span class="line">git config --global https.proxy socks5://127.0.0.1:10800</span><br><span class="line"></span><br><span class="line"><span class="comment"># unset</span></span><br><span class="line">git config --global --<span class="built_in">unset</span> http.proxy</span><br><span class="line">git config --global --<span class="built_in">unset</span> https.proxy</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ssh</span></span><br><span class="line"><span class="built_in">sudo</span> apt install connect-proxy</span><br><span class="line">vim ~/.ssh/config</span><br><span class="line"><span class="comment"># socks5</span></span><br><span class="line">Host github.com</span><br><span class="line">User git</span><br><span class="line">ProxyCommand connect -S 127.0.0.1:10800 %h %p</span><br><span class="line"><span class="comment"># http || https</span></span><br><span class="line">Host github.com</span><br><span class="line">User git</span><br><span class="line">ProxyCommand connect -H 127.0.0.1:10801 %h %p</span><br></pre></td></tr></table></figure><h2 id="zsh"><a href="#zsh" class="headerlink" title="zsh"></a>zsh</h2><p><a href="https://sanzo.top/Linux/zsh/">https://sanzo.top/Linux/zsh/</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装zsh</span></span><br><span class="line"><span class="built_in">sudo</span> apt install zsh</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装ohmyzsh</span></span><br><span class="line">sh -c <span class="string">&quot;<span class="subst">$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 切换shell为zsh</span></span><br><span class="line">chsh -s /bin/zsh</span><br></pre></td></tr></table></figure><blockquote><p>插件</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 自动补全</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/zsh-users/zsh-autosuggestions.git <span class="variable">$ZSH_CUSTOM</span>/plugins/zsh-autosuggestions</span><br><span class="line"></span><br><span class="line"><span class="comment"># 高亮</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/zsh-users/zsh-syntax-highlighting.git <span class="variable">$ZSH_CUSTOM</span>/plugins/zsh-syntax-highlighting</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改配置文件</span></span><br><span class="line">vim ~/.zshrc</span><br><span class="line">plugins=(</span><br><span class="line">  git</span><br><span class="line">  zsh-autosuggestions</span><br><span class="line">  zsh-syntax-highlighting</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重置zsh环境</span></span><br><span class="line"><span class="built_in">source</span> ~/.zshrc</span><br></pre></td></tr></table></figure><h2 id="鼠标"><a href="#鼠标" class="headerlink" title="鼠标"></a>鼠标</h2><blockquote><p>修改滑轮速度</p></blockquote><p><a href="https://wiki.archlinux.org/title/IMWheel#Run_IMWheel_on_startup_using_a_service">IMWheel</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install imwheel</span><br><span class="line">sudo vim ~/.imwheelrc</span><br><span class="line"></span><br><span class="line">&quot;.*&quot;</span><br><span class="line">None,      Up,   Button4, 5 # 速度</span><br><span class="line">None,      Down, Button5, 5 # 速度</span><br><span class="line">Control_L, Up,   Control_L|Button4</span><br><span class="line">Control_L, Down, Control_L|Button5</span><br><span class="line">Shift_L,   Up,   Shift_L|Button4</span><br><span class="line">Shift_L,   Down, Shift_L|Button5</span><br></pre></td></tr></table></figure><blockquote><p>开机自启</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">sudo ~/.config/systemd/user</span><br><span class="line">vim ~/.config/systemd/user/imwheel.service</span><br><span class="line"></span><br><span class="line">[Unit]</span><br><span class="line">Description=IMWheel</span><br><span class="line">Wants=display-manager.service</span><br><span class="line">After=display-manager.service</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=simple</span><br><span class="line">Environment=XAUTHORITY=%h/.Xauthority</span><br><span class="line">ExecStart=/usr/bin/imwheel -d</span><br><span class="line">ExecStop=/usr/bin/pkill imwheel</span><br><span class="line">RemainAfterExit=yes</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=graphical-session.target</span><br><span class="line"></span><br><span class="line">systemctl --user daemon-reload</span><br><span class="line">systemctl --user enable --now imwheel.service</span><br><span class="line">journalctl --user --unit imwheel.service</span><br></pre></td></tr></table></figure><h2 id="网速监控"><a href="#网速监控" class="headerlink" title="网速监控"></a>网速监控</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor -y</span><br><span class="line">sudo apt update</span><br><span class="line">sudo apt-get install indicator-sysmonitor</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行</span></span><br><span class="line">indicator-sysmonitor</span><br><span class="line"></span><br><span class="line">cpu: (&#123;cpu&#125; &#123;cputemp&#125;) gpu: (&#123;nvgputemp&#125;) mem: (&#123;mem&#125;) net: &#123;net&#125; &#123;totalnet&#125;</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/linux/image-20211008210121275.png" alt="image-20211008210121275"></p><p><img src="/blog/img/Blog/linux/image-20211008205948437.png" alt="image-20211008205948437"></p><h2 id="截图"><a href="#截图" class="headerlink" title="截图"></a>截图</h2><p>我在windows上用的<a href="https://www.snipaste.com/">snipaste</a>，不过linux还没出，有两个方案可以代替：</p><p>1、系统默认的截图工具</p><ul><li><code>PrtSc</code> – 获取整个屏幕的截图并保存到 Pictures 目录。</li><li><code>Shift + PrtSc</code> – 获取屏幕的某个区域截图并保存到 Pictures 目录。</li><li><code>Alt + PrtSc</code> –获取当前窗口的截图并保存到 Pictures 目录。</li><li><code>Ctrl + PrtSc</code> – 获取整个屏幕的截图并存放到剪贴板。</li><li><code>Shift + Ctrl + PrtSc</code> – 获取屏幕的某个区域截图并存放到剪贴板。</li><li><code>Ctrl + Alt + PrtSc</code> – 获取当前窗口的 截图并存放到剪贴板。</li></ul><p>2、<a href="https://github.com/flameshot-org/flameshot">flameshot</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">install</span></span><br><span class="line">apt install flameshot</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">start</span></span><br><span class="line">flameshot gui</span><br></pre></td></tr></table></figure><h2 id="显卡"><a href="#显卡" class="headerlink" title="显卡"></a>显卡</h2><p><a href="https://developer.nvidia.com/zh-cn/cuda-gpus#compute">显卡算力</a></p><p><a href="https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html">cuda对应的最低驱动版本</a></p><p><a href="https://www.mlzhilu.com/archives/ubuntu2004%E5%AE%89%E8%A3%85nvidia%E6%98%BE%E5%8D%A1%E9%A9%B1%E5%8A%A8">Ubuntu20.04安装NVIDIA显卡驱动+cuda+cudnn配置深度学习环境</a></p><blockquote><p>驱动安装</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看显卡型号</span></span><br><span class="line">lspci | grep -i nvidia</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/linux/image-20211008193000787.png" alt="image-20211008193000787"></p><p><a href="https://www.nvidia.com/Download/index.aspx?lang=en-us">下载驱动</a></p><p><img src="/blog/img/Blog/linux/image-20211008193044041.png" alt="image-20211008193044041"></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install -y lightdm gcc make</span><br><span class="line">sudo passwd root</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">切换桌面，选择lightdm</span></span><br><span class="line">sudo dpkg-reconfigure gdm3</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">关闭lightdm桌面</span></span><br><span class="line">systemctl stop lightdm</span><br><span class="line"></span><br><span class="line">sudo chmod a+x NVIDIA-Linux-x86_64-450.80.02.run</span><br><span class="line">sudo ./NVIDIA-Linux-x86_64-450.80.02.run -no-x-check -no-nouveau-check -no-opengl-files --no-kernel-module</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-no-x-check:安装时关闭X服务</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-no-nouveau-check: 安装时禁用nouveau</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-no-opengl-files:只安装驱动文件，不安装OpenGL文件</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">后面出来的提示，选择默认选项</span></span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试是否成功</span></span><br><span class="line">nvidia-smi</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/linux/image-20211008204151165.png" alt="image-20211008204151165"></p><p>如果出现<code>/dev/xxx: clean</code>的问题，进不了桌面，可能是因为驱动不匹配的问题。可以删除<code>/etc/X11/xorg.conf</code>。</p><p>如果出现<code>An NVIDIA kernel module &#39;nvidia-drm&#39; appears to already be loaded in your kernel. This may be because it is in use (for example, by an X server, a CUDA program, or the NVIDIA Persistence Daemon), but this may also happen if your kernel was configured without support for module unloading.</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># https://unix.stackexchange.com/questions/440840/how-to-unload-kernel-module-nvidia-drm</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> systemctl isolate multi-user.target</span><br><span class="line">modprobe -r nvidia-drm</span><br><span class="line"></span><br><span class="line"><span class="comment"># reinstall you nvidia driver</span></span><br><span class="line"><span class="comment"># then</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl start graphical.target</span><br></pre></td></tr></table></figure><blockquote><p>安装cuda</p></blockquote><p><a href="https://developer.nvidia.com/cuda-toolkit-archive">下载cuda</a>，这里我选择的是cuda 11.2。</p><p><img src="/blog/img/Blog/linux/image-20211008204125042.png" alt="image-20211008204125042"></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wget https://developer.download.nvidia.com/compute/cuda/11.2.0/local_installers/cuda_11.2.0_460.27.04_linux.run</span><br><span class="line"><span class="built_in">sudo</span> sh cuda_11.2.0_460.27.04_linux.run</span><br></pre></td></tr></table></figure><p>回车取消勾选<code>Driver</code>，因为前面已经装过驱动，然后install，也可以在Options中自定义安装位置。</p><p><img src="/blog/img/Blog/linux/image-20211008204241869.png" alt="image-20211008204241869"></p><p>在.bashrc文件中配置环境变量</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">export PATH=/usr/local/cuda-11.2/bin:$&#123;PATH&#125;</span><br><span class="line">export LD_LIBRARY_PATH=/usr/local/cuda-11.2/lib64:$&#123;LD_LIBRARY_PATH&#125;</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">source ～/.bashrc</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试cuda</span></span><br><span class="line">nvcc -V</span><br></pre></td></tr></table></figure><p><img src="/blog/img/Blog/linux/image-20211008204439775.png" alt="image-20211008204439775"></p><blockquote><p>安装cudnn</p></blockquote><p><a href="https://developer.nvidia.com/rdp/cudnn-download">下载cudnn</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">将文件复制到cuda对应的文件夹下</span></span><br><span class="line">sudo cp cuda/include/cudnn.h /usr/local/cuda/include/</span><br><span class="line">sudo cp cuda/include/cudnn_version.h /usr/local/cuda/include/ # for cudnn v8+</span><br><span class="line">sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64/</span><br></pre></td></tr></table></figure><blockquote><p>测试</p></blockquote><p>在<code>~/NVIDIA_CUDA-11.2_Samples</code>下编译代码，然后运行cuda提供的例子。</p><p><img src="/blog/img/Blog/linux/image-20211008204814707.png" alt="image-20211008204814707"></p><p><img src="/blog/img/Blog/linux/image-20211008204917470.png" alt="image-20211008204917470"></p><blockquote><p>踩坑</p></blockquote><ol><li><p>apt 更新软件包之后，导致显卡驱动失效，这是因为内核版本发生了变化，将内核回退到上一个版本即可。</p><p><a href="https://www.jianshu.com/p/5ac8aa703075">https://www.jianshu.com/p/5ac8aa703075</a></p></li></ol><h2 id="显示器"><a href="#显示器" class="headerlink" title="显示器"></a>显示器</h2><p>适用于多个显示器。</p><p>我这里有两块屏幕<code>HDMI-1</code>，<code>HDMI-1-0</code>。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看当前显示器信息</span></span><br><span class="line">xrandr</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置HDMI-1为主屏幕</span></span><br><span class="line">xrandr --output HDMI-1 --primary</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">只显示一个屏幕，关闭HDMI-1-0屏幕</span></span><br><span class="line">xrandr --output HDMI-1 --auto --output HDMI-1-0 --off</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">复制屏幕</span></span><br><span class="line">xrandr --output HDMI-1-0 --same-as HDMI-1 --auto</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置HDMI-1-0为左扩展屏</span></span><br><span class="line">xrandr --output HDMI-1-0 --left-of HDMI-1 --auto</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置HDMI-1-0右扩展屏</span></span><br><span class="line">xrandr --output HDMI-1-0 --right-of HDMI-1 --auto</span><br></pre></td></tr></table></figure><blockquote><p>开机自启</p></blockquote><p>还没找到合适的开机自启命令，不过可以在系统设置中调。</p><h2 id="VSCode"><a href="#VSCode" class="headerlink" title="VSCode"></a>VSCode</h2><p><a href="https://code.visualstudio.com/">vscode</a></p><blockquote><p>server端网络不好，“Downloading VS Code Server”</p></blockquote><p>进入<code>~/.vscode-server/bin/</code>查看vscode server的commit id，然后手动下载上传到服务器。</p><p>下载链接：<code>https://update.code.visualstudio.com/commit:$&#123;commit_id&#125;/server-linux-x64/stable</code></p><p>解压之后重命名为commit id，然后放到<code>~/.vscode-server/bin/</code></p><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><p><a href="https://typora.io/#linux">typora</a></p><p><a href="https://sanzo.top/Default/python-env/?highlight=python">python环境</a></p><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;ubuntu常用设置.&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="linux" scheme="https://sanzo.top/blog/tags/linux/"/>
    
    <category term="setup" scheme="https://sanzo.top/blog/tags/setup/"/>
    
    <category term="ubuntu" scheme="https://sanzo.top/blog/tags/ubuntu/"/>
    
  </entry>
  
  <entry>
    <title>yabai: macOS的窗口管理</title>
    <link href="https://sanzo.top/blog/Blog/yabai/"/>
    <id>https://sanzo.top/blog/Blog/yabai/</id>
    <published>2024-07-14T07:25:56.000Z</published>
    <updated>2024-07-14T07:25:56.000Z</updated>
    
    <content type="html"><![CDATA[<p>自动分屏</p><span id="more"></span><p>cite: <a href="https://www.josean.com/posts/yabai-setup">How To Setup And Use The Yabai Tiling Window Manager On Mac</a></p><h2 id="setup"><a href="#setup" class="headerlink" title="setup"></a>setup</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install yabai</span></span><br><span class="line">brew install koekeishiya/formulae/yabai</span><br><span class="line">yabai --start-service</span><br><span class="line">yabai --restart-service</span><br><span class="line"></span><br><span class="line"><span class="comment"># install skhd</span></span><br><span class="line">brew install koekeishiya/formulae/skhd</span><br><span class="line">skhd --start-service</span><br><span class="line">skhd --restart-service</span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> ~/.config/yabai</span><br><span class="line"><span class="built_in">cd</span> ~/.config/yabai</span><br><span class="line">wget https://raw.githubusercontent.com/Sanzo00/config/main/yabai/yabairc</span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> ~/.config/skhd</span><br><span class="line"><span class="built_in">cd</span> ~/.config</span><br><span class="line">wget https://raw.githubusercontent.com/Sanzo00/config/main/skhd/skhdrc</span><br></pre></td></tr></table></figure><h2 id="command"><a href="#command" class="headerlink" title="command"></a>command</h2><table><thead><tr><th>Function</th><th>Shortcuts</th></tr></thead><tbody><tr><td>Focus within space</td><td>Alt + (H, J, K, L)</td></tr><tr><td>Focus between display</td><td>Alt + (W, E)</td></tr><tr><td>Toggle window float</td><td>Shift + Alt + F</td></tr><tr><td>Maximize window</td><td>Alt + M</td></tr><tr><td>Balance  layout</td><td>Alt + B</td></tr><tr><td>Swap window</td><td>Shift  + Alt + (H, J, K, L)</td></tr><tr><td></td><td></td></tr></tbody></table>]]></content>
    
    
    <summary type="html">&lt;p&gt;自动分屏&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>zsh安装与配置</title>
    <link href="https://sanzo.top/blog/Blog/zsh/"/>
    <id>https://sanzo.top/blog/Blog/zsh/</id>
    <published>2021-10-01T15:11:13.000Z</published>
    <updated>2021-10-01T15:11:13.000Z</updated>
    
    <content type="html"><![CDATA[<p>zsh终端配置。</p><span id="more"></span><hr><h2 id="下载安装"><a href="#下载安装" class="headerlink" title="下载安装"></a>下载安装</h2><p><a href="https://github.com/ohmyzsh/ohmyzsh">ohmyzsh</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装zsh</span></span><br><span class="line">sudo apt install zsh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装ohmyzsh</span></span><br><span class="line">sh -c &quot;$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)&quot;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">切换shell为zsh</span></span><br><span class="line">chsh -s /bin/zsh</span><br></pre></td></tr></table></figure><p>离线安装：</p><p><a href="https://www.jianshu.com/p/c65f145772c2">https://www.jianshu.com/p/c65f145772c2</a></p><p><a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH">https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install zsh</span></span><br><span class="line">https://sourceforge.net/projects/zsh/files/latest/download</span><br><span class="line"></span><br><span class="line">xz -d zsh.tar.xz</span><br><span class="line">tar -xf zsh.tar </span><br></pre></td></tr></table></figure><h2 id="按键映射"><a href="#按键映射" class="headerlink" title="按键映射"></a>按键映射</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">编辑.zshrc文件，添加如下配置</span></span><br><span class="line">vim .zshrc</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">Rebind HOME and END to <span class="keyword">do</span> the decent thing:</span></span><br><span class="line">bindkey &#x27;\e[1~&#x27; beginning-of-line</span><br><span class="line">bindkey &#x27;\e[4~&#x27; end-of-line</span><br><span class="line">case $TERM in (xterm*)</span><br><span class="line">bindkey &#x27;\eOH&#x27; beginning-of-line</span><br><span class="line">bindkey &#x27;\eOF&#x27; end-of-line</span><br><span class="line">esac</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">To discover what keycode is being sent, hit ^v</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">and <span class="keyword">then</span> the key you want to <span class="built_in">test</span>.</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">And DEL too, as well as PGDN and insert:</span></span><br><span class="line">bindkey &#x27;\e[3~&#x27; delete-char</span><br><span class="line">bindkey &#x27;\e[6~&#x27; end-of-history</span><br><span class="line">bindkey &#x27;\e[2~&#x27; redisplay</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">Now <span class="built_in">bind</span> pgup to <span class="built_in">paste</span> the last word of the last <span class="built_in">command</span>,</span></span><br><span class="line">bindkey &#x27;\e[5~&#x27; insert-last-word</span><br></pre></td></tr></table></figure><h2 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">自动补全</span></span><br><span class="line">git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestions</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">高亮</span></span><br><span class="line">git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlighting</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改配置文件</span></span><br><span class="line">vim ~/.zshrc</span><br><span class="line">plugins=(</span><br><span class="line">  git</span><br><span class="line">  zsh-autosuggestions</span><br><span class="line">  zsh-syntax-highlighting</span><br><span class="line">)</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置zsh环境</span></span><br><span class="line">source ~/.zshrc</span><br></pre></td></tr></table></figure><h2 id="代理"><a href="#代理" class="headerlink" title="代理"></a>代理</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 打开配置文件</span></span><br><span class="line">vim ~/.zshrc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在最后一行添加</span></span><br><span class="line"><span class="built_in">export</span> ALL_PROXY=<span class="string">&quot;socks5://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> all_proxy=<span class="string">&quot;socks5://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> http_proxy=<span class="string">&quot;http://127.0.0.1:7890&quot;</span></span><br><span class="line"><span class="built_in">export</span> https_proxy=<span class="string">&quot;https://127.0.0.1:7890&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#重新加载配置文件</span></span><br><span class="line"><span class="built_in">source</span> ~/.zshrc</span><br></pre></td></tr></table></figure><!-- Q.E.D. -->]]></content>
    
    
    <summary type="html">&lt;p&gt;zsh终端配置。&lt;/p&gt;</summary>
    
    
    
    <category term="Blog" scheme="https://sanzo.top/blog/categories/Blog/"/>
    
    
    <category term="linux" scheme="https://sanzo.top/blog/tags/linux/"/>
    
    <category term="zsh" scheme="https://sanzo.top/blog/tags/zsh/"/>
    
  </entry>
  
</feed>
