Machine Learning-感知器分类算法详解

机器学习系列专栏

选自 python-machine-learning-book on GitHub

作者:Sebastian Raschka

翻译&整理 by Sam

最近在GitHub上面发现了一个炒鸡赞的项目,果然直接拿过来消化一波,这个项目的内容是关于机器学习的指导,我会挑一些内容来完成下面的一系列文章。

今天我们来讲解的内容是感知器分类算法,本文的结构如下:

  • 什么是感知器分类算法
  • 在Python中实现感知器学习算法
    • 在iris(鸢尾花)数据集上训练一个感知器模型
  • 自适应线性神经元和融合学习
    • 使用梯度下降方法来最小化损失函数
    • 在Python中实现一个自适应的线性神经元

什么是感知器分类算法

‍‍‍‍‍‍‍‍‍设想我们改变逻辑回归算法,“迫使”它只能输出-1或1抑或其他定值。在这种情况下,之前的逻辑函数‍‍g就会变成阈值函数sign:

如果我们令假设为hθ(x)=g(θTx)hθ(x)=g(θTx),将其带入之前的迭代法中:

至此我们就得出了感知器学习算法。简单地来说,感知器学习算法是神经网络中的一个概念,单层感知器是最简单的神经网络,输入层和输出层直接相连。

每一个输入端和其上的权值相乘,然后将这些乘积相加得到乘积和,这个结果与阈值相比较(一般为0),若大于阈值输出端就取1,反之,输出端取-1。

初始权重向量W=[0,0,0],更新公式W(i)=W(i)+ΔW(i);ΔW(i)=η*(y-y’)*X(i); η:学习率,介于[0,1]之间 y:输入样本的正确分类 y’:感知器计算出来的分类 通过上面公式不断更新权值,直到达到分类要求。

图:单层感知器模型

初始化权重向量W,与输入向量做点乘,将结果与阈值作比较,得到分类结果1或-1。

在Python中实现感知器学习算法

下面直接贴上实现代码:(也可在公众号后台输入“感知器”进行获取ipynb文件)

 1import numpy as np
 2class  Perceptron(object):
 3"""Perceptron classifier.
 4Parameters
 5------------
 6eta : float
 7    Learning rate (between 0.0 and 1.0)
 8n_iter : int
 9    Passes over the training dataset.
10Attributes
11-----------
12w_ : 1d-array
13    Weights after fitting.
14errors_ : list
15    Number of misclassifications (updates) in each epoch.
16"""
17def __init__(self, eta=0.01, n_iter=10):
18    self.eta = eta
19    self.n_iter = n_iter
20def fit(self, X, y):
21    """Fit training data.
22    Parameters
23    ----------
24    X : {array-like}, shape = [n_samples, n_features]
25        Training vectors, where n_samples is the number of samples and
26        n_features is the number of features.
27    y : array-like, shape = [n_samples]
28        Target values.
29    Returns
30    -------
31    self : object
32    """
33    self.w_ = np.zeros(1 + X.shape[1])
34    self.errors_ = []
35    for _ in range(self.n_iter):
36        errors = 0
37        for xi, target in zip(X, y):
38            update = self.eta * (target - self.predict(xi))
39            self.w_[1:] += update * xi
40            self.w_[0] += update
41            errors += int(update != 0.0)
42        self.errors_.append(errors)
43    return self
44def net_input(self, X):
45    """Calculate net input"""
46    return np.dot(X, self.w_[1:]) + self.w_[0]
47def predict(self, X):
48    """Return class label after unit step"""
49    return np.where(self.net_input(X) >= 0.0, 1, -1)

特别说明:

学习速率η(eta)只有在权重(一般取值0或者很小的数)为非零值的时候,才会对分类结果产生作用。如果所有的权重都初始化为0,学习速率参数eta只影响权重向量的大小,而不影响其方向,为了使学习速率影响分类结果,权重需要初始化为非零值。需要更改的代码中的相应行在下面突出显示:

