感知机


参考资料:

题目要求

  1. 手动实现感知机
  2. 对模型评估

基本原理

直观定义:感知机接受多个输入信号,输出一个信号,输入信号配以权重,用阈值 $\theta$ 判定这个神经元是否被激活。

正规定义:感知机是根据输入实例的特征向量 $x$ ,对其进行 二分类 的线性分类模型:
$$f(x)=sign(w \cdot x+b)$$

感知机学习算法,是基于随机梯度下降法的对损失函数的最优化算法,有 原始形式对偶形式

随机梯度下降法 Stochastic Gradient Descent,随机抽取一个误分类点使其梯度下降。


二范数:$\Vert x \Vert_2$,即距离

损失函数:

$$L(w,b)=−\sum_{x_i \in M}y_i(w⋅x_i+b)$$

代码实现

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# iris数据集5个属性:花萼长、花萼宽、花瓣长、花瓣宽、种类(3种)
# 每种花各有 50 个数据
def get_data():
    iris = load_iris()
    #print(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']
    data = np.array(df.iloc[:100, [0, 1, -1]])
    X, y = data[:,:-1], data[:,-1]
    y = np.array([1 if i == 1 else -1 for i in y])
    return X, y

def show_model(model):
    x_ = np.linspace(4, 7, 100)
    y_ = -(model.w[0] * x_ + model.b)/model.w[1]
    plt.scatter([i[0] for i in X[:50]], [i[1] for i in X[:50]], label='0')  # scatter散点
    plt.scatter([i[0] for i in X[50:]], [i[1] for i in X[50:]], label='1')
    plt.plot(x_, y_)
    plt.title("After")
    plt.xlabel('sepal length')
    plt.ylabel('sepal width')
    plt.legend()
    plt.show()

class Perceptron:
    def __init__(self):
        self.w = np.zeros(2)
        self.b = 0
        self.l_rate = 0.1  #步长

    def sign(self, x, w, b):
        return np.dot(w, x) + b

    def fit_yuan_shi(self, X_train, y_train):
        flag = False          # 是否完成
        while not flag:
            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.w + self.l_rate * np.dot(y, X)
                    self.b = self.b + self.l_rate * y
                    wrong_count += 1
            if wrong_count == 0:
                flag = True

    def fit_dui_ou(self, X_train, y_train):
        n = len(X_train)

        flag = False          # 是否完成
        gram = np.array([np.dot(i,j) for i in X_train for j in X_train]).reshape(n, n)
        alpha = [0]*n

        while not flag:
            wrong_count = 0
            for d in range(n):
                X = X_train[d]
                y = y_train[d]
                #print("No.{}:".format(d),X,y,alpha)
                if y * (sum([alpha[i]*y_train[i]*gram[d][i] for i in range(n)]) + self.b) <= 0:
                    alpha[d] += 1     #学习率为 1
                    self.b += y
                    wrong_count += 1
            if wrong_count == 0:
                flag = True

        self.w[0] = sum([alpha[i]*y_train[i]*X_train[i][0] for i in range(n)])
        self.w[1] = sum([alpha[i]*y_train[i]*X_train[i][1] for i in range(n)])

#if __name__ == "__main__":

X, y = get_data()

plt.scatter([i[0] for i in X[:50]], [i[1] for i in X[:50]], label='0')
plt.scatter([i[0] for i in X[50:]], [i[1] for i in X[50:]], label='1')
plt.title("Before")
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()

model1, model2 = Perceptron(), Perceptron()
model1.fit_yuan_shi(X, y)
show_model(model1)

model2.fit_dui_ou([[3,3],[4,3],[1,1]], [1,1,-1])
X, y = [[3,3],[4,3],[1,1]], [1,1,-1]
x_ = np.linspace(1, 4, 100)
y_ = -(model2.w[0] * x_ + model2.b)/model2.w[1]
plt.scatter([i[0] for i in X[:2]], [i[1] for i in X[:2]], label='0')  # scatter散点
plt.scatter([i[0] for i in X[2:]], [i[1] for i in X[2:]], label='1')
plt.plot(x_, y_)
plt.title("After")
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()

#对偶形式在这效率好低,如果用水仙花数据就跑不出来,alpha半天只改动了前几项

对偶形式应该没问题吧…


文章作者: ╯晓~
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ╯晓~ !
评论
  目录