前几天认把感知机这一章读完了,顺带作了点笔记 如今把笔记作第三次的整理 (不得不说博客园的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()
更新了代码实现部分