python感知机实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/details/78066956

感知机(perceptron)作为机器学习的基础,理解了感知机的原理以及实现,就基本知道机器学习的本质了:

“通过对错误数据集的学习,不断调整更新自身的参数,使得模型参数对当前系统的输入数据集,得到最佳输出”

上面是自己个人的理解。

本文主要是参考了李航的《统计学习方法》,然后使用python实现了感知机,并对二维数据集进行分类,验证了算法的有效性。

本文主要内容如下:

  1. 感知机基本原理
  2. 算法步骤
  3. 代码实现

下面先贴出最终的运行结果,数据集红色点集合,以及蓝色点集合是二分类数据集,红线为最终的分类平面,运行结果如下:

输出console中

  1. epoch代表每行的错误率,
  2. array,代表学习的参数权重 w1, w2, 偏置 b

代码结构图如下,数据集为2维如图,最后一列为其类别,(为了方便,最终训练中把 0 转化为了 -1):

感知机基本原理


感知机是二分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别取+1、-1。感知机将输入空间分为正负两类的超平面,称为判别模型。感知机的学习目的在于求出最佳超平面,由此导入基于误分类的损失函数。利用随机梯度下降法(**不是严格上的随机梯度下降法**)对损失函数进行最小化,求得感知机模型。

感知机是神经网络与支持向量机的基础。

定义如下(截图来自本人的笔记):

具体模型可见下图:

具体解释如下(截图来自本人笔记):

假设数据是线性可分的,那如何找到这样一个超平面呢?即确定感知机模型参数w、b。由此我们需要一个学习策略,即定义(经验)损失函数并将损失函数最小化。

loss损失函数的选取要考虑到w,b的连续可导,因此我们选择误分类点到超平面的距离。

误分类数据(本来y=1结果却分类为了-1,而-1分类为了1)因此y(w*x+b)<0

算法步骤


前面提到:

机器学习通过对错误数据集的学习,不断调整更新自身的参数,使得模型参数对当前系统的输入数据集,得到最佳输出

当有误分类数据的时候,对于感知机

误分类数据(本来y=1结果却分类为了-1,而-1分类为了1)因此y(w*x+b)<0

对于w,b计算梯度:

至于为何加上学习率,主要是更好的调整w,b的变化,一般取0.01

(图片来自李航博士《统计学习方法》)

至于具体的神经网络的学习与理解,建议看下,这个英文教材,也有中文版,自己网上搜索一下。

http://neuralnetworksanddeeplearning.com/chap1.html

本bolg的代码风格,就是模仿这个教程。

代码实现


接下来是代码的实现了,本文的数据集是二维特征(见上面代码结构图),对应公式:

y=w2∗x2+w1∗x1+by=w_2*x_2 + w_1*x_1 + b

代码数据集合见本人github

代码的总体思路:

  1. 从dataset.txt读取数据,生成训练数据形式(将类别0转化为了-1,主要是方便运算)
  2. 生成感知机类,以及随机梯度下降法(不是严格上的随机梯度下降法)参数,并训练网络
  3. 画出训练数据集的散点图,以及最终生成的分类平面
# _*_ coding:utf-8 _*_
import numpy as np
from utils.FileUtil import get_line_lst
import matplotlib.pyplot as plt


class Perception(object):

    def __init__(self, var_num):
        """var_num为特征的个数,本例中设为2"""
        # self.w = np.random.randn(1, var_num)
        # 参数初始化
        self.w = np.ones(var_num)
        self.b = 1
        self.var_num = var_num
        # 错误率低于0.02则终止
        self.min_error_rate = 0.02

    def train(self, train_data, eta):
        """
        training model
        :param train_data: array like [[1, 2, -1], [1.1, 0.8, 1]]
        :param eta: learning rate:
        :return none:
        """
        for item in train_data:
            output = (np.dot(self.w, item[0:-1]) + self.b)*item[-1]
            if output <= 0:
                self.w += eta * item[-1] * item[0:-1]
                self.b += eta * item[-1]

    def sgd(self, train_data, epoch, eta, batch_size):
        """
        Training perception model by stochastic gradient descent
        :param train_data: 2D array like [[1.1, 2.3, -1]] the last
                            item -1 train_date[0][-1] means label
        :param epoch:
        :param eta:learning rate
        :return:none
        """
        for i in xrange(epoch):
            np.random.shuffle(train_data)
            batch_lst = [train_data[k:k+batch_size] for k in xrange(0, len(train_data), batch_size)]
            for mini_batch in batch_lst:
                self.train(mini_batch, eta)

            current_error_rate = self.get_error_rate(train_data)
            print 'epoch {0} current_error_rate: {1}'.format(i+1, current_error_rate)
            print self.get_current_para()
            if current_error_rate <= self.min_error_rate:
                break

    def get_error_rate(self, validate_data):
        all_len = validate_data.shape[0]
        error_len = 0
        for item in validate_data:
            output = np.dot(self.w, item[0:-1]) + self.b
            output = 1 if output >= 0 else -1
            error = True if output != item[-1] else False
            if error:
                error_len += 1

        return float(error_len) / all_len

    def get_current_para(self):
        return self.w, self.b

    def get_weight(self):
        return self.w

    def get_bias(self):
        return self.b