1def __init__(self, eta=0.01, n_iter=50, random_seed=1): # add random_seed=1
2    ...
3    self.random_seed = random_seed # add this line
4def fit(self, X, y):
5    ...
6    # self.w_ = np.zeros(1 + X.shape[1]) ## remove this line
7    rgen = np.random.RandomState(self.random_seed) # add this line
8    self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1]) # add this line

在iris(鸢尾)数据集上训练一个感知器模型

读取iris数据集

1import pandas as pd
2import collections
3df = pd.read_csv('https://archive.ics.uci.edu/ml/'
4        'machine-learning-databases/iris/iris.data', header=None)
5print (df.head())
6print ("\n")
7print (df.describe())
8print ("\n")
9print (collections.Counter(df[4]))

output:

可视化iris数据

 1%matplotlib inline
 2import matplotlib.pyplot as plt
 3import numpy as np
 4# 为了显示中文(这里是Mac的解决方法,其他的大家可以去百度一下)
 5from matplotlib.font_manager import FontProperties
 6font = FontProperties(fname='/System/Library/Fonts/STHeiti Light.ttc')
 7# 选择 setosa and versicolor类型的花
 8y = df.iloc[0:100, 4].values
 9y = np.where(y == 'Iris-setosa', -1, 1)
10# 提取它们的特征 (sepal length and petal length)
11X = df.iloc[0:100, [0, 2]].values
12# 可视化数据,因为数据有经过处理,总共150行数据,1-50行是setosa花,51-100是versicolor花,101-150是virginica花
13plt.scatter(X[:50, 0], X[:50, 1],
14            color='red', marker='o', label='setosa')
15plt.scatter(X[50:100, 0], X[50:100, 1],
16            color='blue', marker='x', label='versicolor')
17plt.xlabel('sepal 长度 [cm]',FontProperties=font,fontsize=14)
18plt.ylabel('petal 长度 [cm]',FontProperties=font,fontsize=14)
19plt.legend(loc='upper left')
20plt.tight_layout()
21plt.show()

output:

训练感知器模型

1# Perceptron是我们前面定义的感知器算法函数,这里就直接调用就好
2ppn = Perceptron(eta=0.1, n_iter=10)
3ppn.fit(X, y)
4plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker='o')
5plt.xlabel('迭代次数',FontProperties=font,fontsize=14)
6plt.ylabel('权重更新次数(错误次数)',FontProperties=font,fontsize=14)
7plt.tight_layout()
8plt.show()

output:

绘制函数决策区域

 1from matplotlib.colors import ListedColormap
 2def plot_decision_regions(X, y, classifier, resolution=0.02):
 3    # setup marker generator and color map
 4    markers = ('s', 'x', 'o', '^', 'v')
 5    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
 6    cmap = ListedColormap(colors[:len(np.unique(y))])
 7    # plot the decision surface
 8    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
 9    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
10    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
11                           np.arange(x2_min, x2_max, resolution))
12    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
13    Z = Z.reshape(xx1.shape)
14    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
15    plt.xlim(xx1.min(), xx1.max())
16    plt.ylim(xx2.min(), xx2.max())
17    # plot class samples
18    for idx, cl in enumerate(np.unique(y)):
19        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
20                    alpha=0.8, c=cmap(idx),
21                    edgecolor='black',
22                    marker=markers[idx], 
23                    label=cl)
1plot_decision_regions(X, y, classifier=ppn)
2plt.xlabel('sepal 长度 [cm]',FontProperties=font,fontsize=14)
3plt.ylabel('petal 长度 [cm]',FontProperties=font,fontsize=14)
4plt.legend(loc='upper left')
5plt.tight_layout()
6plt.show()

output:

自适应线性神经元和融合学习

使用梯度下降方法来最小化损失函数

