![91b474b1c6df1e51efb86327044acc79.png](https://i-blog.csdnimg.cn/blog_migrate/934f1b6408ddcb8de8949de7f72d3859.png)
本不打算写感知机模型,因为其实在太简单,在实际业务中也很少用到!
可后来接触越来越多的算法,发现感知机模型才是最为简接概述分类模型三要素:
模型,策略,算法!
想来,李航博士将其作为《统计学习方法》分类模型第一章,大概就是出于这个原因!
![af90092bf86d9552322bc4fddb64009b.png](https://i-blog.csdnimg.cn/blog_migrate/a7714ed0730d483b2814b7d3142e19c0.jpeg)
从这段话中,可以抽象出分类模型三要素:
感知机模型的假设空间:分离超平面
![e1cf4e02c2d6c0797ba954d666942ad8.png](https://i-blog.csdnimg.cn/blog_migrate/c4309e78adb64d5ab455f3214253ae34.png)
W为法向量,b为截距,确定了这两个参数,超平面也就确定了;
sign是符号函数;取值{+1,-1}
学习策略:误分类点到超平面的总距离(直观来看,总距离越小越好!)
![82587fa7af4e9cef0b85a737aa4e49a1.png](https://i-blog.csdnimg.cn/blog_migrate/fcf6d28dff6b74077277bcd354f85ad0.jpeg)
为什么不以误分类点的个数作为损失函数?
我们学习策略最终的目的是寻找w,b参数的解!这就要求损失函数对w,b连续可导。
而误分类点的个数无法满足这个条件!
算法:通过随机梯度下降法快速找到w,b!
我们的目标是最小化损失函数,如下图:
![cf078706241aa300b3a509643b9ba180.png](https://i-blog.csdnimg.cn/blog_migrate/bb7f507102c5ca6e17c5b82ccd899775.jpeg)
我们就可以用常用的梯度下降方法来进行更新,对w,b参数分别进行求偏导可得
![1a9dcd5990abd2a035bab129f6863345.png](https://i-blog.csdnimg.cn/blog_migrate/c59571c595b36fe8dc459bdbd1de931d.jpeg)
那么我们任意初始化w,b之后,碰到误分类点时,采取的权值更新为w,b分别为:
![bfa64d61ca1e18632e049dbf999edb60.png](https://i-blog.csdnimg.cn/blog_migrate/def5e0c4afc8c610ca5a370df4c7ce5e.jpeg)
是步长(
),也叫做学习率。初始值w,b=0,那么学习率无论如何设置都不影响最后的影响!如果w,b不等于0:最终得出的w,b不同(超平面不一样)。
感知机模型:最终寻求的是满足条件的满意解,所以有多个满足条件的超平面!
因为是求最小值,沿着负梯度的方向收敛最快!
算法实现
import numpy as np
class MyPerceptron:
def __init__(self):
self.w=None#初始化
self.b=0
self.l_rate=1#学习率设为1
def fit(self,X_train,y_train):
#用样本点的特征数更新初始w,如x1=(3,3)T,有两个特征,则self.w=[0,0],初始化w补零;X_train.shape[1]表示axis=1,所以为2,X_train.shape[0]表示axis=0,所以为3;
self.w=np.zeros(X_train.shape[1])
i=0
while i<X_train.shape[0]:
X=X_train[i]#axis=0轴上第i个元素
y=y_train[i]
# 如果y*(wx+b)≤0 说明是误判点 ,更新w,b
if y*(np.dot(self.w, X) + self.b) <= 0:
self.w = self.w + self.l_rate * np.dot(y, X)
self.b = self.b + self.l_rate * y
i=0 #如果是误判点,从头进行检测
else:
i+=1
def main():
# 构造训练数据集
X_train=np.array([[3,3],[4,3],[1,1]])
y_train=np.array([1,1,-1])
# 构建感知机对象,对数据集继续训练
perceptron=MyPerceptron()
perceptron.fit(X_train,y_train)
print(perceptron.w)
print(perceptron.b)
if __name__=="__main__":
main()
计算时,x自动转为(3,3)T
数据结构参考求知鸟:Python科学计算:庖丁解牛之Numpy
为了便于调参,将sklearn中的感知机模型也写出来:
from sklearn.linear_model import Perceptron
from sklearn.linear_model import SGDClassifier
import numpy as np
X_train = np.array([[3, 3], [4, 3], [1, 1]])
y = np.array([1, 1, -1])
perceptron=Perceptron(penalty="l2",alpha=0.01,eta0=1,max_iter=50,tol=1e-3)
perceptron=Perceptron()
perceptron=SGDClassifier(loss="perceptron",eta0=1, learning_rate="constant", penalty=None)
perceptron.fit(X_train,y)
print(perceptron.coef_)
print(perceptron.intercept_)
print(perceptron.n_iter_)
X=np.array([[2,2]])
y=perceptron.predict(X)
![1823d133ce59c7ba51bb77a2ea380311.png](https://i-blog.csdnimg.cn/blog_migrate/782243d0fcbdabaed408437f169d8ae2.jpeg)
max_iter(迭代次数),当达到迭代次数,模型停止训练,默认为1000
tol(终止条件):模型收敛条件,感知机模型用“误分类点到超平面的总距离(直观来看,总距离越小越好!)”来收敛,所以极限值为0!
迭代次数,终止条件都可以作为收敛参数使用!
正则项:
L1:特征值更稀疏
L2:均值更均匀
正则化系数过小:无约束效力,“欠拟合”
正则化系数过大:约束过紧,“过拟合”
可以调控正则化系数与正则项来控制,“欠拟合”与“过拟合”
总结:
模型的复杂度:输入特征x的特征数量!
感知机模型的收敛条件:数据集必须绝对线性可分!
感知机模型:只是考虑将数据分割开,并不考虑分割的有多好;这是与支持向量机最大的差别!
感知机模型的优点:简单容易实现,作为神经网络与支持向量机的理论基础!
感知机模型的缺点:数据集必须线性可分,适用于二分类问题!
机器学习常用模型:
求知鸟:数据分析|自编程实现k近邻算法
求知鸟:数据分析|自编程实现朴素贝叶斯