统计学习方法(第二章)–感知器(python实现以及sklearn调用)
1 原理
找到一个分离超平面y=f(wx + b),可以将数据分开,使wx + b>0的属于正类,wx + b<=0的属于负类。因此感知器是一个线性二分类模型。
三要素:
模型:y = f(wx + b)
策略:定义损失函数,误分类的点到超平面的距离和最小化。点到超平面的距离公式是|wx+b|/||w||.因为限制误分类的点,所以y(wx+b)<=0.忽略第二范数||w||。则损失函数L(Y,f(X)) = -y(wx+b)之和,x属于误分类的点。
算法:随机梯度下降法。分别对w,b求偏导,w偏导=-yx,b偏导=-y,因为是下降,所以相减。
w = w - w偏导 = w + etayx, (eta是学习速率)
b = b - b偏导 = w + etay
过程
1给模型变量赋初值。w = [0,0,0…],维数是样本特征个数,b= 0 ,eta=1.
2随机取一个训练样本数据(xi,yi),检验yi*(wxi+b)<=0.
如果y(w*x+b)<=0.则根据公式更新权值向量w和偏置b
如果>0,则随机取下一个样本。
3 直至权值向量w和偏置b能正确分类所有数据。
对偶形式
由值向量w和偏置b的更新公式可知,
w = alpha* y* x之和(x是所有样本数据),alpha的意义是没有样本误分类的次数eta速率。
b = alphay之和
因此感知器公式 y = f(alpha* y* x之和* x + b)
过程:1给模型变量赋初值。alpha = [0,0,0…],维数是样本数量,b= 0 ,eta=1.
2随机取一个训练样本数据(xi,yi),检验 yi* (alpha* y* x之和* xi + b)<=0.
如果<=0,则alphai(alpha第i维) += eta,b = eta* yi
如果>0,则随机取下一个样本。
直至权值向量w和偏置b能正确分类所有数据。
python实现
准备数据
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris.data,columns=iris.feature_names)
df['label'] = iris.target
df.head()
选取数据及画图
data = np.array(df.iloc[:100,[0,1,-1]])
X,y = data[:,:-1],data[:,-1]
y = np.array([1 if i==1 else -1 for i in y]) #将其他类别设置成-1
#画图,看看是否线性可分
fig = plt.figure()
idx1 = np.where(y>0) #返回正样本的下标
idx2 = np.where(y<=0)#返回负样本的下标
plt.scatter(data[idx1,0],data[idx1,1],c='b',marker='o')
plt.scatter(data[idx2,0],data[idx2,1],c='orange',marker='*')
plt.show()
定义感知机
class Perceptrons(object):
def __init__(self,eta = 0.1):
self.eta = eta
def fit(self,X,y):
#特征个数
numFeatures = X.shape[1]
#样本个数
numLines = X.shape[0]
#初始化向量
self.wb = np.zeros(numFeatures+1) #+1是存储偏置b
#是否有误分类
isWrong = True
#误分类个数
wrongNum = 0
while isWrong:
wrongNum = 0
for xi,yi in zip(X,y):
if yi*(np.sum(self.wb[1:]*xi) + self.wb[0])<= 0:
self.wb[1:] += self.eta * yi * xi
self.wb[0] += self.eta * yi
wrongNum += 1
if wrongNum == 0:
isWrong = False
训练
ppt = Perceptrons()
ppt.fit(X,y)
ppt.wb
画图
xPoint = np.linspace(4,7,10)
yPoint = -(ppt.wb[0] + ppt.wb[1]*xPoint)/ppt.wb[2]
plt.scatter(data[idx1,0],data[idx1,1],c='b',marker='o')
plt.scatter(data[idx2,0],data[idx2,1],c='orange',marker='*')
plt.plot (xPoint,yPoint)
plt.show()
sklearn调用感知机
from sklearn.linear_model import Perceptron
ppt = Perceptron(fit_intercept=True,max_iter=1000,shuffle=True) #fit_intercept优化偏置b,shuffle每次迭代后洗牌,
ppt.fit(X,y)
#权值向量
ppt.coef_
#偏置
ppt.intercept_