def generate_data(data_path):
    lst_data = get_line_lst(data_path)

    # lst_ret = []
    # for item in lst_data:
    #     lst_ret.append([float(s) for s in item.split()])
    # the following one line  is equivalent to the above for loop
    lst_ret = [[float(s) for s in item.split()] for item in lst_data]

    ret_arr = np.array(lst_ret)

    # change all the label whose value is 0 to -1
    for i in xrange(ret_arr.shape[0]):
        if ret_arr[i][-1] == 0:
            ret_arr[i][-1] = -1

    return ret_arr


def plot_data_scatter(train_data, w, b):
    x = np.linspace(-5, 5, 10)
    plt.figure()
    # 画散点图(plot scatter)
    for i in range(len(train_data)):
        if train_data[i][-1] == 1:
            plt.scatter(train_data[i][0], train_data[i][1], c=u'b')
        else:
            plt.scatter(train_data[i][0], train_data[i][1], c=u'r')

    # 画感知机分类,slope斜率图
    plt.plot(x, -(w[0]*x+b) / w[1], c=u'r')
    plt.show()

if __name__ == '__main__':
    data_path = '../dataset/perception/dataset.txt'
    train_data = generate_data(data_path)
    # epoch迭代次数,eta学习率,var_num特征个数
    epoch, eta, var_num, batch_size = 100, 0.1, 2, 20
    # 创建感知机对象
    p = Perception(var_num)
    # 训练
    p.sgd(train_data, epoch, eta, batch_size)
    # 画出最终的分类模型
    plot_data_scatter(train_data, p.get_weight(), p.get_bias())

转载注明出处,并在下面留言!!!

http://blog.csdn.net/haluoluo211/article/details/78066956

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏闪电gogogo的专栏

《统计学习方法》笔记二 感知机

感知机(perceptron)是二分类的线性分类模型,输入为实例的特征向量,输出为实例的类别,取±1。感知机对应与输入空间中将实例划分为正负两类的分离超平面,属...

8420
来自专栏张俊红

决策树-CART算法

总第80篇 01|前言: 本篇接着上一篇决策树详解,CART是英文“classification and regression tree”的缩写,翻译过来是分...

39450
来自专栏AI科技评论

开发 | 手把手教你用 TensorFlow 实现卷积神经网络(附代码)

AI科技评论按:本文作者徐凯文,原文载于作者个人博客,已获授权。 在知乎上看到一段介绍卷积神经网络的文章,感觉讲的特别直观明了,我整理了一下。首先介绍原理部分。...

39380
来自专栏LhWorld哥陪你聊算法

【深度学习篇】--神经网络中解决梯度弥散问题

在梯度下降中,随着算法反向反馈到前面几层,梯度会越来越小,最终,没有变化,这时或许还没有收敛到比较好的解,这就是梯度消失问题,深度学习遭受不稳定的梯度,不同层学...

47940
来自专栏iOSDevLog

估计器接口小结摘自:《Python 机器学习基础教程》 第3章 无监督学习与预处理(三)

scikit-learn 中的所有算法——无论是预处理、监督学习还是无监督学习算法——都被实现为类。这些类在 scikit-learn 中叫作估计器(estim...

16020
来自专栏Petrichor的专栏

opencv: 获取 图像属性 (源码)

  说明了读取的图片是一张 大小 为 (424, 600, 3) ,数据类型 为 uint8 ,像素总数 为 763200 的图片。

22910
来自专栏机器学习养成记

Twitter情感分析CNN+word2vec(翻译)

Rickest Ricky 对Twitter内容做了一系列的文本分析处理,并把内容整理成博文发布到:https://medium.com/@rickykim78...

27410
来自专栏瓜大三哥

matlab神经网络1

神经网络的通用函数 一、神经网络仿真函数 [Y,Pf,Af,E,Perf]=sim(net,P,Pi,Ai,T) 其中,参数Y为网络的输出;Pf表示最终的输入延...

24980
来自专栏Bingo的深度学习杂货店

使用Tensorflow实现一个简单的神经网络

输入层、隐藏层、输出层的数目分别为2、3、1; 隐藏层和输出层的激活函数使用的是 ReLU; 训练的样本总数为 512,每次迭代读取的批量为 10; 交叉熵为损...

26340
来自专栏机器学习养成记

特征工程(一):前向逐步回归(R语言)

“ 建模过程中,选择合适的特征集合,可以帮助控制模型复杂度,防止过拟合等问题。为了选取最佳的特征集合,可以遍历所有的列组合,找出效果最佳的集合,但这样需要大量的...

420110

扫码关注云+社区

领取腾讯云代金券