forked from LiXinyuan1015/LiXinyuan1015.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
73 lines (34 loc) · 61.1 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Astar算法</title>
<link href="/2023/07/13/Astar/"/>
<url>/2023/07/13/Astar/</url>
<content type="html"><![CDATA[<h1 id="A-算法"><a href="#A-算法" class="headerlink" title="A*算法"></a>A*算法</h1><p><strong>课程名称</strong>:当代人工智能</p><p><strong>姓名</strong>:李昕原</p><p><strong>院校</strong>:华东师范大学 数据科学与工程学院</p><p><strong>日期</strong>:2023.3.24</p><h2 id="算法简介"><a href="#算法简介" class="headerlink" title="算法简介"></a>算法简介</h2><p>Astar算法(A-Star Algorithm)是一种广泛应用于路径查找和图形搜索的算法。该算法由 Peter Hart、Nils Nilsson 和 Bertram Raphael 于 1968 年共同提出。Astar算法通过结合 Dijkstra 算法(最短路径搜索)和 Best-First-Search(启发式搜索)的优点,实现了在寻找最短路径的同时具有较高搜索效率的特点。Astar算法的核心思想是在每一步中选择具有最低 f(n) 值的节点进行扩展,其中:</p><ul><li>f(n) = g(n) + h(n)</li><li>g(n) 是从起点到当前节点 n 的实际代价。</li><li>h(n) 是从当前节点 n 到终点的启发式(预估)代价。</li></ul><p>启发式函数 h(n) 的选择对算法的效率有很大影响。一个好的启发式函数应尽量接近实际代价,但计算起来又不要太复杂,常用的启发式函数包括曼哈顿距离、欧几里得距离等。</p><p>以下是Astar算法的基本步骤:</p><ol><li>将起始节点添加到开放列表(Open List)中。</li><li>如果开放列表为空,表示没有找到路径,算法结束。</li><li>从开放列表中选取具有最低 f(n) 值的节点,将其从开放列表中移除并添加到关闭列表(Closed List)中。</li><li>检查选中节点的所有相邻节点:<ul><li>如果相邻节点在关闭列表中,忽略它。</li><li>如果相邻节点不在开放列表中,计算其 g(n)、h(n) 和 f(n) 值,然后将其添加到开放列表中。</li><li>如果相邻节点已经在开放列表中,但新路径的 g(n) 值更低,更新该节点的值并重新排序开放列表。</li></ul></li><li>如果终点已经在开放列表中,则找到了最短路径,算法结束。否则,返回步骤 2。</li></ol><h2 id="编程题目"><a href="#编程题目" class="headerlink" title="编程题目"></a>编程题目</h2><p>使用A*算法解决两道题目:</p><h3 id="森林宝石的秘密通道"><a href="#森林宝石的秘密通道" class="headerlink" title="森林宝石的秘密通道"></a>森林宝石的秘密通道</h3><p>在一个神秘的森林⾥,有⼀块由 9 个小方格组成的魔法石板。石板上有 8 个宝石,每个宝石上刻有 1-8 中的一个数字(每个数字都不重复)。石板上还有一个空位,用 0表示。通过移动空位周围的宝石,你可以改变宝石的位置。传说中,当宝石按照某个特定的顺序排列时(本题设为 1 3 5 7 0 2 6 8 4),魔法石板将会显露出通往一个宝藏的秘密通道。现在,你站在这块魔法石板前,需要找到⼀种最少步骤的移动方法,将宝石排列成目标顺序。为了解开这个谜题,请使用 A*算法来设计一个程序,帮助你从初始状态成功解锁秘密通道。</p><h4 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h4><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> heapq</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Puzzle</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, state, goal</span>):</span><br><span class="line"> self.state = state</span><br><span class="line"> self.goal = goal</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 排序方法</span></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__lt__</span>(<span class="params">self, other</span>):</span><br><span class="line"> <span class="keyword">return</span> self.priority() < other.priority()</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 计算当前状态和目标状态之间的曼哈顿距离作为启发式函数</span></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">heuristic</span>(<span class="params">self, current, goal</span>):</span><br><span class="line"> distance = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>): <span class="comment">#3*3</span></span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">3</span>):</span><br><span class="line"> current_pos = current.index(<span class="built_in">str</span>(i * <span class="number">3</span> + j))</span><br><span class="line"> goal_pos = goal.index(<span class="built_in">str</span>(i * <span class="number">3</span> + j))</span><br><span class="line"> current_x, current_y = current_pos // <span class="number">3</span>, current_pos % <span class="number">3</span></span><br><span class="line"> goal_x, goal_y = goal_pos // <span class="number">3</span>, goal_pos % <span class="number">3</span></span><br><span class="line"> distance += <span class="built_in">abs</span>(current_x - goal_x) + <span class="built_in">abs</span>(current_y - goal_y)</span><br><span class="line"> <span class="keyword">return</span> distance</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">priority</span>(<span class="params">self</span>):</span><br><span class="line"> <span class="comment"># 计算优先级</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">len</span>(self.state_history) + self.heuristic(self.state, self.goal)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">solved</span>(<span class="params">self</span>):</span><br><span class="line"> <span class="comment"># 判断当前状态是否为目标状态</span></span><br><span class="line"> <span class="keyword">return</span> self.state == self.goal</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">get_next</span>(<span class="params">self</span>):</span><br><span class="line"> <span class="comment"># 获取所有可能的下一步状态</span></span><br><span class="line"> next_puzzles = []</span><br><span class="line"> zero_pos = self.state.index(<span class="string">'0'</span>)</span><br><span class="line"> <span class="keyword">for</span> offset <span class="keyword">in</span> [-<span class="number">3</span>, -<span class="number">1</span>, <span class="number">1</span>, <span class="number">3</span>]:</span><br><span class="line"> new_pos = zero_pos + offset</span><br><span class="line"> <span class="keyword">if</span> new_pos < <span class="number">0</span> <span class="keyword">or</span> new_pos >= <span class="number">9</span>:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> <span class="keyword">if</span> zero_pos <span class="keyword">in</span> [<span class="number">2</span>, <span class="number">5</span>, <span class="number">8</span>] <span class="keyword">and</span> offset == <span class="number">1</span>:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> <span class="keyword">if</span> zero_pos <span class="keyword">in</span> [<span class="number">0</span>, <span class="number">3</span>, <span class="number">6</span>] <span class="keyword">and</span> offset == -<span class="number">1</span>:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> new_state = <span class="built_in">list</span>(self.state)</span><br><span class="line"> new_state[zero_pos], new_state[new_pos] = new_state[new_pos], new_state[zero_pos]</span><br><span class="line"> next_puzzles.append(Puzzle(<span class="string">''</span>.join(new_state), self.goal))</span><br><span class="line"> <span class="keyword">return</span> next_puzzles</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">a_star</span>(<span class="params">self</span>):</span><br><span class="line"> self.state_history = [] <span class="comment">#记录状态历史</span></span><br><span class="line"> frontier = [self]</span><br><span class="line"> <span class="keyword">while</span> frontier:</span><br><span class="line"> current = heapq.heappop(frontier)</span><br><span class="line"> <span class="keyword">if</span> current.solved():</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">len</span>(current.state_history)</span><br><span class="line"> <span class="keyword">for</span> puzzle <span class="keyword">in</span> current.get_next():</span><br><span class="line"> <span class="keyword">if</span> puzzle.state <span class="keyword">not</span> <span class="keyword">in</span> current.state_history:</span><br><span class="line"> puzzle.state_history = current.state_history + [current.state]</span><br><span class="line"> heapq.heappush(frontier, puzzle)</span><br><span class="line"> <span class="keyword">return</span> -<span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> init = <span class="built_in">input</span>().strip()</span><br><span class="line"> goal = <span class="string">'135702684'</span></span><br><span class="line"> <span class="comment"># 创建puzzle对象并调用A*算法得到结果</span></span><br><span class="line"> puzzle = Puzzle(init, goal)</span><br><span class="line"> result = puzzle.a_star()</span><br><span class="line"> <span class="built_in">print</span>(result)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>通过 Class Puzzle定义了该八数码问题的状态和操作,包含以下方法:<br>·init(self, state, goal):初始化 Puzzle 对象的状态和目标状态。<br>·lt(self, other):定义了对象之间的比较方法,将对象按照优先级从小到大排序。<br>·heuristic(self, current, goal):计算曼哈顿距离作为启发式函数。<br>·priority(self):计算当前状态的优先级,即 f(n) = g(n) + h(n)</p><p>·solved(self):判断当前状态是否为目标状态。<br>·get_next(self):获取所有可能的下一步状态。<br>·a_star(self):使用Astar算法求解八数码问题。<br>其中的 get_next()方法通过将空格 0 向上下左右移动来生成当前状态的所有可能的下一步状态。该方法检查移动是否有效(即 0 越过边界),并创建一个新的 Puzzle 对象,更新状态。a_star()方法实现了Astar算法,使用了一个优先队列 frontier 来存储待扩展的节点。在每次迭代中,从优先队列中取出优先级最高的节点进行扩展(f(n) = g(n) +h(n)最小)。如果该节点为目标状态,则返回状态历史的长度,即从起始状态到达目标状态的步数。如果该节点不是目标状态,则将其所有可能的下一步状态加入到优先队列中,并记录状态历史。通过这种方式,Astar算法可以保证总代价最小的节点被先访问,从而找到最优解。</p><h4 id="案例测试"><a href="#案例测试" class="headerlink" title="案例测试"></a>案例测试</h4><table><thead><tr><th><strong>Input</strong></th><th><strong>Output</strong></th></tr></thead><tbody><tr><td>135720684</td><td>1</td></tr><tr><td>105732684</td><td>1</td></tr><tr><td>015732684</td><td>2</td></tr><tr><td>135782604</td><td>1</td></tr><tr><td>715032684</td><td>3</td></tr></tbody></table><h3 id="杰克的金字塔探险"><a href="#杰克的金字塔探险" class="headerlink" title="杰克的金字塔探险"></a>杰克的金字塔探险</h3><p>在一个神秘的王国里,有一个名叫杰克的冒险家,他对宝藏情有独钟。传说在那片广袤的土地上,有一座名叫金字塔的奇迹,隐藏着无尽的财富。杰克决定寻找这座⾦字塔,挖掘隐藏在其中的宝藏。金字塔共有 N 个神秘的房间,其中 1 号房间位于塔顶,N号房间位于塔底。在这些房间之间,有先知们预先设计好的 M 条秘密通道。这些房间按照它们所在的楼层顺序进行了编号。杰克想从塔顶房间⼀直探险到塔底,带走其中的宝藏。然而,杰克对寻宝路线有着特别的要求:(1)他希望走尽可能短的路径,但为了让探险更有趣和挑战性,他想尝试 K 条不同的较短路径。(2)他希望在探险过程中尽量节省体力,所以在选择通道时,他总是从所在楼层的高处到低处。现在问题来了,给你一份金字塔内房间之间通道的列表,每条通道用(X_i, Y_i, D_i)表示,表示房间 X_i和房间 Y_i 之间有⼀条长度为 D_i 的下行通道。你需要计算出杰克可以选择的 K 条最短路径的⻓度,以便了解他在探险过程中的消耗程度。</p><h4 id="代码-1"><a href="#代码-1" class="headerlink" title="代码"></a>代码</h4><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> heapq</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Node</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, room, cost, estimate</span>):</span><br><span class="line"> self.room = room</span><br><span class="line"> self.cost = cost</span><br><span class="line"> self.estimate = estimate</span><br><span class="line"></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__lt__</span>(<span class="params">self, other</span>):</span><br><span class="line"> <span class="keyword">if</span> self.cost + self.estimate == other.cost + other.estimate:</span><br><span class="line"> <span class="comment"># 当估计距离相等时,按照节点编号升序排序</span></span><br><span class="line"> <span class="keyword">return</span> self.room < other.room</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">return</span> self.cost + self.estimate < other.cost + other.estimate</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">a_star</span>(<span class="params">N, M, K, edges</span>):</span><br><span class="line"> <span class="comment"># 邻接表表示图</span></span><br><span class="line"> graph = [[] <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(N+<span class="number">1</span>)]</span><br><span class="line"> <span class="keyword">for</span> x, y, d <span class="keyword">in</span> edges:</span><br><span class="line"> graph[x].append((y, d))</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 启发式函数</span></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">heuristic</span>(<span class="params">room</span>):</span><br><span class="line"> <span class="comment"># 如果节点没有出边,估计距离设为0</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> graph[room]:</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="comment"># 否则使用每条边的权重作为估计距离</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">min</span>(edge[<span class="number">1</span>] <span class="keyword">for</span> edge <span class="keyword">in</span> graph[room])</span><br><span class="line"></span><br><span class="line"> <span class="comment"># A*算法</span></span><br><span class="line"> k_shortest_paths = []</span><br><span class="line"> start = Node(<span class="number">1</span>, <span class="number">0</span>, heuristic(<span class="number">1</span>))</span><br><span class="line"> open_set = [start]</span><br><span class="line"> <span class="keyword">while</span> open_set <span class="keyword">and</span> <span class="built_in">len</span>(k_shortest_paths) < K:</span><br><span class="line"> visited = <span class="built_in">set</span>()</span><br><span class="line"> current = heapq.heappop(open_set)</span><br><span class="line"> <span class="keyword">if</span> current.room == N:</span><br><span class="line"> k_shortest_paths.append(current.cost)</span><br><span class="line"> <span class="keyword">for</span> neighbor, cost <span class="keyword">in</span> graph[current.room]:</span><br><span class="line"> <span class="keyword">if</span> neighbor <span class="keyword">in</span> visited:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> next_node = Node(neighbor, current.cost + cost, heuristic(neighbor))</span><br><span class="line"> heapq.heappush(open_set, next_node)</span><br><span class="line"> visited.add(current.room)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 补充不足K条路径的情况</span></span><br><span class="line"> <span class="keyword">while</span> <span class="built_in">len</span>(k_shortest_paths) < K:</span><br><span class="line"> k_shortest_paths.append(-<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> k_shortest_paths</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> N, M, K = <span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">input</span>().split())</span><br><span class="line"> edges = [<span class="built_in">tuple</span>(<span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">input</span>().split())) <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(M)]</span><br><span class="line"> result = a_star(N, M, K, edges)</span><br><span class="line"> <span class="keyword">for</span> path_length <span class="keyword">in</span> result:</span><br><span class="line"> <span class="built_in">print</span>(path_length)</span><br></pre></td></tr></table></figure><p>首先通过输入的内容构建有向图,然后定义了一个 Node 类,用于表示图中的节点。该类有三个属性:room 表示节点编号,cost 表示到该节点的路径长度,estimate 表示该节点到终点的估计距离。在 a_star()方法中,用邻接表表示图后定义启发式函数:选择该节点的所有出边中权重最小的那条边的权重作为估计距离(没有出边则估计距离为 0)。接下来开始使用 A*算法求解前 K 短路径问题,先定义一个列表 k_shortest_paths,用于存储前 K 短路径的长度,接着初始化起点 start,并将其加入到优先队列 open_set 中。然后进入一个循环,不断从优先队列中取出距离起点最短的节点 current,并根据该节点的出边更新优先队列,即遍历 current 的所有出边,对于每个邻居节点 neighbor,计算从起点到该节点的路径长度 current.cost + cost,并将该节点作为下一个节点 next_node 的父节点,并通过先前定义的启发式函数计算 next_node 到终点的估计距离 next_node.estimate,并将 next_node加入到优先队列 open_set 中,从而完成一次节点扩展。在节点扩展完毕后,检查是否已经找到了 K 条路径,若是则直接返回k_shortest_paths,否则补充不足 K 条路径的情况(设为-1,表示路径不存在)。</p><h4 id="案例测试-1"><a href="#案例测试-1" class="headerlink" title="案例测试"></a>案例测试</h4><table><thead><tr><th><strong>Input</strong></th><th><strong>Output</strong></th></tr></thead><tbody><tr><td>5 6 4<br />1 2 1 <br />1 3 1 <br />2 4 2 <br />2 5 2 <br />3 4 2 <br />3 5 2</td><td>3<br />3 <br />-1 <br />-1</td></tr><tr><td>6 9 4<br />1 2 1 <br />1 3 3 <br />2 4 2 <br />2 5 3 <br />3 6 1 <br />4 6 3</td><td>4<br />5 <br />6 <br />7</td></tr><tr><td>7 12 6<br />1 2 1 <br />1 3 3 <br />2 4 2 <br />2 5 3 <br />3 6 1 <br />4 7 3 <br />5 7 1 <br />6 7 2 <br />1 7 10 <br />2 6 4 <br />3 4 2 <br />4 5 1</td><td>5<br />5 <br />6 <br />6 <br />7 <br />7</td></tr><tr><td>5 8 7<br />1 2 1 <br />1 3 3 <br />2 4 1 <br />2 5 3 <br />3 4 2 <br />3 5 2 <br />1 4 3 <br />1 5 4</td><td>4<br />4 <br />5 <br />-1<br />-1<br />-1<br />-1</td></tr><tr><td>6 10 8<br />1 2 1 <br />1 3 2 <br />2 4 2 2 5 3 <br />3 6 3 <br />4 6 3 <br />5 6 1 <br />1 6 8 <br />2 6 5 <br />3 4 1</td><td>5<br />5 <br />6 <br />6 <br />6 <br />8 <br />-1 <br />-1</td></tr></tbody></table><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>本次通过 Astar算法解决了两道题目,通过解决具体问题巩固了 A算法的相关知识,<br>成功将理论落实到应用,但过程中也遇到了不少问题:</p><ol><li>在实现第二道题目的时候,误解题意为无向图,最后输出了 5 5 6,最后经过仔细查看题意修改为有向图,咨询后才知道给定条件中的“5 1 5”为冗余条件(因为只能下行)</li><li>在实现第二道题目时会出现无法找到部分路径问题(可以找到最短路径,但其他路径有时找不到),检查代码并调试时发现是节点的状态标记出现了问题,将已访问节点的 set设置在了搜索节点的循环之外,导致部分节点加入集合(被访问过)后被设为永久被访问,每次搜索节点都会将该节点排除在外,因此在寻找最优路径时没有影响,但查找其他路径时可能会出现找不到的情况(比如测试案例输出了 5 6 -1)</li><li>对于第二道题目的第二个测试案例,代码输出了“5 4 6 7”,经过排查调试后发现是启发式函数的选取有问题,最初基于贪心策略选取了曼哈顿距离作为启发式函数(N-room),但在一些情境下会先探索估计离目标节点近,但实际上代价更高的节点,从而导致错误的发生,修改启发式函数为选择节点的所有出边中权重最小的边的权重作为估计距离(没有出边则估计距离为 0),修改后成功解决该问题。</li></ol><p>综上,在不断解决问题的过程中进一步加深了对 A*算法的理解,认识到了启发式函数选择的重要性。</p>]]></content>
<tags>
<tag> 强化学习 </tag>
<tag> 算法 </tag>
</tags>
</entry>
<entry>
<title>基于CMU Machine Learning Faces的人脸分类识别</title>
<link href="/2023/07/13/FaceRecognition/"/>
<url>/2023/07/13/FaceRecognition/</url>
<content type="html"><![CDATA[<h2 id="基于CMU-Machine-Learning-Faces的人脸分类识别"><a href="#基于CMU-Machine-Learning-Faces的人脸分类识别" class="headerlink" title="基于CMU Machine Learning Faces的人脸分类识别"></a><strong>基于CMU Machine Learning Faces的人脸分类识别</strong></h2><p><strong>课程名称</strong>:统计方法与机器学习</p><p><strong>姓名</strong>:李昕原</p><p><strong>院校</strong>:华东师范大学 数据科学与工程学院</p><p><strong>日期</strong>:2022.12.20</p><h3 id="一、实验任务"><a href="#一、实验任务" class="headerlink" title="一、实验任务"></a><strong>一、实验任务</strong></h3><p>获取CMU Machine Learning Faces 数据集,包含 20 人中每人 32 张含表情脸图。</p><p><strong>任务 1</strong>:使用机器学习进行人脸分类识别,给出识别<strong>准确率</strong></p><p><strong>任务 2</strong>:使用<strong>聚类或分类算法</strong>发现表情相似的脸图</p><h3 id="二、实验过程"><a href="#二、实验过程" class="headerlink" title="二、实验过程"></a><strong>二、实验过程</strong></h3><h4 id="2-1-获取并查看数据集"><a href="#2-1-获取并查看数据集" class="headerlink" title="2.1 获取并查看数据集"></a>2.1 <strong>获取并查看数据集</strong></h4><p>从<a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/user/mitchell/ftp/faces.html">http://www.cs.cmu.edu/afs/cs.cmu.edu/user/mitchell/ftp/faces.html</a> 下载faces数据集,查看数据集文件夹的基本信息:<img src="https://s2.loli.net/2023/07/13/gjfqCIc2lGRAQdZ.png"></p><p>该数据集文件有 20 个文件夹,代表 20 个人的不同图片,每个文件夹里存有 32 张图片,而图片 的文件名代表了此人的面部表情,包括名字(an2i)、面部方向(left,right,straight,up)、表情(angry,happy,neutral,sad)、是否戴墨镜(open,sunglasses),通过划分文件名将各个元素写入对应列表,结果如图所示:</p><p><img src="https://s2.loli.net/2023/07/13/DR2pBiFvd3zIoKk.png"></p><h4 id="2-2-数据预处理及训练集、测试集划分"><a href="#2-2-数据预处理及训练集、测试集划分" class="headerlink" title="2.2 数据预处理及训练集、测试集划分"></a>2.2 <strong>数据预处理及训练集、测试集划分</strong></h4><p>得到该人脸识别数据集的基本组成后需要将其构造为可以用于机器学习模型训练的数据。主要思路是将 name、direction、expression、sunglasses 中的各个属性定量化(如 sunglasses 中的两个属性open 和 sunglasses 的取值分别设为 0 和 1),得到 name 取值为[0,19],direction 取值为[0,3],expression 取值为[0,3],sunglasses 取值为[0,1](均取整数),由于对各个文件遍历时是顺序读取文 件,会出现某类特征全部属于训练集或测试集的情况,且训练集与测试集的样本特征重合度不高,从而导致模型训练的效果不佳,因此需要将文件的排序打乱,考虑使用 random.shuffle 实现这一要求:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">random.shuffle(paths)</span><br></pre></td></tr></table></figure><p>训练集与测试集的比例定为 3:1,将打乱顺序后的文件名拆分为词并量化为整数,并以字典的方式存储(包括四个基本属性及图像特征),构造训练集及测试集数据并查看:</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">data</span>(<span class="params">path</span>):</span><br><span class="line"> img, name_, direction_, expression_, sunglasses_ = [], [], [], [], []</span><br><span class="line"> <span class="keyword">for</span> f <span class="keyword">in</span> path:</span><br><span class="line"> img.append(np.array(<span class="built_in">list</span>(Image.<span class="built_in">open</span>(f).convert(<span class="string">'L'</span>).getdata())))</span><br><span class="line"> str_ = f.split(<span class="string">'_'</span>)</span><br><span class="line"> <span class="comment">#特征量化</span></span><br><span class="line"> num = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(name)):</span><br><span class="line"> <span class="keyword">if</span> name[i] == str_[<span class="number">0</span>].split(<span class="string">'/'</span>)[<span class="number">2</span>]:</span><br><span class="line"> num = i</span><br><span class="line"> name_.append(num)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(direction)):</span><br><span class="line"> <span class="keyword">if</span> direction[i] == str_[<span class="number">1</span>]:</span><br><span class="line"> num = i</span><br><span class="line"> direction_.append(num)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(expression)):</span><br><span class="line"> <span class="keyword">if</span> expression[i] == str_[<span class="number">2</span>]:</span><br><span class="line"> num = i</span><br><span class="line"> expression_.append(num)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(sunglasses)):</span><br><span class="line"> <span class="keyword">if</span> sunglasses[i] == str_[<span class="number">3</span>]:</span><br><span class="line"> num = i</span><br><span class="line"> sunglasses_.append(num)</span><br><span class="line"></span><br><span class="line"> img = np.array(img)</span><br><span class="line"> name_ = np.array(name_)</span><br><span class="line"> direction_ = np.array(direction_)</span><br><span class="line"> expression_ = np.array(expression_)</span><br><span class="line"> sunglasses_ = np.array(sunglasses_)</span><br><span class="line"> <span class="keyword">return</span> {<span class="string">'image'</span>: img, <span class="string">'name'</span>: name_, <span class="string">'direction'</span>: direction_, <span class="string">'expression'</span>: expression_, <span class="string">'sunglasses'</span>: sunglasses_}</span><br><span class="line"></span><br><span class="line"><span class="comment">#训练集与测试集大小比例为3:1</span></span><br><span class="line">train_size= <span class="built_in">int</span>(<span class="built_in">len</span>(paths) * <span class="number">0.75</span>)</span><br><span class="line">path_1 = paths[:train_size]</span><br><span class="line">path_2 = paths[train_size:]</span><br><span class="line">Data = data(paths)</span><br><span class="line">train_data = data(path_1)</span><br><span class="line">test_data = data(path_2)</span><br><span class="line"><span class="built_in">print</span>(train_data)</span><br><span class="line"><span class="built_in">print</span>(train_data[<span class="string">'image'</span>].shape)</span><br><span class="line"><span class="built_in">print</span>(test_data[<span class="string">'image'</span>].shape)</span><br></pre></td></tr></table></figure><p>查看训练集及训练集与测试集规模:</p><p><img src="https://s2.loli.net/2023/07/13/7Th8FvqjuLaki6y.png"></p><p>可见训练集的规模为(468,960),测试集规模为(156,960)。</p><h4 id="2-3-使用机器学习进行人脸分类识别,给出识别准确率"><a href="#2-3-使用机器学习进行人脸分类识别,给出识别准确率" class="headerlink" title="2.3 使用机器学习进行人脸分类识别,给出识别准确率"></a>2.3 <strong>使用机器学习进行人脸分类识别,给出识别准确率</strong></h4><p>在人脸分类识别任务中,name 为需要分类的标签,图像的信息为特征,将通过<strong>支持向量机 SVM</strong>与一个<strong>神经网络</strong>来实现人脸识别分类。SVM 比较重要的参数有核函数类型 kernal、惩罚系数 C 与核函数参数 gamma,将使用网格搜索寻找最优超参数:</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></pre></td><td class="code"><pre><span class="line"><span class="comment">#SVM</span></span><br><span class="line">params = {<span class="string">'kernel'</span>:[<span class="string">'linear'</span>, <span class="string">'rbf'</span>, <span class="string">'poly'</span>, <span class="string">'sigmoid'</span>],</span><br><span class="line"> <span class="string">'C'</span>: [<span class="number">1e-2</span>, <span class="number">0.1</span>, <span class="number">1</span>, <span class="number">10</span>, <span class="number">1e2</span>],</span><br><span class="line"> <span class="string">'gamma'</span>: [<span class="string">'auto'</span>, <span class="number">0.08</span>, <span class="number">0.2</span>, <span class="number">0.4</span>, <span class="number">0.6</span>, <span class="number">0.8</span>]}</span><br><span class="line">svm = GridSearchCV(SVC(decision_function_shape=<span class="string">'ovr'</span>), params)</span><br><span class="line">svm = svm.fit(train_data[<span class="string">'image'</span>], train_data[<span class="string">'name'</span>])</span><br><span class="line"><span class="built_in">print</span>(svm.best_params_)</span><br><span class="line">y_pred = svm.predict(test_data[<span class="string">'image'</span>])</span><br><span class="line"><span class="built_in">print</span>(classification_report(test_data[<span class="string">'name'</span>], y_pred, target_names=name))</span><br><span class="line"><span class="comment">#五折交叉验证</span></span><br><span class="line">scores = cross_val_score(svm, Data[<span class="string">'image'</span>], Data[<span class="string">'name'</span>], cv=<span class="number">5</span>, scoring=<span class="string">'accuracy'</span>)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">'五折交叉验证结果'</span>, scores)</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2023/07/13/hTXY5KjSyOIgvso.png"></p><p>可见最优的超参数组合为多项式核函数 poly、惩罚系数 C=0.01,核函数参数 gamma 为auto(1/n_features),最终的 SVM 模型人脸分类识别准确率达到了 0.99,且五折交叉验证的结果也很 好,可见分类效果非常理想。 接下来实现一个神经网络来进行人脸分类识别。神经网络的实现依靠深度学习库 Keras 实现,将通过 keras.model.Sequential 构建网络模型,model.compile 与 model.fit 来分别配置训练方法并进行训练。神经网络配置的选择方面,采用一层全连接层,为了保证充分拟合的同时避免过拟合,神经元数 目设为 30;激活函数方面,选择 softmax 激活函数,可以增加区分对比度并提高学习效率,同时softmax 连续可导无拐点,对于梯度下降法非常必要;正则化方面选择 L2 正则化来提高泛化能力;学 习率设置为 0.01,采用随机梯度下降法 SGD,损失函数则使用交叉熵损失函数,在模型效果差的时候学习速度比较快,在模型效果好的时候学习速度变慢。</p><p><img src="https://s2.loli.net/2023/07/13/mziBoKX1wlZNhjD.png"></p><p>最后要将神经网络输出的<strong>one-hot 编码</strong>转为对应类别以通过 sklearn 中的 classification_report 计算准确率,并将训练过程可视化作图:</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><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="comment">#neural networks</span></span><br><span class="line">model = tf.keras.models.Sequential([</span><br><span class="line"> tf.keras.layers.Dense(</span><br><span class="line"> <span class="number">30</span>,</span><br><span class="line"> activation = <span class="string">"softmax"</span>,</span><br><span class="line"> kernel_regularizer = tf.keras.regularizers.l2()</span><br><span class="line"> )</span><br><span class="line">])</span><br><span class="line">model.<span class="built_in">compile</span>(</span><br><span class="line"> optimizer = tf.keras.optimizers.SGD(learning_rate = <span class="number">0.01</span>), </span><br><span class="line"> loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits = <span class="literal">False</span>), </span><br><span class="line"> metrics = [<span class="string">'accuracy'</span>] </span><br><span class="line">)</span><br><span class="line">history = model.fit( </span><br><span class="line"> train_data[<span class="string">'image'</span>], train_data[<span class="string">'name'</span>], </span><br><span class="line"> batch_size = <span class="number">64</span>,</span><br><span class="line"> epochs = <span class="number">400</span>,</span><br><span class="line"> validation_split = <span class="number">0.2</span></span><br><span class="line">)</span><br><span class="line">y_pred_hot = model.predict(test_data[<span class="string">'image'</span>])</span><br><span class="line">y_pred=[]</span><br><span class="line"><span class="comment">#one-hot编码转为对应类别</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> y_pred_hot:</span><br><span class="line"> y_pred.append(np.argmax(i))</span><br><span class="line"><span class="built_in">print</span>(classification_report(test_data[<span class="string">'name'</span>], y_pred, target_names=name))</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2023/07/13/qxlapMUEVoy81d2.png"></p><p>损失下降与训练集、测试集准确率图:</p><p><img src="https://s2.loli.net/2023/07/13/y1PsSlNBJRmn8ax.png"></p><p><img src="https://s2.loli.net/2023/07/13/fv1SnmE4Oz2HaYy.png"></p><p>最终报告:</p><p><img src="https://s2.loli.net/2023/07/13/8u3eM67ZJkBoRqj.png"></p><p>可见神经网络人脸分类识别的最终识别准确率达到了<strong>0.98</strong>,效果也非常理想。</p><p>综上,人脸分类识别任务通过 SVM 支持向量机、神经网络分别实现,准确率均在<strong>0.99</strong> 左右,效果很好。</p><h4 id="2-4-使用聚类或分类算法发现表情相似的脸图"><a href="#2-4-使用聚类或分类算法发现表情相似的脸图" class="headerlink" title="2.4 使用聚类或分类算法发现表情相似的脸图"></a>2.4 <strong>使用聚类或分类算法发现表情相似的脸图</strong></h4><p>在该数据集中人物的表情特征包括人脸朝向 direction、人的表情 expression、是否戴墨镜sunglasses,而发现表情相似脸图这一问题的标签为表情 expression,首先通过任务一中使用的 SVM 与神经网络进行人脸表情识别,代码与之前任务的人脸识别分类类似(仅将标签由 name 修改为expression),故不再列出,仅列出结果。</p><p>****SVM:</p><p><img src="https://s2.loli.net/2023/07/13/EGiz97LaPhsgFbY.png"></p><p>神经网络及可视化结果:</p><p><img src="https://s2.loli.net/2023/07/13/HpsrdWKxXE6oqaP.png"></p><p><img src="https://s2.loli.net/2023/07/13/54ifljbwEBPVpWT.png"></p><p>由图可知神经网络训练过程中损失波动很大且下降幅度小,而训练集与测试集的准确率都有较大 波动,可知分类效果较差,报告也验证了这一点:</p><p><img src="https://s2.loli.net/2023/07/13/NACYLKue1O7XVrI.png"></p><p>SVM 的相似表情识别准确率为 0.23,神经网络为 0.19,这与人脸分类识别时两个模型的高分类准 确率大相径庭,效果非常不理想。接下来使用聚类算法<strong>KMeans</strong> 尝试进行表情相似分类,由于表情expression 有四类,故无监督学习 KMeans 的 n_clusters 设为 4:</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></pre></td><td class="code"><pre><span class="line">clf = cluster.KMeans(</span><br><span class="line"> init=<span class="string">'k-means++'</span>,</span><br><span class="line"> n_clusters=<span class="number">4</span>, </span><br><span class="line"> random_state=<span class="number">1</span>, </span><br><span class="line"> max_iter = <span class="number">2000</span></span><br><span class="line">)</span><br><span class="line">clf.fit(train_data[<span class="string">'image'</span>])</span><br><span class="line">y_pred = clf.predict(test_data[<span class="string">'image'</span>])</span><br></pre></td></tr></table></figure><p>聚类后将每一类的前 10 个样本对应的图像输出:</p><p><img src="https://s2.loli.net/2023/07/13/myVM7LR65pbh8wo.png"></p><p><img src="https://s2.loli.net/2023/07/13/eMCHtx4w7NPDBW2.png"></p><p><img src="https://s2.loli.net/2023/07/13/1Myg3jn7WH5seUB.png"></p><p><img src="https://s2.loli.net/2023/07/13/8tm7wP1ZoYkuVHa.png"></p><p>直观上看感觉表情相似聚类效果一般,报告也证明了确实效果不佳:</p><p><img src="https://s2.loli.net/2023/07/13/TCQrZsA2x5O84dE.png"></p><p>KMeans 聚类的准确率仅有 0.29,比 SVM 与神经网络的准确率稍高一点,可见不论是分类算法 还是聚类算法在表情相似识别这一问题上均效果不佳,通过 PCA 对数据进行降维再进行 KMeans 聚 类:</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">#PCA降维</span></span><br><span class="line">pca = PCA(n_components = <span class="number">2</span>)</span><br><span class="line">pca.fit(train_data[<span class="string">'image'</span>])</span><br><span class="line">train_data_pca = pca.transform(train_data[<span class="string">'image'</span>])</span><br><span class="line">test_data_pca = pca.transform(test_data[<span class="string">'image'</span>])</span><br><span class="line">clf_pca = cluster.KMeans(</span><br><span class="line"> init=<span class="string">'k-means++'</span>,</span><br><span class="line"> n_clusters=<span class="number">4</span>, </span><br><span class="line"> random_state=<span class="number">1</span>, </span><br><span class="line"> max_iter = <span class="number">2000</span></span><br><span class="line">)</span><br><span class="line">clf_pca.fit(train_data_pca)</span><br><span class="line">y_pred = clf.predict(test_data[<span class="string">'image'</span>])</span><br><span class="line"><span class="built_in">print</span>(classification_report(test_data[<span class="string">'expression'</span>], y_pred, target_names=expression))</span><br></pre></td></tr></table></figure><p>对表情分类识别的聚类簇进行可视化并标记聚类中心:</p><p><img src="https://s2.loli.net/2023/07/13/LhbW3r1dXVx6DOv.png"></p><p><img src="https://s2.loli.net/2023/07/13/543EfQzULF6bykT.png"></p><p>准确率依然较低,推测三种分类与聚类算法准确率均较低的原因有以下两点:</p><ol><li>数据集除人脸外还包括了与人脸无关的背景,因此存在比较严重的噪声;</li><li>数据集规模较小且是两通道灰度图,人脸表情的特征损失较多。</li></ol><h4 id="2-5-使用-SVM-识别人脸方向与是否戴墨镜"><a href="#2-5-使用-SVM-识别人脸方向与是否戴墨镜" class="headerlink" title="2.5 使用 SVM 识别人脸方向与是否戴墨镜"></a>2.5 <strong>使用</strong> SVM <strong>识别人脸方向与是否戴墨镜</strong></h4><p>前面两个任务分别将 name 与 expression 作为标签,而剩下的人脸方向 direction 与是否戴墨镜sunglasses 并未做过分类识别任务,因此基于 SVM 将这两个特征作为标签进行分类识别,代码与上 述相似故不展示,仅展示分类效果及分类结果部分样本的图像: 人脸方向:</p><p><img src="https://s2.loli.net/2023/07/13/G9m7TfMAJjSiqWC.png"></p><p><img src="https://s2.loli.net/2023/07/13/YKTicQJj75xAhby.png"></p><p>是否戴墨镜:</p><p><img src="https://s2.loli.net/2023/07/13/Mvhu1YKz69dxbFg.png"></p><p><img src="https://s2.loli.net/2023/07/13/c5n3aNRPpg9wElK.png"></p><p>样本分别为人脸朝向右侧与不戴墨镜的情况,准确率分别为 0.99 与 0.95 效果均不错,可见除了 表情 expression 其余标签的分类识别效果均很优秀,这同样印证了上述人脸表情特征损失较多这一推论。</p><h3 id="三、总结"><a href="#三、总结" class="headerlink" title="三、总结"></a><strong>三、总结</strong></h3><p>本次实验获取并查看了 CMU Machine Learning Faces 数据集,通过 SVM 与神经网络模型训练完 成了任务 1:人脸分类识别,准确率均在 0.99 左右,取得了不错的效果,后通过 SVM、神经网络与KMeans 聚类进行任务 2:表情相似识别,但效果不佳,并分析了准确率较低的两点原因(背景噪声 严重、人脸表情特征损失较多)。此外还对另外两个标签人脸朝向与是否戴墨镜进行分类识别,准确率也均在 0.95 也上,同样取得了不错的效果。</p>]]></content>
<tags>
<tag> 机器学习 </tag>
</tags>
</entry>
<entry>
<title>夏令营项目总结与反思</title>
<link href="/2023/05/07/Summary/"/>
<url>/2023/05/07/Summary/</url>
<content type="html"><![CDATA[<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><ul><li><h2 id="博客主题及其选取原因"><a href="#博客主题及其选取原因" class="headerlink" title="博客主题及其选取原因"></a>博客主题及其选取原因</h2><p>博客选取了<strong>Hexo</strong>框架,原因如下:</p><ol><li>快速:Hexo使用Node.js来生成静态网页,因此速度非常快,甚至可以在数百毫秒内生成完整的博客网站。</li><li>简单:Hexo具有简单易用的命令行界面,可以轻松创建和管理博客文章、页面、标签、分类等内容。</li><li>主题和插件:Hexo具有丰富的主题和插件,可以轻松地自定义博客的外观和功能,例如社交分享、SEO优化、Google Analytics等。</li><li>安全:由于Hexo是一个静态博客框架,它没有后端服务器,因此不需要担心服务器安全和维护问题。</li><li>可移植性:Hexo生成的静态网页可以轻松地部署到任何Web服务器上,例如GitHub Pages、Netlify、AWS等,使得博客具有高度的可移植性和可扩展性。</li><li>开源:Hexo是一个开源项目,拥有一个庞大的社区,可以轻松地获取技术支持和文档资料。</li></ol><p>博客的主题选取了<strong>Butterfly</strong>,原因如下:</p><ol><li>界面美观:Butterfly主题采用了现代化的设计风格,使得博客的界面非常美观和吸引人。它提供了多种颜色和布局选项,以便用户可以自定义自己的博客。</li><li>响应式设计:Butterfly主题具有响应式设计,可以自适应不同的设备和屏幕尺寸,使得博客在桌面、平板和手机等设备上都能够良好显示。</li><li>支持多种语言:Butterfly主题支持多种语言,包括英语、中文、日语等,可以满足不同语言用户的需求。</li><li>丰富的功能:Butterfly主题提供了许多丰富的功能,包括代码高亮、目录、标签云、评论等,使得博客更加易于阅读和管理。</li><li>插件支持:Butterfly主题支持许多Hexo插件,可以通过插件扩展博客的功能和特性,如社交分享、Google Analytics等。</li></ol></li><li><h2 id="博客页面布局及其设计思路"><a href="#博客页面布局及其设计思路" class="headerlink" title="博客页面布局及其设计思路"></a>博客页面布局及其设计思路</h2><p>Hexo Butterfly的首页采用瀑布流式布局,使文章列表更加美观且易于阅读此外还设计了自我介绍的相关页面与文章列表页面,文章列表按照发布时间倒序排列,每篇文章都显示标题、摘要和发布日期。文章页面布局简洁明了,注重内容展示。文章页面的顶部包括文章的标题、发布日期和标签等信息,接着是文章的正文内容。归档页面按照时间顺序展示所有已发布的文章,并提供了便于导航的文章分类和标签云功能。</p></li><li><h2 id="博客功能实现及其技术选择"><a href="#博客功能实现及其技术选择" class="headerlink" title="博客功能实现及其技术选择"></a>博客功能实现及其技术选择</h2><p>博客主页如下:</p><p><img src="https://s2.loli.net/2023/07/14/9Qauz1RFw56ANDn.png" alt="1689312750780"></p><p>博客功能包括可以查看博文:</p><p><img src="https://s2.loli.net/2023/07/13/JnZ6VGzBdWfFgcH.png" alt="img"></p><p>点击github图标可以给进入我的github主页,点击邮箱图标可以给我发送邮箱 。右上角点击About可以查看我的个人简介:</p><p><img src="https://s2.loli.net/2023/07/13/8RMDOUT2IwikWsn.png" alt="img"></p><p>Archieve可以查看发布博客的归档信息,tag可以查看不同标签下的博客:</p><p><img src="https://s2.loli.net/2023/07/13/7itjZozOPkAJ8ey.png" alt="img"></p><p>Blog的结构性强,里面代码的可读性强,写了关键部分的注释:</p></li></ul><p><img src="https://s2.loli.net/2023/07/13/3hIla2jSQZxHnyF.png" alt="img"></p><p>此外还添加了搜索等等功能,可以去博客网站内查看:</p><p><img src="https://s2.loli.net/2023/07/14/fz5JPuXmU6yIhoK.png" alt="1689312545441"></p><ul><li><h2 id="博客制作过程中遇到的问题及反思其解决方法"><a href="#博客制作过程中遇到的问题及反思其解决方法" class="headerlink" title="博客制作过程中遇到的问题及反思其解决方法"></a>博客制作过程中遇到的问题及反思其解决方法</h2><p>·修改首页图片时发现图片不显示,查找相关教程后得知需要将图片插入themes/butterfly/source/images路径中</p><p>·修改相关配置的时候需要在:后面空格再输入</p><p>由于大学的实验报告几乎没有用markdown写的,因此没法直接发布在博客网站中,等未来有时间了后再一一传上来。</p></li></ul>]]></content>
</entry>
<entry>
<title>Hello World</title>
<link href="/2023/05/05/hello-world/"/>
<url>/2023/05/05/hello-world/</url>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
</entry>
</search>