Python机器学习笔记02——训练简单的机器学习分类算法

训练简单的机器学习分类算法

一、人工神经元

1.人工神经元定义

可以将人工神经元逻辑放在二元分类场景,将两个类分别命名为1(正类)和-1(负类),定义决策函数(φ(z)),接受输入值x及其相应权重w,z为输入值与权重的乘积累加和,z=W1X1+…+WmXm:
在这里插入图片描述
如果某个特定样本的净输入值x(i)比定义的阈值θ大,则预测结果为1,否则为-1
在这里插入图片描述
为了简化,把阈值θ放到等式左边,权重零定义为w0=-θ,x0=1,这样z为
在这里插入图片描述
在这里插入图片描述
机器学习中通常称w0=-θ称为偏置。

2.感知器学习规则

感知器规则可以总结为以下几部:
1.把权重初始化为0或者小的随机数
2.对每个训练样本:*计算输出值 *更新权重

输出值为单位阶跃函数预测的预先定义好的类标签,同时更新权重向量w的每个值wj,表达式为:
在这里插入图片描述
Δwj是用来更新wj的值,该值根据感知器的学习规则计算:
在这里插入图片描述
η为学习率,一般是一个0.0到1.0之间的常数,yi为第i个训练样本的正确类标签,后面的yi为预测的类标签,并且所有权重更新之前,不会重新计算预测的类标签,二维数据集的更新可以表示为:
在这里插入图片描述
在感知机正确预测分类标签的两种情况下,权重保持不变:
在这里插入图片描述
但是如果预测出错,权重会偏向正或负的目标类
在这里插入图片描述

二、在python中实现感知器学习算法

1.面向对象的感知器API

可以用面向对象的方法把感知机接口定义为一个python类,它允许初始化新的perceptron对象,这些对象可以通过fit方法从数据中学习,并通过单独的predict方法进行预测,作为约定,我们在对象初始化时未创建但通过对象的其他方法创建的属性的后面添加下划线,例如self.w_

fit方法实现的功能简单来说就是求训练集X的均值,方差,最大值,最小值等固有属性,可以理解为一个训练过程

下面代码实现了感知器:

class Perceptron(object):
    """Perceptron classifier.

    Parameters
    ------------
    eta : float
      Learning rate (between 0.0 and 1.0)
    n_iter : int
      Passes over the training dataset.
    random_state : int
      Random number generator seed for random weight
      initialization.

    Attributes
    -----------
    w_ : 1d-array
      Weights after fitting.
    errors_ : list
      Number of misclassifications (updates) in each epoch.

    """
    def __init__(self, eta=0.01, n_iter=50, random_state=1):
        self.eta = eta
        self.n_iter = n_iter
        self.random_state = random_state

    def fit(self, X, y):
        """Fit training data.

        Parameters
        ----------
        X : {array-like}, shape = [n_samples, n_features]
          Training vectors, where n_samples is the number of samples and
          n_features is the number of features.
        y : array-like, shape = [n_samples]
          Target values.

        Returns
        -------
        self : object

        """
        rgen = np.random.RandomState(self.random_state)
        self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1])
        self.errors_ = []

        for _ in range(self.n_iter):
            errors = 0
            for xi, target in zip(X, y):
                update = self.eta * (target - self.predict(xi))
                self.w_[1:] += update * xi
                self.w_[0] += update
                errors += int(update != 0.0)
            self.errors_.append(errors)
        return self

    def net_input(self, X):
        """Calculate net input"""
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def predict(self, X):
        """Return class label after unit step"""
        return np.where(self.net_input(X) >= 0.0, 1, -1)

这段实现感知器的代码用所给的学习率eta和迭代次数n_iter初始化新的perceptron对象,通过fit方法,初始化self.w_的权重,并把数据存入向量代表数据集的维数或特征数。

该向量包含来源于正态分布的小随机数,通过调用rgen.normal产生标准差为0.01的正态分布,其中rgen为随机数生成器。

初始化权重后,用fit方法遍历训练集的所有样本,并根据规则更新权重,fit方法调用predict方法来预测分类标签并更新权重。另外将分类错误记录在self.errors列表中。用net_input方法中的np.dot函数来计算向量点积w的转置x

注:numpy中dot()函数主要功能有两个:向量点积和矩阵乘法

格式:x.dot(y)等价于np.dot(x,y),其中x是m*n的矩阵,y是n*m的矩阵,x.dot(y)得到m*m矩阵

2.在鸢尾花数据集上训练感知器模型

在此例子中,我们将从鸢尾花数据集加载setosa和versicolor两种花的数据,实际上感知器并不限于两个维度,感知器算法可以扩展带多元分类,例如一对全部(OvA)的技术。

OvA技术也称为一对其余(OvR),可以把分类器从二元扩展到多元的一种技术,OvA可以为每个类训练一个分类器,所训练的类被视为正类,所有其他类的样本都被视为负类,在目标检测相关项目上,对于一张图片上的样本,有分类的视为正样本,背景则被视为负样本,与感知器相似。

对于鸢尾花数据集的分类,我们可以利用pandas库,从UCI机器学习库把鸢尾花数据集直接加载到DataFrame对象,然后用tail方法把把最后5行数据列出来以确保数据加载的正确性。

import pandas as pd
df =pd.read_csv(iris.data,header=None)
df.tail()

在这里插入图片描述
在这里插入图片描述
莺尾花数据集截图

