感知机实现代码

  数据是基于林轩田老师的《机器学习基石》,如果实在找不到,也可以通过链接进行下载:CSDN下载地址

1. 线性可分数据

1.1 读取数据

import pandas as pd
import numpy as np
from sklearn.metrics import accuracy_score

data = pd.read_csv(r'E:/data/perceptron_15.dat', sep = '\s', header = None)
data.columns = ['x1', 'x2', 'x3', 'x4', 'y']

X_train = data.loc[:, ['x1', 'x2', 'x3', 'x4']]
y_train = data.loc[:, 'y']

X_train = X_train.values
y_train = y_train.values

1.2 感知机实现

  其中为了加快运算速度,把b融入到了W中,所以对训练数据X也要做一定的处理(左边插入一列为1的数据)。

class PerceptronSeparable():
    def __init__(self):
        self.w = None
        self.b = None
        self.W = None
        self.eta = 0.01
        
    def sign(self, x):
        if x >= 0:
            return 1
        else:
            return -1
        
    #检查单个数据是否预测正确
    def check_one(self, x_train, y_train):
        x_train_one = 1
        x_train_extend = np.append(x_train_one, x_train)
        y_predict = np.dot(x_train_extend, self.W)
        y_predict = self.sign(y_predict)
        
        return y_predict == y_train
        
    #检查所有数据是否预测正确   
    def check_all(self, X_train, y_train):
        X_train_ones = np.ones([len(X_train) ,1])
        X_train_extend = np.concatenate([X_train_ones, X_train], axis = 1)
        y_predict = np.dot(X_train_extend, self.W)
        
        y_predict = np.array(list(map(self.sign, y_predict)))
        
        return (y_predict == y_train).all()
        
    def fit(self, X_train, y_train):
        self.w = np.zeros([X_train.shape[1], 1])
        self.b = 0
        self.W = np.append(self.b, self.w)
        times = 0
        
        while True:
            # 如果全部预测正确则退出
            if self.check_all(X_train, y_train):
                break
                
            else:
                random_index = np.random.randint(0, len(X_train))
                x_train_single = X_train[random_index, :].reshape(-1, 1)
                y_train_single = y_train[random_index]
                
                if not self.check_one(x_train_single, y_train_single):
                    self.w = self.w + self.eta * x_train_single * y_train_single
                    self.b = self.b + self.eta * y_train_single
                    self.W = np.append(self.b, self.w)
                    
                    times += 1
                    
    def predict(self, X_test):
        X_test_ones = np.ones([len(X_test), 1])
        X_test_new = np.concatenate([X_test_ones, X_test], axis=1)
        y_test_predict = np.dot(X_test_new, self.W)
        y_test_predict = np.array(list(map(self.sign, y_test_predict)))
        
        return y_test_predict

1.3 效果评估

perceptron = PerceptronSeparable()
perceptron.fit(X_train, y_train)
print(accuracy_score(y_train, perceptron.predict(X_train)))

  由于是线性可分数据,打印结果应该是1.0,否则说明代码是有bug。

2. 线性不可分数据

2.1 读取数据

import pandas as pd
import numpy as np
from sklearn.metrics import accuracy_score

data = pd.read_csv(r'E:/data/perceptron_18.dat', sep = '\s', header = None)
data.columns = ['x1', 'x2', 'x3', 'x4', 'y']

X_train = data.loc[:, ['x1', 'x2', 'x3', 'x4']]
y_train = data.loc[:, 'y']

X_train = X_train.values
y_train = y_train.values

2.2 感知机实现

  实现是大同小异的。最大的区别在于,每次改变参数以后会和之前最优的结果进行比较,如果不如以前的结果,则模型回退到上一个版本。

class PerceptronNonSeparable():
    def __init__(self):
        self.w = None
        self.b = None
        self.W = None
        self.eta = 0.01
        
    def sign(self, x):
        if x >= 0:
            return 1
        else:
            return -1
        
    def check_one(self, x_train, y_train):
        x_train_one = 1
        x_train_extend = np.append(x_train_one, x_train)
        y_predict = np.dot(x_train_extend, self.W)
        y_predict = self.sign(y_predict)
        
        return y_predict == y_train
    
    def check_all(self, X_train, y_train):
        X_train_ones = np.ones([len(X_train) ,1])
        X_train_extend = np.concatenate([X_train_ones, X_train], axis = 1)
        y_predict = np.dot(X_train_extend, self.W)
        
        y_predict = np.array(list(map(self.sign, y_predict)))
        
        return (y_predict == y_train).all()
        
        
    def get_predict_right_nums(self, X_train, y_train):
        X_train_ones = np.ones([len(X_train) ,1])
        X_train_extend = np.concatenate([X_train_ones, X_train], axis = 1)
        y_predict = np.dot(X_train_extend, self.W)
        
        y_predict = np.array(list(map(self.sign, y_predict)))
        
        return np.sum(y_predict == y_train)
        
    def fit(self, X_train, y_train):
        self.w = np.zeros([X_train.shape[1], 1])
        self.b = 0
        self.W = np.append(self.b, self.w)
        times = 0
        predict_best_num = 0
        
        for i in range(1000):
            if self.check_all(X_train, y_train):
                break
                
            else:
                random_index = np.random.randint(0, len(X_train))
                x_train_single = X_train[random_index, :].reshape(-1, 1)
                y_train_single = y_train[random_index]
                
                if not self.check_one(x_train_single, y_train_single):
                    bak_w, bak_b, bak_W = self.w, self.b, self.W
                    
                    self.w = self.w + self.eta * x_train_single * y_train_single
                    self.b = self.b + self.eta * y_train_single
                    self.W = np.append(self.b, self.w)
                    
                    predict_right_num = self.get_predict_right_nums(X_train, y_train)
                    if predict_right_num < predict_best_num:
                        self.w, self.b, self.W = bak_w, bak_b, bak_W

    def predict(self, X_test):
        X_test_ones = np.ones([len(X_test), 1])
        X_test_new = np.concatenate([X_test_ones, X_test], axis=1)
        y_test_predict = np.dot(X_test_new, self.W)
        y_test_predict = np.array(list(map(self.sign, y_test_predict)))
        
        return y_test_predict

2.3 效果评估

perceptron = PerceptronNonSeparable()
perceptron.fit(X_train, y_train)
print(accuracy_score(y_train, perceptron.predict(X_train)))

  由于是线性不可分数据,打印结果应该小于1.0,但也应该大于0.7,否则说明代码是有bug。

发布了178 篇原创文章 · 获赞 389 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/herosunly/article/details/103560623