基于感知机Perceptron的鸢尾花分类实践

文章目录

    • 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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477206.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大火的扩散模型终于杀到了NLP领域

从2020年的初出茅庐&#xff0c;到2021年的日趋火热&#xff0c;再到2022年的大放异彩&#xff0c;扩散模型(Diffusion Models) 正在人工智能学术界和工业界获取越来越多的关注。如果还不是特别了解扩散模型的朋友&#xff0c;可以阅读卖萌屋的几篇历史推文《扩散模型在图像生成…

Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅

在上一篇Spring中使用JdbcTemplate访问数据库 中介绍了一种基本的数据访问方式&#xff0c;结合构建RESTful API和使用Thymeleaf模板引擎渲染Web视图的内容就已经可以完成App服务端和Web站点的开发任务了。 然而&#xff0c;在实际开发过程中&#xff0c;对数据库的操作无非就…

AI终于攻陷了数学领域!高数考试超过普通博士??

文 | 梦晨 丰色 发自 凹非寺源 | 量子位高数考不好&#xff0c;不知道是多少人的噩梦。如果说你高数考得还不如AI好&#xff0c;是不是就更难以接受了&#xff1f;没错&#xff0c;来自OpenAI的Codex已经在MIT的7门高数课程题目中正确率达到81.1%&#xff0c;妥妥的MIT本科生水…

十年内就能实现通用人工智能?先把组合泛化研究明白吧!

文 | Albert Yang编 | 白鹡鸰"乌鸦为什么像写字台&#xff1f;"因为它们都能produce a few notes &#xff08;鸟叫/笔记&#xff09;&#xff0c;因为乌鸦和写字台都是思想与记忆的象征&#xff08;北欧神话&#xff09;&#xff0c;又或者因为&#xff0c;这本身就…

LeetCode 1366. 通过投票对团队排名(自定义排序)

1. 题目 现在有一个特殊的排名系统&#xff0c;依据参赛团队在投票人心中的次序进行排名&#xff0c;每个投票者都需要按从高到低的顺序对参与排名的所有团队进行排位。 排名规则如下&#xff1a; 参赛团队的排名次序依照其所获「排位第一」的票的多少决定。如果存在多个团队…

Spring Boot中使用JdbcTemplate访问数据库

之前介绍了很多Web层的例子&#xff0c;包括构建RESTful API、使用Thymeleaf模板引擎渲染Web视图&#xff0c;但是这些内容还不足以构建一个动态的应用。通常我们做App也好&#xff0c;做Web应用也好&#xff0c;都需要内容&#xff0c;而内容通常存储于各种类型的数据库&#…

LeetCode 1367. 二叉树中的列表(双重递归)

1. 题目 给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表。 如果在二叉树中&#xff0c;存在一条一直向下的路径&#xff0c;且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值&#xff0c;那么请你返回 True &#xff0c;否则返回 False 。 一直向…

Spring Boot构建RESTful API与单元测试

首先&#xff0c;回顾并详细说明一下在快速入门中使用的Controller、RestController、RequestMapping注解。如果您对Spring MVC不熟悉并且还没有尝试过快速入门案例&#xff0c;建议先看一下快速入门的内容。 Controller&#xff1a;修饰class&#xff0c;用来创建处理http请…

推荐系统用户反馈延迟新解法!阿里提出CVR无偏估计算法

文 | Shona在广告、电商场景中&#xff0c;流式样本通常只会在一个较短的窗口采样用户的行为&#xff0c;但用户从点击到转化的时间窗口可能很长&#xff0c;比如逛淘宝时&#xff0c;点击一件商品后可能在其他平台对比很久后才会下单&#xff0c;这导致在流式样本采样的时间窗…

LeetCode 1368. 使网格图至少有一条有效路径的最小代价(BFS最短路径,难)

1. 题目 给你一个 m x n 的网格图 grid 。 grid 中每个格子都有一个数字&#xff0c;对应着从该格子出发下一步走的方向。 grid[i][j] 中的数字可能为以下几种情况&#xff1a; 1 &#xff0c;下一步往右走&#xff0c;也就是你会从 grid[i][j] 走到 grid[i][j 1]2 &#xf…

