Welcome

MSRA Researcher新手,现阶段从事多模态大模型预训练方向。对NLP感兴趣或对博客内容有疑惑及意见建议的,欢迎评论或添加我微信。此外如果有需要内推的同学,也欢迎来骚扰我。联系方式详见concat页面。

统计学习方法|感知机原理剖析及实现

统计学习方法|感知机原理剖析及实现

阅读数:36,515

前言

《统计学习方法》一书在前几天正式看完,由于这本书在一定程度上对于初学者是有一些难度的,趁着热乎劲把自己走过的弯路都写出来,后人也能走得更顺畅一点。

以下是我的github地址,其中有《统计学习方法》书中所有涉及到的算法的实现,也是在写博客的同时编写的。在编写宗旨上是希望所有人看完书以后,按照程序的思路再配合书中的公式,能知道怎么讲所学的都应用上。(有点自恋地讲)程序中的注释可能比大部分的博客内容都多。希望大家能够多多捧场,如果可以的话,为我的github打颗星,也能让更多的人看到。

github:

GitHub|手写实现李航《统计学习方法》书中全部算法

相关博文:

  1. 统计学习方法|感知机原理剖析及实现
  2. 统计学习方法|K近邻原理剖析及实现
  3. 统计学习方法|朴素贝叶斯原理剖析及实现
  4. 统计学习方法|决策树原理剖析及实现
  5. 统计学习方法|逻辑斯蒂原理剖析及实现

 

 

正文

感知机的直观理解

感知机应该属于机器学习算法中最简单的一种算法,其原理可以看下图:

 

 

 

 

 

 

比如说我们有一个坐标轴(图中的黑色线),横的为x1轴,竖的x2轴。图中的每一个点都是由(x1,x2)决定的。如果我们将这张图应用在判断零件是否合格上,x1表示零件长度,x2表示零件质量,坐标轴表示零件的均值长度和均值重量,并且蓝色的为合格产品,黄色为劣质产品,需要剔除。那么很显然如果零件的长度和重量都大于均值,说明这个零件是合格的。也就是在第一象限的所有蓝色点。反之如果两项都小于均值,就是劣质的,比如在第三象限的黄色点。

在预测上很简单,拿到一个新的零件,我们测出它的长度x1,质量x2,如果两项都大于均值,说明零件合格。这就是我们人的人工智能。

那么程序怎么知道长度重量都大于均值的零件就是合格的呢?

或者说

它是怎么学会这个规则的呢?

程序拿到手的是当前图里所有点的信息以及标签,也就是说它知道所有样本x的坐标为(x1, x2),同时它属于蓝色或黄色。对于目前手里的这些点,要是能找到一条直线把它们分开就好了,这样我拿到一个新的零件,知道了它的质量和重量,我就可以判断它在线的哪一侧,就可以知道它可能属于好的或坏的零件了。例如图里的黄、蓝、粉三条线,都可以完美地把当前的两种情况划分开。甚至x1坐标轴或x2坐标轴都能成为一个划分直线(这两个直线均能把所有点正确地分开)。

读者也看到了,对于图中的两堆点,我们有无数条直线可以将其划分开,事实上我们不光要能划分当前的点,当新来的点进来是,也要能很好地将其划分,所以哪条线最好呢?

怎样一条直线属于最佳的划分直线?实际上感知机无法找到一条最佳的直线,它找到的可能是图中所有画出来的线,只要能把所有的点都分开就好了。

得出结论:
如果一条直线能够不分错一个点,那就是一条好的直线

进一步来说:

如果我们把所有分错的点和直线的距离求和,让这段求和的举例最小(最好是0,这样就表示没有分错的点了),这条直线就是我们要找的。

 

感知机的数学角度(配合《统计学习方法》食用更佳)

