感知机模型由Rosenblatt提出, 该模型是模仿单个神经元在大脑中的工作:通过激活神经元。
因此最初的感知机工作原理十分简单,主要步骤如下:
对于每一个训练样本 x(i) 执行下列操作
计算输出的目标值 y^
更新权重(weight)
这里, 输出的目标值就是预测的所属的类,同时我们在预测中,要同时更新每一个在权重向量w中的具体权重(weight) wj ,也即:
wj:=wj+Δwj
对于用于更新权重 wj 值的 Δwj 通过感知机的学习规则计算:
Δwj=η(yi−y^(i))x(i)j
其中 η 为学习率(一个常数, 取值一般为0.0~1.0), y(i) 为第 i 个训练样本的真实标签, y^(i) 为相应的预测标签, x(i)j 为第 i 个训练样本的第 j 个特征值。例如:
Δw0=η(y(i)−output(i))
Δw1=η(y(i)−output(i))x(i)1
Δw2=η(y(i)−output(i))x(i)2
perceptron_classifier.py :
# -*- coding:utf-8 -*-
import numpy as np
class Perceptron(object):
"""
eta: float
学习率
n_inter: int
迭代次数
errors_: list
在每次迭代中,错误分类的的数量
w_: 1d-array
训练后的权重
"""
def __init__(self, eta=0.01, n_iter=10):
self.eta = eta
self.n_iter = n_iter
def fit(self, X, y):
self.w_ = np.zeros(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
self.w_[0] += update
errors += int(update != 0.0)
self.errors_.append(errors)
return self
def net_input(self, X):
return np.dot(X, self.w_[1:]) + self.w_[0]
def predict(self, X):
return np.where(self.net_input(X) >= 0.0, 1, -1)
iris_perceptron_classifier.py :
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import sys
sys.path.append('../')
from perceptron_classifier import Perceptron
# 从网上下载鸢尾花的数据
df = pd.read_csv('https://archive.ics.uci.edu/ml/'
'machine-learning-databases/iris/iris.data', header=None)
# y 取前一百个数据中标签数据, 位于第 5 列中
y = df.iloc[0:100, 4].values
# 将标签数据数值化, 若为Iris-setosa 品种, 则设为-1, 否则为1
y = np.where(y == 'Iris-setosa', -1, 1)
# X 取前一百个样本数据,选取为第1和3个特征作为识别花品种的特征
X = df.iloc[0:100, [0, 2]].values
# 在坐标图中根据花朵的sepal length(萼片长度),petal length(花瓣长度)来标出花朵
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')
plt.xlabel('sepal length')
plt.ylabel('petal length')
plt.legend(loc='upper left')
plt.show()
# 用感知机对训练样本进行训练
ppn = Perceptron(eta=0.1, n_iter=10)
ppn.fit(X, y)
# 画出在每次训练中,错误分类样本的个数
plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Number of misclassification')
plt.show()
sys.path.append('../')
from perceptron_classifier import Perceptron