梯度下降的方法十分常见,具体的了解可以参考附录的文章[2],如今,梯度下降主要用于在神经网络模型中进行权重更新,即在一个方向上更新和调整模型的参数,来最小化损失函数。

图:梯度下降原理过程演示

在Python中实现一个自适应的线性神经元

先贴上定义的python函数,(也可在公众号后台输入“感知器”进行获取ipynb文件)

 1# 定义神经元函数
 2class AdalineGD(object):
 3    """ADAptive LInear NEuron classifier.
 4    Parameters
 5    ------------
 6    eta : float
 7        Learning rate (between 0.0 and 1.0)
 8    n_iter : int
 9        Passes over the training dataset.
10    Attributes
11    -----------
12    w_ : 1d-array
13        Weights after fitting.
14    cost_ : list
15        Sum-of-squares cost function value in each epoch.
16    """
17    def __init__(self, eta=0.01, n_iter=50):
18        self.eta = eta
19        self.n_iter = n_iter
20    def fit(self, X, y):
21        """ Fit training data.
22        Parameters
23        ----------
24        X : {array-like}, shape = [n_samples, n_features]
25            Training vectors, where n_samples is the number of samples and
26            n_features is the number of features.
27        y : array-like, shape = [n_samples]
28            Target values.
29        Returns
30        -------
31        self : object
32        """
33        self.w_ = np.zeros(1 + X.shape[1])
34        self.cost_ = []
35        for i in range(self.n_iter):
36            net_input = self.net_input(X)
37            # Please note that the "activation" method has no effect
38            # in the code since it is simply an identity function. We
39            # could write `output = self.net_input(X)` directly instead.
40            # The purpose of the activation is more conceptual, i.e.,  
41            # in the case of logistic regression, we could change it to
42            # a sigmoid function to implement a logistic regression classifier.
43            output = self.activation(X)
44            errors = (y - output)
45            self.w_[1:] += self.eta * X.T.dot(errors)
46            self.w_[0] += self.eta * errors.sum()
47            cost = (errors**2).sum() / 2.0
48            self.cost_.append(cost)
49        return self
50    def net_input(self, X):
51        """Calculate net input"""
52        return np.dot(X, self.w_[1:]) + self.w_[0]
53    def activation(self, X):
54        """Compute linear activation"""
55        return self.net_input(X)
56    def predict(self, X):
57        """Return class label after unit step"""
58        return np.where(self.activation(X) >= 0.0, 1, -1)

查看不同学习率下的错误率随迭代次数的变化情况:

 1fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
 2# 可视化W调整的过程中,错误率随迭代次数的变化
 3ada1 = AdalineGD(n_iter=10, eta=0.01).fit(X, y)
 4ax[0].plot(range(1, len(ada1.cost_) + 1), np.log10(ada1.cost_), marker='o')
 5ax[0].set_xlabel('Epochs')
 6ax[0].set_ylabel('log(Sum-squared-error)')
 7ax[0].set_title('Adaline - Learning rate 0.01')
 8ada2 = AdalineGD(n_iter=10, eta=0.0001).fit(X, y)
 9ax[1].plot(range(1, len(ada2.cost_) + 1), ada2.cost_, marker='o')
10ax[1].set_xlabel('Epochs')
11ax[1].set_ylabel('Sum-squared-error')
12ax[1].set_title('Adaline - Learning rate 0.0001')
13plt.tight_layout()
14plt.show()

output:

