机器学习算法-感知机代码实现


前言

为了更深入的理解机器学习算法,最近阅读统计学习方法,打算把书上代码复现一遍,顺便把python语法、numpy、pandas、matplotlib巩固下。

一、感知机算法初步理解

感知机本质是二分类任务,如果数据集中有正样本和负样本,那么只需要拟合出一个超平面把正样本和负样本分隔开。

二、代码实现

1.数据集处理

数据集是使用的是鸢尾花数据集,在代码中直接从sklearn中导入即可。
要对数据集进行处理,必须得先知道数据集的特点,鸢尾花共有150个样本,类别数为3.
0~50个样本label=0,50-100样本label=1,100-150个样本label=2。并且鸢尾花特征数=4。
1.使用pandas展示数据集

from sklearn.datasets import load_iris
import pandas as pd
#导入数据集
iris = load_iris()
#iris.data得到数据,columns为列即4个特征
df = pd.DataFrame(iris.data, columns=iris.feature_names)
#添加标签label列
df['label'] = iris.target

注:iris.data得到样本特征,iris.target得到标签。
panda中dataframe用法
鸢尾花数据集分布:

在这里插入图片描述

2.数据处理
取出数据中前100个样本,并且将特征1(“speal length”)和特征2(“speal width”)作为特征
特征数目=2。
用matplotlib中将样本可视化
plt.scatter()用法


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.show()

在这里插入图片描述
准备数据集


#取前100个样本,然后特征1和特征2和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])

2.创建model

#创建模型
class Perceptron:
    def __init__(self,):
        #给w,b进行初始化,需要更新的参数有w1和w2
        self.w=np.ones(2,dtype=np.float32)
        self.b=0
        self.lr=0.1
    #一元一次方程
    def sign(self,x,w,b):
        return np.dot(x,w)+b
    #更新w和b,需要给入训练数据
    def fit(self,x_train,y_train):
        #设置标志位
        flag=True
        while flag:
            wrong_count=0
            #每一次送入一个样本进行更新权重
            for i in range(len(x_train)):
                x=x_train[i]
                y=y_train[i]
                #更新参数w,b
                if y*self.sign(x,self.w,self.b)<=0:
                    self.w+=self.lr*np.dot(y,x)
                    self.b+=self.lr*y
                    #错误样本+1
                    wrong_count+=1
            #在将所有样本遍历一次后如果可以使误分类数为0,即模型已经训练完毕,如果误分类数仍不为0,再遍历一次
            if wrong_count==0:
                flag=False
        #训练完毕,所有样本都已经被分类成功
        return 'Perceptron Model!'
    def score(self):
        pass
#实例化model
model=Perceptron()
#调用model中方法.fit
model.fit(X,y)

3.可视化结果

#可视化分类后的plt图
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')
#以4为start,7为end,(7-4)/10=0.3为间隔
x_points = np.linspace(4, 7, 10)
#这里为什么要除以w[1]
y_ = -(model.w[0] * x_points + model.b) / model.w[1]
plt.plot(x_points, y_)
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.show()

在这里插入图片描述

总结

损失函数的设计:按常理说设计损失函数应该是统计算法误分类样本点的总数:比如将正样本划为负样本,负样本划为正样本。但是如果这样设计损失函数会导致损失函数不是连续可导,没办法更新参数权重,可能能更新权重但不太好优化。因此选择误分类点到超平面的距离来构建损失函数,为什么这样做呢,我觉得这样是将参数w和b考虑进来,然后不断优化参数找到最优的超平面。
使用感知机算法的前提是数据集线性可分,如果数据集不是线性可分,那么不能使用感知机算法,这条结论我很肯定。
怎么更新权重w和b:当然是使用随机梯度下降的方法,一个样本一个样本送进去,去更新w和b,直到没有误分类点。
w,b初始化时不同的值在迭代的过程中也是不同的,但是结果是相同的。
疑问:
1.y_ = -(model.w[0] * x_points + model.b) / model.w[1]为什么要除以w[1]
解释:因为要把直线画到平面图上,因此使用y来表示即遵循了y是因变量,x是自变量的思维。而现在我们的纵坐标是特征2(“speal width”),横坐标是特征1(“speal length”),因此·换种写法就是我们想要的超平面。x0为特征1,x1为特征2。
在这里插入图片描述

2.刚好在超平面上的点属于哪一类?
根据自己代码怎么写,比如本代码中选择在超平面时也会视为误分类。

 if y*self.sign(x,self.w,self.b)<=0:

3.如果特征数目大于2能处理吗
可以处理,但是在平面图上面显示不出来,比如特征数4维的话,那么为4维空间,怎么显示出一个超平面进行分割样本呢?总结就是特征维数不会限制感知机的使用,但是随着维度的升高,样本更为复杂,因此感知机也很难线性切分训练集了,在平时教学时选择二维特征方便在平面图上展示,但这不意味着就不能处理高维度的特征了。

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值