<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>WillFeng&#39;s Blog</title>
  
  
  <link href="http://example.com/atom.xml" rel="self"/>
  
  <link href="http://example.com/"/>
  <updated>2021-04-26T12:59:13.344Z</updated>
  <id>http://example.com/</id>
  
  <author>
    <name>WillFeng</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Swagger使用</title>
    <link href="http://example.com/2021/04/26/Swagger%E4%BD%BF%E7%94%A8/"/>
    <id>http://example.com/2021/04/26/Swagger%E4%BD%BF%E7%94%A8/</id>
    <published>2021-04-26T11:41:03.000Z</published>
    <updated>2021-04-26T12:59:13.344Z</updated>
    
    <content type="html"><![CDATA[<h1 id="swagger"><a href="#swagger" class="headerlink" title="swagger"></a>swagger</h1><p>相信无论是前端还是后端开发，都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力，经常来不及更新。其实无论是前端调用后端，还是后端调用后端，都期望有一个好的接口文档。但是这个接口文档对于程序员来说，就跟注释一样，经常会抱怨别人写的代码没有写注释，然而自己写起代码起来，最讨厌的，也是写注释。所以仅仅只通过强制来规范大家是不够的，随着时间推移，版本迭代，接口文档往往很容易就跟不上代码了。</p><a id="more"></a><h2 id="导入相关依赖"><a href="#导入相关依赖" class="headerlink" title="导入相关依赖"></a>导入相关依赖</h2><figure class="highlight xml"><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">&lt;!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger2<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">       <span class="comment">&lt;!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger-ui<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="编写hello-controller"><a href="#编写hello-controller" class="headerlink" title="编写hello controller"></a>编写hello controller</h2><figure class="highlight java"><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="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HelloController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/hello&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">hello</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;hello,swagger&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="swagger配置类"><a href="#swagger配置类" class="headerlink" title="swagger配置类"></a>swagger配置类</h2><figure class="highlight java"><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"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@EnableSwagger2</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SwaggerConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Docket <span class="title">docket</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Docket(DocumentationType.SWAGGER_2).</span><br><span class="line">                apiInfo(apiInfo());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> ApiInfo <span class="title">apiInfo</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//作者</span></span><br><span class="line">        Contact contact = <span class="keyword">new</span> Contact(<span class="string">&quot;dwf&quot;</span>,<span class="string">&quot;https://dwf0920.github.io/&quot;</span>,<span class="string">&quot;dwf@0920@163.com&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> ApiInfo(</span><br><span class="line">                <span class="string">&quot;dwf的SwaggerAPI文档&quot;</span>,</span><br><span class="line">                <span class="string">&quot;心怀浪漫宇宙，也珍惜人间日常&quot;</span>,</span><br><span class="line">                <span class="string">&quot;1.0&quot;</span>,</span><br><span class="line">                <span class="string">&quot;urn:tos&quot;</span>,</span><br><span class="line">                contact,</span><br><span class="line">                <span class="string">&quot;Apache 2.0&quot;</span>,</span><br><span class="line">                <span class="string">&quot;http://www.apache.org/licenses/LICENSE-2.0&quot;</span>,</span><br><span class="line">                <span class="keyword">new</span> ArrayList());</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>启动项目，访问测试 <a href="http://localhost:8080/swagger-ui.html">http://localhost:8080/swagger-ui.html</a>  看下效果</p><p><img src="/2021/04/26/Swagger%E4%BD%BF%E7%94%A8/figure_1.png" alt></p><h2 id="swagger配置扫描接口"><a href="#swagger配置扫描接口" class="headerlink" title="swagger配置扫描接口"></a>swagger配置扫描接口</h2><figure class="highlight java"><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="meta">@Bean</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> Docket <span class="title">docket</span><span class="params">()</span></span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="keyword">new</span> Docket(DocumentationType.SWAGGER_2).</span><br><span class="line">               apiInfo(apiInfo()).</span><br><span class="line">               select().<span class="comment">// 通过.select()方法，去配置扫描接口,RequestHandlerSelectors配置如何扫描接口</span></span><br><span class="line">               <span class="comment">//any()  任何请求都扫描</span></span><br><span class="line">               <span class="comment">//none() 任何请求都不扫描</span></span><br><span class="line">               <span class="comment">//withClassAnnotation() 根据类上的注解扫描</span></span><br><span class="line">               <span class="comment">//withMethodAnnotation() 根据方法上的注解扫描</span></span><br><span class="line">               apis(RequestHandlerSelectors.basePackage(<span class="string">&quot;com.dwf.controller&quot;</span>)).</span><br><span class="line">               build();</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure><h2 id="配置API文档分组"><a href="#配置API文档分组" class="headerlink" title="配置API文档分组"></a>配置API文档分组</h2><p>配置多个组只需要配置多个Docket即可</p><figure class="highlight java"><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><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Docket <span class="title">docket1</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Docket(DocumentationType.SWAGGER_2).groupName(<span class="string">&quot;group1&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Docket <span class="title">docket2</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Docket(DocumentationType.SWAGGER_2).groupName(<span class="string">&quot;group2&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Docket <span class="title">docket3</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Docket(DocumentationType.SWAGGER_2).groupName(<span class="string">&quot;group3&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>重启项目查看</p><p><img src="/2021/04/26/Swagger%E4%BD%BF%E7%94%A8/figure_2.png" alt></p><h2 id="实体配置"><a href="#实体配置" class="headerlink" title="实体配置"></a>实体配置</h2><p>新建一个实体类</p><figure class="highlight java"><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="meta">@ApiModel(&quot;用户实体类&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">User</span> </span>&#123;</span><br><span class="line">    <span class="meta">@ApiModelProperty(&quot;用户名&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String name;</span><br><span class="line">    <span class="meta">@ApiModelProperty(&quot;密码&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String password;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编写请求接口</p><figure class="highlight java"><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">@PostMapping(&quot;/user&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> User <span class="title">user</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> User(); <span class="comment">//只要这个实体在请求接口的返回值上（即使是泛型），都能映射到实体项中：</span></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>重启项目查看效果</p><p><img src="/2021/04/26/Swagger%E4%BD%BF%E7%94%A8/figure_3.png" alt></p><p><em>注：并不是因为@ApiModel这个注解让实体显示在这里了，而是只要出现在接口方法的返回值上的实体都会显示在这里，而@ApiModel和@ApiModelProperty这两个注解只是为实体添加注释的。</em></p><p>@ApiModel为类添加注释</p><p>@ApiModelProperty为类属性添加注释</p><h2 id="常用注解"><a href="#常用注解" class="headerlink" title="常用注解"></a>常用注解</h2><div class="table-container"><table><thead><tr><th style="text-align:left">Swagger注解</th><th><strong>简单说明</strong></th></tr></thead><tbody><tr><td style="text-align:left">@Api(tags = “xxx模块说明”)</td><td>作用在模块类上</td></tr><tr><td style="text-align:left">@ApiOperation(“xxx接口说明”)</td><td>作用在接口方法上</td></tr><tr><td style="text-align:left">@ApiModel(“xxxPOJO说明”)</td><td>作用在模型类上：如VO、BO</td></tr><tr><td style="text-align:left">@ApiModelProperty(value = “xxx属性说明”,hidden = true)</td><td>作用在类方法和属性上，hidden设置为true可以隐藏该属性</td></tr><tr><td style="text-align:left">@ApiParam(“xxx参数说明”)</td><td>作用在参数、方法和字段上，类似@ApiModelProperty</td></tr></tbody></table></div><figure class="highlight java"><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">@ApiOperation(&quot;定义的接口hello2&quot;)</span></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/hello2&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">hello2</span><span class="params">(<span class="meta">@ApiParam(&quot;这个名字会被返回&quot;)</span>String username)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;hello&quot;</span>+username;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p><img src="/2021/04/26/Swagger%E4%BD%BF%E7%94%A8/figure_4.png" alt></p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;swagger&quot;&gt;&lt;a href=&quot;#swagger&quot; class=&quot;headerlink&quot; title=&quot;swagger&quot;&gt;&lt;/a&gt;swagger&lt;/h1&gt;&lt;p&gt;相信无论是前端还是后端开发，都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力，经常来不及更新。其实无论是前端调用后端，还是后端调用后端，都期望有一个好的接口文档。但是这个接口文档对于程序员来说，就跟注释一样，经常会抱怨别人写的代码没有写注释，然而自己写起代码起来，最讨厌的，也是写注释。所以仅仅只通过强制来规范大家是不够的，随着时间推移，版本迭代，接口文档往往很容易就跟不上代码了。&lt;/p&gt;</summary>
    
    
    
    <category term="java" scheme="http://example.com/categories/java/"/>
    
    
    <category term="java" scheme="http://example.com/tags/java/"/>
    
    <category term="springboot" scheme="http://example.com/tags/springboot/"/>
    
    <category term="swagger" scheme="http://example.com/tags/swagger/"/>
    
  </entry>
  
  <entry>
    <title>shiro整合springboot实现登录认证</title>
    <link href="http://example.com/2021/04/26/shiro%E6%95%B4%E5%90%88springboot%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/"/>
    <id>http://example.com/2021/04/26/shiro%E6%95%B4%E5%90%88springboot%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/</id>
    <published>2021-04-26T08:10:58.000Z</published>
    <updated>2021-04-26T13:04:34.431Z</updated>
    
    <content type="html"><![CDATA[<h1 id="shiro"><a href="#shiro" class="headerlink" title="shiro"></a>shiro</h1><p>Apache Shiro 是 Java 的一个安全框架。目前，使用 Apache Shiro 的人越来越多，因为它相当简单，对比 Spring Security，可能没有 Spring Security 做的功能强大，但是在实际工作时可能并不需要那么复杂的东西，所以使用小而简单的 Shiro 就足够了。对于它俩到底哪个好，这个不必纠结，能更简单的解决项目问题就好了。</p><a id="more"></a><p><img src="/2021/04/26/shiro%E6%95%B4%E5%90%88springboot%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/Figure_1.png" alt></p><p>可以看到：应用代码直接交互的对象是 Subject，也就是说 Shiro 的对外 API 核心就是 Subject；其每个 API 的含义：</p><p><strong>Subject</strong>：主体，代表了当前 “用户”，这个用户不一定是一个具体的人，与当前应用交互的任何东西都是 Subject，如网络爬虫，机器人等；即一个抽象概念；所有 Subject 都绑定到 SecurityManager，与 Subject 的所有交互都会委托给 SecurityManager；可以把 Subject 认为是一个门面；SecurityManager 才是实际的执行者；</p><p><strong>SecurityManager</strong>：安全管理器；即所有与安全有关的操作都会与 SecurityManager 交互；且它管理着所有 Subject；可以看出它是 Shiro 的核心，它负责与后边介绍的其他组件进行交互，如果学习过 SpringMVC，你可以把它看成 DispatcherServlet 前端控制器；</p><p><strong>Realm</strong>：域，Shiro 从从 Realm 获取安全数据（如用户、角色、权限），就是说 SecurityManager 要验证用户身份，那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法；也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作；可以把 Realm 看成 DataSource，即安全数据源。</p><p>也就是说对于我们而言，最简单的一个 Shiro 应用：</p><ol><li>应用代码通过 Subject 来进行认证和授权，而 Subject 又委托给 SecurityManager；</li><li>我们需要给 Shiro 的 SecurityManager 注入 Realm，从而让 SecurityManager 能得到合法的用户及其权限进行判断。</li></ol><p><strong>从以上也可以看出，Shiro 不提供维护用户 / 权限，而是通过 Realm 让开发人员自己注入。</strong>（来源：w3cschool）</p><h2 id="导入相关依赖"><a href="#导入相关依赖" class="headerlink" title="导入相关依赖"></a>导入相关依赖</h2><figure class="highlight xml"><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="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.shiro<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>shiro-spring<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- shiro整合thymeleaf --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.github.theborakompanioni<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>thymeleaf-extras-shiro<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-thymeleaf<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="自定义Realm"><a href="#自定义Realm" class="headerlink" title="自定义Realm"></a>自定义Realm</h2><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserRealm</span> <span class="keyword">extends</span> <span class="title">AuthorizingRealm</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserServiceImpl userService;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//授权</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> AuthorizationInfo <span class="title">doGetAuthorizationInfo</span><span class="params">(PrincipalCollection principalCollection)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;执行了=》授权doGetAuthorizationInfo方法&quot;</span>);</span><br><span class="line">        SimpleAuthorizationInfo info = <span class="keyword">new</span> SimpleAuthorizationInfo();</span><br><span class="line">        <span class="comment">//获取当前登陆的用户对象，从认证方法传递过来</span></span><br><span class="line">        Subject subject = SecurityUtils.getSubject();</span><br><span class="line">        User currentUser = (User) subject.getPrincipal();</span><br><span class="line">        <span class="comment">//设置当前用户权限</span></span><br><span class="line">        info.addStringPermission(currentUser.getPerms());</span><br><span class="line">        <span class="keyword">return</span> info;</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="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> AuthenticationInfo <span class="title">doGetAuthenticationInfo</span><span class="params">(AuthenticationToken authenticationToken)</span> <span class="keyword">throws</span> AuthenticationException </span>&#123;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;执行了=》认证doGetAuthenticationInfo方法&quot;</span>);</span><br><span class="line">        <span class="comment">//用户名密码，应该从数据库中读取</span></span><br><span class="line">       <span class="comment">/* String username= &quot;root&quot;;</span></span><br><span class="line"><span class="comment">        String password = &quot;123456&quot;;*/</span></span><br><span class="line">        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;</span><br><span class="line">        User user = userService.queryByName(userToken.getUsername());</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (user == <span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;<span class="comment">//会抛出异常 UnknownAccountException</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//密码验证，交给shiro做</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SimpleAuthenticationInfo(user,user.getPassword(),<span class="string">&quot;&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="定义shiro配置类"><a href="#定义shiro配置类" class="headerlink" title="定义shiro配置类"></a>定义shiro配置类</h2><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ShiroConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ShiroFilterFactoryBean <span class="title">shiroFilterFactoryBean</span><span class="params">(<span class="meta">@Qualifier(&quot;securityManager&quot;)</span> DefaultWebSecurityManager defaultWebSecurityManager)</span></span>&#123;</span><br><span class="line">        ShiroFilterFactoryBean shiroFilterFactoryBean = <span class="keyword">new</span> ShiroFilterFactoryBean();</span><br><span class="line">        <span class="comment">//设置安全管理器</span></span><br><span class="line">        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//添加shiro的内置过滤器</span></span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">        * anon:无需认证</span></span><br><span class="line"><span class="comment">        * authc:必须认证</span></span><br><span class="line"><span class="comment">        * user:必须拥有记住我功能才能访问</span></span><br><span class="line"><span class="comment">        * perms:拥有对某个资源的权限才能访问</span></span><br><span class="line"><span class="comment">        * role:拥有某个角色才能访问</span></span><br><span class="line"><span class="comment">        * */</span></span><br><span class="line">        Map&lt;String,String&gt; filterMap = <span class="keyword">new</span> LinkedHashMap&lt;&gt;();</span><br><span class="line">        <span class="comment">//授权</span></span><br><span class="line">        filterMap.put(<span class="string">&quot;/user/add&quot;</span>,<span class="string">&quot;perms[user:add]&quot;</span>);</span><br><span class="line">        filterMap.put(<span class="string">&quot;/user/update&quot;</span>,<span class="string">&quot;perms[user:update]&quot;</span>);</span><br><span class="line">        filterMap.put(<span class="string">&quot;/user/*&quot;</span>,<span class="string">&quot;authc&quot;</span>);</span><br><span class="line">        <span class="comment">//使用自带注销功能</span></span><br><span class="line">        filterMap.put(<span class="string">&quot;/logout&quot;</span>, <span class="string">&quot;logout&quot;</span>);</span><br><span class="line">        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);</span><br><span class="line">        shiroFilterFactoryBean.setLoginUrl(<span class="string">&quot;/toLogin&quot;</span>);</span><br><span class="line">        <span class="comment">//未授权页面</span></span><br><span class="line">        shiroFilterFactoryBean.setUnauthorizedUrl(<span class="string">&quot;/noauth&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> shiroFilterFactoryBean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">// DefaultWebSecurityManager:2</span></span><br><span class="line">    <span class="meta">@Bean(&quot;securityManager&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> DefaultWebSecurityManager <span class="title">getDefaultWebSecurityManager</span><span class="params">(<span class="meta">@Qualifier(&quot;userRealm&quot;)</span>UserRealm userRealm)</span></span>&#123;</span><br><span class="line">        DefaultWebSecurityManager securityManager = <span class="keyword">new</span> DefaultWebSecurityManager();</span><br><span class="line">        securityManager.setRealm(userRealm);</span><br><span class="line">        <span class="keyword">return</span> securityManager;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//创建Realm对象，需要自定义类:1</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> UserRealm <span class="title">userRealm</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> UserRealm();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//用来整合thymeleaf和shiro: ShiroDialect</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ShiroDialect <span class="title">shiroDialect</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> ShiroDialect();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="前台首页"><a href="#前台首页" class="headerlink" title="前台首页"></a>前台首页</h2><figure class="highlight html"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span> <span class="attr">xmlns:th</span>=<span class="string">&quot;http://www.thymeleaf.org&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">xmlns:shiro</span>=<span class="string">&quot;http://www.thymeleaf.org/thymeleaf-extras-shiro&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span>&gt;</span> 首页 <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">shiro:notAuthenticated</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/toLogin&#125;&quot;</span>&gt;</span>登录<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">shiro:user</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/logout&#125;&quot;</span>&gt;</span>注销<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">shiro:hasPermission</span>=<span class="string">&quot;user:add&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/user/add&#125;&quot;</span>&gt;</span>add<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">shiro:hasPermission</span>=<span class="string">&quot;user:update&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/user/update&#125;&quot;</span>&gt;</span>update<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p><img src="/2021/04/26/shiro%E6%95%B4%E5%90%88springboot%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/Figure_2.png" alt></p><h2 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h2><p><img src="/2021/04/26/shiro%E6%95%B4%E5%90%88springboot%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/Figure_4.png" alt><br><img src="/2021/04/26/shiro%E6%95%B4%E5%90%88springboot%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/Figure_5.png" alt><br><img src="/2021/04/26/shiro%E6%95%B4%E5%90%88springboot%E5%AE%9E%E7%8E%B0%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/Figure_6.png" alt></p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;shiro&quot;&gt;&lt;a href=&quot;#shiro&quot; class=&quot;headerlink&quot; title=&quot;shiro&quot;&gt;&lt;/a&gt;shiro&lt;/h1&gt;&lt;p&gt;Apache Shiro 是 Java 的一个安全框架。目前，使用 Apache Shiro 的人越来越多，因为它相当简单，对比 Spring Security，可能没有 Spring Security 做的功能强大，但是在实际工作时可能并不需要那么复杂的东西，所以使用小而简单的 Shiro 就足够了。对于它俩到底哪个好，这个不必纠结，能更简单的解决项目问题就好了。&lt;/p&gt;</summary>
    
    
    
    <category term="java" scheme="http://example.com/categories/java/"/>
    
    
    <category term="java" scheme="http://example.com/tags/java/"/>
    
    <category term="springboot" scheme="http://example.com/tags/springboot/"/>
    
    <category term="shiro" scheme="http://example.com/tags/shiro/"/>
    
  </entry>
  
  <entry>
    <title>ex1线性回归</title>
    <link href="http://example.com/2020/10/12/ex1%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/"/>
    <id>http://example.com/2020/10/12/ex1%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/</id>
    <published>2020-10-12T12:57:02.000Z</published>
    <updated>2020-10-13T09:08:14.813Z</updated>
    
    <content type="html"><![CDATA[<h1 id="单变量回归问题"><a href="#单变量回归问题" class="headerlink" title="单变量回归问题"></a>单变量回归问题</h1><p>​       我们将使用一个变量实现线性回归，根据城市人口数量，预测开小吃店的利润，数据在ex1data1.txt里，第一列是城市人口数量，第二列是该城市小吃店利润。</p><a id="more"></a><h2 id="读取数据"><a href="#读取数据" class="headerlink" title="读取数据"></a>读取数据</h2><p>利用pandas读取数据，并显示前5行数据检查是否读取成功。</p><figure class="highlight python"><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="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line">data = pd.read_csv(<span class="string">&#x27;ex1data1.txt&#x27;</span>, header=<span class="literal">None</span>, names=[<span class="string">&#x27;Population&#x27;</span>, <span class="string">&#x27;Profit&#x27;</span>])</span><br><span class="line">print(data.head())</span><br></pre></td></tr></table></figure><div class="table-container"><table><thead><tr><th></th><th style="text-align:center">Population</th><th>Profit</th></tr></thead><tbody><tr><td>0</td><td style="text-align:center">6.1101</td><td>17.5920</td></tr><tr><td>1</td><td style="text-align:center">5.5277</td><td>9.1302</td></tr><tr><td>2</td><td style="text-align:center">8.5186</td><td>13.6620</td></tr><tr><td>3</td><td style="text-align:center">7.0032</td><td>11.8540</td></tr><tr><td>4</td><td style="text-align:center">5.8598</td><td>6.8233</td></tr></tbody></table></div><h2 id="数据可视化"><a href="#数据可视化" class="headerlink" title="数据可视化"></a>数据可视化</h2><p>第一步我们需要对数据进行可视化，初步判断数据之间是否存在线性关系，这对后面的分析十分重要。</p><figure class="highlight python"><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="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line">plt.scatter(x=data[<span class="string">&#x27;Population&#x27;</span>], y=data[<span class="string">&#x27;Profit&#x27;</span>], label=<span class="string">&#x27;data&#x27;</span>, marker=<span class="string">&#x27;.&#x27;</span>, color=<span class="string">&#x27;b&#x27;</span>)</span><br><span class="line">plt.legend()</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p><img src="/2020/10/12/ex1%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/Figure_1.png" alt></p><h2 id="数据处理"><a href="#数据处理" class="headerlink" title="数据处理"></a>数据处理</h2><p>根据吴恩达课程所讲，我们需要在x的第一列加上一列x_0=1,初始化初值为0的theta。</p><figure class="highlight python"><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="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line">data.insert(<span class="number">0</span>, <span class="string">&#x27;ones&#x27;</span>, <span class="number">1</span>)  <span class="comment"># 在第0列插入1，表头为ones </span></span><br><span class="line">x = data.iloc[:, <span class="number">0</span>:<span class="number">-1</span>]  <span class="comment"># 切片工具[几行到几行, 几列到几列]</span></span><br><span class="line">y = data.iloc[:, <span class="number">-1</span>:]</span><br><span class="line">x, y = np.matrix(x.values), np.matrix(y.values)</span><br><span class="line">theta = np.matrix(np.zeros(x.shape[<span class="number">1</span>]))  <span class="comment"># 初始化theta</span></span><br></pre></td></tr></table></figure><h2 id="代价函数"><a href="#代价函数" class="headerlink" title="代价函数"></a>代价函数</h2><p>采用回归问题中常用的平方误差代价函数。</p><script type="math/tex; mode=display">J（\Theta）= \frac{1}{2m}\times\sum_{i=1}^m(h_\Theta(x^i)-y^i)^2</script><p>其中</p><script type="math/tex; mode=display">h_\Theta(x)=\Theta_0+\Theta_1\times x_1</script><p>注意在前面初始化的时候添加了一列x_0,故</p><script type="math/tex; mode=display">h_\Theta(x)=x\cdot\Theta^T</script><p>我们的目标是求出能够最小化J(θ)的θ，这样预测值才能更加接近y，即:</p><script type="math/tex; mode=display">argmin_\Theta=J(\Theta)</script><figure class="highlight python"><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="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="comment"># 计算代价函数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">cost_function</span>(<span class="params">x_, y_, theta_</span>):</span></span><br><span class="line">    ans = np.power(x_.dot(theta_.T)-y_, <span class="number">2</span>)</span><br><span class="line">    <span class="keyword">return</span> np.sum(ans)/(<span class="number">2</span>*x_.shape[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line">print(cost_function(x, y, theta))</span><br></pre></td></tr></table></figure><p>得出的结果应为theta=32.072733877455676。</p><h2 id="梯度下降"><a href="#梯度下降" class="headerlink" title="梯度下降"></a>梯度下降</h2><script type="math/tex; mode=display">\Theta_j:=\Theta_j-\alpha\times\frac{\partial J(\Theta)}{\partial \Theta_j}        :=\Theta_j-\frac{1}{m}\times \sum_{i=1}^m(h_\Theta(x^i)-y^i)x^i</script><p>其中α为learning rate,用来控制梯度下降的幅度。</p><figure class="highlight python"><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="function"><span class="keyword">def</span> <span class="title">gradient_descent</span>(<span class="params">x_, y_, theta_, alpha_, inters_</span>):</span></span><br><span class="line">    temp = np.matrix(np.zeros(theta.shape))</span><br><span class="line">    nums = int(theta_.shape[<span class="number">1</span>])</span><br><span class="line">    cost = np.zeros(inters_)</span><br><span class="line">    <span class="keyword">for</span> inter <span class="keyword">in</span> range(inters_):</span><br><span class="line">        ans = x_.dot(theta_.T)-y_</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> range(nums):</span><br><span class="line">            temp[<span class="number">0</span>, i] = theta_[<span class="number">0</span>, i] - alpha_*np.sum(np.multiply(ans, x_[:, i]))/len(x_)</span><br><span class="line">        theta_ = temp</span><br><span class="line">        cost[inter] = cost_function(x_, y_, theta_)</span><br><span class="line">    <span class="keyword">return</span> theta_, cost</span><br></pre></td></tr></table></figure><h2 id="预测函数"><a href="#预测函数" class="headerlink" title="预测函数"></a>预测函数</h2><p>设置α以及梯度下降的迭代次数，对θ进行求解。</p><figure class="highlight python"><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">alpha = <span class="number">0.01</span></span><br><span class="line">inters = <span class="number">1500</span></span><br><span class="line">g, cost = gradient_descent(x, y, theta, alpha, inters)</span><br><span class="line"><span class="comment"># 画出预测函数</span></span><br><span class="line">x_test = np.linspace(data[<span class="string">&#x27;Population&#x27;</span>].min(), data[<span class="string">&#x27;Population&#x27;</span>].max(), data.shape[<span class="number">0</span>])</span><br><span class="line"><span class="comment"># linspace(start,end,num=50)从间隔取出50个数</span></span><br><span class="line">predict = g[<span class="number">0</span>, <span class="number">0</span>]+g[<span class="number">0</span>, <span class="number">1</span>]*x_test</span><br><span class="line">plt.scatter(x=data[<span class="string">&#x27;Population&#x27;</span>], y=data[<span class="string">&#x27;Profit&#x27;</span>], label=<span class="string">&#x27;data&#x27;</span>, marker=<span class="string">&#x27;.&#x27;</span>, color=<span class="string">&#x27;b&#x27;</span>)</span><br><span class="line">plt.plot(x_test, predict, c=<span class="string">&#x27;r&#x27;</span>, label=<span class="string">&#x27;predict&#x27;</span>)</span><br><span class="line">plt.xlabel(<span class="string">&#x27;Population&#x27;</span>)</span><br><span class="line">plt.ylabel(<span class="string">&#x27;Profit&#x27;</span>)</span><br><span class="line">plt.legend()</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p>得出最后的预测函数如下图所示。</p><p><img src="/2020/10/12/ex1%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/Figure_2.png" alt></p><h1 id="多变量回归问题"><a href="#多变量回归问题" class="headerlink" title="多变量回归问题"></a>多变量回归问题</h1><p>​      在这一部分中，我们将使用多个变量实现线性回归以预测房屋价格。假设你正在出售房屋，并且想知道一个好的市场价格。一种方法是首先收集最近有关出售房屋的信息，并建立房屋价格模型。<br>​    文件ex1data2.txt包含某地区房屋价格的训练集。第一列是房屋的大小（以平方英尺为单位），第二列是卧室的数量，第三列是房屋的价格。</p><h2 id="读取数据-1"><a href="#读取数据-1" class="headerlink" title="读取数据"></a>读取数据</h2><figure class="highlight python"><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">data2 = pd.read_csv(<span class="string">&#x27;ex1data2.txt&#x27;</span>, header=<span class="literal">None</span>, names=[<span class="string">&#x27;Size&#x27;</span>, <span class="string">&#x27;Bedrooms&#x27;</span>, <span class="string">&#x27;Price&#x27;</span>])</span><br><span class="line">print(data2.head())</span><br></pre></td></tr></table></figure><p>显示前5行数据如下，</p><div class="table-container"><table><thead><tr><th style="text-align:center"></th><th style="text-align:center">Size</th><th style="text-align:center">Bedrooms</th><th style="text-align:center">Price</th></tr></thead><tbody><tr><td style="text-align:center">0</td><td style="text-align:center">2104</td><td style="text-align:center">3</td><td style="text-align:center">399900</td></tr><tr><td style="text-align:center">1</td><td style="text-align:center">1600</td><td style="text-align:center">3</td><td style="text-align:center">329900</td></tr><tr><td style="text-align:center">2</td><td style="text-align:center">2400</td><td style="text-align:center">3</td><td style="text-align:center">369000</td></tr><tr><td style="text-align:center">3</td><td style="text-align:center">1416</td><td style="text-align:center">2</td><td style="text-align:center">232000</td></tr><tr><td style="text-align:center">4</td><td style="text-align:center">3000</td><td style="text-align:center">4</td><td style="text-align:center">539900</td></tr></tbody></table></div><p>这时我们需要进行均值归一化让数据统一量级，让梯度下降算法更快的收敛。均值归一化就是将每个特征的值减去平均值再除以标准差。</p><figure class="highlight python"><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">data2 = (data2-data2.mean())/data2.std()</span><br><span class="line">print(data2.head())</span><br></pre></td></tr></table></figure><div class="table-container"><table><thead><tr><th style="text-align:center"></th><th style="text-align:center">Size</th><th style="text-align:center">Bedrooms</th><th style="text-align:center">Price</th></tr></thead><tbody><tr><td style="text-align:center">0</td><td style="text-align:center">0.130010</td><td style="text-align:center">-0.223675</td><td style="text-align:center">0.475747</td></tr><tr><td style="text-align:center">1</td><td style="text-align:center">-0.504190</td><td style="text-align:center">-0.223675</td><td style="text-align:center">-0.084074</td></tr><tr><td style="text-align:center">2</td><td style="text-align:center">0.502476</td><td style="text-align:center">-0.223675</td><td style="text-align:center">0.228626</td></tr><tr><td style="text-align:center">3</td><td style="text-align:center">-0.735723</td><td style="text-align:center">-1.537767</td><td style="text-align:center">-0.867025</td></tr><tr><td style="text-align:center">4</td><td style="text-align:center">1.257476</td><td style="text-align:center">1.090417</td><td style="text-align:center">1.595389</td></tr></tbody></table></div><h2 id="数据处理-1"><a href="#数据处理-1" class="headerlink" title="数据处理"></a>数据处理</h2><figure class="highlight python"><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">data2.insert(<span class="number">0</span>, <span class="string">&#x27;ones&#x27;</span>, <span class="number">1</span>)</span><br><span class="line">x2 = data2.iloc[:, <span class="number">0</span>:<span class="number">-1</span>]  </span><br><span class="line">y2 = data2.iloc[:, <span class="number">-1</span>:]</span><br><span class="line">x2, y2 = np.matrix(x2.values), np.matrix(y2.values)</span><br><span class="line">theta2 = np.matrix(np.zeros(x2.shape[<span class="number">1</span>]))  </span><br></pre></td></tr></table></figure><h2 id="梯度下降-1"><a href="#梯度下降-1" class="headerlink" title="梯度下降"></a>梯度下降</h2><figure class="highlight plain"><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">g2, cost2 &#x3D; gradient_descent(x2, y2, theta2, alpha, inters)</span><br><span class="line">print(g2)</span><br></pre></td></tr></table></figure><p>输出结果为[[-1.10892383e-16  8.84042349e-01 -5.24551809e-02]]    </p><h2 id="特征方程"><a href="#特征方程" class="headerlink" title="特征方程"></a>特征方程</h2><p>正规方程是通过求解下面的方程来找出使得代价函数最小的参数的：</p><script type="math/tex; mode=display">\frac{\partial J(\Theta_j)}{\partial\Theta_j}=0</script><p>通过特征方程，解得：</p><script type="math/tex; mode=display">\Theta=(X^TX)^{-1}X^TY</script><p>python实现代码如下：</p><figure class="highlight python"><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="function"><span class="keyword">def</span> <span class="title">normal_eqn</span>(<span class="params">x_, y_</span>):</span>  <span class="comment"># 正规方程</span></span><br><span class="line">    <span class="keyword">return</span> np.linalg.inv(x_.T.dot(x_)).dot(x_.T).dot(y_)</span><br></pre></td></tr></table></figure><p>梯度下降与正规方程的比较：</p><p>梯度下降：需要选择学习率α，需要多次迭代，当特征数量n大时也能较好适用，适用于各种类型的模型</p><p>正规方程：不需要选择学习率α，一次计算得出，需要计算逆矩阵，如果特征数量n较大则运算代价大。</p><p>下面使用特征方程求解θ与梯度下降的结果进行对比。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">print(normal_eqn(x2, y2))</span><br></pre></td></tr></table></figure><p>结果为如下，可以看出与梯度下降所得的结果很相近。</p><p>[[-9.36750677e-17]<br> [ 8.84765988e-01]<br> [-5.31788197e-02]]</p><p>最后给出预测函数图像：</p><p><img src="/2020/10/12/ex1%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/Figure_3.png" alt="Figure_3"></p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;单变量回归问题&quot;&gt;&lt;a href=&quot;#单变量回归问题&quot; class=&quot;headerlink&quot; title=&quot;单变量回归问题&quot;&gt;&lt;/a&gt;单变量回归问题&lt;/h1&gt;&lt;p&gt;​       我们将使用一个变量实现线性回归，根据城市人口数量，预测开小吃店的利润，数据在ex1data1.txt里，第一列是城市人口数量，第二列是该城市小吃店利润。&lt;/p&gt;</summary>
    
    
    
    <category term="吴恩达机器学习练习" scheme="http://example.com/categories/%E5%90%B4%E6%81%A9%E8%BE%BE%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E7%BB%83%E4%B9%A0/"/>
    
    
    <category term="机器学习" scheme="http://example.com/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    
    <category term="线性回归" scheme="http://example.com/tags/%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/"/>
    
  </entry>
  
  <entry>
    <title>二叉树遍历模板</title>
    <link href="http://example.com/2020/10/12/%E4%BA%8C%E5%8F%89%E6%A0%91%E9%81%8D%E5%8E%86%E6%A8%A1%E6%9D%BF/"/>
    <id>http://example.com/2020/10/12/%E4%BA%8C%E5%8F%89%E6%A0%91%E9%81%8D%E5%8E%86%E6%A8%A1%E6%9D%BF/</id>
    <published>2020-10-12T12:57:02.000Z</published>
    <updated>2021-04-21T08:40:09.343Z</updated>
    
    <content type="html"><![CDATA[<h1 id="二叉树遍历模板"><a href="#二叉树遍历模板" class="headerlink" title="二叉树遍历模板"></a>二叉树遍历模板</h1><a id="more"></a><h2 id="1-节点定义"><a href="#1-节点定义" class="headerlink" title="1.节点定义"></a>1.节点定义</h2><figure class="highlight java"><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="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TreeNode</span> </span>&#123;</span><br><span class="line">     <span class="keyword">int</span> val;</span><br><span class="line">     TreeNode left;</span><br><span class="line">     TreeNode right;</span><br><span class="line">     TreeNode() &#123;&#125;</span><br><span class="line">     TreeNode(<span class="keyword">int</span> val) &#123; <span class="keyword">this</span>.val = val; &#125;</span><br><span class="line">     TreeNode(<span class="keyword">int</span> val, TreeNode left, TreeNode right) &#123;</span><br><span class="line">        <span class="keyword">this</span>.val = val;</span><br><span class="line">        <span class="keyword">this</span>.left = left;</span><br><span class="line">        <span class="keyword">this</span>.right = right;</span><br><span class="line">     &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure><h2 id="1-递归"><a href="#1-递归" class="headerlink" title="1.递归"></a>1.递归</h2><figure class="highlight java"><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"><span class="comment">//时间复杂度：O(n)，n为节点数，访问每个节点恰好一次。</span></span><br><span class="line"><span class="comment">//空间复杂度：空间复杂度：O(h)，h为树的高度。最坏情况下需要空间O(n)，平均情况为O(logn)</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">   </span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">postorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(root == <span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> list;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//list.add(root.val);前序遍历</span></span><br><span class="line">        postorderTraversal(root.left);</span><br><span class="line">        <span class="comment">//list.add(root.val);中序遍历</span></span><br><span class="line">        postorderTraversal(root.right);</span><br><span class="line">        list.add(root.val);<span class="comment">//后序遍历</span></span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="2-迭代"><a href="#2-迭代" class="headerlink" title="2.迭代"></a>2.迭代</h2><figure class="highlight java"><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><br><span class="line"><span class="comment">//时间复杂度：O(n)，n为节点数，访问每个节点恰好一次。</span></span><br><span class="line"><span class="comment">//空间复杂度：O(h)，h为树的高度。取决于树的结构，最坏情况存储整棵树，即O(n)</span></span><br><span class="line"><span class="comment">//迭代1：前序遍历最常用模板（后序同样可以用）</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">postorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//迭代</span></span><br><span class="line">        List&lt;Integer&gt; list = <span class="keyword">new</span> ArrayList();</span><br><span class="line">        Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack();</span><br><span class="line">        <span class="keyword">if</span>(root != <span class="keyword">null</span>) stack.push(root);</span><br><span class="line">       <span class="comment">//前序迭代模板：最常用的二叉树DFS迭代遍历模板</span></span><br><span class="line"><span class="keyword">while</span>(!stack.isEmpty())&#123;           </span><br><span class="line">             TreeNode res = stack.pop();</span><br><span class="line">             list.add(res.val);</span><br><span class="line">             <span class="keyword">if</span>(res.right!=<span class="keyword">null</span>) stack.push(res.right);</span><br><span class="line">             <span class="keyword">if</span>(res.left!=<span class="keyword">null</span>) stack.push(res.left);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">        </span><br><span class="line">       <span class="comment">//后序迭代，相同模板：将前序迭代进栈顺序稍作修改</span></span><br><span class="line">       <span class="comment">/*</span></span><br><span class="line"><span class="comment">         while(!stack.isEmpty())&#123;</span></span><br><span class="line"><span class="comment">            TreeNode res = stack.pop();</span></span><br><span class="line"><span class="comment">            if(res.left!=null) stack.push(res.left);</span></span><br><span class="line"><span class="comment">            if(res.right!=null) stack.push(res.right);</span></span><br><span class="line"><span class="comment">            list.add(0,res.val);</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">        return list;</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight java"><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">//迭代2</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;Integer&gt; list = <span class="keyword">new</span> ArrayList&lt;Integer&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">inorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        List&lt;Integer&gt; list = <span class="keyword">new</span> ArrayList();</span><br><span class="line">        Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack();</span><br><span class="line">        TreeNode cur = root;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty()||cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">                stack.push(cur);</span><br><span class="line">                cur = cur.left;</span><br><span class="line">            &#125;</span><br><span class="line">            cur = stack.pop();</span><br><span class="line">            list.add(cur.val);</span><br><span class="line">            cur = cur.right;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-染色法、标记法、莫里斯、N叉树"><a href="#3-染色法、标记法、莫里斯、N叉树" class="headerlink" title="3.染色法、标记法、莫里斯、N叉树"></a>3.染色法、标记法、莫里斯、N叉树</h2><figure class="highlight python"><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><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 迭代3：标记法迭代（需要双倍的空间来存储访问状态）：</span></span><br><span class="line"><span class="comment"># 前、中、后、层序通用模板，只需改变进栈顺序或即可实现前后中序遍历，</span></span><br><span class="line"><span class="comment"># 而层序遍历则使用队列先进先出。0表示当前未访问，1表示已访问。</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">preOrd</span>(<span class="params">self, root: TreeNode</span>) -&gt; List[int]:</span></span><br><span class="line">        res = []</span><br><span class="line">        stack = [(<span class="number">0</span>, root)]</span><br><span class="line">        <span class="keyword">while</span> stack:</span><br><span class="line">            flag, cur = stack.pop()</span><br><span class="line">            <span class="keyword">if</span> <span class="keyword">not</span> cur: <span class="keyword">continue</span></span><br><span class="line">            <span class="keyword">if</span> flag == <span class="number">0</span>:</span><br><span class="line">                <span class="comment"># 前序，标记法</span></span><br><span class="line">                stack.append((<span class="number">0</span>, cur.right))</span><br><span class="line">                stack.append((<span class="number">0</span>, cur.left))</span><br><span class="line">                stack.append((<span class="number">1</span>, cur))</span><br><span class="line">                </span><br><span class="line">                <span class="comment"># # 后序，标记法</span></span><br><span class="line">                <span class="comment"># stack.append((1, cur))</span></span><br><span class="line">                <span class="comment"># stack.append((0, cur.right))</span></span><br><span class="line">                <span class="comment"># stack.append((0, cur.left))</span></span><br><span class="line">                </span><br><span class="line">                <span class="comment"># # 中序，标记法</span></span><br><span class="line">                <span class="comment"># stack.append((0, cur.right))</span></span><br><span class="line">                <span class="comment"># stack.append((1, cur))</span></span><br><span class="line">                <span class="comment"># stack.append((0, cur.left))  </span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                res.append(cur.val)  </span><br><span class="line">        <span class="keyword">return</span> res</span><br><span class="line">        </span><br><span class="line">        <span class="comment"># # 层序，标记法</span></span><br><span class="line">        <span class="comment"># res = []</span></span><br><span class="line">        <span class="comment"># queue = [(0, root)]</span></span><br><span class="line">        <span class="comment"># while queue:</span></span><br><span class="line">        <span class="comment">#     flag, cur = queue.pop(0)  # 注意是队列，先进先出</span></span><br><span class="line">        <span class="comment">#     if not cur: continue</span></span><br><span class="line">        <span class="comment">#     if flag == 0:</span></span><br><span class="line">                  <span class="comment"># 层序遍历这三个的顺序无所谓，因为是队列，只弹出队首元素</span></span><br><span class="line">        <span class="comment">#         queue.append((1, cur))</span></span><br><span class="line">        <span class="comment">#         queue.append((0, cur.left))</span></span><br><span class="line">        <span class="comment">#         queue.append((0, cur.right))</span></span><br><span class="line">        <span class="comment">#     else:</span></span><br><span class="line">        <span class="comment">#         res.append(cur.val)</span></span><br><span class="line">        <span class="comment"># return res</span></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"># 时间复杂度：O(n)，n为节点数，看似超过O(n)，有的节点可能要访问两次，实际分析还是O(n)</span></span><br><span class="line"><span class="comment"># 空间复杂度：O(1)，如果在遍历过程中就输出节点值，则只需常数空间就能得到中序遍历结果，空间只需两个指针。</span></span><br><span class="line"><span class="comment"># 如果将结果储存最后输出，则空间复杂度还是O(n)。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># PS：莫里斯遍历实际上是在原有二叉树的结构基础上，构造了线索二叉树，</span></span><br><span class="line"><span class="comment"># 线索二叉树定义为：原本为空的右子节点指向了中序遍历顺序之后的那个节点，把所有原本为空的左子节点都指向了中序遍历之前的那个节点</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 此处只给出中序遍历，前序遍历只需修改输出顺序即可</span></span><br><span class="line"><span class="comment"># 而后序遍历，由于遍历是从根开始的，而线索二叉树是将为空的左右子节点连接到相应的顺序上，使其能够按照相应准则输出</span></span><br><span class="line"><span class="comment"># 但是后序遍历的根节点却已经没有额外的空间来标记自己下一个应该访问的节点，</span></span><br><span class="line"><span class="comment"># 所以这里需要建立一个临时节点dump，令其左孩子是root。并且还需要一个子过程，就是倒序输出某两个节点之间路径上的各个节点。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 莫里斯遍历，借助线索二叉树中序遍历（附前序遍历）</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">inOrd</span>(<span class="params">self, root: TreeNode</span>) -&gt; List[int]:</span></span><br><span class="line">        res = []</span><br><span class="line">        <span class="comment"># cur = pre = TreeNode(None)</span></span><br><span class="line">        cur = root</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> cur:</span><br><span class="line">            <span class="keyword">if</span> <span class="keyword">not</span> cur.left:</span><br><span class="line">                res.append(cur.val)</span><br><span class="line">                <span class="comment"># print(cur.val)</span></span><br><span class="line">                cur = cur.right</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                pre = cur.left</span><br><span class="line">                <span class="keyword">while</span> pre.right <span class="keyword">and</span> pre.right != cur:</span><br><span class="line">                    pre = pre.right</span><br><span class="line">                <span class="keyword">if</span> <span class="keyword">not</span> pre.right:</span><br><span class="line">                    <span class="comment"># print(cur.val) 这里是前序遍历的代码，前序与中序的唯一差别</span></span><br><span class="line">                    pre.right = cur</span><br><span class="line">                    cur = cur.left</span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    pre.right = <span class="literal">None</span></span><br><span class="line">                    res.append(cur.val)</span><br><span class="line">                    <span class="comment"># print(cur.val)</span></span><br><span class="line">                    cur = cur.right</span><br><span class="line">        <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># N叉树遍历</span></span><br><span class="line"><span class="comment"># 时间复杂度：时间复杂度：O(M)，其中 M 是 N 叉树中的节点个数。每个节点只会入栈和出栈各一次。</span></span><br><span class="line"><span class="comment"># 空间复杂度：O(M)。在最坏的情况下，这棵 N 叉树只有 2 层，所有第 2 层的节点都是根节点的孩子。</span></span><br><span class="line"><span class="comment"># 将根节点推出栈后，需要将这些节点都放入栈，共有 M−1个节点，因此栈的大小为 O(M)。</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># N叉树简洁递归</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">preorder</span>(<span class="params">self, root: <span class="string">&#x27;Node&#x27;</span></span>) -&gt; List[int]:</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> root: <span class="keyword">return</span> []</span><br><span class="line">        res = [root.val]</span><br><span class="line">        <span class="keyword">for</span> node <span class="keyword">in</span> root.children:</span><br><span class="line">            res.extend(self.preorder(node))</span><br><span class="line">        <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"><span class="comment"># N叉树通用递归模板</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">preorder</span>(<span class="params">self, root: <span class="string">&#x27;Node&#x27;</span></span>) -&gt; List[int]:</span></span><br><span class="line">        res = []</span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">helper</span>(<span class="params">root</span>):</span></span><br><span class="line">            <span class="keyword">if</span> <span class="keyword">not</span> root:</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            res.append(root.val)</span><br><span class="line">            <span class="keyword">for</span> child <span class="keyword">in</span> root.children:</span><br><span class="line">                helper(child)</span><br><span class="line">        helper(root)</span><br><span class="line">        <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"><span class="comment"># N叉树迭代方法</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">preorder</span>(<span class="params">self, root: <span class="string">&#x27;Node&#x27;</span></span>) -&gt; List[int]:</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> root:</span><br><span class="line">            <span class="keyword">return</span> []</span><br><span class="line">        s = [root]</span><br><span class="line">        <span class="comment"># s.append(root)</span></span><br><span class="line">        res = []</span><br><span class="line">        <span class="keyword">while</span> s:</span><br><span class="line">            node = s.pop()</span><br><span class="line">            res.append(node.val)</span><br><span class="line">            <span class="comment"># for child in node.children[::-1]:</span></span><br><span class="line">            <span class="comment">#     s.append(child)</span></span><br><span class="line">            s.extend(node.children[::<span class="number">-1</span>])</span><br><span class="line">        <span class="keyword">return</span> res</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;二叉树遍历模板&quot;&gt;&lt;a href=&quot;#二叉树遍历模板&quot; class=&quot;headerlink&quot; title=&quot;二叉树遍历模板&quot;&gt;&lt;/a&gt;二叉树遍历模板&lt;/h1&gt;</summary>
    
    
    
    <category term="leetcode刷题笔记" scheme="http://example.com/categories/leetcode%E5%88%B7%E9%A2%98%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="Leetcode" scheme="http://example.com/tags/Leetcode/"/>
    
    <category term="二叉树" scheme="http://example.com/tags/%E4%BA%8C%E5%8F%89%E6%A0%91/"/>
    
    <category term="算法" scheme="http://example.com/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>（转载）简单线性回归-基于高斯核函数</title>
    <link href="http://example.com/2020/09/27/GaussianRegression/"/>
    <id>http://example.com/2020/09/27/GaussianRegression/</id>
    <published>2020-09-27T13:14:58.000Z</published>
    <updated>2020-09-27T14:55:30.896Z</updated>
    
    <content type="html"><![CDATA[<h2 id="高斯过程"><a href="#高斯过程" class="headerlink" title="高斯过程"></a>高斯过程</h2><p>高斯过程 Gaussian Processes 是概率论和数理统计中随机过程的一种，是多元高斯分布的扩展，被应用于机器学习、信号处理等领域。本文对高斯过程进行公式推导、原理阐述、可视化以及代码实现，介绍了以高斯过程为基础的高斯过程回归 Gaussian Process Regression 基本原理、超参优化、高维输入等问题。</p><a id="more"></a><ul><li><p>一元高斯分布公式<br>其概率密度公式如下：</p><script type="math/tex; mode=display">p(x)=\frac{1}{σ\sqrt{2\times\pi}}exp(-\frac{(x-μ)^2}{2σ^2})</script></li><li><p>核函数(协方差函数)<br>核函数是一个高斯过程的核心，核函数决定了一个高斯过程的性质。核函数在高斯过程中起的作用是生成一个协方差矩阵（相关系数矩阵），衡量任意两个点之间的“距离”。最常用的一个核函数为高斯核函数，也成为径向基函数 RBF。其基本形式如下。其中 σ 和 h 是高斯核的超参数。</p><script type="math/tex; mode=display">K(x_i,x_j)=σ^2exp(-\frac{-||x_i-x_j||^2}{2h^2})</script></li></ul><h1 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h1><h2 id="1-定义核函数"><a href="#1-定义核函数" class="headerlink" title="1.定义核函数"></a>1.定义核函数</h2><figure class="highlight python"><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">   <span class="function"><span class="keyword">def</span> <span class="title">kernel</span>(<span class="params">self, x1, x2</span>):</span></span><br><span class="line">       m,n = x1.shape[<span class="number">0</span>], x2.shape[<span class="number">0</span>]</span><br><span class="line">       dist_matrix = np.zeros((m,n), dtype=float)</span><br><span class="line">       <span class="keyword">for</span> i <span class="keyword">in</span> range(m):</span><br><span class="line">           <span class="keyword">for</span> j <span class="keyword">in</span> range(n):</span><br><span class="line">               dist_matrix[i][j] = np.sum((x1[i]-x2[j])**<span class="number">2</span>)</span><br><span class="line">       <span class="keyword">return</span> np.exp(<span class="number">-0.5</span>/self.h**<span class="number">2</span>*dist_matrix)</span><br></pre></td></tr></table></figure><h2 id="2-主要代码"><a href="#2-主要代码" class="headerlink" title="2.主要代码"></a>2.主要代码</h2><figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 导入相关库</span></span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="comment"># 定义高斯过程类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GPR</span>:</span></span><br><span class="line">   <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, h</span>):</span></span><br><span class="line">       self.is_fit = <span class="literal">False</span></span><br><span class="line">       self.train_x, self.train_y = <span class="literal">None</span>, <span class="literal">None</span></span><br><span class="line">       self.h = h</span><br><span class="line">       </span><br><span class="line">   <span class="function"><span class="keyword">def</span> <span class="title">fit</span>(<span class="params">self, x, y</span>):</span></span><br><span class="line">       self.train_x = np.asarray(x)</span><br><span class="line">       self.train_y = np.asarray(y)</span><br><span class="line">       self.is_fit = <span class="literal">True</span></span><br><span class="line">       </span><br><span class="line">   <span class="function"><span class="keyword">def</span> <span class="title">predict</span>(<span class="params">self, x</span>):</span></span><br><span class="line">       <span class="keyword">if</span> <span class="keyword">not</span> self.is_fit:</span><br><span class="line">           print(<span class="string">&quot;Sorry! GPR Model can&#x27;t fit!&quot;</span>)</span><br><span class="line">           <span class="keyword">return</span></span><br><span class="line">       </span><br><span class="line">       x = np.asarray(x)</span><br><span class="line">       kff = self.kernel(x,x)</span><br><span class="line">       kyy = self.kernel(self.train_x, self.train_x)</span><br><span class="line">       kfy = self.kernel(x, self.train_x)</span><br><span class="line">       kyy_inv =  np.linalg.inv(kyy + <span class="number">1e-8</span>*np.eye(len(self.train_x)))</span><br><span class="line">       </span><br><span class="line">       mu = kfy.dot(kyy_inv).dot(self.train_y)</span><br><span class="line">       <span class="keyword">return</span> mu</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="function"><span class="keyword">def</span> <span class="title">kernel</span>(<span class="params">self, x1, x2</span>):</span></span><br><span class="line">       m,n = x1.shape[<span class="number">0</span>], x2.shape[<span class="number">0</span>]</span><br><span class="line">       dist_matrix = np.zeros((m,n), dtype=float)</span><br><span class="line">       <span class="keyword">for</span> i <span class="keyword">in</span> range(m):</span><br><span class="line">           <span class="keyword">for</span> j <span class="keyword">in</span> range(n):</span><br><span class="line">               dist_matrix[i][j] = np.sum((x1[i]-x2[j])**<span class="number">2</span>)</span><br><span class="line">       <span class="keyword">return</span> np.exp(<span class="number">-0.5</span>/self.h**<span class="number">2</span>*dist_matrix)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创造训练集</span></span><br><span class="line">train_x = np.arange(<span class="number">0</span>,<span class="number">10</span>).reshape(<span class="number">-1</span>,<span class="number">1</span>)</span><br><span class="line">train_y = np.cos(train_x) + train_x</span><br><span class="line"><span class="comment"># 制造槽点</span></span><br><span class="line">train_y = train_y + np.random.normal(<span class="number">0</span>, <span class="number">0.01</span>, size=train_x.shape)</span><br><span class="line"><span class="comment"># 显示训练集的分布</span></span><br><span class="line">plt.figure()</span><br><span class="line">plt.scatter(train_x, train_y, label=<span class="string">&quot;train&quot;</span>, c=<span class="string">&quot;red&quot;</span>, marker=<span class="string">&quot;x&quot;</span>)</span><br><span class="line">plt.legend()</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></figure><p>输出的图：</p><p><img src="/2020/09/27/GaussianRegression/Figure_1.png" alt="1"></p><h2 id="3-学习代码"><a href="#3-学习代码" class="headerlink" title="3.学习代码"></a>3.学习代码</h2><figure class="highlight python"><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"># 创建训练集</span></span><br><span class="line">test_x = np.arange(<span class="number">0</span>, <span class="number">10</span>, <span class="number">0.1</span>).reshape(<span class="number">-1</span>,<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 针对不同h值得到拟合图像</span></span><br><span class="line">h=<span class="number">0.1</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">10</span>):</span><br><span class="line">    gpr = GPR(h)</span><br><span class="line">    gpr.fit(train_x, train_y)</span><br><span class="line">    mu = gpr.predict(test_x)</span><br><span class="line">    test_y = mu.ravel()</span><br><span class="line">    plt.figure()</span><br><span class="line">    plt.title(<span class="string">&quot;h=%.2f&quot;</span>%(h))</span><br><span class="line">    plt.plot(test_x, test_y, label=<span class="string">&quot;predict&quot;</span>)</span><br><span class="line">    plt.scatter(train_x, train_y, label=<span class="string">&quot;train&quot;</span>, c=<span class="string">&quot;red&quot;</span>, marker=<span class="string">&quot;x&quot;</span>)</span><br><span class="line">    plt.legend()</span><br><span class="line">    plt.show()</span><br><span class="line">    h += <span class="number">0.1</span></span><br></pre></td></tr></table></figure><p>输出图像：</p><p><img src="/2020/09/27/GaussianRegression/Figure_2.png" alt="2"></p><p><img src="/2020/09/27/GaussianRegression/Figure_3.png" alt="2"></p><p><img src="/2020/09/27/GaussianRegression/Figure_4.png" alt="2"></p><p><img src="/2020/09/27/GaussianRegression/Figure_5.png" alt="2"></p><h1 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h1><p>本人是刚接触机器学习的小白，这篇文章让对老师布置的作业更好的理解。文章转载自CSDN（<a href="https://me.csdn.net/Vince_Cheng">Vince_Cheng</a>），<a href="https://blog.csdn.net/Vince_Cheng/article/details/102250958">文章地址</a>转载仅作为本人学习使用的笔记，同时也是我的第一篇博客，相信日后我也能写出原创的文章。感谢这位大佬的分享，侵删！    </p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;高斯过程&quot;&gt;&lt;a href=&quot;#高斯过程&quot; class=&quot;headerlink&quot; title=&quot;高斯过程&quot;&gt;&lt;/a&gt;高斯过程&lt;/h2&gt;&lt;p&gt;高斯过程 Gaussian Processes 是概率论和数理统计中随机过程的一种，是多元高斯分布的扩展，被应用于机器学习、信号处理等领域。本文对高斯过程进行公式推导、原理阐述、可视化以及代码实现，介绍了以高斯过程为基础的高斯过程回归 Gaussian Process Regression 基本原理、超参优化、高维输入等问题。&lt;/p&gt;</summary>
    
    
    
    <category term="机器学习" scheme="http://example.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="机器学习" scheme="http://example.com/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    
    <category term="线性回归" scheme="http://example.com/tags/%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92/"/>
    
    <category term="核函数" scheme="http://example.com/tags/%E6%A0%B8%E5%87%BD%E6%95%B0/"/>
    
  </entry>
  
</feed>
