二、感知机--统计学习方法总结

二、感知机

感知机(perceptron)是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1 , -1 二值。感知机对应于输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型。感知机学习旨在求出将训练数据进行线性划分的分离超平面,为此,导入基于误分类的损失函数,利用梯度下降法对损失函数进行极小化,求得感知器模型。
感知机学习算法具有简单而易于实现的优点,分为原始形式对偶形式,是神经网络与支持向量机的基础。

2.1感知机模型

假设输入空间(特征空间)是 XRn ,输出空间是 y={+1,1} ,由输入空间到输出空间的如下函数

f(x)=sign(ωx+b)
称为感知机。其中, ω 称为权值(weight)或者权值向量, b 叫做偏置(bias),ωx表示两者之间的内积, sign 是符号函数。
感知机的几何解释:线性方程
ωx+b=0
对应于特征空间 Rn 中的一个超平面 S ,其中ω是超平面的法向量, b 是超平面的截距。超平面将特征空间分为两个部分,位于两部分的点(特征向量)分别被分为正负两类。因此,超平面S称为分离超平面(separating hyperplane)。

2.2 感知机学习策略

2.2.1数据集的线性可分性

如果存在某个超平面 S ωx+b=0,能够将数据集的正实例点和负实例点完全正确地划分到超平面的两侧,即对所有的 yi=+1 的实例 i ,有ωx+b>0,对于所有 y=1 的实例 i ,有ωx+b<0,则称数据集 T 为线性可分数据集(linearly separable data set);否则,称数据集T线性不可分。

2.2.2感知机学习策略

假设训练数据集是线性可分的,感知机学习的目标是求得一个能够将训练集正实例点和负实例点完全正确分开的分离超平面。为了找出这样的超平面,即确定感知机模型参数 ω,b ,需要确定一个学习策略,即定义(经验)损失函数并将损失函数极小化。
损失函数的定义为

L(ω,b)=xiMyi(ωxi+b)

其中, M 为误分类点的集合。这个损失函数就是感知机学习的经验风险函数。

2.3感知机学习算法

感知机学习问题转化为求解以上损失函数的最优化问题,最优化的方法是随机梯度下降法。本节叙述感知机学习的具体算法,包括原始形式和对偶形式,并证明在训练数据线性可分条件下感知机学习算法的收敛性。

2.3.1感知机学习算法的原始形式

输入:训练数据集T={(x1,y1),(x2,y2),,(xN,yN)},其中 xiRN , yi{1,+1} ,学习率 η(0<η1) ;
输出: ω,b ;感知机模型 f(x)=sign(ωx+b)

(1)选取初值 ω0,b0
(2)在训练集中选取数据 (xi,yi)
(3)如果 yi(ωx+b)0

w=w+ηyixi

b=b+ηyi

(4)转至(2),直到训练集中没有误分类点

import os
import sys

# An example in that book, the training set and parameters' sizes are fixed
training_set = []

w = []
b = 0
lens = 0
n = 0

# update parameters using stochastic gradient descent
def update(item):
    global w, b, lens, n
    for i in range(lens):
        w[i] = w[i] + n * item[1] * item[0][i]
    b = b + n * item[1]
    print w, b # you can uncomment this line to check the process of stochastic gradient descent

# calculate the functional distance between 'item' an the dicision surface
def cal(item):
    global w, b
    res = 0
    for i in range(len(item[0])):
        res += item[0][i] * w[i]
    res += b
    res *= item[1]
    return res

# check if the hyperplane can classify the examples correctly
def check():
    flag = False
    for item in training_set:
        if cal(item) <= 0:
            flag = True
            update(item)
    if not flag: #False
        print "RESULT: w: " + str(w) + " b: "+ str(b)
        tmp = ''
        for keys in w:
            tmp += str(keys) + ' '
        tmp = tmp.strip()
        modelFile.write(tmp + '\n')
        modelFile.write(str(b) + '\n')
        modelFile.write(str(lens) + '\n')
        modelFile.write(str(n) + '\n')
        modelFile.close()
        os._exit(0)
    flag = False

if __name__=="__main__":
    if len(sys.argv) != 4:
        print "Usage: python perceptron.py n trainFile modelFile"
        exit(0)
    n = float(sys.argv[1])
    trainFile = file(sys.argv[2])
    modelFile= file(sys.argv[3], 'w')
    lens = 0
    for line in trainFile:
        chunk = line.strip().split(' ')
        lens = len(chunk) - 1
        tmp_all = []
        tmp = []
        for i in range(1, lens+1):
            tmp.append(int(chunk[i]))
        tmp_all.append(tmp)
        tmp_all.append(int(chunk[0]))
        training_set.append(tmp_all)
    trainFile.close()
    for i in range(lens):
        w.append(0)

    for i in range(1000):
        check()
    print "The training_set is not linear separable. "
