统计学习方法——第2章 感知机模型编程实现

       在上一篇统计学习方法———第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!")

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章