使用 Python 探索 感知机 算法

简介: 使用 Python 探索 感知机 算法

动动发财的小手,点个赞吧!

从理论到实践,我们将从简要的理论介绍开始研究感知机(器)学习方法,然后实现。

在这篇博文的最后,您将能够了解何时以及如何使用这种机器学习算法,清楚地了解它的所有优缺点。

1. 理论

1.1. 引言

感知器有其存在的生物学原因。我们的神经元不断从其他神经元接收能量,但只有在它们接收到的能量大于或等于一定量后,它们才会决定“激活”并发出自己的信号。

让我们从最后开始。给定一个 4 维输入,这个输入用 4 个不同的权重进行处理,总和进入激活函数,你就得到了结果。

讲的更清除一点,假设您有这张功能表(列)X1、X2、X3 和 X4。这些特征是 4 个不同的值,用于表征数据集的单个实例(行)。

这个实例需要进行二进制分类,这样你就会有一个额外的值 t,它是目标,可以是 -1 或 1。

感知机算法将 X1、X2、X3 和 X4 乘以一组 4 个权重。出于这个原因,我们认为感知器是一种线性算法。

然后,激活函数将应用于此乘法的结果。

这是整个过程中的方程式:

其中 a 是所谓的激活函数。

当然,输入可以是 N 维的(N 不一定是四维),这样您也可以使用 N 权重 + 1 偏差。尽管如此,纯感知器算法旨在用于二进制分类。

当然,y=a(w_1x_1+…+w_4x_4)的结果需要在-1到1之间。换句话说,归根结底,所谓的激活函数需要能够给你一个分类。

N 维输入与 N 维权重的乘积将为您提供一个数字。那么如果这个数字大于 0,你的算法会说“1”,否则会说“-1”。

这就是它的运行方式,也是它做出决定的方式。

1.2. 损失函数

我们都知道机器学习算法带有损失函数。在这种情况下,损失函数是错误分类点的加权和。

假设您有一个分类不正确的点。这意味着,例如,将您的参数与您的输入相乘,您将得到 -0.87 的最终结果。

好的,重点来了,错误分类,记得吗?因此,这意味着该点 (t=1) 的目标确实为“1”。所以这意味着如果你做这个乘法:

你实际上得到了一个数,告诉你你错了多少,你应该改变你的权重和 bias 来做更好的分类工作。

一般来说,损失函数是所有错误分类点的负和:

其中S是错误分类点的集合。

我们将开始优化这个损失函数,当然我们想要最小化。

您在上面看到的等式称为梯度下降。这意味着我们遵循损失达到最小值的方向,并按照这个方向更新参数。

由于损失函数取决于错误分类点的数量,这意味着我们将慢慢开始纠正实例,直到如果数据集是线性可分的,将不再有目标“正确”,我们的分类任务将是完美的。

2. 实现

当然,SkLearn Perceptron 是众所周知的现成实现。尽管如此,为了更好地理解它,让我们从头开始创建这个感知器。

让我们从库开始:

import matplotlib.pyplot as plt
import numpy as np
plt.style.use('ggplot')
plt.rcParams['font.family'] = 'sans-serif' 
plt.rcParams['font.serif'] = 'Ubuntu' 
plt.rcParams['font.monospace'] = 'Ubuntu Mono' 
plt.rcParams['font.size'] = 14 
plt.rcParams['axes.labelsize'] = 12 
plt.rcParams['axes.labelweight'] = 'bold' 
plt.rcParams['axes.titlesize'] = 12 
plt.rcParams['xtick.labelsize'] = 12 
plt.rcParams['ytick.labelsize'] = 12 
plt.rcParams['legend.fontsize'] = 12 
plt.rcParams['figure.titlesize'] = 12 
plt.rcParams['image.cmap'] = 'jet' 
plt.rcParams['image.interpolation'] = 'none' 
plt.rcParams['figure.figsize'] = (10, 10
                                 ) 