首先我们确定一下终极目标:甭管找最佳划分直线啥中间乱七八糟的步骤,反正最后生成一个函数f(x),当我们把新的一个数据x扔进函数以后,它会预测告诉我这是蓝的还是黄的,多简单啊。所以我们不要去考虑中间过程,先把结果定了。

 

 

瞧,f(x)不是出来了嘛,sign是啥?wx+b是啥?别着急,我们再看一下sigin函数是什么。

 

 

 

sign好像很简单,当x大于等于0,sign输出1,否则输出-1。那么往前递归一下,wx+b如果大于等于0,f(x)就等于1,反之f(x)等于-1。

那么wx+b是啥?

它就是那条最优的直线。我们把这个公式放在二维情况下看,二维中的直线是这样定义的:y=ax+b。在二维中,w就是a,b还是b。所以wx+b是一条直线(比如说本文最开始那张图中的蓝线)。如果新的点x在蓝线左侧,那么wx+b<0,再经过sign,最后f输出-1,如果在右侧,输出1。等等,好像有点说不通,把情况等价到二维平面中,y=ax+b,只要点在x轴上方,甭管点在线的左侧右侧,最后结果都是大于0啊,这个值得正负跟线有啥关系?emmm….其实wx+b和ax+b表现直线的形式一样,但是又稍有差别。我们把最前头的图逆时针旋转45度,蓝线是不是变成x轴了?哈哈这样是不是原先蓝线的右侧变成了x轴的上方了?其实感知机在计算wx+b这条线的时候,已经在暗地里进行了转换,使得用于划分的直线变成x轴,左右侧分别为x轴的上方和下方,也就成了正和负。

那么,为啥是wx+b,而不叫ax+b?

在本文中使用零件作为例子,上文使用了长度和重量(x1,x2)来表示一个零件的属性,所以一个二维平面就足够,那么如果零件的品质和色泽也有关系呢?那就得加一个x3表示色泽,样本的属性就变成了(x1,x2,x3),变成三维了。wx+b并不是只用于二维情况,在三维这种情况下,仍然可以使用这个公式。所以wx+b与ax+b只是在二维上近似一致,实际上是不同的东西。在三维中wx+b是啥?我们想象屋子里一个角落有蓝点,一个角落有黄点,还用一条直线的话,显然是不够的,需要一个平面!所以在三维中,wx+b是一个平面!至于为什么,后文会详细说明。四维呢?emmm…好像没法描述是个什么东西可以把四维空间分开,但是对于四维来说,应该会存在一个东西像一把刀一样把四维空间切成两半。能切成两半,应该是一个对于四维来说是个平面的东西,就像对于三维来说切割它的是一个二维的平面,二维来说是一个一维的平面。总之四维中wx+b可以表示为一个相对于四维来说是个平面的东西,然后把四维空间一切为二,我们给它取名叫超平面。由此引申,在高维空间中,wx+b是一个划分超平面,这也就是它正式的名字。

正式来说:

wx+b是一个n维空间中的超平面S,其中w是超平面的法向量,b是超平面的截距,这个超平面将特征空间划分成两部分,位于两部分的点分别被分为正负两类,所以,超平面S称为分离超平面。

细节:

w是超平面的法向量:对于一个平面来说w就是这么定义的,是数学知识,可以谷歌补习一下

b是超平面的截距:可以按照二维中的ax+b理解

特征空间:也就是整个n维空间,样本的每个属性都叫一个特征,特征空间的意思是在这个空间中可以找到样本所有的属性组合

 

感知机的学习策略:

 

 

 

 

 

 

我们从最初的要求有个f(x),引申到能只输出1和-1的sign(x),再到现在的wx+b,看起来越来越简单了,只要能找到最合适的wx+b,就能完成感知机的搭建了。前文说过,让误分类的点距离和最大化来找这个超平面,首先我们要放出单独计算一个点与超平面之间距离的公式,这样才能将所有的点的距离公式求出来对不?

 

 

 

