《Python神經網路程式設計》1.4節蟲子分類器的實現
阿新 • • 發佈:2019-02-10
最近在看這本書,覺得裡面蟲子分類器也值得試試實現,因為這個方法已經包含了神經網路的核心思想。
以下是實現的過程。
按照《Python神經網路程式設計》(非同步圖書出版)第一章蟲子分類器訓練的過程,模仿書中第二章的3層神經網路的實現過程,來構建一個可執行的蟲子分類器。
首先,構造出來分類器的框架,包含訓練和查詢.
In [ ]:
class BugClassifier: def __init__(self): pass def train(self, target_bug_size, target_bug): pass def query(self, input_bug_size): pass
蟲子分類器,核心是一個線性函式,分類器的主要引數就是其斜率,同時也包括了訓練過程中的學習率。 由於書中已經預設了蟲子和線形分類器的關係,所以需要把這個關係對應的修正量也預設好。 例如瓢蟲線上形函式下面,毛蟲在上面。在查詢時,也需要根據這個關係來做分類的結論。 另外因此可以得到一個推論:該分類器並不需要就蟲子和線形函式的位置關係進行學習(這算是已知的知識)。
In [ ]:
class BugClassifier: def __init__(self, coefficient, learning_rate, corrections): self.coefficient = coefficient # 初始係數 self.learning_rate = learning_rate # 學習率 self.corrections = corrections # 預定義的根據蟲類的計算值修正量 def train(self, target_bug_size, target_bug): pass def query(self, input_bug_size): pass # 測試程式碼 bc = BugClassifier(0.25, 0.5, {'瓢蟲':{'修正量':0.1, '關係':lambda c,t:c>t and True or False}, '毛蟲':{'修正量':-0.1, '關係':lambda c,t:c<t and True or False}})
訓練的過程,核心思路就是利用訓練資料來計算,得到與目標之間的誤差。 再利用誤差來反向傳播到對核心引數(分類器所使用的線形函式的斜率係數)的調整, 調整的步伐,則是依據初始化時設定的學習率。
In [6]:
class BugClassifier: def __init__(self, coefficient, learning_rate, corrections): self.coefficient = coefficient # 初始係數 self.learning_rate = learning_rate # 學習率 self.corrections = corrections # 預定義的根據蟲類的計算值修正量 def feedforward(self, width): ''' 前饋函式,此處是利用輸入的寬度乘以分類器內部係數計算出來輸出的長度 ''' return width * self.coefficient def feedback(self, width, error): ''' 反饋函式,此處是利用輸入的寬度和輸出的誤差來反向調節分類器內部係數 ''' self.coefficient += self.learning_rate * (error / width) def train(self, target_bug_size, target_bug): target_bug_width = target_bug_size[0] target_bug_length = target_bug_size[1] computed_bug_length = self.feedforward(target_bug_width) # 誤差計算。誤差計算時,需要根據蟲子分類和線形函式的預設關係來修正目標值 error = (target_bug_length + self.corrections[target_bug]['修正量']) - computed_bug_length # 反饋誤差 self.feedback(target_bug_width, error) def query(self, input_bug_size): pass # 測試程式碼 bc = BugClassifier(0.25, 0.5, {'瓢蟲':{'修正量':0.1, '關係滿足?':lambda c,t:c>t and True or False}, '毛蟲':{'修正量':-0.1, '關係滿足?':lambda c,t:c<t and True or False}}) bc.train([3.0, 1.0], '瓢蟲') print('訓練第一個樣本後的斜率:', bc.coefficient) bc.train([1.0, 3.0], '毛蟲') print('訓練第二個樣本後的斜率:', bc.coefficient)
訓練第一個樣本後的斜率: 0.30833333333333335 訓練第二個樣本後的斜率: 1.6041666666666667
可以看到,兩次訓練的結果,和書上例子展示的結果一樣,因此程式碼是正確的。
查詢的過程,則是利用已經訓練好的分類器,對比分類器計算的分界線值與目標值的大小, 並結合預設的關係滿足謂詞,例如分界線值>目標值,則為瓢蟲;分界線值<目標值,則為毛蟲,來給出分類的結果。
In [13]:
class BugClassifier: def __init__(self, coefficient, learning_rate, corrections): self.coefficient = coefficient # 初始係數 self.learning_rate = learning_rate # 學習率 self.corrections = corrections # 預定義的根據蟲類的計算值修正量 def feedforward(self, width): ''' 前饋函式,此處是利用輸入的寬度乘以分類器內部係數計算出來輸出的長度 ''' return width * self.coefficient def feedback(self, width, error): ''' 反饋函式,此處是利用輸入的寬度和輸出的誤差來反向調節分類器內部係數 ''' self.coefficient += self.learning_rate * (error / width) def train(self, target_bug_size, target_bug): target_bug_width = target_bug_size[0] target_bug_length = target_bug_size[1] computed_bug_length = self.feedforward(target_bug_width) # 誤差計算。誤差計算時,需要根據蟲子分類和線形函式的預設關係來修正目標值 error = (target_bug_length + self.corrections[target_bug]['修正量']) - computed_bug_length # 反饋誤差 self.feedback(target_bug_width, error) def query(self, input_bug_size): input_bug_width = input_bug_size[0] input_bug_length = input_bug_size[1] computed_bug_length = self.feedforward(input_bug_width) for bug, correction in self.corrections.items(): if correction['關係滿足?'](computed_bug_length, input_bug_length): return bug # 只有可能屬於一種分類,因此立即返回 # 測試程式碼 bc = BugClassifier(0.25, 0.5, {'瓢蟲':{'修正量':0.1, '關係滿足?':lambda c,t:c>t and True or False}, '毛蟲':{'修正量':-0.1, '關係滿足?':lambda c,t:c<t and True or False}}) bc.train([3.0, 1.0], '瓢蟲') print('訓練第一個樣本後的斜率:', bc.coefficient) bc.train([1.0, 3.0], '毛蟲') print('訓練第二個樣本後的斜率:', bc.coefficient) test_case_1 = [2.8, 0.9] print('輸入:', test_case_1, ' 識別結果:', bc.query(test_case_1))
訓練第一個樣本後的斜率: 0.30833333333333335 訓練第二個樣本後的斜率: 1.6041666666666667 輸入: [2.8, 0.9] 識別結果: 瓢蟲
可以看到,分類成功了!