文章目录

  • 1. 感知机简介
  • 2. 编写感知机实践
    • 2.1 数据处理
    • 2.2 编写感知机类
    • 2.3 多参数组合运行
  • 3. sklearn 感知机实践
  • 4. 附完整代码

本文将使用感知机模型,对鸢尾花进行分类,并调整参数,对比分类效率。

1. 感知机简介

感知机(perceptron)是二类分类的线性分类模型

  • 输入:实例的特征向量
  • 输出:实例的类别,取 +1 和 -1 二值
  • 感知机对应于输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型
  • 旨在求出将训练数据进行线性划分的分离超平面,为此,导入基于误分类的损失函数,利用梯度下降法对损失函数进行极小化,求得感知机模型。
  • 感知机学习算法具有简单而易于实现的优点,分为原始形式和对偶形式。
  • 预测:对新的输入进行分类

具体内容见李航《统计学习方法》第二章,感知机 读书笔记。

2. 编写感知机实践

本文代码参考了此处:fengdu78,本人添加了感知机算法的对偶形式,并对不同的参数下的迭代次数进行比较。

2.1 数据处理

  • 数据采用sklearn内置的鸢尾花数据(数据介绍请参考此处)
# 读取鸢尾花数据
iris = load_iris()
# 将鸢尾花4个特征,以4列存入pandas的数据框架
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# 在最后一列追加 加入标签(分类)列数据
df['lab'] = iris.target# df.columns=[iris.feature_names[0], iris.feature_names[1], iris.feature_names[2], iris.feature_names[3], 'lab']
# df['lab'].value_counts()
# 选取前两种花进行划分(每种数据50组)
plt.scatter(df[:50][iris.feature_names[0]], df[:50][iris.feature_names[1]], label=iris.target_names[0])
plt.scatter(df[50:100][iris.feature_names[0]], df[50:100][iris.feature_names[1]], label=iris.target_names[1])
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])# 选取数据,前100行,前两个特征,最后一列标签
data = np.array(df.iloc[:100, [0, 1, -1]])
# X是除最后一列外的所有列,y是最后一列
X, y = data[:, :-1], data[:, -1]
# 生成感知机的标签值,+1, -1, 第一种-1,第二种+1
y = np.array([1 if i == 1 else -1 for i in y])

2.2 编写感知机类

class PerceptronModel():def __init__(self, X, y, eta):self.w = np.zeros(len(X[0]), dtype=np.float)  # 权重self.b = 0  # 偏置self.eta = eta  # 学习率self.dataX = X  # 数据self.datay = y  # 标签self.iterTimes = 0  # 迭代次数# 对偶形式的参数self.a = np.zeros(len(X), dtype=np.float)  # alphaself.Gmatrix = np.zeros((len(X), len(X)), dtype=np.float)self.calculateGmatrix()  # 计算Gram矩阵def sign0(self, x, w, b):  # 原始形式sign函数y = np.dot(w, x) + breturn ydef sign1(self, a, G_j, Y, b):  # 对偶形式sign函数y = np.dot(np.multiply(a, Y), G_j) + breturn ydef OriginClassifier(self):  # 原始形式的分类算法self.iterTimes = 0self.b = 0stop = Falsewhile not stop:wrong_count = 0for i in range(len(self.dataX)):X = self.dataX[i]y = self.datay[i]if (y * self.sign0(X, self.w, self.b)) <= 0:self.w += self.eta * np.dot(X, y)self.b += self.eta * ywrong_count += 1self.iterTimes += 1if wrong_count == 0:stop = Trueprint("原始形式,分类完成!步长:%.4f, 共迭代 %d 次" % (self.eta, self.iterTimes))def calculateGmatrix(self):  # 计算Gram矩阵for i in range(len(self.dataX)):for j in range(0, i + 1):  # 对称的计算一半就行self.Gmatrix[i][j] = np.dot(self.dataX[i], self.dataX[j])self.Gmatrix[j][i] = self.Gmatrix[i][j]def DualFormClassifier(self):  # 对偶形式分类算法self.iterTimes = 0self.b = 0stop = Falsewhile not stop:wrong_count = 0for i in range(len(self.dataX)):y = self.datay[i]G_i = self.Gmatrix[i]if (y * self.sign1(self.a, G_i, self.datay, self.b)) <= 0:self.a[i] += self.etaself.b += self.eta * ywrong_count += 1self.iterTimes += 1if wrong_count == 0:stop = Trueprint("对偶形式,分类完成!步长:%.4f, 共迭代 %d 次" % (self.eta, self.iterTimes))