先看wx+b,在二维空间中,我们可以认为它是一条直线,同时因为做过转换,整张图旋转后wx+b是x轴,那么所有点到x轴的距离其实就是wx+b的值对不?当然了,考虑到x轴下方的点,得加上绝对值->|wx+b|,求所有误分类点的距离和,也就是求|wx+b|的总和,让它最小化。很简单啊,把w和b等比例缩小就好啦,比如说w改为0.5w,b改为0.5b,线还是那条线,但是值缩小两倍啦!你还不满意?我可以接着缩!缩到0去!所以啊,我们要加点约束,让整个式子除以w的模长。啥意思?就是w不管怎么样,要除以它的单位长度。如果我w和b等比例缩小,那||w||也会等比例缩小,值一动不动,很稳。没有除以模长之前,|wx+b|叫函数间隔,除模长之后叫几何间隔,几何间隔可以认为是物理意义上的实际长度,管你怎么放大缩小,你物理距离就那样,不可能改个数就变。在机器学习中求距离时,通常是使用几何间隔的,否则无法求出解。

 

 

 

 

 

 

 

 

 

对于误分类的数据,例如实际应该属于蓝色的点(线的右侧,y>0),但实际上预测出来是在左侧(wx+b<0),那就是分错了,结果是负,这时候再加个符号,结果就是正了,再除以w的模长,就是单个误分类的点到超平面的举例。举例总和就是所有误分类的点相加。

上图最后说不考虑除以模长,就变成了函数间隔,为什么可以这么做呢?不考虑wb等比例缩小这件事了吗?上文说的是错的吗?

有一种解释是这样说的:感知机是误分类驱动的算法,它的终极目标是没有误分类的点,如果没有误分类的点,总和距离就变成了0,w和b值怎样都没用。所以几何间隔和函数间隔在感知机的应用上没有差别,为了计算简单,使用函数间隔。

 

 

 

 

 

 

 

 

以上是损失函数的正式定义,在求得划分超平面的终极目标就是让损失函数最小化,如果是0的话就相当完美了。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

感知机使用梯度下降方法求得w和b的最优解,从而得到划分超平面wx+b,关于梯度下降及其中的步长受篇幅所限可以自行谷歌。

这里给出书中的一个例子:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

关于对偶形式:

由于夜深了,可能写不下去了。我相信看懂了前面部分的同学,对偶形式能自行看懂,所以具体公式不再讲解。这里说一下我的直观感觉,方便大家理解。

在算法的最初需要给定一个w和b的值,这样才能使得w和b可以进行梯度下降,我们可以随便给一个,也可以随机初始化一个。在对偶形式中,让w和b初值都为0,这样w和b最终最优值其实就是相对于0的增量,也就是相对于初值的增量。此时公式中出现了xi*x,因为需要频繁计算这两项,可以提前先做一个矩阵,里头是对于所有i的xi*x的值,那在计算过程中就不需要再算了,直接查矩阵就好了。提高了速度,也就是Gram矩阵

 

每次写博客都有很多话想说,整得博客很像个话痨,诶。

 

贴代码:(建议去本文最上方的github链接下载,有书中所有算法的实现以及详细注释)

#coding=utf-8
#Author:Dodo
#Date:2018-11-15
#Email:lvtengchao@pku.edu.cn

'''
数据集:Mnist
训练集数量:60000
测试集数量:10000
------------------------------
运行结果:
正确率:81.72%(二分类)
运行时长:78.6s
'''

import numpy as np
import time