2.3.2算法的收敛性

对于线性可分数据集,感知机学习算法原始形式收敛,即经过有限次迭代可以得到一个将训练数据集完全正确划分的分离超平面及感知机模型。

2.3.3感知机学习算法的对偶模式

对偶形式的基本想法是,将 w b表示为实例 xi 和标记 yi 的线性组合的形式,通过求解其系数而求得 w b
假设对于误分类的点 (xi,yi) 共n次修改 ω,b 的值,则 ω,b 关于 (xi,yi) 的增量分别是 αiyixi αyi ,这里 αi=niη .从学习过程中不难看出,最后学习到的 ω,b 可以分别表示为

ω=i=1Nαiyixi

b=i=1Nαiyi

感知机学习算法的对偶模式
输入:线性可分的数据集 T={(x1,y1),(x2,y2),,(xN,yN)} ,其中 xiRN , yi{1,+1} ,学习率 η(0<η1) ;
输出: α,b ;感知机模型 f(x)=sign(Nj=1ajyjxj+b)
其中 α=(α1,α2,,αN)T

(1) α=0,b=0
(2)在训练集中选取数据 (xi,yi)
(3)如果 yi(Nj=1αjyjxjxi+b)0

αi=αi+η

b=b+ηyi

(4)转至(2),直到训练集中没有误分类数据

import os
import sys

# An example in that book, the training set and parameters' sizes are fixed
training_set = []

w = []
a = []
b = 0
lens = 0
n = 0
Gram = []

def calInnerProduct(i, j):
    global lens
    res = 0
    for p in range(lens):
        res += training_set[i][0][p] * training_set[j][0][p]
    return res

def AddVector(vec1, vec2):
    for i in range(len(vec1)):
        vec1[i] = vec1[i] + vec2[i]
    return vec1

def NumProduct(num, vec):
    for i in range(len(vec)):
        vec[i] *= num
    return vec 

def createGram():
    global lens
    for i in range(len(training_set)):
        tmp = []
        for j in range(0, len(training_set)):
            tmp.append(calInnerProduct(i, j))
        Gram.append(tmp)

# update parameters using stochastic gradient descent
def update(k):
    global a, b, n
    a[k] += n
    b = b + n * training_set[k][1] 
    print a, b # you can uncomment this line to check the process of stochastic gradient descent

# calculate the functional distance between 'item' an the dicision surface
def cal(k):
    global a, b
    res = 0
    for i in range(len(training_set)):
        res += a[i] * int(training_set[i][1]) * Gram[i][k]
    res += b
    res *= training_set[k][1]
    return res

# check if the hyperplane can classify the examples correctly
def check():
    global w, a
    flag = False
    for i in range(len(training_set)):
        if cal(i) <= 0:
            flag = True
            update(i)

    if not flag: #False
        for i in range(len(training_set)):
            w = AddVector(w, NumProduct(a[i] * int(training_set[i][1]), training_set[i][0]))
        print "RESULT: w: ", w, " b: ", b
        tmp = ''
        for keys in w:
            tmp += str(keys) + ' '
        tmp = tmp.strip()
        modelFile.write(tmp + '\n')
        modelFile.write(str(b) + '\n')
        modelFile.write(str(lens) + '\n')
        modelFile.write(str(n) + '\n')
        modelFile.close()
        os._exit(0)
    flag = False

if __name__=="__main__":
    if len(sys.argv) != 4:
        print "Usage: python perceptron_duality.py n trainFile modelFile"
        exit(0)
    n = float(sys.argv[1])
    trainFile = file(sys.argv[2])
    modelFile= file(sys.argv[3], 'w')
    lens = 0
    for line in trainFile:
        chunk = line.strip().split(' ')
        lens = len(chunk) - 1
        tmp_all = []
        tmp = []
        for i in range(1, lens+1):
            tmp.append(int(chunk[i]))
        tmp_all.append(tmp)
        tmp_all.append(int(chunk[0]))
        training_set.append(tmp_all)
    trainFile.close()

    createGram()
    for i in range(len(training_set)):
        a.append(0)
    for i in range(lens):
        w.append(0)

    for i in range(1000):
        check()
    print "The training_set is not linear separable. "

对偶形式中训练实例仅以内积的形式出现。为了方便,可以预先将训练集中的实例间的内积计算出并以矩阵的形式存储,这个矩阵就是所谓的 Gram 矩阵

G=[xixj]N×N

代码参考链接:http://www.cnblogs.com/kaituorensheng/p/3561091.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值