1.感知机模型

       感知机:假设输入空间为X,输出空间为Y,其中Y={+1,-1}。由输入空间到输出空间的如下函数f(x),称为感知机。其中,w和b为感知机模型参数,w为权重值,b为偏置,sign为符号函数。

sl2_f

       感知机是一种线性分类模型,属于判别模式。感知机模型的假设空间是定义在特征空间中的所有线性分类模型或线性分类器的集合,即函数的集合{f|f(x)=w*x+b}。

       感知机的几何解释:线性方程w*x+b=0,它代表了法向量为w,截距为b的超平面S,这个超平面将特征空间分为两个部分,分别对应正类和负类(+1和-1)。

2.感知机学习策略

       对于一个数据集,若存在一个超平面S能将该数据集的正实例点和负实例点完全正确的划分到超平面两侧,则该数据集就是线性可分的。

       感知学习的目标就是求得一个超平面S将数据集完全分为征服两类。那么就可以定义损失函数为误分类点的总数,但是这样的损失函数并不是关于w和b连续可导,不易进行优化求解。感知机的损失函数选择的是误分类点到超平面S的距离总和,然后忽略其中的分母得到最终的损失函数。

sl2_lossf

       之所以可以忽略分母,个人理解为:由于超平面S的方程w*x+b=0,等式两边可以任意缩放,则可以不考虑上式分母。这样也可以简化之后的计算。

3.求解算法

       感知学习求解算法,就是求解参数w和b,使得上述损失函数最小。感知机学习算法是误分类驱动的,可以采用随机梯度下降法。

sl2_sgd

       这种学习算法直观解释为:初始化一个超平面S,然后不断的移动S向误分类点的一侧移动,直至超平面最终对数据集正确分类。

4.对偶问题

       假设w和b初始值设为0,一共迭代了m次得到最终的w和b,则有以下关系式。其中N表示输入空间共有N个实例,ni代表第i个实例在迭代中因为误分类而更新的次数,即若某个实例一直处于正确的分类,则其对应的ni值为0。

sl2_1

       将上述关于参数w的等式带入到感知机的一般模型中就可以得出新的模型。求解新模型就是求解原问题的对偶问题,具体过程参考原问题。

sl2_2


1.参考文档:

       [1]. 统计学习方法              李航 著

2.代码实现

一维输入的感知机:

class perceptron (object) :
        def __init__(self, w, b, lr) :
                self.w = w
                self.b = b
                self.lr = lr               
        def train(self, x, y) :
                n = 0
                while(True) :
                        num = 0
                        for i in range(len(x)) :
                                r = self.test(x[i])   
                                if r == y[i] :
                                        num += 1
                                        continue
                                else :
                                        self.update_w(x[i],y[i])
                                        self.update_b(y[i])
                                        n += 1                                    
                        if len(x) == num :
                                #总的迭代次数
                                print("N = ", n)
                                return

        def test(self, x) :
                return self.sign(x*self.w + self.b)
                
        def update_w(self, x, y) :
                self.w += x * y * self.lr
                
        def update_b(self, y) :
                self.b += y * self.lr
        
        #输出超平面S
        def output_S(self) :
                print("S: ", self.w, "* x + ", self.b, " = 0")
                
        def sign(self, x) :
                if x > 0 :
                        return 1
                else :
                        return -1

if __name__ == '__main__'    :
        x = [ 1,  3,  6,  5,  4]
        y = [-1, -1,  1,  1, -1]
        per = perceptron(0,0,1)  
        per.train(x,y)
        per.output_S()
        print("Predict:")
        print("x = 1 ", "y = ",per.test(1))
        print("x = 7 ", "y = ",per.test(7))