def loadData(fileName):
    '''
    加载Mnist数据集
    :param fileName:要加载的数据集路径
    :return: list形式的数据集及标记
    '''
    print('start to read data')
    # 存放数据及标记的list
    dataArr = []; labelArr = []
    # 打开文件
    fr = open(fileName, 'r')
    # 将文件按行读取
    for line in fr.readlines():
        # 对每一行数据按切割福','进行切割,返回字段列表
        curLine = line.strip().split(',')

        # Mnsit有0-9是个标记,由于是二分类任务,所以将>=5的作为1,<5为-1
        if int(curLine[0]) >= 5:
            labelArr.append(1)
        else:
            labelArr.append(-1)
        #存放标记
        #[int(num) for num in curLine[1:]] -> 遍历每一行中除了以第一哥元素(标记)外将所有元素转换成int类型
        #[int(num)/255 for num in curLine[1:]] -> 将所有数据除255归一化(非必须步骤,可以不归一化)
        dataArr.append([int(num)/255 for num in curLine[1:]])

    #返回data和label
    return dataArr, labelArr

def perceptron(dataArr, labelArr, iter=50):
    '''
    感知器训练过程
    :param dataArr:训练集的数据 (list)
    :param labelArr: 训练集的标签(list)
    :param iter: 迭代次数,默认50
    :return: 训练好的w和b
    '''
    print('start to trans')
    #将数据转换成矩阵形式(在机器学习中因为通常都是向量的运算,转换称矩阵形式方便运算)
    #转换后的数据中每一个样本的向量都是横向的
    dataMat = np.mat(dataArr)
    #将标签转换成矩阵,之后转置(.T为转置)。
    #转置是因为在运算中需要单独取label中的某一个元素,如果是1xN的矩阵的话,无法用label[i]的方式读取
    #对于只有1xN的label可以不转换成矩阵,直接label[i]即可,这里转换是为了格式上的统一
    labelMat = np.mat(labelArr).T
    #获取数据矩阵的大小,为m*n
    m, n = np.shape(dataMat)
    #创建初始权重w,初始值全为0。
    #np.shape(dataMat)的返回值为m,n -> np.shape(dataMat)[1])的值即为n,与
    #样本长度保持一致
    w = np.zeros((1, np.shape(dataMat)[1]))
    #初始化偏置b为0
    b = 0
    #初始化步长,也就是梯度下降过程中的n,控制梯度下降速率
    h = 0.0001

    #进行iter次迭代计算
    for k in range(iter):
        #对于每一个样本进行梯度下降
        #李航书中在2.3.1开头部分使用的梯度下降,是全部样本都算一遍以后,统一
        #进行一次梯度下降
        #在2.3.1的后半部分可以看到(例如公式2.6 2.7),求和符号没有了,此时用
        #的是随机梯度下降,即计算一个样本就针对该样本进行一次梯度下降。
        #两者的差异各有千秋,但较为常用的是随机梯度下降。
        for i in range(m):
            #获取当前样本的向量
            xi = dataMat[i]
            #获取当前样本所对应的标签
            yi = labelMat[i]
            #判断是否是误分类样本
            #误分类样本特诊为: -yi(w*xi+b)>=0,详细可参考书中2.2.2小节
            #在书的公式中写的是>0,实际上如果=0,说明改点在超平面上,也是不正确的
            if -1 * yi * (w * xi.T + b) >= 0:
                #对于误分类样本,进行梯度下降,更新w和b
                w = w + h *  yi * xi
                b = b + h * yi
        #打印训练进度
        print('Round %d:%d training' % (k, iter))

    #返回训练完的w、b
    return w, b


def test(dataArr, labelArr, w, b):
    '''
    测试准确率
    :param dataArr:测试集
    :param labelArr: 测试集标签
    :param w: 训练获得的权重w
    :param b: 训练获得的偏置b
    :return: 正确率
    '''
    print('start to test')
    #将数据集转换为矩阵形式方便运算
    dataMat = np.mat(dataArr)
    #将label转换为矩阵并转置,详细信息参考上文perceptron中
    #对于这部分的解说
    labelMat = np.mat(labelArr).T

    #获取测试数据集矩阵的大小
    m, n = np.shape(dataMat)
    #错误样本数计数
    errorCnt = 0
    #遍历所有测试样本
    for i in range(m):
        #获得单个样本向量
        xi = dataMat[i]
        #获得该样本标记
        yi = labelMat[i]
        #获得运算结果
        result = -1 * yi * (w * xi.T + b)
        #如果-yi(w*xi+b)>=0,说明该样本被误分类,错误样本数加一
        if result >= 0: errorCnt += 1
    #正确率 = 1 - (样本分类错误数 / 样本总数)
    accruRate = 1 - (errorCnt / m)
    #返回正确率
    return accruRate