plt.rcParams['axes.grid']=True
plt.rcParams['lines.linewidth'] = 2 
plt.rcParams['lines.markersize'] = 8
colors = ['xkcd:pale range', 'xkcd:sea blue', 'xkcd:pale red', 'xkcd:sage green', 'xkcd:terra cotta', 'xkcd:dull purple', 'xkcd:teal', 'xkcd: goldenrod', 'xkcd:cadet blue',
'xkcd:scarlet']
bbox_props = dict(boxstyle="round,pad=0.3", fc=colors[0], alpha=.5)

让我们定义决策函数:

def step_func(z):
        return 1.0 if (z > 0) else 0.0

2.1. 线性数据

让我们使用 SkLearn 创建一个线性可分的数据集。

from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler


X, y = datasets.make_blobs(n_samples=150,n_features=2,
                           centers=2,cluster_std=3.20)
y[y==0]=-1

#Plotting

min_max_scaler = MinMaxScaler()
X = min_max_scaler.fit_transform(X)

fig = plt.figure(figsize=(10,8))
plt.plot(X[:, 0][y == -1], X[:, 1][y == -1], 'r^')
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'bs')
plt.xlabel("feature 1")
plt.ylabel("feature 2")
plt.title('Random Classification Data with 2 classes')

2.2. 感知器函数

使用这个函数,实际上实现了之前讲解过的所有思路:

def perceptron(X, y, lr, epochs):
    
    # X --> Inputs.
    # y --> labels/target.
    # lr --> learning rate.
    # epochs --> Number of iterations.
    
    # m-> number of training examples
    # n-> number of features 
    m, n = X.shape
    
    # Initializing parapeters(theta) to zeros.
    # +1 in n+1 for the bias term.
    theta = np.zeros((n+1,1))
    
    # Empty list to store how many examples were 
    # misclassified at every iteration.
    n_miss_list = []
    loss_list = []
    # Training.
    for epoch in range(epochs):
        
        # variable to store #misclassified.
        n_miss = 0
        
        # looping for every example.
        for idx, x_i in enumerate(X):
            
            # Insering 1 for bias, X0 = 1.
            x_i = np.insert(x_i, 0, 1).reshape(-1,1)
            
            # Calculating prediction/hypothesis.
            y_hat = step_func(np.dot(x_i.T, theta))
            if y_hat==0:
              y_hat = -1
            # Updating if the example is misclassified.
            if (np.squeeze(y_hat) - y[idx]) != 0:
                theta += lr*((y[idx] - y_hat)*x_i)

                # Incrementing by 1.
                n_miss += 1
        #Defining the loss function
        x1 = X[:,0]
        x2 = X[:,1]
        theta_array = theta
        loss_value = (theta_array[1]*x1+theta_array[2]*x2+theta_array[0])*y
        loss_value = loss_value.sum()/len(x1)
        loss_list.append(loss_value)
        # Appending number of misclassified examples
        # at every iteration.
        n_miss_list.append(n_miss)

    return theta, n_miss_list,loss_list

然后我们可以使用以下代码绘制决策边界:

def plot_decision_boundary(X, theta):
    
    # X --> Inputs
    # theta --> parameters
    
    # The Line is y=mx+c
    # So, Equate mx+c = theta0.X0 + theta1.X1 + theta2.X2
    # Solving we find m and c
    x1 = [min(X[:,0]), max(X[:,0])]
    m = -theta[1]/theta[2]
    c = -theta[0]/theta[2]
    x2 = m*x1 + c
    
    # Plotting
    fig = plt.figure(figsize=(10,8))
    plt.plot(X[:, 0][y==-1], X[:, 1][y==-1], "r^")
    plt.plot(X[:, 0][y==1], X[:, 1][y==1], "bs")
    plt.xlabel("Feature 1")
    plt.ylabel("Feature 2")
    plt.title('Perceptron Algorithm')
    plt.plot(x1, x2, 'y-')

那么让我们看看玩具数据集中发生了什么:

learning_rate , epoch = 0.005,200
theta, miss_l,loss_list= perceptron(X, y, learning_rate, epoch)
plot_decision_boundary(X, theta)

可以看出,所有的点都被很好地分类了(即使是小的红色三角形)。

让我们看看损失函数图:

def plot_training(miss_l):
  plt.figure(figsize=(12,12))
  list_array = np.arange(0,len(miss_l),1)
  plt.xlabel('Number of Epochs')
  plt.ylabel('Number of Wrong Classified Points')
  plt.plot(list_array,miss_l)
plot_training(miss_l)

这意味着数据集现在已经完全分类了。

2.3. 非线性数据

让我们考虑一个更难的非线性可分数据集。

from sklearn import datasets
X, y = datasets.make_blobs(n_samples=150,n_features=2,
                           centers=2,cluster_std=3.20)
y[y==0]=-1

#Plotting

min_max_scaler = MinMaxScaler()
X = min_max_scaler.fit_transform(X)

fig = plt.figure(figsize=(10,8))
plt.plot(X[:, 0][y == -1], X[:, 1][y == -1], 'r^')
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'bs')
plt.xlabel("feature 1")
plt.ylabel("feature 2")
plt.title('Random Classification Data with 2 classes')

让我们运行算法:

def plot_decision_boundary(X, theta):
    
    # X --> Inputs
    # theta --> parameters
    
    # The Line is y=mx+c
    # So, Equate mx+c = theta0.X0 + theta1.X1 + theta2.X2
    # Solving we find m and c
    x1 = [min(X[:,0]), max(X[:,0])]
    m = -theta[1]/theta[2]
    c = -theta[0]/theta[2]
    x2 = m*x1 + c
    
    # Plotting
    fig = plt.figure(figsize=(10,8))
    plt.plot(X[:, 0][y==-1], X[:, 1][y==-1], "r^")
    plt.plot(X[:, 0][y==1], X[:, 1][y==1], "bs")
    plt.xlabel("Feature 1")
    plt.ylabel("Feature 2")
    plt.title('Perceptron Algorithm')
    plt.plot(x1, x2, 'y-')
    plt.xlim(-0.1,1.1)
    plt.ylim(-0.1,1.1)
    
theta, miss_l,loss = perceptron(X, y, 0.2, 10)

plot_decision_boundary(X, theta)

theta, miss_l,loss = perceptron(X, y, 1, 20)

plot_decision_boundary(X, theta)    

好的,现在我们可能需要做一些工作才能获得最佳分类。

让我们运行不同数量的 epoch 和不同的学习率(所谓的超参数调整)以获得感知器的最佳版本:

from sklearn.linear_model import Perceptron
num_of_epochs = [10,100,500,1000]
etas = np.linspace(1e-5,1,100)
scores = []
for e in etas:
  for num in num_of_epochs:
    clf = Perceptron(eta0=e,max_iter=num)
    clf.fit(X, y)
    scores.append({'Num':num,'Eta':e.round(5),'Score':clf.score(X, y)})
    
    
import pandas as pd
import seaborn as sns
scores=pd.DataFrame(scores)
pivot = scores.pivot('Num','Eta','Score')


sns.heatmap(data=pivot)

所以这是最佳的epoch和学习率:

scores[scores.Score==scores.Score.max()]

总结

  • 感知器算法很快。其实就是一个线性乘法+阶跃函数的应用。它非常简单易用。
  • 当数据集不可线性分离时,算法不会根据损失函数收敛。这意味着该感知器旨在(完美地)仅在线性可分数据集上工作。尽管如此,我们可以对数据集应用转换,并将感知器算法应用于转换后的数据集
  • 超参数调整部分可以大大提高算法的性能。
