感知器是一种人工神经网络,其模拟生物上的神经元结构
感知器是一个二分类器,净输入为:
z = W.T*X = w0 + w1x1 + w2x2 + w3x3 + … + wnxn
然后通过激活函数将z映射[-1,1] (与阈值theta比较)
算法内部只用梯度下降
本文基于鸢尾花 数据集实现
数据集:数据集网盘下载
提取码:p2v9
data = pd.read_csv(r"dataset/iris.arff.csv")
# data.head()
# 删除重复记录
data.drop_duplicates(inplace=True)
# 特征映射 便于后面感知器预测
# Iris-versicolor Iris-virginica Iris-setosa
data["class"] = data["class"].map({"Iris-versicolor":0,"Iris-virginica":1,"Iris-setosa":-1})
# 数据筛选 感知器是一个二分类器 保留类别-1 和 1的数据
data = data[data["class"] != 0]
len(data)
class Perceptron:
"""使用python语言实现感知器算法,实现二分类"""
def __init__(self,alpha,times):
"""初始化方法。
参数:
alpha:int
学习率
times:int
最大迭代次数
"""
self.alpha = alpha
self.times = times
def step(self,z):
"""阶跃函数。
参数:
z:数组类型(或者是标量类型)
阶跃函数的参数,可以将z映射为1或-1。(实现二分类)
返回值:
value:int
如果z>=0 返回1;否则,返回-1
"""
return np.where(z>=0,1,-1)
def fit(self,X,y):
"""根据提供的训练数据,对模型进行训练。
参数:
X:类数组类型,形状为:[样本数量,特征数量]
待训练的样本特征(属性)
y: 类数组类型,形状为:[样本数量]
每个样本的目标值(标签)。
"""
#将X,y转换成ndarray数组类型
X = np.asarray(X)
y = np.asarray(y)
# 创建权重向量,初始值为1,长度比特征多1(多出的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)*1
self.w_[1:] += self.alpha*(target - y_hat)*x
# 将循环累计的误差值增加到误差列表中
self.loss_.append(loss)
def predict(self,X):
"""根据传入的样本,对样本数据进行预测(-1 or 1)
参数:
X:类数组类型,形状为:[样本数量,特征数量]
待预测的样本特征(属性)
返回值:
result:数组类型
预测的分类(-1 or 1)
"""
return self.step(np.dot(X,self.w_[1:]) + self.w_[0])
t1 = data[data["class"] == 1]
t2 = data[data["class"] == -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(alpha=0.1,times=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.figure(figsize=(10,8))
# 绘制真实值
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-")
plt.title("感知器二分类损失值")
plt.xlabel("迭代次数")
plt.ylabel("目标函数损失值")
plt.show()