本文共 4615 字,大约阅读时间需要 15 分钟。
学习资源:
图片加载不出来看这:
对于感知机的学习规则总的来说可以用下面的这一张图来概括:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o5oODQ2q-1599794323207)(https://s1.ax1x.com/2020/09/11/wtSJCd.png)]
先简单的介绍一下感知机的学习规则,这是一个监督式的学习,就是在传入数据中给出答案,感知机自己判断数据,而在判断结果与答案
不同时,自动的通过修正系数的方式进行机器学习,w代表的是进行每次感知机训练传入数据的分别的系数,默认的这些系数是按照一个
数的附近进行正态分布的,而在下面的对传入数据的判断,比如在感知机的训练实例中的根据这些系数进行对数据的进行两种花种类的判
断,那么在我们的感知机的训练中如果判断结果与答案是有出入或者出错的,那么就会自动修改这些系数来进行机器学习。
那么我们是如何通过这些系数和传入的数据对花的种类进行判断的呢?
我们首先定义一个z = w0**1 + w1x1 + w2x2… 为两个向量相乘w[]点乘x[],w为系数,x为样本数据
比如就是说在训练的实例中我们就是通过传入花萼长度和花瓣宽度来得出z,z如果是大于0的那么取为1那么这个数据就是抽象化为1的花,z如果是小于0的那么取-1那么这个数据就是抽抽象化为-1的花。
即z = z>=0?1:-1
其实要注意到的是z的式子中w0*1其实是对z进行判断的时候用来分界的数字z = z<=w0?:1:-1,但是我们并不知道这个参数是什么,那么这时将这个参数放入z的式子中直接将z = z>=0?1:-1那么这时候我们就在感知机训练数据的时候同时对w0进行修正,w0的初始值按照正态分布取值。
那么如何对错误数据反馈给感知机,进而对这些系数进行修正?
我们的感知机对一段花进行分类错误的时候,对全部的系数进行修正的方式是遵循一个公式:
eta是我们创建对象的时候设置的学习速率,predict(xi)为根据数据对花进行分类,taeget为答案
即 w += yn(t)*xi
update = self.eta * (target - self.predict(xi))self.w_[1:] += update * xi#update若不是零的话自然会更新w_数组
即对这两个向量wi与xi进行加法运算:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CKiIG2gK-1599794323214)(https://s1.ax1x.com/2020/09/11/wtF3Uf.png)]
但是我们可以看到,我们对这些点进行区分,我们在直观的在图上描绘可以看出,这些点都是线性可分的,也就是都是可以用一条直线进行区分的,这个感知机只是一个非常初级的感知机只能对线性可分的数据进行区分,还有更复杂的感知机学习规则需要去学习。
感知机class:
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom matplotlib.colors import ListedColormapclass Perceptron(object): """Perceptron classifier. Parameters ------------ eta : float Learning rate (between 0.0 and 1.0) n_iter : int Passes over the training dataset. random_state : int Random number generator seed for random weight initialization. Attributes ----------- w_ : 1d-array Weights after fitting. errors_ : list Number of misclassifications (updates) in each epoch. """ #默认学习速度为0.1,训练次数为50次 def __init__(self, eta=0.01, n_iter=50, random_state=1): self.eta = eta self.n_iter = n_iter self.random_state = random_state def fit(self, X, y): """Fit training data. Parameters ---------- X : {array-like}, shape = [n_samples, n_features] Training vectors, where n_samples is the number of samples and n_features is the number of features. y : array-like, shape = [n_samples] Target values. Returns ------- self : object """ rgen = np.random.RandomState(self.random_state) self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1])#按照随机数进行正态分布生成 self.errors_ = [] for _ in range(self.n_iter): errors = 0 for xi, target in zip(X, y): update = self.eta * (target - self.predict(xi)) self.w_[1:] += update * xi#update若不是零的话自然会更新w_数组,注意这里是对数组中的所有元素都更新了,即向量相加 self.w_[0] += update errors += int(update != 0.0)#将错误反馈回给errors数组 self.errors_.append(errors)#将每次训练错误次数保存下来 return self def net_input(self, X): """Calculate net input""" return np.dot(X, self.w_[1:]) + self.w_[0]#使用wi系数进行向量相乘来生成z def predict(self, X): """Return class label after unit step""" return np.where(self.net_input(X) >= 0.0, 1, -1)
v1 = np.array([1, 2, 3])v2 = 0.5 * v1np.arccos(v1.dot(v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))#norm是线性代数模块中的对向量进行求模长的函数#dot是对两个向量进行点乘的函数,返回值为一个浮点数
读取鸢尾花数据
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)
将答案即花的种类抽象为1-1,这个实例只取了前100组数据,也就是只有两个花的种类。
y = df.iloc[0:100, 4].values#先切片前一百个花,也就是只取训练数据中的前面的两种花,返回值为一个arrayy = np.where(y == 'Iris-setosa', -1, 1)#问号表达式,将花的种类抽象为1和-1,返回值为一个array
取xi
X = df.iloc[0:100, [0, 2]].values#取花萼长和花瓣长,返回值为array
那么现在我们可以先出图看一眼数据是不是为线性可分的:
plt.scatter(X[:50, 0], X[:50, 1], color='red', marker='o', label='setosa')plt.scatter(X[50:100, 0], X[50:100, 1], color='blue', marker='x', label='versicolor')#先出图直观查看两种花能否被线性区分,x坐标为花萼长y坐标为花瓣长plt.xlabel('sepal length [cm]')plt.ylabel('petal length [cm]')plt.legend(loc='upper left')#设置xy轴名字plt.show()
将数据放入感知机继续训练:
#创建感知机,学习速度设置为0.1,训练次数设置为10ppn = Perceptron(eta=0.1, n_iter=10)ppn.fit(X, y)#使用fit方法将训练数据放入感知机进行训练
至此感知机的训练已经完成,我们可以出图看一眼错误数据,错误次数一般来说应该是随着测试次数下降的,因为每次训练我们都在修正wi系数的:
#出图看一眼错误数目plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker='o')plt.xlabel('Epochs')plt.ylabel('Number of updates')plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UhXDaXBg-1599794323217)(https://s1.ax1x.com/2020/09/11/wtZGcD.png)]
也可以直接调用感知机的predict函数来对数据进行预测:
在鸢尾花数据中随便挑选一组数据44:
v = np.array([5.1,1.9])ppn.predict(v)#输出array(-1)
在前面我们对setosa抽象化即为-1
转载地址:http://hncki.baihongyu.com/