第二章 感知机
基本梳理
附上思维导图:
-
感知机模型
- 输入
- 特征向量
- 输出
- 类别
- 判别模型
- 基于误分类损失函数
- 利用梯度下降法对损失函数进行极小化
- 学习算法
- 原始形式
- 对偶形式
- 神经网络与支持向量机的基础
- 定义
- 几何解释
- 输入
-
感知机学习策略
- 定义损失函数
- 距离
- 1 ∥ w ∥ ∣ w ⋅ x 0 + b ∣ \frac { 1 } { \| w \| } \left| w \cdot x _ { 0 } + b \right| ∥w∥1∣w⋅x0+b∣
- 误分类点
- − y i ( w ⋅ x i + b ) > 0 - y _ { i } \left( w \cdot x _ { i } + b \right) > 0 −yi(w⋅xi+b)>0
- 误分类点距离
- − 1 ∥ w ∥ y i ( w ⋅ x i + b ) - \frac { 1 } { \| w \| } y _ { i } \left( w \cdot x _ { i } + b \right) −∥w∥1yi(w⋅xi+b)
- 总距离
- − 1 ∥ w ∥ ∑ x i ∈ M y i ( w ⋅ x i + b ) - \frac { 1 } { \| w \| } \sum _ { x _ { i } \in \mathcal { M } } y _ { i } \left( w \cdot x _ { i } + b \right) −∥w∥1∑xi∈Myi(w⋅xi+b)
- 损失函数
- L ( w , b ) = − ∑ x i ∈ M y i ( w ⋅ x i + b ) L ( w , b ) = - \sum _ { x_{i} \in M } y _ { i } \left( w \cdot x _ { i } + b \right) L(w,b)=−∑xi∈Myi(w⋅xi+b)
- M为误分类点的数目
- 距离
- 定义损失函数
-
感知机学习算法
-
最优化问题
- min w , b L ( w , b ) = − ∑ x i ∈ M y t ( w ⋅ x i + b ) \min _ { w , b } L ( w , b ) = - \sum _ { x _{i}\in M } y _ { t } \left( w \cdot x _ { i } + b \right) minw,bL(w,b)=−∑xi∈Myt(w⋅xi+b)
-
随机梯度下降法
- 首先任意选择一个超平面,w,b,然后不断极小化目标函数,损失函数L的梯度:
- 选取误会
- ∇ w L ( w , b ) = − ∑ x ∈ M y i x i ∇ b L ( w , b ) = − ∑ x ∈ M y t \nabla _ { w } L ( w , b ) = - \sum _ { x \in M } y _ { i } x _ { i } \quad \nabla _ { b } L ( w , b ) = - \sum _ { x \in M } y _ { t } ∇wL(w,b)=−∑x∈Myixi∇bL(w,b)=−∑x∈Myt
- w ← w + η y i x i b ← b + η y i w \leftarrow w + \eta y _ { i } x _ { i } \quad b \leftarrow b + \eta y _ { i } w←w+ηyixib←b+ηyi
-
感知机学习算法的原始形式
-
算法的收敛性
- 误分类的次数k是有上界的,当训练集线性分时,感知机学习算法原始形式迭代是收敛的
- 感知机算法存在许多解,原因?
- 初值
- 迭代过程中误分类的选择顺序
- 为得到唯一分离超平面,需要增加约束,如SVM
- 线性不可分数据集,迭代震荡
-
对偶形式
-
代码小练习
损失函数: L ( w , b ) = − Σ y i ( w ∗ x i + b ) L(w, b) = -\Sigma{y_{i}(w*x_{i} + b)} L(w,b)=−Σyi(w∗xi+b)
算法: 随机梯度下降法
随机抽取一个误分类点使其梯度下降。
w = w + η y i x i w = w + \eta y_{i}x_{i} w=w+ηyixi
b = b + η y i b = b + \eta y_{i} b=b+ηyi
1. 导入数据
拿出iris数据集中两个分类的数据和[sepal length,sepal width]作为特征
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
%matplotlib inline
iris = load_iris()
df = pd.DataFrame(iris.data,columns=iris.feature_names)
df["label"] = iris.target
# 任取10个
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0')
plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
data = np.array(df.iloc[:100,[0,1,-1]])
X, y = data[:,:-1],data[:,-1]
y[y == 0]= -1
X , y X,y X,y分别为特征向量,和标签
2. 训练模型
class Model:
def __init__(self):
self.w = np.random.rand(2)
self.b = 0
self.l_rate = 0.1
def sign(self,x,w,b):
y = np.dot(x,w) + b
return y
def fit(self,X_train,y_train):
is_wrong = True
while is_wrong:
wrong_count = 0
for d in range(len(X_train)):
X = X_train[d]
y = y_train[d]
if y*self.sign(X,self.w,self.b) <= 0:
self.w += self.l_rate*np.dot(y,X)
self.b += self.l_rate*y
wrong_count += 1
if wrong_count == 0:
is_wrong = False
return "Perceptron Model"
perceptron = Model()
perceptron.fit(X,y)
'Perceptron Model'
perceptron.w
array([ 7.88184795, -10.03027928])
perceptron.b
-12.399999999999972
x_points = np.linspace(4, 7,10)
y_ = -(perceptron.w[0]*x_points + perceptron.b)/perceptron.w[1]
plt.plot(x_points, y_)
plt.plot(data[:50, 0], data[:50, 1], 'bo', color='blue', label='0')
plt.plot(data[50:100, 0], data[50:100, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
<matplotlib.legend.Legend at 0x25ce79459b0>
scikit-learn Perceptron
from sklearn.linear_model import Perceptron
clf = Perceptron(fit_intercept=False, max_iter=1000, shuffle=False)
clf.fit(X, y)
Perceptron(alpha=0.0001, class_weight=None, eta0=1.0, fit_intercept=False,
max_iter=1000, n_iter=None, n_jobs=1, penalty=None, random_state=0,
shuffle=False, tol=None, verbose=0, warm_start=False)
# Weights assigned to the features.
print(clf.coef_)
[[ 74.6 -127.2]]
# 截距 Constants in decision function.
print(clf.intercept_)
[ 0.]
clf.coef_
array([[ 74.6, -127.2]])
x_ponits = np.arange(4, 8)
y_ = -(clf.coef_[0][0]*x_ponits + clf.intercept_)/clf.coef_[0][1]
plt.plot(x_ponits, y_)
plt.plot(data[:50, 0], data[:50, 1], 'bo', color='blue', label='0')
plt.plot(data[50:100, 0], data[50:100, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
<matplotlib.legend.Legend at 0x25ce8d7ab70>