感知机模型的基本原理是使得误分类点最小,而数据是基于林轩田老师的《机器学习基石》,如果实在找不到,也可以通过链接进行下载: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。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176489.html原文链接:https://javaforall.net
