目录
工大菜凯,希望通过做笔记记录自己学的知识,也希望能帮助到同样在入门的同学 ❥侵权立删~
感知机的基本知识点:
注:实例点()更新的次数越多,意味着它距离分离超平面越近,也就越难分类。(对学习的结果影响最大)
若()实例点更新了次,,
的变换过程如:
其中:的初始值
其中 等价于
感知机的模型函数:𝑓(𝑥)=𝑠𝑖𝑔𝑛(𝑤∗𝑥+𝑏)
损失函数 𝐿(𝑤,𝑏)=−Σ𝑦𝑖(𝑤∗𝑥𝑖+𝑏)
算法:随机梯度下降法,随机抽取一个误分类点使其梯度下降。
、
当实例点被误分类,即位于分离超平面的错误侧,则调整w,b,使分离超平面向该误分类点的一侧移动,直至误分类点被正确分类。
代码分析:
拿出iris数据集中两个分类的数据和[sepal length,sepal width]作为特征
实验数据集的设置
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris # 利用python自带的数据库
import matplotlib.pyplot as plt
# Iris 数据集是机器学习任务中常用的分类实验数据集
# Iris 数据集一共包含150个样本,分成3类,每类50个数据(样本),每个数据(样本)包含4个特征
4个特征分别为: Sepal.Length(花萼长度)、Sepal.Width(花萼宽度)、Petal.Length(花瓣长度)、Petal.Width(花瓣宽度),根据4个特征预测鸢尾花属于 Iris Setosa(山鸢尾)、Iris Versicolour(杂色鸢尾),Iris Virginica(维吉尼亚鸢尾)
# load data
iris = load_iris()
# 通过iris.data可以获得数据集中的样本特征
# 通过iris.target可以获得每个样本对应的标签信息(目标变量)
# pd.DataFrame 将iris数据集中的样本特征存储在名为df的pandas的数据框中,每列的名称对应于iris数据集# 中的特征名称
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# 将数据集中的标签信息(目标变量)添加到数据框df中,将标签信息赋给一个名为label的新列,这样df数据框就# 包含了每个样本的标签信息
df['label'] = iris.target
#最终得到一个pandas数据框df,其中每一行代表一个样本,每一列代表一个特征,最后一列是样本的标签
# 设置df数据框的每一列的特征标签
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
# 对样本标签进行统计
df.label.value_counts()
plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0')
plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
# iloc函数表示对数据进行位置索引,从而在数据表中提出相应的数据
# 将df数据框中的前100行数据的第0列、1列、最后一列的数据提取出来,并将其转化为numpy数组存储在data变# 量中
data = np.array(df.iloc[:100, [0, 1, -1]])
# data[:,:-1] 提取data中除了最后一列,所有列的数据
# data[:,-1] 只提取data数组的最后一列数据
# X代表两个特征 y代表标签变量
X, y = data[:,:-1], data[:,-1]
# 因为原本的y是分为0 1两个标签值的
# 为了对感知机更好的进行试验 我们将y的值进行了调整 将原本0 1 两个标签值 变换成 -1 1两个标签值
y = np.array([1 if i == 1 else -1 for i in y])
感知机模型的设定:
# 数据线性可分,二分类数据
# 此处为一元一次线性方程
class Model:
def __init__(self):
# 感知机模型初始化操作
# len(data[0] 即取出第一行的元素个数
# 取数据集的列数(因为数据集的最后一列是标签列 所以我们需要-1处理)
# 创建一个长度与特征维度相匹配的全部为1的浮点数组作为初始权重向量,也就是参数w向量
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):
y = np.dot(x, w) + b
return y
# 随机梯度下降法
def fit(self, X_train, y_train):
is_wrong = False # 用来判断训练是否结束的标志
while not is_wrong:
# 因为is_wrong的初始值是False 所以直到is_wrong = True 才结束循环也就是没有误分类点出现
wrong_count = 0 # 记录每次迭代中误分类的样本数量
for d in range(len(X_train)): # 遍历整个训练数据集
X = X_train[d] # 样本特征向量X
y = y_train[d] # 样本标签y
if y * self.sign(X, self.w, self.b) <= 0: # <0 就表示该样本点为误分类点
self.w = self.w + self.l_rate*np.dot(y, X)
self.b = self.b + self.l_rate*y
wrong_count += 1
# 当该次循环误分类点 ==0 没有出现误分类点,则将is_wrong设置为True 结束参数w和b的迭代更新
if wrong_count == 0:
is_wrong = True
return 'Perceptron Model!' # 训练完成的提示
def score(self):
pass
perceptron = Model()
# 运行感知机模型,利用随机梯度下降法对参数进行优化 使得最后没有误分类点出现
perceptron.fit(X, y)
# 生成一个等间距的横坐标点x_points,范围是从4到7,共10个点
x_points = np.linspace(4, 7,10)
# 分离超平面 第二个变量的计算 w1*x1+w2*x2+b=0
y_ = -(perceptron.w[0]*x_points + perceptron.b)/perceptron.w[1]
# 画出分离超平面 也就是分类线
plt.plot(x_points, y_)
# 画出标签为0的样本点(横轴一个特征 纵轴一个特征 组成一个样本点)
plt.plot(data[:50, 0], data[:50, 1], 'o', color='blue', label='0')
# 画出标签为1的样本点
plt.plot(data[50:100, 0], data[50:100, 1], 'o', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
分离结果:
运用scikit-learn Perceptron :
from sklearn.linear_model import Perceptron # 从sklearn中引入感知机函数
# 创建一个感知机对象clf
# 参数fit_intercept:偏置项 决定分类线的位置 max_iter:最大的迭代次数 shuffle:打乱输入数据的顺序
clf = Perceptron(fit_intercept=True, max_iter=1000, shuffle=True)
# 给定训练数据X和对应的标签y对感知机模型进行训练
# X 是一个二维数组,表示训练样本的特征。每一行代表一个样本的特征向量,每一列代表不同的样本的不同特征
# y 是一个一维数组,表示训练样本的标签。
clf.fit(X, y)
# Weights assigned to the features.
# 返回一个数组,其中存储这感知机模型训练后得到的权重系数,数组中的每一个元素对应一个特征
print(clf.coef_)
# 截距b Constants in decision function.
print(clf.intercept_)
x_points = np.linspace(4, 7,10)
# 对权值参数w的取值w1:clf.coef_[0][0]、wclf.coef_[0][1]
y_ = -(clf.coef_[0][0]*x_ponits + clf.intercept_)/clf.coef_[0][1]
plt.plot(x_ponits, y_)
plt.plot(data[:50, 0], data[:50, 1], 'o', color='blue', label='0')
plt.plot(data[50:100, 0], data[50:100, 1], 'o', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()