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

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
感知机是二分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取 +1 和 -1 二值。感知机对应于输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型感知机学习算法是基于随机梯度下降法的。具体地,首先任意选取一个超平面,然后用梯度下降法不断地极小化目标函数,找出最优超平面。 以下是感知机算法的C++类实现及案例代码: ```c++ #include <iostream> #include <vector> #include <random> using namespace std; class Perceptron { public: Perceptron(int feature_num) : w(feature_num), b(0) {} void train(const vector<vector<double>>& X, const vector<double>& y, int max_iter = 100) { int n_samples = X.size(); int n_features = X[0].size(); mt19937 rng(0); uniform_int_distribution<int> dist(0, n_samples - 1); for (int iter = 0; iter < max_iter; iter++) { int i = dist(rng); double wx = 0; for (int j = 0; j < n_features; j++) { wx += X[i][j] * w[j]; } double yi = y[i]; if (yi * (wx + b) <= 0) { for (int j = 0; j < n_features; j++) { w[j] += yi * X[i][j]; } b += yi; } } } double predict(const vector<double>& x) { double wx = 0; int n_features = x.size(); for (int i = 0; i < n_features; i++) { wx += x[i] * w[i]; } return wx + b > 0 ? 1 : -1; } void print_weights() const { cout << "w = ["; for (double wi : w) { cout << wi << ", "; } cout << "], b = " << b << endl; } private: vector<double> w; double b; }; int main() { vector<vector<double>> X{ {3, 3}, {4, 3}, {1, 1} }; vector<double> y{1, 1, -1}; Perceptron model(X[0].size()); model.train(X, y); model.print_weights(); cout << "predict([3, 4]) = " << model.predict({3, 4}) << endl; return 0; } ``` 在上述代码中,Perceptron类代表感知机模型。train函数接受训练数据X和y,以及最大迭代次数max_iter,默认为100。predict函数接受一个样本特征向量x,返回其预测的类别标签。print_weights函数打印训练后得到的权重和偏置项。 本例中,使用学习率为1的随机梯度下降法进行模型训练。训练数据X是一个3x2的矩阵,y是一个包含3个元素的向量,表示3个样本的类别标签。模型训练完毕后,使用predict函数对特定样本进行预测。 以上是感知机算法的C++类实现及案例代码,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值