第二章 感知机.(python 代码实现)(《统计学习方法》.pdf可在评论区下载)

感知机模型.

感知器模型主要用于二分类, 具体的模型、策略、算法,见统计学习方法第二章有详细介绍, 这里只进行代码实操的展示.

  1. 模型:所有线性函数(超平面);
  2. 策略:求参数使得所有误分类点到该直线的距离之和最小;
  3. 算法:随机梯度下降.

python实现: 生成数据 --- 训练 --- 预测.

本代码主要参考以下博客进行实现并且修改, 增加了对一些代码的注释. 在原有代码的基础上新增模型所求直线.见下图(绿线为由该线生成的现有数据, 红线表示感知机模型预测得到的直线).机器学习感知机原理及python代码实现_感知机代码_HumbleSwage的博客-CSDN博客

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 全局变量
real_weights = 1
real_bias = 3


def generating_label_data(weight, bias, size=10) -> pd.DataFrame:
    """
    产生需要的数据
    数据集必须是线形可分的,而不是随意的数据,具体的流程如下:
    利用高斯白噪声生成基于某个直线附近的若干点:x2=wx1+b
    :return:df
    """
    # x[:, np.newaxis] ,放在后面,会给列上增加维度.
    # x[np.newaxis, :] ,放在前面,会给行上增加维度.
    x1_point = np.linspace(-1, 1, size)[:, np.newaxis]
    noise = np.random.normal(0, 0.5, x1_point.shape)
    x2_point = weight * x1_point + bias + noise
    input_arr = np.hstack((x1_point, x2_point))
    # np.sign(x) 就是符号函数
    label = np.sign(input_arr[:, 1] - (input_arr[:, 0] * real_weights + real_bias)).reshape((size, 1))
    label_data = np.hstack((input_arr, label))
    # 转换为dataFrame
    df = pd.DataFrame(label_data, columns=["x1", "x2", "y"])
    return df


def split_data(data, ratio) -> (pd.DataFrame, pd.DataFrame):
    """
    数据分割
    :param data: 生成的原始整体数据
    :param ratio: 测试数据的比例
    :return:
            train_data指训练数据集
            test_data指测试数据集合
    """
    test_size = int(len(data) * ratio)
    test_data = data.loc[0:test_size, ]
    train_data = data.loc[test_size:, ]
    return train_data, test_data


def original_perceptron(x1_train, x2_train, y_train, x1_test, x2_test, y_test, learn_rate, train_num):
    """感知机原始算法流程如下所示
    输入:训练数据集、学习率
    输出:感知机模型
    1、选取模型的初始值
    2、在训练数据集中选取数据
    3、计算损失函数,如果小于0,则按照指定的策略对参数模型参数进行更新,直到针对所有点的计算损失函数都大于0
    """
    # 初始化w,b
    # y_train 为pd.series 类型的数据, 可以直接和列表一样进行索引.
    weight = np.random.rand(2, 1)
    bias = 0
    for rounds in range(train_num):
        for i in range(len(x1_train)):
            # 算法核心:参数的迭代逻辑[这个地方的标注的y和坐标的x和y一定要分开]
            if y_train[i] * (weight[0] * x1_train[i] + weight[1] * x2_train[i] + bias) <= 0:
                weight[0] = weight[0] + learn_rate * y_train[i] * x1_train[i]
                weight[1] = weight[1] + learn_rate * y_train[i] * x2_train[i]
                bias = bias + learn_rate * y_train[i]
        if rounds % 10 == 0:
            learn_rate *= 0.9
            compute_accuracy_callback_f1(x1_test, x2_test, y_test, weight, bias)
    return weight, bias


def compute_accuracy_callback_f1(x1_test, x2_test, y_test, weight, bias):
    """
    计算精度:选择精度、召回率、F1
    :return:
    """
    tp = 0
    fn = 0
    fp = 0
    tn = 0
    for i in range(len(x1_test)):
        if y_test[i] != np.sign(x1_test[i] * weight[0] + x2_test[i] * weight[1] + bias):
            if y_test[i] > 0:
                fn += 1
            else:
                fp += 1
        else:
            if y_test[i] > 0:
                tp += 1
            else:
                tn += 1
    if tp + fp == 0 & tp + fn == 0:
        return
    accuracy = tp / (tp + fp)
    callback = tp / (tp + fn)
    f1 = 2 * tp / (2 * tp + fp + fn)
    print("accuracy={0}\t\t\tcallback={1}\t\t\tf1={2}".format(round(accuracy, 5), round(callback, 5), round(f1, 5)))


def data_factory(data):
    """
    返回训练与预测的数据集合
    :param data:原始整体数据集合
    :return:
    """
    
    # .reset_index(drop=True) 旧的索引被丢弃了,而新的默认索引(从 0 到 n-1)被重新生成.
    train_data, test_data = split_data(data, 0.3)
    x1_train = train_data["x1"].reset_index(drop=True)
    x2_train = train_data["x2"].reset_index(drop=True)
    y_train = train_data["y"].reset_index(drop=True)
    x1_test = test_data["x1"].reset_index(drop=True)
    x2_test = test_data["x2"].reset_index(drop=True)
    y_test = test_data["y"].reset_index(drop=True)
    return x1_train, x2_train, y_train, x1_test, x2_test, y_test


def main():
    size = 50       # 生成的总的数据集个数
    learn_rate = 1  # 学习率
    train_num = 100  # 训练次数
    # 生成数据
    data = generating_label_data(real_weights, real_bias, size)
    # 获取数据
    x1_train, x2_train, y_train, x1_test, x2_test, y_test = data_factory(data)
    # 调用模型
    weight, bias = original_perceptron(x1_train, x2_train, y_train, x1_test, x2_test, y_test, learn_rate, train_num)
    # 作图
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    for i in range(len(x1_train)):
        if y_train.loc[i] == 1:
            ax.scatter(x1_train[i], x2_train[i], color='r')
        else:
            ax.scatter(x1_train[i], x2_train[i], color='b')
    x = np.linspace(-1, 1.5, 10)
    y1 = real_weights * x + real_bias
    y2 = (-bias - weight[0]*x)/weight[1]
    ax.plot(x, y1, color='g')
    ax.plot(x, y2, color='r')
    
    plt.show()


if __name__ == '__main__':
    main()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值