相关文章
|
9天前
|
机器学习/深度学习 存储 算法
解锁文件共享软件背后基于 Python 的二叉搜索树算法密码
文件共享软件在数字化时代扮演着连接全球用户、促进知识与数据交流的重要角色。二叉搜索树作为一种高效的数据结构,通过有序存储和快速检索文件,极大提升了文件共享平台的性能。它依据文件名或时间戳等关键属性排序,支持高效插入、删除和查找操作,显著优化用户体验。本文还展示了用Python实现的简单二叉搜索树代码,帮助理解其工作原理,并展望了该算法在分布式计算和机器学习领域的未来应用前景。
|
25天前
|
监控 算法 安全
深度洞察内网监控电脑:基于Python的流量分析算法
在当今数字化环境中,内网监控电脑作为“守城卫士”,通过流量分析算法确保内网安全、稳定运行。基于Python的流量分析算法,利用`scapy`等工具捕获和解析数据包,提取关键信息,区分正常与异常流量。结合机器学习和可视化技术,进一步提升内网监控的精准性和效率,助力企业防范潜在威胁,保障业务顺畅。本文深入探讨了Python在内网监控中的应用,展示了其实战代码及未来发展方向。
|
1月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
130 5
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
2月前
|
存储 缓存 监控
局域网屏幕监控系统中的Python数据结构与算法实现
局域网屏幕监控系统用于实时捕获和监控局域网内多台设备的屏幕内容。本文介绍了一种基于Python双端队列(Deque)实现的滑动窗口数据缓存机制,以处理连续的屏幕帧数据流。通过固定长度的窗口,高效增删数据,确保低延迟显示和存储。该算法适用于数据压缩、异常检测等场景,保证系统在高负载下稳定运行。 本文转载自:https://www.vipshare.com
132 66
|
5天前
|
监控 算法 安全
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
28 10
|
23天前
|
存储 算法 安全
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
50 17
|
1月前
|
存储 监控 算法
员工电脑监控屏幕场景下 Python 哈希表算法的探索
在数字化办公时代,员工电脑监控屏幕是保障信息安全和提升效率的重要手段。本文探讨哈希表算法在该场景中的应用,通过Python代码例程展示如何使用哈希表存储和查询员工操作记录,并结合数据库实现数据持久化,助力企业打造高效、安全的办公环境。哈希表在快速检索员工信息、优化系统性能方面发挥关键作用,为企业管理提供有力支持。
45 20
|
27天前
|
存储 人工智能 算法
深度解密:员工飞单需要什么证据之Python算法洞察
员工飞单是企业运营中的隐性风险,严重侵蚀公司利润。为应对这一问题,精准搜集证据至关重要。本文探讨如何利用Python编程语言及其数据结构和算法,高效取证。通过创建Transaction类存储交易数据,使用列表管理订单信息,结合排序算法和正则表达式分析交易时间和聊天记录,帮助企业识别潜在的飞单行为。Python的强大功能使得从交易流水和沟通记录中提取关键证据变得更加系统化和高效,为企业维权提供有力支持。
|
26天前
|
存储 算法 安全
U 盘管控情境下 Python 二叉搜索树算法的深度剖析与探究
在信息技术高度发达的今天,数据安全至关重要。U盘作为常用的数据存储与传输工具,其管控尤为关键。本文探讨Python中的二叉搜索树算法在U盘管控中的应用,通过高效管理授权U盘信息,防止数据泄露,保障信息安全。二叉搜索树具有快速插入和查找的优势,适用于大量授权U盘的管理。尽管存在一些局限性,如树结构退化问题,但通过优化和改进,如采用自平衡树,可以有效提升U盘管控系统的性能和安全性。
26 3
|
1月前
|
存储 算法 Serverless
剖析文件共享工具背后的Python哈希表算法奥秘
在数字化时代,文件共享工具不可或缺。哈希表算法通过将文件名或哈希值映射到存储位置,实现快速检索与高效管理。Python中的哈希表可用于创建简易文件索引,支持快速插入和查找文件路径。哈希表不仅提升了文件定位速度,还优化了存储管理和多节点数据一致性,确保文件共享工具高效运行,满足多用户并发需求,推动文件共享领域向更高效、便捷的方向发展。