-
Notifications
You must be signed in to change notification settings - Fork 2
/
atom.xml
290 lines (262 loc) · 71.9 KB
/
atom.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Andy's Blog</title>
<subtitle>寫下學習路途的風景test</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://andy112247.github.io/"/>
<updated>2017-03-26T01:36:41.353Z</updated>
<id>https://andy112247.github.io/</id>
<author>
<name>Andy</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title></title>
<link href="https://andy112247.github.io/2017/03/26/%E4%BA%BA%E5%B7%A5%E6%99%BA%E6%85%A7%E4%B9%8B%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92%E4%B9%8B%E7%A5%9E%E7%B6%93%E7%B6%B2%E8%B7%AF%E3%81%AE%E7%AD%86%E8%A8%98(1)-%E6%84%9F%E7%9F%A5%E6%A9%9F/"/>
<id>https://andy112247.github.io/2017/03/26/人工智慧之機器學習之神經網路の筆記(1)-感知機/</id>
<published>2017-03-26T01:12:17.234Z</published>
<updated>2017-03-26T01:36:41.353Z</updated>
<content type="html"><![CDATA[<h1 id="人工智慧之機器學習之神經網路の筆記-1-感知機"><a href="#人工智慧之機器學習之神經網路の筆記-1-感知機" class="headerlink" title="人工智慧之機器學習之神經網路の筆記(1)-感知機"></a>人工智慧之機器學習之神經網路の筆記(1)-感知機</h1><h4 id="c語言-實作and-or-xor-邏輯閘感知機"><a href="#c語言-實作and-or-xor-邏輯閘感知機" class="headerlink" title="c語言 實作and or xor 邏輯閘感知機"></a>c語言 實作and or xor 邏輯閘感知機</h4><p>完成後將會發布至 (<a href="https://andy112247.github.io">https://andy112247.github.io</a>)<br>我是新手LV1 可能會有很多地方打錯(說不定連標題都是錯的<br>總之發現有錯誤的話麻煩指正我,3Q</p>
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p><img src="http://i.imgur.com/xAFiPm3.jpg" alt=""><br>網路上的教學常常都是寫一堆嚇死人的數學公式,要不然就是範例程式寫得一坨拉庫令人退避三舍,對於我這麼一個數學廢物來說要看懂實在是太困難了,於是我決定順便寫一個簡單易懂公式不多程式看起來也不複雜的筆記(應該啦…<br>大概是國中高中會寫if for就能看懂的難度喔~</p>
<p><excerpt in="" index="" |="" 首页摘要=""><br>…<a id="more"></a></excerpt></p>
<the rest="" of="" contents="" |="" 余下全文="">
<h1 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h1><p>看到這邊或許有人會對我的標題感到不解,為啥說不要寫得很複雜標題卻又是麼一坨呢?<br>我想很多人跟我剛開始學這東東一樣不太理解</p>
<ul>
<li>人工智慧</li>
<li>機器學習</li>
<li>神經網路</li>
</ul>
<p>這幾個是甚麼意思差別在哪裡?</p>
<p><a href="https://blogs.nvidia.com.tw/2016/07/whats-difference-artificial-intelligence-machine-learning-deep-learning-ai/" target="_blank" rel="external">nvidia 部落格的解釋</a> 寫得很多啦!我只有停留三秒…<br>重點是這張圖<br><img src="https://blogs.nvidia.com/wp-content/uploads/2016/07/Deep_Learning_Icons_R5_PNG.jpg.png" alt=""></p>
<p><img src="https://www.stockfeel.com.tw/wp-content/uploads/2016/12/%E5%9C%96011.png" alt=""></p>
<p>人工智能領域,有一個方法叫機器學習。在機器學習這個方法裡,有一類算法叫神經網絡。神經網絡如下圖所示:<br><img src="http://si.secda.info/buss-math/images/stories/function/ch12/12function-04.jpg" alt=""></p>
<h6 id="引用自-http-si-secda-info-buss-math-index-php-2013-01-12-15-28-58-2012-09-23-07-08-48"><a href="#引用自-http-si-secda-info-buss-math-index-php-2013-01-12-15-28-58-2012-09-23-07-08-48" class="headerlink" title="引用自:http://si.secda.info/buss-math/index.php/2013-01-12-15-28-58/2012-09-23-07-08-48"></a>引用自:<a href="http://si.secda.info/buss-math/index.php/2013-01-12-15-28-58/2012-09-23-07-08-48" target="_blank" rel="external">http://si.secda.info/buss-math/index.php/2013-01-12-15-28-58/2012-09-23-07-08-48</a></h6><p>不用太認真看上圖 真的<br>上面都是嚇嚇你而已xDDD</p>
<p>下面才是這次要說的重點</p>
<h1 id="單層感知機"><a href="#單層感知機" class="headerlink" title="單層感知機"></a>單層感知機</h1><p>何謂單層?相較於上面那張圖有隱藏層,單層就是顧名思義是單一一層(廢話<br>那感知機呢?感知機是啥詳細請自己GOOGLE一下,我稍微介紹而已<br>介紹前先看看實際在你我身體裡的神經長怎麼樣<br><img src="http://i.imgur.com/AMEYXid.png" alt=""></p>
<p>這個圖有點太詳細啦<br>簡單一點的<br><img src="http://i.imgur.com/HNlqMNB.png" alt=""><br>然後我們的感知機就是要模擬這個神經細胞<br>乃看看感知機長甚麼樣ㄅ~他不是魚也不是蝌蚪<br><img src="http://i.imgur.com/AAz5xSx.png" alt=""><br>其中x1,x2如同樹突一樣是輸入<br>而y就是像突觸一樣是輸出<br>w1,w2則是權重<br><img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Ctheta%20" style="border:none;">這個是閥值</p>
<p>國中生物課有教過<br>印象中神經細胞透過樹突接收訊號再傳到突觸讓下一個神經細胞接收<br>其中在傳遞過程會有不同權重的神經細胞,<br>例如 經過某個神經細胞時就會加強訊號之類的(詳細我不太會解釋…就麻煩各為自己查詢了</p>
<p>總之這其中加強訊號等等的行為我們可以透過以下公式模擬</p>
<p><img src="http://chart.googleapis.com/chart?cht=tx&chl=f(x)%3Dx1*w1%2Bx2*w2%2B%5Ctheta%20" style="border:none;"></p>
<p>輸出 = 輸入 x 權重 + 閥值</p>
<p>閥值….ㄜ….就是一個閥值<br>例如 閥值是(-10) 那 輸入 x 權重 沒有超過10的話就會是負數</p>
<p>阿對 正確數學模型是長這樣</p>
<p><img src="http://i.imgur.com/ttdpuD9.jpg" alt=""></p>
<p>sign()裡面的東西就是剛剛講的這個<img src="http://chart.googleapis.com/chart?cht=tx&chl=f(x)%3Dx1*w1%2Bx2*w2%2B%5Ctheta%20" style="border:none;">公式只是我的圖片只有兩個輸入所以只到x2,w2醬子</p>
<p>而sign就是一個步階公式<br>以下例子的公式</p>
<p>若數字大於0傳出1 小於0則傳出0</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">int fstep(double x){ </div><div class="line"> if (x > 0)</div><div class="line"> return 1;</div><div class="line"> else</div><div class="line"> return 0;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>再補一張圖 在看不懂就沒辦法了<br><img src="http://i.imgur.com/5aW41x6.png" alt=""></p>
<h1 id="感知機的訓練"><a href="#感知機的訓練" class="headerlink" title="感知機的訓練"></a>感知機的訓練</h1><p>機器學習<br>是通過演算法來分析數據、從中學習,以及判斷或預測現實世界裡的某些事,並非手動編寫帶有特定指令的軟體程序來完成某個特殊任務,而是使用大量的數據和演算法來「訓練」機器,讓它學習如何執行任務。</p>
<p>感知器即透過訓練調節權重值w~i~來減少感知器”期望輸出”與”實際輸出”之間的”誤差”,來達到這任務,也就是說當得到適當的權重值w~i~時,我們即可得到決策邊界。<br>假設反覆疊代訓練n次,期望輸出為ya(n),實際輸出為y(n),那麼誤差e(n)為:</p>
<pre><code>e(n)=ya(n)-y(n)
</code></pre><p>為了讓誤差變小<br>如果e(n)為正,就需要增加感知器輸出Y(n);如果e(n)為負,就需要減少感知器輸出Y(n)。</p>
<p>再看一次公式<img src="http://chart.googleapis.com/chart?cht=tx&chl=f(x)%3Dx1*w1%2Bx2*w2%2B%5Ctheta%20" style="border:none;"><br>我們要讓感知機學習調整的有w~i~和<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Ctheta%20" style="border:none;"></p>
<p>為了讓他能學習(其實就是不要一直丟一樣的數字)我們設一個”學習效率”的變數a<br>再設Δw~i~為</p>
<p><br></p>
<p>Δw~i~(n) = a <em> x~i~(n) </em> e(n)</p>
<p><br></p>
<p>整個過程用途來表示就是<br><img src="http://i.imgur.com/bhbFHKJ.jpg" alt=""></p>
<p>(yd=預期輸出答案)</p>
<p>可能有人會疑惑的問為甚麼Δw~i~是用a<em>x~i~</em>e</p>
<p>a的作用是用來讓數字變化<br>e這個透過ya-y計算出的誤差,則是有個其中技巧所在</p>
<p>我們觀察<br>假設x~1~和w~1~相乘為正數,誤差若是正數(ya-y)代表需要增加w~1~的權值;</p>
<p>例如:<br>x~1~=10;<br>w~1~=0.5;<br>ya=7;<br>y=5=10<em>0.5;<br>而期望輸出卻是7,所以應該要增加w~1~的權值,使答案更接近<br>(這裡簡化算式,實際上輸出y是還要加上w~2~</em>x~2~最後在減去<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Ctheta%20" style="border:none;">)</p>
<p>Δw~i~(n) = a <em> x~i~(n) </em> e(n)<br>所以在這裡e為2(7-5),x~i~為10,a設為0.1;<br>則 Δw~i~=0.1 <em> 10 </em> 2 = 2<br>這樣就提高了w~i~的權值了<br><br><br><br></p>
<p>而誤差若是負數(ya-y)代表需要減少w~1~的權值;</p>
<p>例如:<br>x~1~=20;<br>w~1~=0.5;<br>ya=7;<br>y=10=20*0.5;<br>而期望輸出卻是7,所以應該要減少w~1~的權值,使答案更接近</p>
<p>Δw~i~(n) = a <em> x~i~(n) </em> e(n)<br>所以在這裡e為-3(7-10),x~i~為10,a設為0.1;<br>則 Δw~i~=0.1 <em> 10 </em> -3 = -3<br>這樣就減少了w~i~的權值了</p>
<p>(繼續代下去修正數字可能會變得很奇怪,是因為我在這裡簡化算式,實際上輸出y是還要加上w~2~*x~2~最後在減去<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Ctheta%20" style="border:none;">)</p>
<p>學習效率a就是用來控制每次調整權值時的數字差異(別讓他變化太快(<br>?)</p>
<p>其實這個意思就是不斷地改變數字 讓他離答案越來越近<br>這個”答案”又稱為”決策邊界”實際上就只是一個函數<br>用來區分不同答案的函數<br><img src="http://i.imgur.com/7IcT9mY.png" alt=""></p>
<p>就像這張圖感知姬透過不斷的修正w~i~ 和<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Ctheta%20" style="border:none;">來產生出能區分紅點和藍點的方程式w~1~<em>x~1~+w~2~</em>x~2~+<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Ctheta%20" style="border:none;">=0</p>
<h1 id="實作感知機"><a href="#實作感知機" class="headerlink" title="實作感知機"></a>實作感知機</h1><p>以下實作感知機將帶入經典例子AND_OR邏輯閘來輔助敘述<br>增值表如下:<br><img src="http://i.imgur.com/QFJG97e.png" alt=""><br>(抱歉網路上圖片版權太麻煩 隨手畫一張還看得懂就好)</p>
<p>整理上述我們得到感知機的步驟為</p>
<h3 id="1-初始化"><a href="#1-初始化" class="headerlink" title="1.初始化"></a>1.初始化</h3><p>設定權重w~i~的預設值和臨界值<img src="http://chart.googleapis.com/chart?cht=tx&chl=%5Ctheta%20" style="border:none;">的預設值,與匯入資料Xi~1~,Xi~2~,ya_and,ya_or,ya_xor,與學習效率a</p>
<p>xi1 = {0, 0, 1, 1,……<br>這是每4個數字一組,用來重複訓練感知機</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">double w1 = 0.1, w2 = 0.1, a = 0.1, s = -0.1;</div><div class="line"></div><div class="line"></div><div class="line">int xi1[] = {0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1};</div><div class="line"></div><div class="line">int xi2[] = {0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; </div><div class="line"></div><div class="line">int ya_and[] = {0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}; //AND閘 的 預期答案</div><div class="line"></div><div class="line"></div><div class="line">/**/</div><div class="line">int ya_or[] = {0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1}; //OR閘 的 預期答案</div></pre></td></tr></table></figure>
<p><br><br><br><br><br></p>
<h3 id="2-激勵"><a href="#2-激勵" class="headerlink" title="2.激勵"></a>2.激勵</h3><p>(好像這是專有名詞(?反正網路上大家都這樣說啦 就先當成這樣了</p>
<p>第二部主要就是算出Y</p>
<p><img src="http://i.imgur.com/ttdpuD9.jpg" alt=""><br>在我們這個邏輯閘例子中有兩個輸入(X~1~,X~2~)所以n=2</p>
<p>把這個公式拆成兩部分來寫</p>
<p><img src="http://chart.googleapis.com/chart?cht=tx&chl=f(x)%3Dx1*w1%2Bx2*w2%2B%5Ctheta%20" style="border:none;"></p>
<p>和</p>
<p>sign步階公式(我取名叫fstep)<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">/*</div><div class="line"> 階梯函數</div><div class="line"> input 任意含小數點的數字</div><div class="line"> return 若數字大於0傳回1 否則傳回0</div><div class="line">*/</div><div class="line">int fstep(double x){ </div><div class="line"> if (x > 0)</div><div class="line"> return 1;</div><div class="line"> else</div><div class="line"> return 0;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>把前面f(x)丟進fstep()裡面就能融合出Y啦!<br>Y=fste(f(x));</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">int fx(int x1, double w1, int x2, double w2, double s){</div><div class="line"></div><div class="line"> return fstep((x1 * w1 + x2 * w2) + s);</div><div class="line"> </div><div class="line">}</div></pre></td></tr></table></figure>
<p>上面就是return fstep()裡面就是<img src="http://chart.googleapis.com/chart?cht=tx&chl=f(x)%3Dx1*w1%2Bx2*w2%2B%5Ctheta%20" style="border:none;">的程式實作</p>
<p>return時直接帶上fstep<br>就會是<br><img src="http://i.imgur.com/ttdpuD9.jpg" alt=""></p>
<p>數學公式看起來很嚇人但實際上程式碼一行就能解決OAO<br><br><br><br><br><br></p>
<h3 id="3-權重訓練"><a href="#3-權重訓練" class="headerlink" title="3.權重訓練"></a>3.權重訓練</h3><p>修正權重醬子</p>
<ul>
<li>wi = wi + Δwi(n)</li>
<li>Δwi = α ∗ xi(n) ∗ ex</li>
<li>ex = Yd(n)−Y(n)</li>
<li>s = a <em> s </em> ex</li>
</ul>
<p>為了表示誤差ex(),我就多此一舉寫了一個會把前面數字檢後面數字的函數,(實際上直接相減就好</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">int ex(int ya, int yd){ //誤差=期望輸出-實際輸出</div><div class="line"> return ya - yd;</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">w1 = a * xi1[i] * ex(ya[i] , fstep(fx(xi1[i], w1, xi2[i], w2, s))); //調整w1權值</div><div class="line"></div><div class="line"> </div><div class="line">w2 = a * xi2[i] * ex(ya[i] , fstep(fx(xi1[i], w1, xi2[i], w2, s))); //調整w2權值</div><div class="line"></div><div class="line">s = a * s * ex(ya[i] , fstep(fx(xi1[i], w1, xi2[i], w2, s)));//調整s值</div></pre></td></tr></table></figure>
<p><br><br><br><br><br></p>
<h3 id="4-疊代"><a href="#4-疊代" class="headerlink" title="4.疊代"></a>4.疊代</h3><p>好像是專業名詞是這麼叫的,不過實際上就是透過迴圈不停的修正權值來訓練感知機</p>
<p>程式碼部分就是剛剛第三步驟的加上一個for迴圈醬子</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">for (int i = 0; i < 19 * 4; i++){</div><div class="line"></div><div class="line"> if (i % 4 == 0)printf("\n"); //每4組數字換行</div><div class="line"> </div><div class="line"> w1 = a * xi1[i] * ex(ya[i], fstep(fx(xi1[i], w1, xi2[i], w2, s))); //調整w1權值 </div><div class="line"> </div><div class="line"> w2 = a * xi2[i] * ex(ya[i], fstep(fx(xi1[i], w1, xi2[i], w2, s))); //調整w2權值</div><div class="line"> </div><div class="line"> s = a * s * ex(ya[i], fstep(fx(xi1[i], w1, xi2[i], w2, s)));</div><div class="line"> </div><div class="line"> printf("%d ", fstep(fx(xi1[i], w1, xi2[i], w2, s)));</div><div class="line">}</div></pre></td></tr></table></figure>
<p><br><br><br><br><br></p>
<p>c語言程式碼實作</p>
<h1 id="AND-OR-XOR-邏輯閘感知器"><a href="#AND-OR-XOR-邏輯閘感知器" class="headerlink" title="AND OR XOR 邏輯閘感知器"></a>AND OR XOR 邏輯閘感知器</h1><p>其實就是把程式碼組合在一起而已…<br>想靠北的是網路上一堆程式碼都寫得超級複雜得 弱弱的我表示哭哭喔</p>
<p><a href="https://gist.github.com/andy112247/80f50eebcb49f8bba7be5a0ce375aeac" target="_blank" rel="external">https://gist.github.com/andy112247/80f50eebcb49f8bba7be5a0ce375aeac</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div></pre></td><td class="code"><pre><div class="line">#include <stdio.h></div><div class="line">#include <stdlib.h></div><div class="line"></div><div class="line"></div><div class="line">/*</div><div class="line"> 階梯函數</div><div class="line"> input 任意含小數點的數字</div><div class="line"> return 若數字大於0傳回1 否則傳回0</div><div class="line">*/</div><div class="line">int fstep(double x){ </div><div class="line"> if (x > 0)</div><div class="line"> return 1;</div><div class="line"> else</div><div class="line"> return 0;</div><div class="line">}</div><div class="line"></div><div class="line">/*</div><div class="line"> 計算</div><div class="line">*/</div><div class="line">int fx(int x1, double w1, int x2, double w2, double s){</div><div class="line"> double ans;</div><div class="line"> ans = (x1 * w1 + x2 * w2) + s;</div><div class="line"> return fstep(ans);</div><div class="line">}</div><div class="line"></div><div class="line">int ex(int ya, int yd){ //誤差=期望輸出-實際輸出</div><div class="line"> return ya - yd;</div><div class="line">}</div><div class="line"></div><div class="line">int main(void){</div><div class="line"></div><div class="line"> int xi1[] = {0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,</div><div class="line"> 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1};</div><div class="line"></div><div class="line"> int xi2[] = {0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,</div><div class="line"> 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; </div><div class="line"> /*</div><div class="line"> int ya[] = {0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,</div><div class="line"> 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}; //AND閘 的 預期答案</div><div class="line"> */</div><div class="line"></div><div class="line"> /**/</div><div class="line"> int ya[] = {0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,</div><div class="line"> 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1}; //OR閘 的 預期答案</div><div class="line"> /**/</div><div class="line"> /*</div><div class="line"> int ya[] ={0,1,1,0,</div><div class="line"> 0,1,1,0,0,1,1,0,0,1,1,0,</div><div class="line"> 0,1,1,0,0,1,1,0,0,1,1,0,</div><div class="line"> 0,1,1,0,0,1,1,0,0,1,1,0,</div><div class="line"> 0,1,1,0,0,1,1,0,0,1,1,0,</div><div class="line"> 0,1,1,0,0,1,1,0,0,1,1,0,</div><div class="line"> 0,1,1,0,0,1,1,0,0,1,1,0};</div><div class="line"> */</div><div class="line"></div><div class="line"> double w1 = 0.1, w2 = 0.1, a = 0.1, s = -0.1;</div><div class="line"></div><div class="line"> for (int i = 0; i < 19 * 4; i++){</div><div class="line"></div><div class="line"> if (i % 4 == 0)printf("\n"); //每4組數字換行 </div><div class="line"></div><div class="line"> // w = w + a * xi * ex</div><div class="line"> w1 = a * xi1[i] * ex(ya[i], fstep(fx(xi1[i], w1, xi2[i], w2, s))); //調整w1權值</div><div class="line"> </div><div class="line"> </div><div class="line"> w2 = a * xi2[i] * ex(ya[i], fstep(fx(xi1[i], w1, xi2[i], w2, s))); //調整w2權值</div><div class="line"> </div><div class="line"> s = a * s * ex(ya[i], fstep(fx(xi1[i], w1, xi2[i], w2, s)));</div><div class="line"></div><div class="line"> printf("%d ", fstep(fx(xi1[i], w1, xi2[i], w2, s)));</div><div class="line"> }</div><div class="line"> printf("\n w1 = %f w2 = %f s = %f \n", w1, w2 ,s);</div><div class="line"></div><div class="line"> return 0;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>如果乖乖的小朋友實作後一定會發現xor為甚麼訓練出來的答案並不是正確的<br>恩…這就是單層感知機無法做的東西,好像也因此世界科技術這邊卡了一陣子(?</p>
<p>先這樣了,比較有空時會再補全</p>
<h1 id="引用來源"><a href="#引用來源" class="headerlink" title="引用來源"></a>引用來源</h1><p>感謝各位大大在網路上的貢獻小弟也在這裡獻上我的筆記<br>版權問題希望不要太麻煩 有問題email我會盡快處理<br>總之我不做營運使用僅作為學術研究用m(<em> </em>)m</p>
<p><a href="http://arbu00.blogspot.tw/2016/11/1-pythonperceptron.html" target="_blank" rel="external">http://arbu00.blogspot.tw/2016/11/1-pythonperceptron.html</a></p>
<p><a href="https://zh.wikipedia.org/wiki/%E7%A5%9E%E7%B6%93%E5%85%83" target="_blank" rel="external">https://zh.wikipedia.org/wiki/%E7%A5%9E%E7%B6%93%E5%85%83</a></p>
<p><a href="http://www.automatingthefuture.com/blog/2016/9/7/artificial-neural-networks-elixir-and-you" target="_blank" rel="external">http://www.automatingthefuture.com/blog/2016/9/7/artificial-neural-networks-elixir-and-you</a></p>
<p><a href="http://ccckmit.wikidot.com/nn:perceptroncsharp" target="_blank" rel="external">http://ccckmit.wikidot.com/nn:perceptroncsharp</a></p>
<p><a href="https://blogs.nvidia.com.tw/2016/07/whats-difference-artificial-intelligence-machine-learning-deep-learning-ai/" target="_blank" rel="external">https://blogs.nvidia.com.tw/2016/07/whats-difference-artificial-intelligence-machine-learning-deep-learning-ai/</a></p>
<p><a href="http://si.secda.info/buss-math/index.php/2013-01-12-15-28-58/2012-09-23-07-08-48" target="_blank" rel="external">http://si.secda.info/buss-math/index.php/2013-01-12-15-28-58/2012-09-23-07-08-48</a></p>
<p>本文採用創作共用 (Creative Common) 3.0 版的 姓名標示─非商業性─相同方式分享 授權條款,歡迎轉載或修改使用,但若做為商業使用時必須取得授權</p>
</the>]]></content>
<summary type="html">
<h1 id="人工智慧之機器學習之神經網路の筆記-1-感知機"><a href="#人工智慧之機器學習之神經網路の筆記-1-感知機" class="headerlink" title="人工智慧之機器學習之神經網路の筆記(1)-感知機"></a>人工智慧之機器學習之神經網路の筆記(1)-感知機</h1><h4 id="c語言-實作and-or-xor-邏輯閘感知機"><a href="#c語言-實作and-or-xor-邏輯閘感知機" class="headerlink" title="c語言 實作and or xor 邏輯閘感知機"></a>c語言 實作and or xor 邏輯閘感知機</h4><p>完成後將會發布至 (<a href="https://andy112247.github.io">https://andy112247.github.io</a>)<br>我是新手LV1 可能會有很多地方打錯(說不定連標題都是錯的<br>總之發現有錯誤的話麻煩指正我,3Q</p>
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p><img src="http://i.imgur.com/xAFiPm3.jpg" alt=""><br>網路上的教學常常都是寫一堆嚇死人的數學公式,要不然就是範例程式寫得一坨拉庫令人退避三舍,對於我這麼一個數學廢物來說要看懂實在是太困難了,於是我決定順便寫一個簡單易懂公式不多程式看起來也不複雜的筆記(應該啦…<br>大概是國中高中會寫if for就能看懂的難度喔~</p>
<p><Excerpt in index | 首页摘要><br>…
</summary>
</entry>
<entry>
<title></title>
<link href="https://andy112247.github.io/2017/01/25/%E5%BE%9E%E9%9B%B6%E9%96%8B%E5%A7%8B%E4%BA%94%E5%AD%90%E6%A3%8BAI%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98/"/>
<id>https://andy112247.github.io/2017/01/25/從零開始五子棋AI學習筆記/</id>
<published>2017-01-25T12:53:03.242Z</published>
<updated>2017-01-25T13:40:29.513Z</updated>
<content type="html"><![CDATA[<h1 id="從零開始五子棋AI學習筆記"><a href="#從零開始五子棋AI學習筆記" class="headerlink" title="從零開始五子棋AI學習筆記"></a>從零開始五子棋AI學習筆記</h1><p>完成後將會發布至 (<a href="https://andy112247.github.io">https://andy112247.github.io</a>)</p>
<h6 id="tags-五子棋AI-AlphaBeta-MinMax-node-js"><a href="#tags-五子棋AI-AlphaBeta-MinMax-node-js" class="headerlink" title="tags: 五子棋AI AlphaBeta MinMax node.js"></a>tags: <code>五子棋AI</code> <code>AlphaBeta</code> <code>MinMax</code> <code>node.js</code></h6><p>這是我的第一個線上筆記^^</p>
<p>寫下我的學習過程希望能幫助跟我一樣都是新手的人<br>至於為甚麼會想寫五子棋AI程式呢?因為 <a href="https://www.facebook.com/photo.php?fbid=1182458468516759&set=a.203079396454676.44378.100002578513773&type=3&theater" target="_blank" rel="external">詳情</a><br>為甚麼說是從零開始呢?因為小弟<strong>程式廢渣</strong>,也沒接觸過AI更別提AlphaBeta還是MinMax演算法…連個OOXX還是DFS BFS都沒寫過Orz</p>
<p><excerpt in="" index="" |="" 首页摘要=""><br>…<a id="more"></a></excerpt></p>
<the rest="" of="" contents="" |="" 余下全文="">
<h6 id="所以可能會有很多寫錯的地方…"><a href="#所以可能會有很多寫錯的地方…" class="headerlink" title="所以可能會有很多寫錯的地方…"></a>所以可能會有很多寫錯的地方…</h6><h1 id="目標"><a href="#目標" class="headerlink" title="目標"></a>目標</h1><ul>
<li>利用node.js寫出線上對弈五子棋AI程式</li>
<li>兩天內半從完全不會寫出人工智慧來!!!!!</li>
</ul>
<h1 id="演算法簡介"><a href="#演算法簡介" class="headerlink" title="演算法簡介"></a>演算法簡介</h1><h3 id="極小化極大算法-MaxMin演算法"><a href="#極小化極大算法-MaxMin演算法" class="headerlink" title="極小化極大算法(MaxMin演算法)"></a>極小化極大算法(MaxMin演算法)</h3><p><strong>用途:</strong><br>選擇將自己優勢最大化的選擇,另一方則選擇令對手優勢最小化的方法</p>
<p><img src="http://i.imgur.com/2ajMyg9.jpg" alt=""></p>
<p>列出所有可能的走法,就會形成一顆博弈樹,而一個走法(下法)稱為節點。<br>此演算法需要一個評分函數,才能判斷優劣,設此函數為:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">f(p) = (將p中所有空格都放上MAX的棋子後,MAX三子成線的總數) — (將p中所有空格都放上MIN的棋子後,MIN三子成線的總數)。</div></pre></td></tr></table></figure></p>
<p>例如圖片上最左下角的算法為<br>xxx<br>oxx<br>xxx<br>此時x可以連成6條線<br>xoo<br>ooo<br>ooo<br>此時o可以連成5條線<br>分數即為(6)-(5)=1</p>
<ol>
<li><p>以空棋局為根節點,以某個棋局1步後的棋局的該棋局節點的子節點,廣度優先生成一棵博弈樹。然後從樹根開始輪流給每層結點賦予MAX和MIN的稱號。(本文限定博弈樹的深度為3,即只分析雙方各下一子的情況。)</p>
</li>
<li><p>使用評分函數 f( p) 計算各個葉子節點分值。</p>
</li>
<li><p><del>當葉子節點的分值計算出來後,再逆層向推算出各層非葉子節點的得分。推算的方法是:對於處於MAX層的節點,選其子節點中一個最大的得分作為該節點的得分,這是為了使自己在可供選擇的方案中選一個對自己最有利的方案;對處於MIN層的節點,選其子節點中一個最小的得分作為該節點的得分,這是為了立足於最壞的情況,這樣計算出的父節點的得分為倒推值。</del></p>
</li>
<li><p><del>如此反推至根節點下的第一層孩子,如果其中某個孩子能獲得在其兄弟節點中最大的倒推值,則它就是當前棋局最佳的走法。</del></p>
</li>
</ol>
<p>3.4點<strong>白話一點</strong>就是:<br>父狀態在<strong>Min</strong>層,分數為孩子中最小的分數;<br>父狀態在<strong>Max</strong>層,分數為孩子中最大的分數。<br>(注意:AI應該設為自己為MAX層才會得到最佳狀態)</p>
<p>可看出要是複雜一點(狀態較多)的遊戲,向下延伸的節點就會非常多,效率也不佳因此有了Alpha-beta剪枝演算法,此算法主要優點在於其在邊生成博弈樹時候邊計算評估各節點的倒推值,並且根據評估出的倒推值範圍,及時停止擴展那些已無必要再擴展的子節點,即相當於剪去了博弈樹上的一些分枝,從而節約了機器開銷,提高了搜索效率。</p>
<p><strong>白話一點</strong>就是去除一些看起來已經會輸的下法,省去繼續推算他下面的節點。</p>
<h3 id="Pseudocode"><a href="#Pseudocode" class="headerlink" title="Pseudocode:"></a>Pseudocode:</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line"> <span class="function">function <span class="title">minimax</span><span class="params">(node, depth, maximizingPlayer)</span> </span></div><div class="line"> <span class="comment">//(從某個結解開始,指定深度,哪個玩家?)</span></div><div class="line"> <span class="keyword">if</span> depth = <span class="number">0</span> or node is a terminal node</div><div class="line"> <span class="comment">//如果深度已經是0了或者是終端節點</span></div><div class="line"> <span class="keyword">return</span> the heuristic value of node</div><div class="line"> <span class="comment">//傳回已經下到那一層的盤面分數</span></div><div class="line"></div><div class="line"> <span class="keyword">if</span> maximizingPlayer</div><div class="line"> <span class="comment">//如果現在是我方(取最大值的那一方)(Player true=取大的;FALSE=取小的)</span></div><div class="line"> bestValue := −∞</div><div class="line"> <span class="comment">//bestValue設成負無限大(最爛)</span></div><div class="line"> <span class="keyword">for</span> each child of node</div><div class="line"> v := minimax(child, depth − <span class="number">1</span>, FALSE)</div><div class="line"> <span class="comment">//v=遞迴(子代,深度-1,玩家true=取大的;FALSE=取小的)</span></div><div class="line"> bestValue := max(bestValue, v)</div><div class="line"> <span class="comment">//一開始設付無限大,所以只要有任何一個值近來會等他就,然後如果下一個子代有更好max(bestValue,子代的分數)就取他</span></div><div class="line"> <span class="keyword">return</span> bestValue <span class="comment">//傳回bestValue</span></div><div class="line"></div><div class="line"> <span class="keyword">else</span> (* minimizing player *)</div><div class="line"> <span class="comment">//第一次遞迴後因為變成FALSE所以就會執行這裡</span></div><div class="line"> bestValue := +∞</div><div class="line"> <span class="keyword">for</span> each child of node</div><div class="line"> v := minimax(child, depth − <span class="number">1</span>, TRUE)</div><div class="line"> bestValue := min(bestValue, v)</div><div class="line"> <span class="keyword">return</span> bestValue</div><div class="line"> </div><div class="line">(* Initial call <span class="keyword">for</span> maximizing player *)</div><div class="line">minimax(origin, depth, TRUE) <span class="comment">//TRUE是自己</span></div></pre></td></tr></table></figure>
<p><br></p>
<h3 id="Alpha-beta剪枝"><a href="#Alpha-beta剪枝" class="headerlink" title="Alpha-beta剪枝"></a>Alpha-beta剪枝</h3><p><strong>用途:</strong><br>減少搜尋樹的分枝,將搜尋時間用在「更有希望」的子樹上,繼而提升搜尋深度。<br>AlphaBeta修剪法其實是MinMax對局搜尋法的一個修改版,主要是在MinMax當中加入了 α 與 β 兩個紀錄值,用來做為是否要修剪的參考標準</p>
<p><img src="http://i.imgur.com/zhYbywj.jpg" alt=""></p>
<p><br></p>
<ol>
<li>對於一個MIN層節點,若能估計出其倒推值的上確界Beta,並且這個Beta值不大於其的父節點(MAX層節點)的估計倒推值的下確界Alpha,即Alpha≥Beta,則就不必再擴展該MIN節點的其餘子節點了,因為這些節點的估值對MIN父節點的倒推值已無任何影響了,這一過程稱為Alpha剪枝。 <strong>分析解讀中ing</strong> </li>
</ol>
<p><br><br><br>下面兩張圖片是一組的<br><img src="https://upload.wikimedia.org/wikipedia/commons/9/91/AB_pruning.svg" alt=""></p>
<p><img src="https://i.imgur.com/vYatF8t.gif" alt=""></p>
<p>這是gif動圖喔!!他會<strong>慢慢</strong>講解<br>恩…真的很慢大概是要配合下面英文..花點時間看就會懂了</p>
<p><br><br></p>
<h3 id="陳鍾誠教授的影片講解"><a href="#陳鍾誠教授的影片講解" class="headerlink" title="陳鍾誠教授的影片講解:"></a>陳鍾誠教授的影片講解:</h3><p>感謝老師…</p>
<div class="video-container"><iframe src="//www.youtube.com/embed/fB0J0ZrFo-I" frameborder="0" allowfullscreen></iframe></div>
<p><br><br></p>
<h3 id="Pseudocode-1"><a href="#Pseudocode-1" class="headerlink" title="Pseudocode:"></a>Pseudocode:</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"> <span class="function">function <span class="title">alphabeta</span><span class="params">(node, depth, α, β, maximizingPlayer)</span></span></div><div class="line"> <span class="keyword">if</span> depth = <span class="number">0</span> or node is a terminal node</div><div class="line"> <span class="keyword">return</span> the heuristic value of node</div><div class="line"> <span class="keyword">if</span> maximizingPlayer</div><div class="line"> v := -∞</div><div class="line"> <span class="keyword">for</span> each child of node</div><div class="line"> v := max(v, alphabeta(child, depth – <span class="number">1</span>, α, β, FALSE))</div><div class="line"> α := max(α, v)</div><div class="line"> <span class="keyword">if</span> β ≤ α</div><div class="line"> <span class="comment">//如果β ≤ α就break掉,break的話這個回圈就離開了,所以就會切掉很多後面的節點</span></div><div class="line"> <span class="keyword">break</span> (* β cut-off *)</div><div class="line"> <span class="comment">//這個叫做 β cut-off</span></div><div class="line"> <span class="keyword">return</span> v</div><div class="line"> <span class="keyword">else</span></div><div class="line"> v := ∞</div><div class="line"> <span class="keyword">for</span> each child of node</div><div class="line"> v := min(v, alphabeta(child, depth – <span class="number">1</span>, α, β, TRUE))</div><div class="line"> β := min(β, v)</div><div class="line"> <span class="keyword">if</span> β ≤ α</div><div class="line"> <span class="keyword">break</span> (* α cut-off *)</div><div class="line"> <span class="comment">//這個叫做 α cut-off</span></div><div class="line"> <span class="keyword">return</span> v</div><div class="line"> </div><div class="line">(* Initial call *)</div><div class="line">alphabeta(origin, depth, -∞, +∞, TRUE)</div><div class="line"><span class="comment">//一開始的α是設-∞,因為一開始是取大的才會一直提升,β反之亦然才會一直下降</span></div></pre></td></tr></table></figure>
<p><br><br></p>
<p>假設棋盤上的正中心已經下有一個棋子,那麼棋盤上還有224個可以放置的點位,那麼博弈樹搜索的第一層就需要擴展224個狀態節點;<br> 接下來,每個狀態節點都剩餘223個可放置棋子的位置,所以需要繼續擴展223個狀態節點,所以第二層會存在224 <em> 223個狀態節點;<br> 依次類推,第三層會有224 </em> 223 <em> 222個狀態節點;<br> 第四層會有224 </em> 223 <em> 222 </em> 221個狀態節點<br> ……</p>
<p>那麼如果我們就算到第四層,總共需要搜索到:<br>224 + 224 <em> 223 + 224 </em> 223 <em> 222 + 224 </em> 223 <em> 222 </em> 221 = 2 461 884 544<br>呵呵了。每次都要搜索如此多的狀態節點,這樣的開銷是十分可觀的,因此,我們提高效率的方式就鎖定到了:如何減少需要搜索的狀態節點。<br>α-β剪枝就是一種博弈算法中最常用的剪枝算法</p>
<ul>
<li><p>α剪枝:<br> 若任一極小值層節點的β值小於或等於它任一先輩極大值居節點的α值,即α(先輩層)≥β(後繼層),則可中止該極小值層中這個MIN節點以下的搜索過程。這個MIN節點最終的倒推值就確定為這個β值</p>
</li>
<li><p>β剪枝:<br> 若任一極大值層節點的α值大於或等於它任一先輩極小值層節點的β值,即α(後繼層)≥β(先輩層),則可以中止該極大值層中這個MAX節點以下的搜索過程。這個MAX節點的最終倒推值就確定為這個α值。</p>
</li>
</ul>
<p>不用太仔細看定義而以直接從演算法或是下圖理解更快</p>
<p><img src="https://i.imgur.com/Kxkz3lX.png" alt=""><br>這張神圖!配下面解釋慢慢看懂了!!</p>
<p>簡單說一下:<br>帶圈的數字代表搜索節點的次序(博弈樹的搜索是DFS哦);<br>最底層的數字代表狀態評估值,可以認為數字越大,對自己越有利,數字越小,對對方越有利。</p>
<ol>
<li>找到第一個狀態節點,返回估價為0給上一層</li>
<li>這樣的話,上一層節點在擴展完其他節點之前就會知道,自己的估價值肯定不可能比0更高(因為要選擇最小的~)</li>
<li>擴展了第二個狀態節點,返回估價為5</li>
<li>此時上一層節點已經擴展完所有的子節點,因此按照博弈樹的原則,自己的估價就是0啦,所以把這個值返回給再上一層</li>
<li>再上一層獲得了這個返回值之後就會明白,自己的估價肯定不會低於0的(因為它要選擇子層中最大的),那麼繼續擴展</li>
<li>底層節點返回了-3</li>
<li>上一層節點就知道自己肯定會小於-3,然後瞅瞅再上一層節點,人家告訴你它不會低於0的,因此後面的搜索就沒有必要進行了,直接返回就成了</li>
<li>再上一層節點的估價確定為0,繼續返回給上層<br> ……</li>
</ol>
<h1 id="實戰篇"><a href="#實戰篇" class="headerlink" title="實戰篇"></a>實戰篇</h1><p>打這標題同時已經是<strong>2016年12月25日上午4:00</strong><br>沒錯就是一年一度最浪漫的<strong>聖誕節</strong>~~<br>也距離我的挑戰目標差不多只剩24小時…(抖<br>昨天平安夜放棄兩ㄊㄨㄚ的邀約,自幹五子棋沒有使用minmax等演算法但還是花了非常多的時間,所以沒什麼更新筆記現在才在趕進度(嘿嘿<br>廢話打完<br><br><br><br></p>
<h1 id="AI實現的基本思路-極大極小值搜索算法"><a href="#AI實現的基本思路-極大極小值搜索算法" class="headerlink" title="AI實現的基本思路-極大極小值搜索算法"></a>AI實現的基本思路-極大極小值搜索算法</h1><ul>
<li>電腦走棋的層我們稱為 MAX層,這一層電腦要保證自己利益最大化,那麼就需要選分最高的節點。</li>
<li>玩家走棋的層我們稱為MIN層,這一層玩家要保證自己的利益最大化,那麼就會選分最低的節點。</li>
</ul>
<p>這也就是極大極小值搜索算法的名稱由來</p>
<p><img src="https://i.imgur.com/YyOZK2m.png" alt=""></p>
<p>此圖中甲是電腦,乙是玩家,那麼在甲層的時候,總是選其中值最大的節點,乙層的時候,總是選其中最小的節點。</p>
<p>而每一個節點的分數,都是由子節點決定的,因此我們對博弈樹只能進行深度優先搜索而無法進行廣度優先搜索。深度優先搜索用遞歸非常容易實現,然後主要工作其實是完成一個評估函數,這個函數需要對當前局勢給出一個比較準確的評分。</p>
<h3 id="極大極小值搜索"><a href="#極大極小值搜索" class="headerlink" title="極大極小值搜索"></a>極大極小值搜索</h3><p>五子棋是一個15x15的棋盤,因為棋盤大小不會變動,所以目前來看用 15*15 的二維陣列來存儲,效果是最好的。</p>
<p>極大極小值的搜索比較簡單,就是一個DFS</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">AlphaBeta</span>(<span class="params">board, deep, alpha, beta,player</span>)</span>{</div><div class="line"></div><div class="line"> <span class="keyword">var</span> v = evaluate(board); <span class="comment">//先判斷整個棋盤分數</span></div><div class="line"> <span class="keyword">if</span>(deep <= <span class="number">0</span> || gameover) { <span class="comment">//如果搜尋到最上層或是遊戲結束了則不繼續搜尋</span></div><div class="line"> <span class="keyword">return</span> v; <span class="comment">//直接返回分數</span></div><div class="line"> } </div><div class="line"> <span class="keyword">var</span> bestx=<span class="number">0</span>,besty=<span class="number">0</span>; <span class="comment">//要紀錄最好的分數</span></div><div class="line"> </div><div class="line"> <span class="keyword">if</span>(player){ <span class="comment">//如果是電腦?</span></div><div class="line"> <span class="keyword">var</span> v=MIN;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="number">15</span>;i++) <span class="comment">//搜尋整個棋盤上每個位子</span></div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> j=<span class="number">0</span>;j<<span class="number">15</span>;j++) { </div><div class="line"> board[i][j] = chr.AI; <span class="comment">//先假設ai下在這個位子</span></div><div class="line"> <span class="keyword">var</span> AlphaBetaTemp=AlphaBeta(board, deep<span class="number">-1</span>, alpha, beta,<span class="literal">false</span>); </div><div class="line"> v = (v>AlphaBetaTemp?v:AlphaBetaTemp); <span class="comment">//照出最大的分數</span></div><div class="line"> board[i][j] = chr.empty; <span class="comment">//把先前假設的位子還回去(設回空的</span></div><div class="line"> <span class="keyword">if</span>(v == alpha) { <span class="comment">//如果搜尋出來的分數跟之前最大的一樣大</span></div><div class="line"> bestx=i; <span class="comment">//紀錄最好的結果</span></div><div class="line"> besty=j;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span>(v>alpha){ <span class="comment">//如果搜尋出來的分數比之前最大的更大</span></div><div class="line"> alpha = v; <span class="comment">//把alpha設為目前最高分</span></div><div class="line"> bestx=i; <span class="comment">//紀錄最好的結果</span></div><div class="line"> besty=j; </div><div class="line"> } </div><div class="line"> <span class="keyword">return</span> v; <span class="comment">//回傳分數</span></div><div class="line"> }</div><div class="line"> <span class="keyword">else</span>{ <span class="comment">//如果不是電腦則是玩家</span></div><div class="line"> <span class="keyword">var</span> v=MAX;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="number">15</span>;i++) <span class="comment">//搜尋整個棋盤</span></div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> j=<span class="number">0</span>;j<<span class="number">15</span>;j++) {</div><div class="line"> board[i][j] = chr.hum; <span class="comment">//假設玩家下在某個位子</span></div><div class="line"> <span class="keyword">var</span> AlphaBetaTemp=AlphaBeta(board, deep<span class="number">-1</span>, alpha, beta,<span class="literal">true</span>);</div><div class="line"> v=(v<AlphaBetaTemp?v:AlphaBetaTemp); <span class="comment">//這邊是要找對電腦最沒有利的位子(分數最小</span></div><div class="line"> board[p[<span class="number">0</span>]][p[<span class="number">1</span>]] = chr.empty; <span class="comment">//把剛才假設玩家下的位子還回去</span></div><div class="line"> beta=(beta<v?beta:v); <span class="comment">//尋找最低分(對電腦最沒有利</span></div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> v; <span class="comment">//回傳分數</span></div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="評估函數"><a href="#評估函數" class="headerlink" title="評估函數"></a>評估函數</h3><p>我們對五子棋的評分是簡單的把棋盤上的各種連子的分值加起來得到的,對各種連子的基本評分規則如下:</p>
<pre><code>成五,1000000
活四, 100000
活三 10000
活二 1000
活一 100
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">SCORE = {</div><div class="line"> ONE: 100,</div><div class="line"> TWO: 1000,</div><div class="line"> THREE: 10000,</div><div class="line"> FOUR: 100000,</div><div class="line"> FIVE: 1000000,</div><div class="line"> BLOCKED_ONE: 10,</div><div class="line"> BLOCKED_TWO: 100,</div><div class="line"> BLOCKED_THREE: 1000,</div><div class="line"> BLOCKED_FOUR: 10000</div><div class="line">}</div></pre></td></tr></table></figure>
<p>按照這個規則把棋盤上電腦的所有棋子打分,之和即為電腦的單方面得分 scoreCom,然後對玩家的棋子同樣打分 得到 scoreHum。</p>
<p>scoreCom-scoreHum 即為當前局勢的總分數。</p>
<p><br></p>
<h1 id="Alpha-Beta剪枝"><a href="#Alpha-Beta剪枝" class="headerlink" title="Alpha Beta剪枝"></a>Alpha Beta剪枝</h1><p>前面講到過,AI會在MAX層選擇最大節點,而玩家會在MIN層選擇最小節點。那麼如下兩種情況就是分別對雙方不利的選擇:</p>
<ul>
<li>在MAX層,假設當前層已經搜索到一個最大值 X, 如果發現下一個節點的下一層(也就是MIN層)會產生一個比X還小的值,那麼就直接剪掉此節點。</li>
</ul>
<p>解釋一下,也就是在MAX層的時候會把當前層已經搜索到的最大值X存起來,如果下一個節點的下一層會產生一個比X還小的值Y,那麼之前說過玩家總是會選擇最小值的。也就是說這個節點玩家的分數不會超過Y,那麼這個節點顯然沒有必要進行計算了。</p>
<p>通俗點來講就是,AI發現這一步是對玩家更有利的,那麼當然不會走這一步。</p>
<ul>
<li>在MIN層,假設當前層已經搜索到一個最小值 Y, 如果發現下一個節點的下一層(也就是MIN層)會產生一個比Y還大的值,那麼就直接剪掉此節點。</li>
</ul>
<p>這個是一樣的道理,如果玩家走了一步棋發現其實對AI更有利,玩家必定不會走這一步。<br><img src="https://upload.wikimedia.org/wikipedia/commons/9/91/AB_pruning.svg" alt=""></p>
<p>如上圖所示,在第二層,也就是MIN層,當計算到第三個節點的時候,已知前面有一個3和一個6,也就是最小值為3。 在計算第三個節點的時候,發現它的第一個孩子的結果是5,因為它的孩子是MAX節點,而MAX節點是會選擇最大值的,那麼此節點的值不會比5小,因此此節點的後序孩子就沒有必要計算了,因為這個節點不可能小於5,而同一層已經有一個值為3的節點了。</p>
<p>其實這個圖裡面第三層分數為7的節點也是不需要計算的。</p>
<p>這是 MAX 節點的剪枝,MIN節點的剪枝也是同樣的道理,就不再講了。 Alpha Beta 剪枝的 Alpha 和 Beta 分別指的是MAX 和 MIN節點。</p>
<h3 id="程式碼"><a href="#程式碼" class="headerlink" title="程式碼"></a>程式碼</h3><p>對max和min函數都增加一個 alpha 和 beta 參數。在 max 函數中如果發現一個子節點的值大於 alpha,則不再計算後序節點,此為 Alpha 剪枝。在 min 函數中如果發現一個子節點的值小於 beta,則不再計算後序節點,此為 Beta剪枝。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">AlphaBeta</span>(<span class="params">board, deep, alpha, beta,player</span>)</span>{</div><div class="line"></div><div class="line"> <span class="keyword">var</span> v = evaluate(board); <span class="comment">//先判斷整個棋盤分數</span></div><div class="line"> <span class="keyword">if</span>(deep <= <span class="number">0</span> || gameover) { <span class="comment">//如果搜尋到最上層或是遊戲結束了則不繼續搜尋</span></div><div class="line"> <span class="keyword">return</span> v; <span class="comment">//直接返回分數</span></div><div class="line"> } </div><div class="line"> <span class="keyword">var</span> bestx=<span class="number">0</span>,besty=<span class="number">0</span>; <span class="comment">//紀錄最好的分數</span></div><div class="line"> </div><div class="line"> <span class="keyword">if</span>(player){ <span class="comment">//如果是電腦?</span></div><div class="line"> <span class="keyword">var</span> v=MIN;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="number">15</span>;i++) <span class="comment">//搜尋整個棋盤上每個位子</span></div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> j=<span class="number">0</span>;j<<span class="number">15</span>;j++) { </div><div class="line"> board[i][j] = chr.AI; <span class="comment">//先假設ai下在這個位子</span></div><div class="line"> <span class="keyword">var</span> AlphaBetaTemp=AlphaBeta(board, deep<span class="number">-1</span>, alpha, beta,<span class="literal">false</span>); </div><div class="line"> v = (v>AlphaBetaTemp?v:AlphaBetaTemp); <span class="comment">//照出最大的分數</span></div><div class="line"> board[i][j] = chr.empty; <span class="comment">//把先前假設的位子還回去(設回空的</span></div><div class="line"> <span class="keyword">if</span>(v == alpha) { <span class="comment">//如果搜尋出來的分數跟之前最大的一樣大</span></div><div class="line"> bestx=i; <span class="comment">//紀錄最好的結果</span></div><div class="line"> besty=j;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span>(v>alpha){ <span class="comment">//如果搜尋出來的分數比之前最大的更大</span></div><div class="line"> alpha = v; <span class="comment">//把alpha設為目前最高分</span></div><div class="line"> bestx=i; <span class="comment">//紀錄最好的結果</span></div><div class="line"> besty=j; </div><div class="line"> } </div><div class="line"> <span class="keyword">if</span>(beta<=alpha)<span class="keyword">break</span>; <span class="comment">// AlphaBeta剪枝</span></div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> v; <span class="comment">//回傳分數</span></div><div class="line"> }</div><div class="line"> <span class="keyword">else</span>{ <span class="comment">//如果不是電腦則是玩家</span></div><div class="line"> <span class="keyword">var</span> v=MAX;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="number">15</span>;i++) <span class="comment">//搜尋整個棋盤</span></div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> j=<span class="number">0</span>;j<<span class="number">15</span>;j++) {</div><div class="line"> board[i][j] = chr.hum; <span class="comment">//假設玩家下在某個位子</span></div><div class="line"> <span class="keyword">var</span> AlphaBetaTemp=AlphaBeta(board, deep<span class="number">-1</span>, alpha, beta,<span class="literal">true</span>);</div><div class="line"> v=(v<AlphaBetaTemp?v:AlphaBetaTemp); <span class="comment">//這邊是要找對電腦最沒有利的位子(分數最小</span></div><div class="line"> board[p[<span class="number">0</span>]][p[<span class="number">1</span>]] = chr.empty; <span class="comment">//把剛才假設玩家下的位子還回去</span></div><div class="line"> beta=(beta<v?beta:v); <span class="comment">//尋找最低分(對電腦最沒有利</span></div><div class="line"> <span class="keyword">if</span>(beta<=alpha)<span class="keyword">break</span>; <span class="comment">// AlphaBeta剪枝 </span></div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> v; <span class="comment">//回傳分數</span></div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p><br><br><br></p>
<h1 id="引用-amp-參考"><a href="#引用-amp-參考" class="headerlink" title="引用&參考:"></a>引用&參考:</h1><h6 id="引用網址:http-blog-csdn-net-tianranhe-article-details-8301756"><a href="#引用網址:http-blog-csdn-net-tianranhe-article-details-8301756" class="headerlink" title="引用網址:http://blog.csdn.net/tianranhe/article/details/8301756"></a>引用網址:<a href="http://blog.csdn.net/tianranhe/article/details/8301756" target="_blank" rel="external">http://blog.csdn.net/tianranhe/article/details/8301756</a></h6><h6 id="引用網址:http-programmermagazine-github-io-201407-htm-focus3-html"><a href="#引用網址:http-programmermagazine-github-io-201407-htm-focus3-html" class="headerlink" title="引用網址:http://programmermagazine.github.io/201407/htm/focus3.html"></a>引用網址:<a href="http://programmermagazine.github.io/201407/htm/focus3.html" target="_blank" rel="external">http://programmermagazine.github.io/201407/htm/focus3.html</a></h6><h6 id="引用網址:http-blueve-me-archives-825"><a href="#引用網址:http-blueve-me-archives-825" class="headerlink" title="引用網址:http://blueve.me/archives/825"></a>引用網址:<a href="http://blueve.me/archives/825" target="_blank" rel="external">http://blueve.me/archives/825</a></h6><h6 id="引用網址:http-www-voidcn-com-blog-lihongxun945-cata-6089493"><a href="#引用網址:http-www-voidcn-com-blog-lihongxun945-cata-6089493" class="headerlink" title="引用網址:http://www.voidcn.com/blog/lihongxun945/cata/6089493/"></a>引用網址:<a href="http://www.voidcn.com/blog/lihongxun945/cata/6089493/" target="_blank" rel="external">http://www.voidcn.com/blog/lihongxun945/cata/6089493/</a></h6><h6 id="【本文取材並修改自維基百科和以上引用網址】"><a href="#【本文取材並修改自維基百科和以上引用網址】" class="headerlink" title="【本文取材並修改自維基百科和以上引用網址】"></a>【本文取材並修改自維基百科和以上引用網址】</h6></the>]]></content>
<summary type="html">
<h1 id="從零開始五子棋AI學習筆記"><a href="#從零開始五子棋AI學習筆記" class="headerlink" title="從零開始五子棋AI學習筆記"></a>從零開始五子棋AI學習筆記</h1><p>完成後將會發布至 (<a href="https://andy112247.github.io">https://andy112247.github.io</a>)</p>
<h6 id="tags-五子棋AI-AlphaBeta-MinMax-node-js"><a href="#tags-五子棋AI-AlphaBeta-MinMax-node-js" class="headerlink" title="tags: 五子棋AI AlphaBeta MinMax node.js"></a>tags: <code>五子棋AI</code> <code>AlphaBeta</code> <code>MinMax</code> <code>node.js</code></h6><p>這是我的第一個線上筆記^^</p>
<p>寫下我的學習過程希望能幫助跟我一樣都是新手的人<br>至於為甚麼會想寫五子棋AI程式呢?因為 <a href="https://www.facebook.com/photo.php?fbid=1182458468516759&amp;set=a.203079396454676.44378.100002578513773&amp;type=3&amp;theater">詳情</a><br>為甚麼說是從零開始呢?因為小弟<strong>程式廢渣</strong>,也沒接觸過AI更別提AlphaBeta還是MinMax演算法…連個OOXX還是DFS BFS都沒寫過Orz</p>
<p><Excerpt in index | 首页摘要><br>…
</summary>
</entry>
<entry>
<title>Hello World</title>
<link href="https://andy112247.github.io/2017/01/25/hello-world/"/>
<id>https://andy112247.github.io/2017/01/25/hello-world/</id>
<published>2017-01-25T11:01:57.668Z</published>
<updated>2017-03-26T05:37:05.293Z</updated>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="external">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="external">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" target="_blank" rel="external">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="external">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><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo new <span class="string">"My New Post"</span></div></pre></td></tr></table></figure>
<p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="external">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><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo server</div></pre></td></tr></table></figure>
<p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="external">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><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo generate</div></pre></td></tr></table></figure>
<p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="external">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><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo deploy</div></pre></td></tr></table></figure>
<p>More info: <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="external">Deployment</a></p>
]]></content>
<summary type="html">
<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="external">Hexo</a>! This is your very first post. Check <a href="https://hexo.
</summary>
</entry>
</feed>