if __name__ == '__main__':
    #获取当前时间
    #在文末同样获取当前时间,两时间差即为程序运行时间
    start = time.time()

    #获取训练集及标签
    trainData, trainLabel = loadData('../Mnist/mnist_train.csv')
    #获取测试集及标签
    testData, testLabel = loadData('../Mnist/mnist_test.csv')

    #训练获得权重
    w, b = perceptron(trainData, trainLabel, iter = 30)
    #进行测试,获得正确率
    accruRate = test(testData, testLabel, w, b)

    #获取当前时间,作为结束时间
    end = time.time()
    #显示正确率
    print('accuracy rate is:', accruRate)
    #显示用时时长
    print('time span:', end - start)

 

*

Dodo

60条评论

匿名 发布于2:10 下午 - 11月 1, 2023

博主写得非常清晰易懂!!!

匿名 发布于6:44 上午 - 1月 28, 2023

Dear pkudodo.com webmaster, Keep up the good work, admin!

匿名 发布于6:08 下午 - 1月 9, 2023

Greetings! Quite valuable guidance within this publish! It is the very little adjustments that is likely to make the most important changes. Thanks for sharing!

匿名 发布于6:07 下午 - 1月 9, 2023

Hello I am so grateful I discovered your Web page, I really observed you by error, though I was searching on Bing for something else, Anyways I am here now and would much like to say quite a few many thanks for an amazing submit as well as a all spherical thrilling site (I also like the topic/style and design), I don’t have time to undergo everything for the time being but I’ve bookmarked it and also integrated your RSS feeds, so After i have time I are going to be back again to go through quite a bit a lot more, Make sure you do sustain The good task

匿名 发布于6:02 下午 - 1月 9, 2023

You might be so brilliant! I don’t believe that I’ve truly browse one factor like that ahead of. So great to discover another person that has a number of exceptional views on this concern. Definitely.. thanks for beginning this up. This Website is one thing that is needed on the internet, an individual with a few originality!

匿名 发布于5:59 下午 - 1月 9, 2023

Thanks on your wonderful submitting! I very seriously loved examining it, you may be a terrific writer. I will be sure to bookmark your site and definitely will return in some unspecified time in the future. I would like to really encourage that you just keep on your great work, Have a very great holiday weekend!

匿名 发布于4:04 下午 - 10月 30, 2022

It’s hard to find educated folks relating to this issue, having said that, you seem to be you determine what you’re talking about! Thanks

匿名 发布于3:58 下午 - 9月 13, 2022

为什么要进行30轮训练呢,我感觉一轮就可以求出超平面

匿名 发布于3:55 下午 - 9月 13, 2022

在感知机算法中的更新w和b时,作者好像是从第一份数据有序地读取到60000份,更新w和b,我想的是,用一个误判的点更新w和b后,这个误判的点还是有可能是误判的点,我认为用一个误判的点更新w和b后,应该再从头查找误判的点进行更新w和b,这样最终能够得到完全将两类分开的超平面。我还验证了一下,用作者的方法训练出w和b后,用训练集当作测试集,但准确率并不是100%,这说明最终得出的超平面还是会将一些点误判。以上是我自己的想法,有哪位网友看到后,希望批评指正。

    匿名 发布于8:36 下午 - 9月 13, 2022

    准确率不是百分百的原因是默认只进行50次迭代,如果全部迭代完的话会达到100%,不过这样会耗费很多时间

    匿名 发布于10:36 上午 - 11月 6, 2022

    我认为数据集可能不是完全线性可分的,如果按照您的这种思路,每一次误判就重新循环,时间开销可能会很大
    不过如果线性可分,那么在训练集上的准确率应该就能到100%了,但是在测试集上还是不能到100

