转载出处https://www.pianshen.com/article/4156259057/
一.步骤(参考李航老师的《统计学习方法》)
(1)给定一个初始的w和b,通过一次次更改w和b的值使结果变得更好
(2)定义 loss function
第一种:loss=I( yi * (w * xi +b) <0) ;计算分类错误的数量;不好,因为对于w 和 b 不是连续可导
第二种:loss= sum(- yi *( w * xi +b) )(只包括错误分类的点);一般用这一种,代表被错误分类点到分离边界的距离,注意,前面加了一个负号,为了保证loss值为正数
(3)第二种loss 对 w 求导,梯度为-yi *xi
对 b 求导,梯度为 -yi
(4) 判断每个样本是否被正确分类,如果没有被正确分类,
更新参数 w 和 b ,一个点一个点的更正
w(t+1)=w(t)+lamda *(-yi * xi)
b(t+1)=b(t) +lamda *(-yi )
lamda为学习率
import sklearn as sk
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
iris=load_iris()
print(iris.feature_names)#每一列的名称,但后面还要手动标注,为什么?
# print(iris.data.shape)
# iris.target.shape
df = pd.DataFrame(iris.data, columns=iris.feature_names)#dataFrame 化
dz=df.values #numpy化
df['label'] = iris.target#加上label
# df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']#数据标注,之前的后面有(cm),重新标注一下
# # df.label.value_counts()#计算label 有几种和每种多少个
plt.scatter(df[:50]['sepal length (cm)'], df[:50]['sepal width (cm)'], label='0')#这个地方'sepal length (cm)'需要复制,自己打报错,应该是格式不对
plt.scatter(df[50:100]['sepal length (cm)'], df[50:100]['sepal width (cm)'], label='1')
data = np.array(df.iloc[:100, [0, 1, -1]])#用iloc 提取列,loc 提取行;这里提取了0,1列和 代表最后一列的-1,也就是标签
X, y = data[:, :-1], data[:, -1] #这里提取了代表特征的前两列数据, data[:, :-1]不包括最后一列
y = np.array([1 if i == 1 else -1 for i in y]) # 将label中的0标签替换为-1,因为感知机算法基于标签-1,+1定义损失
#从上面可以看出这两个维度线性可分,所以可以使用感知机算法
np.ones(len(data[0]) - 1, dtype=np.float32) #data[0]是第一行数据,包括label;w 是两行一列的矩阵,和特征X做运算时
class Model:
# 类创建对象时自动执行,进行初始化操作
def __init__(self): # 初始化数据
self.w = np.ones(len(data[0]) - 1, dtype=np.float32) # 初始化权重
self.b = 0 # 初始化截距项
self.l_rate = 0.1 # 学习步长
self.data = data
# 定义符号函数
def sign(self, x, w, b): #这个是w*x+b
y = np.dot(x, w) + b
return y
# 随机梯度下降法
def fit(self, X_train, y_train):
is_wrong = False #布尔值
while not is_wrong: # not wrong=true ,代表可以继续执行
wrong_count = 0 #这个代表错误分类的数量,感知机算法是将数据完全正确分类的,这里应该可以通过修改这个值将条件放松
for d in range(len(X_train)):
X = X_train[d]
y = y_train[d]
if y * self.sign(X, self.w, self.b) <= 0:
self.w = self.w + self.l_rate * np.dot(y, X) # 更新权重
self.b = self.b + self.l_rate * y # 更新步长
wrong_count += 1
if wrong_count == 0:
is_wrong = True
return 'Perceptron Model!'
def score(self):
pass
结果如下
参考文首链接,查看使用sklearn 直接引入感知机算法
算法收敛性的证明以及感知机算法的对偶形式:也请参考李航老师的书(知道是收敛的就行了)
问题:(1)感知机算法存在许多解,依赖于初值和误分类的选择顺序
(2)为了得到唯一的分离超平面,需要约束条件
(3)线性不可分时,来回震荡