Spring Boot工程结构推荐

今天看了一位简书上朋友发来的工程&#xff0c;于是想到应该要写这么一篇。前人总结的最佳实践案例可以帮助我们免去很多不必要的麻烦。花点时间来看一下本文&#xff0c;绝对物超所值。 工程结构&#xff08;最佳实践&#xff09; Spring Boot框架本身并没有对工程结构有特别…

GPT-3写了一篇论文

文 | Pine 发自 凹非寺源 | 量子位咦&#xff1f;这篇论文有点不对劲&#xff0c;第一作者看起来不像是人类的名字&#xff1a;一作的署名GPT-3&#xff0c;所属单位OpenAI。是的&#xff01;你没看错&#xff0c;GPT-3写了一篇关于自己的论文。此前&#xff0c;GPT-3已经撰写过…

程序员面试金典 - 面试题 02.03. 删除中间节点

1. 题目 实现一种算法&#xff0c;删除单向链表中间的某个节点&#xff08;除了第一个和最后一个节点&#xff0c;不一定是中间节点&#xff09;&#xff0c;假定你只能访问该节点。 示例&#xff1a; 输入&#xff1a;单向链表a->b->c->d->e->f中的节点c 结果…

Spring Boot开发Web应用

Spring Boot快速入门中我们完成了一个简单的RESTful Service&#xff0c;体验了快速开发的特性。在留言中也有朋友提到如何把处理结果渲染到页面上。那么本篇就在上篇基础上介绍一下如何进行Web应用的开发。 静态资源访问 在我们开发Web应用的时候&#xff0c;需要引用大量的j…

双塔模型的最强出装,谷歌又开始玩起“老古董”了?

文 | 兔子酱双塔模型已经证明在搜索和问答任务中是非常有效的建模方法&#xff0c;理论和业务落地已相当成熟。双塔根据参数共享程度不同&#xff0c;通常会归纳成两类&#xff1a;Simese dual encoder和Asymmetric dual encoder&#xff0c;前者参数结构完全对称&#xff0c;后…

LintCode解题目录

看见 LintCode 的代码能力测试CAT&#xff08;Coding Ability Test&#xff09;挺好&#xff0c;有倒计时&#xff0c;挺有面试紧迫感。做个记录。 另有本人 LeetCode解题目录、《程序员面试金典》解题目录、《剑指Offer》解题目录 我的 LintCode 主页 75 / 1505 算法问题 …

BERTopic:NLP主题模型的未来!

文| ZenMoore编| 小轶以前我一直以为&#xff0c;主题建模(提取文档的主题词)这种机器学习时代就开始研究的基础工具&#xff0c;现在肯定已经到头了&#xff0c;虽然...有时效果可能不是那么让人满意。但突然看到一则推文&#xff1a;“彻底疯了&#xff01;不需要预先清洗数据…

K 近邻法(K-Nearest Neighbor, K-NN)

文章目录1. k近邻算法2. k近邻模型2.1 模型2.2 距离度量2.2.1 距离计算代码 Python2.3 kkk 值的选择2.4 分类决策规则3. 实现方法, kd树3.1 构造 kdkdkd 树Python 代码3.2 搜索 kdkdkd 树Python 代码4. 鸢尾花KNN分类4.1 KNN实现4.2 sklearn KNN5. 文章完整代码k近邻法&#xf…

通用人工智能可行吗?组合泛化视角漫谈

"乌鸦为什么像写字台&#xff1f;"因为它们都能produce a few notes &#xff08;鸟叫/笔记&#xff09;&#xff0c;因为乌鸦和写字台都是思想与记忆的象征&#xff08;北欧神话&#xff09;&#xff0c;又或者因为&#xff0c;这本身就是一句没有道理的话&#xff…

Transformer 在美团搜索排序中的实践

引言 美团搜索是美团 App 连接用户与商家的一种重要方式&#xff0c;而排序策略则是搜索链路的关键环节&#xff0c;对搜索展示效果起着至关重要的效果。目前&#xff0c;美团的搜索排序流程为多层排序&#xff0c;分别是粗排、精排、异构排序等&#xff0c;多层排序的流程主要…