接下来提取与50朵iris-setosa和50朵iris-versicolor鸢尾花相对应的前100个类标签,然后转换为整数型的类标签1(versicolor)和-1(setosa),并存入向量y,再调用pandas的DataFrame的方法获得到相应的Numpy表示。

同样可以从100个训练样本中提取特征的第一列(萼片长度)和第三列(花瓣长度),并将它们存入特征矩阵X,然后经过可视化处理形成二维散点图

import matplotlib.pyplot as plt

y=df.iloc[0:100,4].values
y = np.where(y == 'Iris-setosa', -1, 1)

X = df.iloc[0:100, [0, 2]].values

plt.scatter(X[:50, 0], X[:50, 1],
            color='red', marker='o', label='setosa')
plt.scatter(X[50:100, 0], X[50:100, 1],
            color='blue', marker='x', label='versicolor')

plt.xlabel('sepal length [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc='upper left')

plt.show()

执行代码后产生二维散点图
在这里插入图片描述
散点图显示了莺尾花数据集的样本在花瓣长度和萼片长度两个特征轴的分布情况,一个线性的决策边界足以把setosa花与versicolor花区别开,因此,感知器这样的线性分类器能够完美对数据集中的花朵进行分类。

然后我们需要在鸢尾花数据子集上训练感知器算法,另外将绘制每个迭代的分类错误,以检查算法是否收敛,并找到分隔两类鸢尾花的决策边界

ppn = Perceptron(eta=0.1, n_iter=10)

ppn.fit(X, y)

plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Number of updates')

plt.show()

执行前面的代码,可以看到分类错误与迭代之间的关系
在这里插入图片描述
感知器在第6次迭代后开始收敛,现在应该能够完美地对训练样本进行分类,下面进行二维数据决策边界可视化

def plot_decision_regions(X, y, classifier, resolution=0.02):

    # setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # plot the decision surface
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    # plot class samples
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0],
                    y=X[y == cl, 1],
                    alpha=0.8,
                    c=colors[idx],
                    marker=markers[idx],
                    label=cl,
                    edgecolor='black')

首先定义颜色和标记并通过ListedColormap来从颜色列表创建色度图,然后通过Numpy的meshgrid函数创建网格阵列xx1和xx2,利用特征向量确定特征的最小和最大值,由于在两个特征维度上训练感知器分类器,这样就可以调用predict方法来预测相应网格点的分类标签z

把预测获得的分类标签z改造成与xx1和xx2相同维数的网格后,现在可以通过调用Matplotlib的contourf函数画出轮廓图,并且把网格阵列中每个预测的分类结果标注在不同颜色的决策区域。

plot_decision_regions(X, y, classifier=ppn)
plt.xlabel('sepal length [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc='upper left')

plt.show()

执行后结果如图
在这里插入图片描述
这样就通过学习掌握了决策边界,能够把鸢尾花训练集的样本完美分开

三、自适应神经元和学习收敛

自适应感知器(Adaline)是感知器的优化和改进,Adaline规则和感知器之间的关键差异在于Adaline规则的权重更新时基于线性激活函数,而感知器是基于单位阶跃函数,Adaline的线性激活函数φ(z)是净输入的等同函数
在这里插入图片描述

虽然线性激活函数可用于学习权重,但仍然使用阈值函数做最终预测,这类似与先前的单位阶跃函数,下图是感知器与自适应算法的主要区别:
在这里插入图片描述

1.梯度下降为最小代价函数

有监督机器学习算法的一个关键是在学习过程中优化目标函数,该目标函数通常是要最小化的代价函数,对自适应神经元而言,可以把学习权重的代价函数J定义为在计算结果和真正的分类标签之间的误差平方和
在这里插入图片描述

2.用python实现Adaline

class AdalineGD(object):
    """ADAptive LInear NEuron classifier.

    Parameters
    ------------
    eta : float
      Learning rate (between 0.0 and 1.0)
    n_iter : int
      Passes over the training dataset.
    random_state : int
      Random number generator seed for random weight
      initialization.


    Attributes
    -----------
    w_ : 1d-array
      Weights after fitting.
    cost_ : list
      Sum-of-squares cost function value in each epoch.

    """
    def __init__(self, eta=0.01, n_iter=50, random_state=1):
        self.eta = eta
        self.n_iter = n_iter
        self.random_state = random_state

    def fit(self, X, y):
        """ Fit training data.

        Parameters
        ----------
        X : {array-like}, shape = [n_samples, n_features]
          Training vectors, where n_samples is the number of samples and
          n_features is the number of features.
        y : array-like, shape = [n_samples]
          Target values.

        Returns
        -------
        self : object

        """
        rgen = np.random.RandomState(self.random_state)
        self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1])
        self.cost_ = []

        for i in range(self.n_iter):
            net_input = self.net_input(X)
            # Please note that the "activation" method has no effect
            # in the code since it is simply an identity function. We
            # could write `output = self.net_input(X)` directly instead.
            # The purpose of the activation is more conceptual, i.e.,  
            # in the case of logistic regression (as we will see later), 
            # we could change it to
            # a sigmoid function to implement a logistic regression classifier.
            output = self.activation(net_input)
            errors = (y - output)
            self.w_[1:] += self.eta * X.T.dot(errors)
            self.w_[0] += self.eta * errors.sum()
            cost = (errors**2).sum() / 2.0
            self.cost_.append(cost)
        return self

    def net_input(self, X):
        """Calculate net input"""
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def activation(self, X):
        """Compute linear activation"""
        return X

    def predict(self, X):
        """Return class label after unit step"""
        return np.where(self.activation(self.net_input(X)) >= 0.0, 1, -1)


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值