2.3 多参数组合运行

# 调用感知机进行分类,学习率etaperceptron = PerceptronModel(X, y, eta=0.3)perceptron.OriginClassifier()  # 原始形式分类# 绘制原始算法分类超平面x_points = np.linspace(4, 7, 10)y0 = -(perceptron.w[0] * x_points + perceptron.b) / perceptron.w[1]plt.plot(x_points, y0, 'r', label='原始算法分类线')perceptron.DualFormClassifier()  # 对偶形式分类# 由alpha,b 计算omega向量omega0 = sum(perceptron.a[i] * y[i] * X[i][0] for i in range(len(X)))omega1 = sum(perceptron.a[i] * y[i] * X[i][1] for i in range(len(X)))y1 = -(omega0 * x_points + perceptron.b) / omega1# 绘制对偶算法分类超平面plt.plot(x_points, y1, 'b', label='对偶算法分类线')plt.rcParams['font.sans-serif'] = 'SimHei'  # 消除中文乱码plt.legend()plt.show()

原始算法 对偶算法
η=0.1\eta=0.1η=0.1 初值全0,迭代1518次,初值全1,迭代1473次 初值全0,迭代1488次,初值全1,迭代2378次
η=0.5\eta=0.5η=0.5 初值全0,迭代1562次,初值全1,迭代1472次 初值全0,迭代1518次,初值全1,迭代1325次
η=1\eta=1η=1 初值全0,迭代1562次,初值全1,迭代1486次 初值全0,迭代1518次,初值全1,迭代1367次
# ------------------学习率不同,查看迭代次数----------------------------
n = 100
i = 0
eta_iterTime = np.zeros((n, 3), dtype=float)
for eta in np.linspace(0.01, 1.01, n):eta_iterTime[i][0] = eta    # 第一列,学习率perceptron = PerceptronModel(X, y, eta)perceptron.OriginClassifier()eta_iterTime[i][1] = perceptron.iterTimes # 第二列,原始算法迭代次数perceptron.DualFormClassifier()eta_iterTime[i][2] = perceptron.iterTimes # 第三列,对偶算法迭代次数i += 1
x = eta_iterTime[:, 0]  # 数据切片
y0 = eta_iterTime[:, 1]
y1 = eta_iterTime[:, 2]
plt.scatter(x, y0, c='r', marker='o', label='原始算法')
plt.scatter(x, y1, c='b', marker='x', label='对偶算法')
plt.xlabel('步长(学习率)')
plt.ylabel('迭代次数')
plt.title("不同步长,不同算法形式下,迭代次数")
plt.legend()
plt.show()


结论:

  • 感知机的两种算法形式均会因为初值和学习率的不同,而造成的多种迭代路径
  • 从上面图标也印证了,对于线性可分的数据,感知机学习算法迭代是收敛

3. sklearn 感知机实践

sklearn.linear_model.Perceptron 官网参数介绍

class sklearn.linear_model.Perceptron(penalty=None, alpha=0.0001,
fit_intercept=True, max_iter=1000, tol=0.001, shuffle=True,
verbose=0, eta0=1.0, n_jobs=None, random_state=0,
early_stopping=False,validation_fraction=0.1,
n_iter_no_change=5, class_weight=None, warm_start=False)
classify = Perceptron(fit_intercept=True, max_iter=1000, shuffle=True, eta0=0.1, tol=None)
classify.fit(X, y)
print("特征权重:", classify.coef_)  # 特征权重 w
print("截距(偏置):", classify.intercept_)  # 截距 b# 可视化
plt.scatter(df[:50][iris.feature_names[0]], df[:50][iris.feature_names[1]], label=iris.target_names[0])
plt.scatter(df[50:100][iris.feature_names[0]], df[50:100][iris.feature_names[1]], label=iris.target_names[1])
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])# 绘制分类超平面
x_points = np.linspace(4, 7, 10)
y = -(classify.coef_[0][0] * x_points + classify.intercept_) / classify.coef_[0][1]
plt.plot(x_points, y, 'r', label='sklearn Perceptron分类线')plt.title("sklearn内置感知机分类")
plt.legend()
plt.show()

