python实现感知机

一、加载库

import numpy as np
import pandas as pd

二、数据预处理

data = pd.read_csv(r"Iris.csv")
# data.head()
data.drop("Id", axis=1, inplace=True)
data.drop_duplicates(inplace=True)
# 之所以映射为1与-1,而不是之前的0,1,2,是因为感知器的预测结果为1与-1。
# 目的是为了与感知器预测的结果相符。
data["Species"] = data["Species"].map({"Iris-versicolor": 0, "Iris-virginica": 1, "Iris-setosa": -1})
# data["Species"].value_counts()
data = data[data["Species"] != 0]
len(data)

三、编写方法实现感知机

class Perceptron:
    """使用Python语言实现感知器算法,实现二分类。"""
    
    def __init__(self, alpha, times):
        """初始化方法。
        
        Parameters
        -----
        alpha : float
            学习率。
            
        times : int
            最大迭代次数
        
        """
        self.alpha = alpha
        self.times = times
        
    def step(self, z):
        """阶跃函数。
        
        
        Parameters
        -----
        z : 数组类型(或者是标量类型)
            阶跃函数的参数。可以根据z的值,返回1或-1(这样就可以实现二分类)。
            
        Returns
        -----
        value : int
            如果z >= 0,返回1, 否则返回-1。
        """
        
#         return 1 if z >=0 else 0
        return np.where(z >= 0, 1, -1)

    def fit(self, X, y):
        """根据提供的训练数据,对模型进行训练。
        
        Parameters
        -----
        X : 类数组类型。形状:[样本数量,特征数量]
            待训练的样本数据。
            
        y : 类数组类型。 形状: [样本数量]
            每个样本的目标值。(分类)
        
        
        """
        X = np.asarray(X)
        y = np.asarray(y)
        # 创建权重的向量,初始值为0.长度比特征多1.(多出的一个就是截距)。
        self.w_ = np.zeros(1 + X.shape[1])
        #创建损失列表,用来保存每次迭代后的损失值。
        self.loss_ = []
        # 循环指定的次数。
        for i in range(self.times):
            #  感知器与逻辑回归的区别:逻辑回归中,使用所有样本计算梯度,然后更新权重。
            # 而感知器中,是使用单个样本,依次进行计算梯度,更新权重。
            loss = 0
            for x, target in zip(X, y):
                # 计算预测值
                y_hat = self.step(np.dot(x, self.w_[1:]) + self.w_[0])
                loss += y_hat != target
                # 更新权重。
                # 更新公式: w(j) = w(j) +  学习率 * (真实值 - 预测值) * x(j)
                self.w_[0] += self.alpha * (target - y_hat)
                self.w_[1:] += self.alpha * (target - y_hat) * x
            # 将循环中累计的误差值增加到误差列表当中。
            self.loss_.append(loss)
            
    def predict(self, X):
        """根据参数传递的样本,对样本数据进行预测。(1或-1)
        
        Parameters
        -----
        X : 类数组类型, 形状为:[样本数量, 特征数量]
            待预测的样本特征。
            
        Returns
        -----
        result : 数组类型
            预测的结果值(分类值1或-1)
        
        """
        
        return self.step(np.dot(X, self.w_[1:]) + self.w_[0])

四、调用方法

t1 = data[data["Species"] == 1]
t2 = data[data["Species"] == -1]
t1 = t1.sample(len(t1), random_state=0)
t2 = t2.sample(len(t2), random_state=0)
train_X = pd.concat([t1.iloc[:40, :-1], t2.iloc[:40, :-1]], axis=0)
train_y = pd.concat([t1.iloc[:40, -1], t2.iloc[:40, -1]], axis=0)
test_X = pd.concat([t1.iloc[40:, :-1], t2.iloc[40:, :-1]], axis=0)
test_y = pd.concat([t1.iloc[40:, -1], t2.iloc[40:, -1]], axis=0)
p = Perceptron(0.1, 10)
p.fit(train_X, train_y)
result = p.predict(test_X)
display(result)
display(test_y.values)
display(p.w_)
display(p.loss_)

五、数据可视化

import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.family"] = "SimHei"
mpl.rcParams["axes.unicode_minus"] = False

# 绘制真实值
plt.plot(test_y.values, "go", ms=15, label="真实值")
# 绘制预测值
plt.plot(result, "rx", ms=15, label="预测值")
plt.title("感知器二分类")
plt.xlabel("样本序号")
plt.ylabel("类别")
plt.legend()
plt.show()

# 绘制目标函数的损失值。
plt.plot(range(1, p.times + 1), p.loss_, "o-")

你可能感兴趣的:(python,机器学习)