iris数据的应用情况:

 1# 标准化特征
 2X_std = np.copy(X)
 3X_std[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std()
 4X_std[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std()
 5# 调用函数开始训练
 6ada = AdalineGD(n_iter=15, eta=0.01)
 7ada.fit(X_std, y)
 8# 绘制效果
 9plot_decision_regions(X_std, y, classifier=ada)
10plt.title('Adaline - Gradient Descent')
11plt.xlabel('sepal length [standardized]')
12plt.ylabel('petal length [standardized]')
13plt.legend(loc='upper left')
14plt.tight_layout()
15plt.show()
16# 可视化W调整的过程中,错误率随迭代次数的变化
17plt.plot(range(1, len(ada.cost_) + 1), ada.cost_, marker='o')
18plt.xlabel('Epochs')
19plt.ylabel('Sum-squared-error')
20plt.tight_layout()
21plt.show()

output:

参考文献

1)机器学习系列:感知器

https://blog.csdn.net/u013719780/article/details/51755409

2)机器学习入门系列04,Gradient Descent(梯度下降法)

https://blog.csdn.net/zyq522376829/article/details/66632699

3)一文看懂各种神经网络优化算法:从梯度下降到Adam方法

https://zhuanlan.zhihu.com/p/27449596?utm_source=weibo&utm_medium=social

4)机器学习与神经网络(三):自适应线性神经元的介绍和Python代码实现

https://blog.csdn.net/huakai16/article/details/77701020

5)《Training Machine Learning Algorithms for Classification》

http://nbviewer.jupyter.org/github/rasbt/python-machine-learning-book/blob/master/code/ch02/ch02.ipynb

—End—

本文分享自微信公众号 - SAMshare(gh_8528ce7b7e80)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-05-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能机器学习

机器学习之卷积神经网络

深度学习与计算机视觉可以帮助汽车,查明周围的行人和汽车,并帮助汽车避开它们。还使得人脸识别技术变得更加效率和精准,我们可以体验到通过刷脸就能解锁手机或者门锁的便...

11530
来自专栏腾讯智能钛AI开发者

【技术分享】特征工程方法综述

随着我们底层特征库中特征数目的不断增长,如何组合特征,如何针对不同场景选择适合的特征,如何评估特征优劣?这些问题已经日益凸显,所以这次想梳理现有的特征工程方法,...

39330
来自专栏Jerry的SAP技术分享

当SAP云平台account的service Marke place里找不到Machine Learning服务该怎么办

我在CloudFoundry环境的Service Market place里根本找不到Leonardo ML foundation这组服务。

9020
来自专栏数据探索君

我眼中的数据分析

数据分析的任务必须是明确的,带着问题出发。它可以是一张简单的报表,也可以是专题或者综合分析。

13220
来自专栏Jerry的SAP技术分享

部署在SAP Cloud Platform CloudFoundry环境的应用如何消费

Jerry的前一篇文章 如何在Web应用里消费SAP Leonardo的机器学习API 里介绍的例子是Neo测试环境的Web应用消费sandbox版本的机器学习...

7720
来自专栏Jerry的SAP技术分享

如何在Web应用里消费SAP Leonardo的机器学习API

去年5月的时候,Jerry曾经写了一篇文章:使用Java程序消费SAP Leonardo的机器学习API,而最近另外做的一个项目,需要在Web应用里做同样的事情...

12950
来自专栏公众号PowerBI大师

关于数据分析工具的终极问题

昨晚在CPDA微课堂做了场直播,聊了一个终极问题,也是很多人在关注的话题。我把内容整理下来供读者们阅读、质疑和思考。(全文长6000多字)

18840
来自专栏RPA机器人

随着RPA的发展,人类将越来越多地退居二线

机器人过程自动化(RPA)行业在过去一年中激增,一些领先的参与者 – 如UiPath,Automation Anywhere和Blue Prism – 增长速度...

14400
来自专栏三言两语

初识机器学习

机器学习解决的问题无非两类:预测、分类 预测:预测所属分类、预测预测数值,区别:预测目标Y是连续的还是离散的

13850
来自专栏Jerry的SAP技术分享

如何对SAP Leonardo上的机器学习模型进行重新训练

Jerry之前的两篇文章介绍了如何通过Restful API的方式,消费SAP Leonardo上预先训练好的机器学习模型:

8630

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励