运行结果:

特征权重: [[ 6.95 -8.73]]
截距(偏置): [-11.2]

  • 可以看出在这两个特征下,两种花线性可分,感知机将两类花分类成功

我们稍微更改下数据为后两种花,再次运行

  • 可以看出,后两种花在这2个特征下线性不可分,感知机做出了错误分类线

4. 附完整代码

# -*- coding:utf-8 -*-
# @Python 3.7
# @Time: 2020/2/28 22:07
# @Author: Michael Ming
# @Website: https://michael.blog.csdn.net/
# @File: 2.perceptron.py
# @Reference: https://github.com/fengdu78/lihang-codeimport pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import Perceptron
import matplotlib.pyplot as pltclass PerceptronModel():def __init__(self, X, y, eta):self.w = np.zeros(len(X[0]), dtype=np.float)  # 权重self.b = 0  # 偏置self.eta = eta  # 学习率self.dataX = X  # 数据self.datay = y  # 标签self.iterTimes = 0  # 迭代次数# 对偶形式的参数self.a = np.zeros(len(X), dtype=np.float)  # alphaself.Gmatrix = np.zeros((len(X), len(X)), dtype=np.float)self.calculateGmatrix()  # 计算Gram矩阵def sign0(self, x, w, b):  # 原始形式sign函数y = np.dot(w, x) + breturn ydef sign1(self, a, G_j, Y, b):  # 对偶形式sign函数y = np.dot(np.multiply(a, Y), G_j) + breturn ydef OriginClassifier(self):  # 原始形式的分类算法self.iterTimes = 0self.b = 0stop = Falsewhile not stop:wrong_count = 0for i in range(len(self.dataX)):X = self.dataX[i]y = self.datay[i]if (y * self.sign0(X, self.w, self.b)) <= 0:self.w += self.eta * np.dot(X, y)self.b += self.eta * ywrong_count += 1self.iterTimes += 1if wrong_count == 0:stop = Trueprint("原始形式,分类完成!步长:%.4f, 共迭代 %d 次" % (self.eta, self.iterTimes))def calculateGmatrix(self):  # 计算Gram矩阵for i in range(len(self.dataX)):for j in range(0, i + 1):  # 对称的计算一半就行self.Gmatrix[i][j] = np.dot(self.dataX[i], self.dataX[j])self.Gmatrix[j][i] = self.Gmatrix[i][j]def DualFormClassifier(self):  # 对偶形式分类算法self.iterTimes = 0self.b = 0stop = Falsewhile not stop:wrong_count = 0for i in range(len(self.dataX)):y = self.datay[i]G_i = self.Gmatrix[i]if (y * self.sign1(self.a, G_i, self.datay, self.b)) <= 0:self.a[i] += self.etaself.b += self.eta * ywrong_count += 1self.iterTimes += 1if wrong_count == 0:stop = Trueprint("对偶形式,分类完成!步长:%.4f, 共迭代 %d 次" % (self.eta, self.iterTimes))if __name__ == '__main__':# 读取鸢尾花数据iris = load_iris()# 将鸢尾花4个特征,以4列存入pandas的数据框架df = pd.DataFrame(iris.data, columns=iris.feature_names)# 在最后一列追加 加入标签(分类)列数据df['lab'] = iris.target# df.columns=[iris.feature_names[0], iris.feature_names[1], iris.feature_names[2], iris.feature_names[3], 'lab']# df['lab'].value_counts()# 选取前两种花进行划分(每种数据50组)plt.scatter(df[:50][iris.feature_names[0]], df[:50][iris.feature_names[1]], label=iris.target_names[0])plt.scatter(df[50:100][iris.feature_names[0]], df[50:100][iris.feature_names[1]], label=iris.target_names[1])plt.xlabel(iris.feature_names[0])plt.ylabel(iris.feature_names[1])# 选取数据,前100行,前两个特征,最后一列标签data = np.array(df.iloc[:100, [0, 1, -1]])# X是除最后一列外的所有列,y是最后一列X, y = data[:, :-1], data[:, -1]# 生成感知机的标签值,+1, -1, 第一种-1,第二种+1y = np.array([1 if i == 1 else -1 for i in y])# 调用感知机进行分类,学习率etaperceptron = PerceptronModel(X, y, eta=0.1)perceptron.OriginClassifier()  # 原始形式分类# 绘制原始算法分类超平面x_points = np.linspace(4, 7, 10)y0 = -(perceptron.w[0] * x_points + perceptron.b) / perceptron.w[1]plt.plot(x_points, y0, 'r', label='原始算法分类线')perceptron.DualFormClassifier()  # 对偶形式分类# 由alpha,b 计算omega向量omega0 = sum(perceptron.a[i] * y[i] * X[i][0] for i in range(len(X)))omega1 = sum(perceptron.a[i] * y[i] * X[i][1] for i in range(len(X)))y1 = -(omega0 * x_points + perceptron.b) / omega1# 绘制对偶算法分类超平面plt.plot(x_points, y1, 'b', label='对偶算法分类线')plt.rcParams['font.sans-serif'] = 'SimHei'  # 消除中文乱码plt.legend()plt.show()# ------------------学习率不同,查看迭代次数----------------------------n = 5i = 0eta_iterTime = np.zeros((n, 3), dtype=float)for eta in np.linspace(0.01, 1.01, n):eta_iterTime[i][0] = eta  # 第一列,学习率perceptron = PerceptronModel(X, y, eta)perceptron.OriginClassifier()eta_iterTime[i][1] = perceptron.iterTimes  # 第二列,原始算法迭代次数perceptron.DualFormClassifier()eta_iterTime[i][2] = perceptron.iterTimes  # 第三列,对偶算法迭代次数i += 1x = eta_iterTime[:, 0]  # 数据切片y0 = eta_iterTime[:, 1]y1 = eta_iterTime[:, 2]plt.scatter(x, y0, c='r', marker='o', label='原始算法')plt.scatter(x, y1, c='b', marker='x', label='对偶算法')plt.xlabel('步长(学习率)')plt.ylabel('迭代次数')plt.title("不同步长,不同算法形式下,迭代次数")plt.legend()plt.show()# ------------------sklearn实现----------------------------classify = Perceptron(fit_intercept=True, max_iter=10000, shuffle=False, eta0=0.5, tol=None)classify.fit(X, y)print("特征权重:", classify.coef_)  # 特征权重 wprint("截距(偏置):", classify.intercept_)  # 截距 b# 可视化plt.scatter(df[:50][iris.feature_names[0]], df[:50][iris.feature_names[1]], label=iris.target_names[0])plt.scatter(df[50:100][iris.feature_names[0]], df[50:100][iris.feature_names[1]], label=iris.target_names[1])plt.xlabel(iris.feature_names[0])plt.ylabel(iris.feature_names[1])# 绘制分类超平面x_points = np.linspace(4, 7, 10)y = -(classify.coef_[0][0] * x_points + classify.intercept_) / classify.coef_[0][1]plt.plot(x_points, y, 'r', label='sklearn Perceptron分类线')plt.title("sklearn内置感知机分类")plt.legend()plt.show()

