- 实验目的
1. 采用感知机学习算法建立模型
2. 神经元激活函数建议选用sign函数(数据集最后一列的标签请将 0 转换为 -1)
3. 迭代输出每一次更新后的 W 和 θ
4. 数据集线性可分,最好求解出线性超平面
- 实验内容:
- 首先要把数据集里的数据进行处理,使用np.loadtxt()把数据读入ndarray,把前两列和最后一列的标签分开,并且数据集最后一列的标签请将 0 转换为 -1。
- 定义Perceptron单层感知机类,参数有四个,分别是学习率lr、迭代次数epochs、权重向量w和偏置项b,lr和epochs提供默认参数值0.01和100。
- 训练函数train(),首先初始化w和b,w使用Xavier初始化方法,可以获得更好的训练效果,b初始值设为0。然后两层循环,外层是迭代次数,内层循环每次取一个坐标值和lable,按照
进行计算,f()激活函数使用sign函数。根据
和
对w和b进行更新,并输出更新后的w和b的值。
- 经过训练之后,使用matplotlib对训练结果进行可视化,通过w和b的值得到超平面。直线的函数表达式为ax + by + c = 0,w的两个参数w[0],w[1]分别是a,b,b是表达式中的c,用plt.plot可以画出。数据集中的点根据其标签值,分为蓝色和红色的点,使用plt.scatter()画出。
实验结果
使用epoch=10,每个x都可以更新一次参数,可以看到10轮之内就可以收敛,达到不错的效果
开始训练时的参数更新情况
收敛
线性超平面为:0.13245762 * x - 0.08317062 * y + 0.5800000000000002 = 0
划分情况可视化
可以看到效果不错
- 实验原理:
- 心得体会:
实验中遇到的问题及解决方法:
- 权重的初始化对收敛速度等有影响,并且网络训练的过程中, 容易出现梯度消失和梯度爆炸的情况,导致大部分反向传播得到的梯度不起作用或者起反作用。通过查阅资料发现Xavier初始化方法是一种比较常用的且性能优秀的方法,可以尽可能的让输入和输出服从相同的分布,这样就能够避免后面层的激活函数的输出值趋向于0。
- 在画图的时候,数据集中的点要使用原来的标签而不是带入线性超平面中求出分类,这样会导致可视化结果中,相同颜色的点一定在直线两侧。
心得体会:
通过这次实验,我对于感知机模型的原理有了进一步的了解,也通过实验对这一算法进行了实践,加深了印象。虽然实验中用到的模型比较简单,但是学习到了反向传播优化这一思想。通过可视化得出比较好的分类效果也令我备受鼓舞,期望在后面的学习中可以学到更多机器学习相关知识。为以后的学习工作打下坚实的基础。
import numpy as np
import matplotlib.pyplot as plt
class Perceptron:
def __init__(self, lr=0.01, epochs=100):
self.lr = lr # 学习率
self.epochs = epochs # 最大迭代次数
self.w = None # 权重向量
self.b = None # 偏置项
def train(self, X, lable):
# self.w = np.zeros(X.shape[1])
self.w = np.random.randn(X.shape[1]) * np.sqrt(1 / X.shape[1])
self.b = 0
for epoch in range(self.epochs):
for x, y in zip(X, lable):
# y_hat = np.sign(np.dot(x, self.w) + self.b)
y_hat = 1 if np.dot(x, self.w) + self.b >= 0 else -1
self.w += self.lr * (y - y_hat) * x
self.b += self.lr * (y - y_hat)
print(self.w, self.b)
def picture(self, X, lable):
x1 = []
x2 = []
y1 = []
y2 = []
for x, y in zip(X, lable):
if y == 1:
x1.append(x[0])
y1.append(x[1])
else:
x2.append(x[0])
y2.append(x[1])
plt.figure()
x = [i for i in range(-5, 5)]
y = [-(self.w[0] / self.w[1]) * i - self.b / self.w[1] for i in x]
plt.plot(x, y)
plt.scatter(x1, y1, color='blue')
plt.scatter(x2, y2, color='red')
plt.show()
def get_data():
dataset = np.loadtxt(r"D:\pythonProject\Machine_learning\test4\perceptron_data.txt")
data = dataset[:, :2]
lable = dataset[:, -1]
lable = [-1.0 if i == 0 else i for i in lable]
return data, lable
data, lable = get_data()
net = Perceptron(0.01, 10)
net.train(data, lable)
# net.train(data, lable)
net.picture(data, lable)