参考资料:
1.https://www.cnblogs.com/hapjin/p/6714526.html;
2.https://blog.csdn.net/yxhlfx/article/details/79093456
最近在Youtube上学习李宏毅老师的DeepLearning,在介绍其历史时有一张ppt如下:
感知机(Perceptron)1958年就被提出来,它是2012年后迅速崛起的深度学习(DeepLearning)的基础。
1.感知机是二分类的线性分类模型,其输入是实例的特征向量,输出是实例的类别,+1或-1.
2.感知机模型的定义(简易版):
由n维输入空间到输出空间(只有+1,-1)的如下函数f(x)=sign(w·x+b)称为感知机。
其中,w和b是感知机模型参数,w叫做权值向量,b叫做偏置,w·x为内积。
3.感知机是一种线性分类模型,给定具体的w和b也就定义了一个具体的感知机,任意一个感知机只会对输入空间(特征空间)做一个线性划分,因此如果待分类数据不是线性可分的,那么应当采用其它分类模型,如SVM。
从几何上直观理解感知机:
线性方程w·x+b=0对应于特征空间Rn中的一个超平面S,其中w是超平面的法向量,b是超平面的截距。这个超平面将特征空间划分为两个部分,位于两个部分的点(特征向量)分别被分为正、负两类,因此感知机就可以理解为特征空间Rn中的超平面S。
4.感知机学习的损失函数
假设训练数据集是线性可分的,那么感知机学习是这样一个过程,就是找到感知机模型参数w和b(即找到分离超平面S),使得其能将训练数据集T的正、负实例点完全正确分开。为了找到这样的感知机模型参数w和b,需要一定的策略(学习策略),一般我们会定义一个损失函数并通过最小化这个损失函数来找到模型参数w和b。直观地想,我们容易想到用模型输出标签和正确标签之间不一致的点个数(误分类点)作为损失函数,但该函数不连续,因此有人想到用“所有误分类的点到超平面S的距离来衡量分类失败的程度”。
为此,写出任意点x0到超平面w和b的距离:
以上参考:点到平面距离公式的七种推导方法探讨,点到平面的距离公式
对于误分类点(xi,yi),始终有-yi(w·xi+b)>0,因此我们将上式摘掉绝对值,得到:
用M来标记所有误分类点的集合,则所有误分类点到超平面S的总距离为:
忽略前面的系数项,得到感知机学习的经验风险函数:
5.损失函数的最优化方法——随机梯度下降法
至此,问题就变得简单了,那就是求L(w,b)的极小值。对于极大值极小值的求解方法有许多,这儿首先讲述一种梯度下降的方法求极小值,根据梯度的定义,我们可以得到损失函数L(w,b)的梯度如下:
随机选取一个误分类点(xi,yi),对w,b进行更新:(即我们只需要在每次出现误分类时按如下方法更新w,b的值即可)
式中0<η≤1是步长,又称学习率。
6.感知机的python实现,测试用例
下面给出一个链接,里面有感知机的Python实现以及用例
其中def perceptron(): 函数部分网页上显示有误,应当为:
# -*- coding: utf-8 -*- import numpy as np # Perceptron function def perceptron(x, y, z, eta, t): ''' Input Parameters: x: data set of input features y: actual outputs z: activation function threshold eta: learning rate t: number of iterations ''' # initializing the weights w = np.zeros(len(x[0])) n = 0 # initializing additional parameters to compute sum-of-squared errors yhat_vec = np.ones(len(y)) # vector for predictions errors = np.ones(len(y)) # vector for errors (actual - predictions) J = [] # vector for the SSE cost function while n < t: for i in range(0, len(x)):#i取0,1,2,3,代表训练样本标签 f = np.dot(x[i],w)# dot product if f >= z:# activation function yhat = 1. else: yhat = 0. yhat_vec[i] = yhat # updating the weights for j in range(0, len(w)): w[j] = w[j] + eta*(y[i]-yhat)*x[i][j] n += 1 # computing the sum-of-squared errors for i in range(0,len(y)): errors[i] = (y[i]-yhat_vec[i])**2 J.append(0.5*np.sum(errors)) return w, J
其中def perceptron_test(): 函数照搬(原来的xrange()应改为range(),可能是Python版本的不同导致的):
# -*- coding: utf-8 -*- import numpy as np def perceptron_test(x, w, z, eta, t): y_pred = [] for i in range(0, len(x-1)):#用i遍历所有的测试数据集 f = np.dot(x[i], w) # activation function if f > z: yhat = 1 else: yhat = 0 y_pred.append(yhat) return y_pred
简单测试用例一:
# -*- coding: utf-8 -*- from perceptron import perceptron x = [[1.,0.,0.], [1.,0.,1.], [1.,1.,0.], [1.,1.,1.]] y = [1., 1., 1., 0.] z = 0.0 eta = 0.1 t = 50 print ("The weights are:") print (perceptron(x,y,z,eta,t)[0]) print ('The errors are:') print (perceptron(x,y,z,eta,t)[1])
简单测试用例二:
# -*- coding: utf-8 -*- ''' 以下是dataset的读取、训练及测试样本的准备 ''' import numpy as np import matplotlib.pyplot as plt import pandas as pd from perceptron import perceptron #此种写法为spyder,eclipse等IDE的同一个project中可用,其它解释器用此法可能行不通 df = pd.read_csv("dataset.csv") #注意此处如果文件不在当前目录,应当写出绝对路径,如"D:/perceptron/dataset.csv" plt.scatter(df.values[:,1],df.values[:,2],c=df['3'],alpha=0.8)#画图 df = df.values#将df转换为numpy数组 np.random.seed(5) np.random.shuffle(df)#打乱df中各行数据 train = df[0:int(0.7*len(df))] test = df[int(0.7*len(df)):int(len(df))] x_train = train[:,0:3] y_train = train[:,3] x_test = test[:,0:3] y_test = test[:,3] z = 0.0 eta = 0.1 t = 50 ''' 以下是用自己编写的perceptron进行训练、预测 ''' from perceptron_test import perceptron_test #此种写法为spyder,eclipse等IDE的同一个project中可用,其它解释器用此法可能行不通 from sklearn.metrics import accuracy_score w = perceptron(x_train, y_train, z, eta, t)[0] y_pred = perceptron_test(x_test, w, z, eta, t) print ("The accuracy score by perceptron is:") print(accuracy_score(y_test.tolist(), y_pred)) print ("The weights by perceptron is:") print(w) ''' 以下是用sklearn的perceptron进行预测 ''' from sklearn.linear_model import Perceptron # training the sklearn Perceptron clf = Perceptron(random_state=None, eta0=0.1, shuffle=False, fit_intercept=False) clf.fit(x_train, y_train) y_predict = clf.predict(x_test) print ("The accuracy score by sklearn is:") print(accuracy_score(y_test.tolist(), y_predict)) print ("The weights by sklearn is:") print(clf.coef_)