基于感知机Perceptron的鸢尾花分类实践相关推荐

  1. 猿创征文|深度学习基于前馈神经网络完成鸢尾花分类

    大家我是猿童学!这次给大家带来的是基于前馈神经网络完成鸢尾花分类! 在本实验中,我们使用的损失函数为交叉熵损失:优化器为随机梯度下降法:评价指标为准确率. 一.小批量梯度下降法 在梯度下降法中,目标函 ...

  2. 机器学习算法(九): 基于线性判别LDA模型的分类(基于LDA手写数字分类实践)

    机器学习算法(九): 基于线性判别模型的分类 1.前言:LDA算法简介和应用 1.1.算法简介 线性判别模型(LDA)在模式识别领域(比如人脸识别等图形图像识别领域)中有非常广泛的应用.LDA是一种监 ...

  3. 基于逻辑回归的鸢尾花分类预测

    基于逻辑回归的分类预测 1 逻辑回归的介绍和应用 1.1 逻辑回归的介绍 1.2 逻辑回归的应用 2 学习目标 3 代码流程 4 算法实战 4.1 Demo实践 Step1:库函数导入 Step2:模 ...

  4. 基于sklearn的LogisticRegression二分类实践

    文章目录 1. 预备知识 2. 实践代码 3. 结果对比 3.1 正态分布 3.2 均匀分布 3.3 修改Pipeline 3.3.1 删除多项式转换 3.3.2 删除归一化项 3.3.3 删除多项式 ...

  5. Python 基于BP神经网络的鸢尾花分类

    本文用Python实现了BP神经网络分类算法,根据鸢尾花的4个特征,实现3种鸢尾花的分类. 算法参考文章:纯Python实现鸢尾属植物数据集神经网络模型 2020.07.21更新: 增加了分类结果可视 ...

  6. 基于逻辑回归的鸢尾花分类

    二分类实现辨别是否是鸢尾花 尽管名为逻辑回归,但实际上是一个分类模型,尤其是在我们只有两个类时.逻辑回归的名称来源于将输入的任意实值x转换成值在0到1 采用sigmoid,划为[0,1]之间的数据 , ...

  7. 基于sklearn的LogisticRegression鸢尾花多类分类实践

    文章目录 1. 问题描述 2. 数据介绍 2.1 数据描述 2.2 数据 2.3 数据可视化 3. 模型选择 3.1 固有的多类分类器 3.2 1对多的多类分类器 3.3 OneVsRestClass ...

  8. python决策树分类鸢尾花_基于决策树—鸢尾花分类

    决策树算法广泛应用于:语音识别.医疗诊断.客户关系管理.模式识别.专家系统等,在实际工作中,必须根据数据类型的特点及数据集的大小,选择合适的算法. 本文选择经典案例--<鸢尾花分类> 一. ...

  9. 机器学习项目实践——鸢尾花分类

    基于SVM算法实现鸢尾花分类 摘要:支持向量机,因其英文名为support vector machine,故一般简称SVM,通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分 ...

