赞
踩
1. Minsky与Papert指出:感知机是线性模型,所以不能表示复杂的函数,如异或(XOR).验证感知机为什么不能表示异或。
首先写出异或函数对应的输入输出:
y | ||
1 | 1 | -1 |
1 | -1 | +1 |
-1 | 1 | +1 |
-1 | -1 | -1 |
我们可以可视化上述实例及其标签:
- import numpy as np
- import matplotlib.pyplot as plt
-
- x = np.array([[1,1],[1,-1],[-1,1],[-1,-1]])
- y = np.array([-1,1,1,-1])
-
- plt.scatter(x[:,0],x[:,1],c=y)
- plt.xlabel('x1')
- plt.ylabel('x2')
- plt.ylim(-2,2)
- plt.xlim(-2,2)
- plt.xticks([-2,-1,0,1,2])
- plt.yticks([-2,-1,0,1,2])
- plt.title('XOR')
- plt.show()
显然异或问题是线性不可分的,感知机算法无法用一条直线把两类样本点完全分开。
2. 模仿上一节中的例题,构建从训练数据集求解感知机模型的例子。
- import numpy as np
- from sklearn.linear_model import Perceptron
-
- X_train = np.array([[3,3],[4,3],[1,1]])
- y_train = np.array([1,1,-1])
-
- #初始化感知机模型
- perceptron_model = Perceptron()
- #训练
- perceptron_model.fit(X_train,y_train)
- #打印学好的参数
- print("w:",perceptron_model.coef_,"\nb:",perceptron_model.intercept_,"\n")
-
- #在训练集上进行预测
- res = perceptron_model.predict(X_train)
- print(res)
3. 证明以下定理:样本集线性可分的充要条件是正实例点集所构成的凸壳与负实例点集所构成的凸壳互不相交。
在2维情况下,凸壳可用下面的图形来表示:
其中向量A,B,C,D,F可以看作是集合S中的元素,他们围成的整个多边形区域就是集合S的凸壳Conv(S),区域内所有的点或者向量都是Conv(S)中的元素。
线性可分的定义:
4. 思考感知机模型假设空间是什么?模型复杂度体现在哪?、
假设空间 {f|f=wx+b},即特征空间中的所有线性分类器。
模型的复杂度主要体现在实例特征向量
5. 已知训练数据集D,其正实例点是x1=(3,3)T,x2=(4,3)T,负实例点是x3=(1,1)T:
1)试调用sklearn.linear_model 的Perceptron模块,对训练数据集进行分类,并对比不同学习率
Perceptron模块/对象主要的方法或属性:
- import numpy as np
- from sklearn.linear_model import Perceptron
-
- X_train = np.array([[3,3],[4,3],[1,1]])
- y_train = np.array([1,1,-1])
-
- #初始化感知机模型
- perceptron_model = Perceptron()
- #训练
- perceptron_model.fit(X_train,y_train)
-
- #打印学好的参数和迭代次数
- print("w:",perceptron_model.coef_,"\nb:",perceptron_model.intercept_,"\nn_iter:",perceptron_model.n_iter_,"\n")
-
- #在训练集上进行预测
- res = perceptron_model.predict(X_train)
- print(res)
-
- #计算在训练集上的准确率
- acc = perceptron_model.score(X_train,y_train)
- print('correct accuracy:{:.0%}'.format(acc))
Perceptron模块/对象主要的参数:
设定tol=1e-3,max_iter=1000:
perceptron_model = Perceptron(tol=1e-3,max_iter=1000)
设置学习率:
perceptron_model = Perceptron(eta0=0.5,tol=1e-3,max_iter=1000)
w,b变成了原来的0.5倍。
perceptron_model = Perceptron(eta0=0.1,tol=1e-3,max_iter=1000)
w,b变成了原来的0.1倍。
改变学习率虽然w,b变了,但是他们之间的比例没有变,即表示的分离超平面是不变的,说明改变学习率对最终的结果没有影响,对收敛的速度会有影响。
原因在于,我们w,b的初始值为0,根据更新规则:
不管更新多少次,因为初始值为0,w,b都可以表示为
正则化:
可以选择使用l1或l2正则化,或者混合正则化()
正则化是为了防止过拟合(减小权值/参数),L1正则化会使权重/参数更稀疏;L2正则化会使权重/参数更均匀。
perceptron_model = Perceptron(penalty="l1",eta0=1,tol=1e-3,max_iter=1000)
perceptron_model = Perceptron(penalty="l2",eta0=1,tol=1e-3,max_iter=1000)
正则化系数控制惩罚或约束力度,过小无约束效力;过大约束太狠,可能会出现欠拟合(模型过于简单,参数会变得很小)。
perceptron_model = Perceptron(penalty="l2",alpha=0.0001,eta0=1,tol=1e-3,max_iter=1000)
perceptron_model = Perceptron(penalty="l2",alpha=0.1,eta0=1,tol=1e-3,max_iter=1000)
2) 用python 自编程实现感知机模型,对训练数据集进行分类,并对比误分类点选择次序不同对最终结果的影响。可采用函数式编程或面向对象的编程。
- import numpy as np
- import matplotlib.pyplot as plt
- from matplotlib.colors import ListedColormap
-
- class MyPerceptron:
- def __init__(self):
- self.w=None
- self.b=0
- self.l_rate=1
-
- def fit(self,X_train,y_train):
- #用样本点的特征数更新初始w,如x1=(3,3)T,有两个特征,则self.w=[0,0]
- #尽量使用二维数组来表示行向量/列向量
- self.w=np.zeros(X_train.shape[1]).reshape(-1,1)
- i=0
- while i<X_train.shape[0]:
- X=X_train[i]
- y=y_train[i]
- # 如果y*(wx+b)≤0 说明是误判点,更新w,b
- if y*(np.dot(X, self.w) + self.b) <= 0:
- self.w = self.w + self.l_rate * y*X.reshape(-1,1)
- self.b = self.b + self.l_rate * y
- i=0 #如果是误判点,从头进行检测
- else:
- i+=1
-
- def draw(X,w,b):
- #产生分离超平面上的两点
- X_new=np.array([[0], [6]])
- y_predict=-b-(w[0]*X_new)/w[1]
- #绘制训练数据集的散点图
- plt.plot(X[:2,0],X[:2,1],"g*",label="1")
- plt.plot(X[2:,0], X[2:,1], "rx",label="-1")
- #绘制分离超平面
- plt.plot(X_new,y_predict,"b-")
- #设置两坐标轴起止值
- plt.axis([0,6,0,6])
- #设置坐标轴标签
- plt.xlabel('x1')
- plt.ylabel('x2')
- #显示图例
- plt.legend()
- #显示图像
- plt.show()
-
- #也可以使用等高线图 通过生成网格的方式 渲染出决策边界
- def visual(X,w,b,label):
-
- h = .01
- # 生成网格点
- min1 = np.min(X[:, 0]) - 0.5
- max1 = np.max(X[:, 0]) + 0.5
- min2 = np.min(X[:, 1]) - 0.5
- max2 = np.max(X[:, 1]) + 0.5
- xx, yy = np.meshgrid(np.arange(min1, max1, h), np.arange(min2, max2, h)) # 在x,y轴上以0.02为间隔,生成网格点
-
- # 计算每个网格点在判别函数下的值
- Z = np.concatenate([xx.ravel().reshape(-1, 1), yy.ravel().reshape(-1, 1)],
- axis=1)
- res = Z.dot(w)+b
-
- res[res <= 0] = -1
- res[res > 0] = 1
-
- res = res.reshape(xx.shape) # 转型为网格的形状
-
- # 绘制决策边界
- plt.contourf(xx, yy, res, alpha=0.5, cmap=ListedColormap(('red', 'blue')))
- # 添加图例 注释
- plt.xlabel('x1')
- plt.ylabel('x2')
-
- # 绘制数据点
- for i, j in enumerate(np.unique(label)):
- plt.scatter(X[label == j, 0], X[label == j, 1], c=ListedColormap(('red', 'blue'))(i),
- label=str(j))
-
- plt.legend()
- plt.show()
-
- def main():
- # 构造训练数据集
- X_train=np.array([[3,3],[4,3],[1,1]])
- y_train=np.array([1,1,-1])
- # 构建感知机对象,对数据集继续训练
- perceptron=MyPerceptron()
- perceptron.fit(X_train,y_train)
- print(perceptron.w)
- print(perceptron.b)
- # 结果图像绘制
- #draw(X_train,perceptron.w,perceptron.b)
- visual(X_train,perceptron.w,perceptron.b,y_train)
-
-
- if __name__=="__main__":
- main()
3) 对比传统感知机算法及其对偶形式的运行速度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。