匿名 发布于10:07 上午 - 9月 3, 2022

bunadisisj nsjjsjsisjsmizjzjjzjzz zumzsert

匿名 发布于2:18 下午 - 4月 13, 2022

作者您好呀!请问那个” print(‘Round %d:%d training’ % (k, iter))“里面的k是什么呀?

    匿名 发布于4:00 下午 - 9月 13, 2022

    这个K是当前训练到第几轮次,他上面不是有一个for循环吗

匿名 发布于2:31 下午 - 3月 1, 2022

666

匿名 发布于7:37 下午 - 1月 4, 2022

写的很好哦!

    匿名 发布于9:15 下午 - 2月 8, 2023

    242、
    47、42

匿名 发布于9:21 下午 - 7月 31, 2021

赞👍

匿名 发布于5:00 下午 - 4月 27, 2021

“我们从最初的要求有个f(x),引申到能只输出1和-1的sign(x),再到现在的wx+b,看起来越来越简单了,只要能找到最合适的wx+b,就能完成感知机的搭建了。前文说过,让误分类的点距离和最大化来找这个超平面,首先我们要放出单独计算一个点与超平面之间距离的公式,这样才能将所有的点的距离公式求出来对不?”
让误分类的点距离和最大化 应该是和最小化吧。

匿名 发布于12:33 上午 - 10月 30, 2020

如果加上验证集结果会不会变好一点

匿名 发布于3:18 下午 - 10月 27, 2020

不愧标签pku.edu.cn,写的清新脱俗,简洁易懂又不失幽默!

匿名 发布于9:01 下午 - 9月 7, 2020

如果不归一化,直接就出结果了,并且准确率为1.

    匿名 发布于1:57 下午 - 9月 1, 2021

    去归一化还能提升精度?

匿名 发布于11:32 下午 - 8月 20, 2020

建议loadData函数这样写,更python,借助pandas:
def loadData(filename):

print(‘start to load file’)

df = pd.read_csv(filename, header=None)
dataArr = df.iloc[:,1:]
labelArr= pd.Series((num>=5) for num in df.iloc[:,0]).map({True:1,False:-1})

return dataArr, labelArr

    匿名 发布于3:33 下午 - 10月 5, 2020

    谢谢,我运行作者源代码时,遇到了memoryerror,用了你的方法确实可以

匿名 发布于4:49 下午 - 7月 29, 2020

”所以wx+b与ax+b只是在二维上近似一致“,这边应该改成ax+by+c,因为是个二维平面,而ax只表示一维,必须把y加进去

    匿名 发布于11:11 下午 - 9月 16, 2020

    不对哦,y是标签,这里x是两维(x1,x2)的。想想超平面定义wx+b=0在这里是直线

      匿名 发布于6:37 下午 - 10月 1, 2020

      正解

匿名 发布于5:20 下午 - 7月 21, 2020

匿名 发布于3:44 下午 - 6月 29, 2020

优秀!

匿名 发布于10:20 下午 - 6月 14, 2020

个人感觉对于二维特征将wx+b写成f=ax+by+c更好理解些。

    匿名 发布于2:52 下午 - 6月 28, 2020

    y = b * 1 + w1 * x1 + w2 * x2

匿名 发布于8:17 下午 - 5月 27, 2020

这里函数间隔方便用梯度下降法去学习参数,有没有这种可能。

匿名 发布于11:29 上午 - 5月 23, 2020

写的很友好,github开源的代码也很给力,膜大佬

匿名 发布于7:18 下午 - 5月 21, 2020

