前幾天認把感知機這一章讀完了,順帶作了點筆記 如今把筆記作第三次的整理 (不得不說博客園的LaTex公式和markdown排版真的不太舒服,該考慮在服務器上建一個博客了)python
輸入空間 $ \mathcal{X} \subseteq R^n $ 輸出空間 $ \mathcal{Y} \subseteq {-1, +1} $ 假設空間 $ \mathcal{F} \subseteq {f|f(x) = \omega \cdot x + b} $ 參數 $ \omega \in R^n, b \in R $ 模型 $ f(x) = sign(\omega \cdot x + b) $算法
其中 符號函數爲 $$ sign(x)=\left{\begin{matrix} +1 , x \geqslant 0\ -1 , x \geqslant 0 \end{matrix}\right. $$服務器
線性方程 $ \omega \cdot x + b $ 能夠表示爲特徵空間 $ R^n $中的一個分離超平面markdown
(定義的損失函數,並極小化損失函數) (注意損失函數非負的性質)app
爲了使損失函數更容易優化,咱們選擇誤分類點到超平面的距離做爲損失函數 任意向量$x \in R^n$距分離超平面的距離爲 $ S=\frac{1}{|\omega|}|\omega \cdot x + b| $函數
接下來優化一下這個距離,讓它更好的成爲一個損失函數學習
(如何實現最優化問題) 注意最終訓練出的模型參數的值取決於初值和誤分類點的選取,因此通常值不一樣優化
爲了極小化損失函數,咱們採用梯度降低的方法spa
由於感知機對數據要求很嚴格,爲了實現這個模型,我用到了iris的數據集,用來給鳶尾花分類 又由於感知機只能作二分類,因此仍是要把原數據的兩個類別合併.net
爲了學習numpy,仍是用了python實現
import numpy as np from matplotlib import pyplot as plt class Perceptron: # use the primitive algorithm arguments={ "item_class":{ "Iris-setosa": -1, "Iris-versicolor": 1, "Iris-virginica": 1, }, "epoch": 800, "colors": ['blue', 'red'], "draw_start_x": 4, "draw_end_x": 7.5, "epsilon": 0.0, "learning_rate": 0.25, } def __init__(self, vec_dim, learning_rate=None, epsilon=None): # self.data=np.empty(dim) # self.counter=np.zeros(dim) self.data=None self.vec_dim=vec_dim self.lr=learning_rate if epsilon: self.epsilon=epsilon else: self.epsilon=self.arguments["epsilon"] if learning_rate: self.lr=learning_rate else: self.lr=self.arguments["learning_rate"] self.weight=np.zeros((self.vec_dim-1, 1)) self.bias=0 def read_data(self, filepath): raw_data=[] with open(filepath, "r") as file: for line in file.readlines(): if line=='\n': break item=line.replace('\n', '').split(',') itemc=self.arguments["item_class"][item[-1]] vec=[float(x) for x in item[0:2]]+[itemc] raw_data.append(vec) self.data=np.array(raw_data).T def process(self): # it is dual form vec=self.data[:, 0:2] self.gram=np.dot(vec, vec.T) def train(self): self.bias=0 self.weight=np.zeros((self.vec_dim-1, 1)) # self.counter=np.zeros(dim) for epoch in range(1, self.arguments["epoch"]+1): error_counter=0 for idx in range(self.data.shape[1]): vec=self.data[:, idx] x, y=vec[0:-1, np.newaxis], vec[-1] if y*(np.dot(self.weight.T, x)+self.bias)<=self.epsilon: self.weight+=self.lr*y*x self.bias+=self.lr*y error_counter+=1 print("epoch #%03d: error:%03d total:%03d"%( epoch, error_counter, self.data.shape[1])) print("weight:", self.weight.ravel()) print("bias:", self.bias, "\n") if error_counter==0: print("train done!") break def show(self): for idx in range(self.data.shape[1]): color=self.arguments["colors"][0] if self.data[2, idx]<0: color=self.arguments["colors"][1] plt.scatter(self.data[0, idx], self.data[1, idx], color=color) y=[-(self.weight[0, 0]*self.arguments["draw_start_x"] + self.bias)/self.weight[1, 0], -(self.weight[0, 0]*self.arguments["draw_end_x"] + self.bias)/self.weight[1, 0]] plt.plot([self.arguments["draw_start_x"], self.arguments["draw_end_x"]], y) plt.show()
更新了代碼實現部分