最新文章

  1. Kubernetes 1.14 版本发布:正式支持Windows 节点,持久化本地卷进入GA
  2. linux 进程做成服务,Linux自定义后台服务进程
  3. SQL 解决从分组数据中总是挑选第一条数据的问题
  4. 严重: Dispatcher initialization failed java.lang.RuntimeException
  5. 2021-01-07 matlab数值分析 线性代数的直接接法  追赶法
  6. anasys hpc集群_这可能是最简单的并行方案,如何基于 AWS ParallelCluster 运行 ANSYS Fluent...
  7. 前端工具--less篇
  8. 软件开发,维护与支持的困惑
  9. JavaScript-传值(引用类型,基本类型)
  10. 贝叶斯学派与频率学派有何不同?
  11. 2018年香港访港旅客超6500万人次 创16年新高
  12. nginx 代理部署前端项目
  13. IBM小型机安装AIX系统
  14. 栅栏密码怎么写java程序_栅栏密码
  15. delphi与python_python和delphi哪个好
  16. Flash视频播放器 JW PLAYER怎么在网页中运用?
  17. # 关于Dran,Cran,CloundRan ,的区别
  18. 腾讯云轻量服务器搭建,腾讯云轻量服务器配置系统镜像自定义建站及安全组配置...
  19. PATC语言1-50
  20. win7 打开“计算机”慢,怎么解决win7开机慢|win7系统开机速度慢的三大解决方法...

热门文章

  1. python *args和**kwargs以及序列解包
  2. c语言中用文件处理数据,C语言文件处理 -C语言从文件中读写格式化数据
  3. android防谷歌滑动效果,谷歌是如何做到这一点的?在Android应用程序中滑动ActionBar...
  4. uboot的目录分析
  5. Python学习之路——装饰器
  6. Window系统下安装Redis
  7. JAVA中获得一个月最大天数的方法(备忘)
  8. 实现DIV居中布局三种途径(转)
  9. 图的定义与术语 - 数据结构和算法54
  10. Server操作Mxd文件详细讲解