我想问下mnist 数据集设二分类是线性可分的嘛,哈哈

    匿名 发布于5:09 下午 - 10月 26, 2020

    根据结果,显然是可分的了

匿名 发布于4:32 下午 - 5月 21, 2020

风格挺好的,就像聊天一样,不过几何距离那边有点没看懂

    匿名 发布于8:26 下午 - 7月 31, 2020

    +1

匿名 发布于3:17 下午 - 5月 19, 2020

MemoryError: Unable to allocate 359. MiB for an array with shape (60000, 784) and data type float64
是我电脑没设置好,还是电脑太烂,九代i7,16G内存,1660ti显卡的笔记本Y7000P

    匿名 发布于4:57 下午 - 5月 19, 2020

    emmm我python32位的,重装了64位的可以用了

    匿名 发布于9:21 上午 - 7月 21, 2020

    你是来秀配置的,太假了

      匿名 发布于6:39 下午 - 10月 1, 2020

      哈哈哈哈哈哈哈

匿名 发布于10:58 上午 - 3月 28, 2020

那个平面距离就是点到平面的距离公式吧,感觉这样说从我们以前学过的知识容易理解一点,我没有理解到旋转wx+b = 0的直接带入值然后除以|w|(转不过圈来)

    匿名 发布于5:51 下午 - 5月 19, 2020

    我想说这个w的作用是放大的作用,那么除以一个|W|能够让这个值更小,而且各个点的值更具有比较性

匿名 发布于7:39 下午 - 3月 23, 2020

大佬,我零基础入门机器学习,有前途吗?

匿名 发布于2:44 下午 - 12月 13, 2019

感知学习算法有很多缺点 :
感知机是线性的模型,其不能表达复杂的函数,不能出来线性不可分的问题,其连异或问题(XOR)都无法解决,因为异或问题是线性不可分的 .
1.人工神经网络
2.用非线性模型,核技巧,如SVM进行处理
博主还可以补充点吗

匿名 发布于8:24 下午 - 11月 15, 2019

是pku的师兄吗?感谢分享,内容真详细每行都有注释,来自tsu的学渣

匿名 发布于10:44 上午 - 8月 20, 2019

误分类到超平面的距离那里的理解是不是不太对,那个不是点到直线的距离公式吗?

    Dodo 发布于7:18 下午 - 8月 23, 2019

    不太明白你说的是文章内还是代码中?
    超平面在二维情况下就是那条线,高维情况下本质上是一样的。
    代码中距离没有除以模,是因为感知机是误分类驱动的,它最终的目的是减少误分类的个数,误分类个数为0是目标,所以不除以模没有影响。

      匿名 发布于5:59 下午 - 11月 4, 2019

      感谢楼主分享!这个人说的意思应该是,|wx+b|/||w|| 这个是点到直线的距离公式

      匿名 发布于9:54 下午 - 5月 24, 2020

      忽略|w|的前提是数据线性可分,否则肯定要加约束条件,比如||w||=1

匿名 发布于10:03 下午 - 4月 2, 2019

minist数据集在哪里下载呢

    Dodo 发布于11:29 下午 - 4月 2, 2019

    在我的github中已经有准备好的mnist数据集。
    github.com/Dod-o/Statistical-Learning-Method_Code

      匿名 发布于10:05 上午 - 8月 2, 2019

      数据集没有了

        Dodo 发布于10:51 上午 - 8月 7, 2019

        github上吗? 在mnist文件夹内

匿名 发布于9:43 上午 - 2月 21, 2019

可以转载吗?很优秀

匿名 发布于1:22 上午 - 2月 12, 2019

YOUXIU

匿名 发布于5:24 下午 - 1月 16, 2019

优秀

匿名 发布于8:43 上午 - 11月 18, 2018

挺容易懂的

    匿名 发布于4:34 上午 - 11月 10, 2023

    1+1