在上一篇统计学习方法———第2章感知机模型中介绍了感知机学习模型、策略和算法,这里通过编程实现对iris数据集的萼片长度(sepal length)和萼片宽度(sepal width)进行线性分类。
Iris 鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例。数据集内包含 3 类共 150 条记录,每类各 50 个数据,每条记录都有 4 项特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度,可以通过这4个特征预测鸢尾花卉属于(iris-setosa, iris-versicolour, iris-virginica)中的哪一品种。
实验结果如下:
由于sklearn库自带了Perceptron感知机模型,作为对照,设计了skclassifier分类器,对比二者分类效果:
正如之前讨论的那样,由于采用随机梯度下降方法会选取不同的训练初值,最终感知机的解存在多种情况,更好的实现方法是采用线性SVM分类器。
基于一般形式的感知机分类器编程实现如下:
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import random
'''
preception for binary linear classification
'''
class Model:
#define init entry
def __init__(self):
self.w = np.zeros(len(data[0])-1, dtype=np.float32)
self.b = 1
self.lr = 0.5
#define sign function
def sign(self, x, w, b):
y = np.dot(x, w) + b
return y
#define SGD
def fit(self, x_train, y_train):
flage = False
while not flage:
count = 0
for i in range(len(x_train)):
j = np.random.randint(len(x_train))
x = x_train[j]
y = y_train[j]
if y * self.sign(x, self.w, self.b) <= 0:
self.w += self.lr * np.dot(y, x)
self.b += self.lr * y
count += 1
if count == 0:
flage = True
return 'perception model!'
def classifier():
perception = Model()
perception.fit(x, y)
#plot figure
x_axis = np.linspace(4, 7, 10)
y_axis = -(perception.w[0] * x_axis + perception.b) / perception.w[1]
plt.plot(x_axis, y_axis)
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()
plt.title('prediction with classifier result')
plt.show()
plt.pause(1)
def skclassifier():
from sklearn.linear_model import Perceptron
perception = Perceptron(fit_intercept=False, max_iter=1000, shuffle=True)
perception.fit(x, y)
x_axis = np.arange(4, 8)
y_axis = -(perception.coef_[0][0] * x_axis + perception.intercept_) / perception.coef_[0][1]
plt.plot(x_axis, y_axis)
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()
plt.title('prediction with skclassifier result')
plt.show()
def loadDate():
#load irisdata
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
df.label.value_counts()
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()
plt.title('original date')
plt.show()
plt.pause(1)
#take the columns:0, 1, -1, ie, sepal length, sepal width, label
data = np.array(df.iloc[:100, [0, 1, -1]])
return data
if __name__ == '__main__':
data = loadDate()
x, y = data[:, :-1], data[:, -1]
y = np.array([1 if i == 1 else -1 for i in y])
#load classifier
classifier()
skclassifier()
print("success!")