核方法和支持向量机

来源:互联网 发布:夜光玩具 辐射 知乎 编辑:程序博客网 时间:2024/05/01 13:43

数据准备

class matchrow():    def __init__(self,row,allnum=False):        if allnum:            self.data=[float(row[i] for i in range(len(row) - 1))]        else:            self.data=row[0:len(row)-1]        self.match=int(row[len(row)-1)#最后一个栏位,是否匹配#导入文件格式:lineformat:(age,smoke?,want childrens?,interests,location)#lineformat,lineformat,boolean,代表了两个人信息以及是否匹配def loadmatchInfo(f,allnum=False):    rows=[]    for line in file(f):        rows.append(matchrow(line.split(","),allnum))    return rows

线性分类器

#数据集的interest部分是非线性的,且是相互作用的变量。#基本线性分类,计算平均点,找出一条线划分#averages中返回两个向量1:匹配的,0:不匹配的def lineartrain(rows):    averages={}    counts={}    for row in rows:        cl=row.match#匹配结果        averages.setdefault(cl,[0.0]*len(row.data))        counts.setdefault(cl,0)        for i in range(len(row.data)):            averages[cl][i]+=float(row.data[i])        counts[cl]+=1    for cl,avg in averages.items():        for i in range(len(avg)):            avg[i]/=counts[cl]    return averages#v1和v2向量的乘积def dotproduct(v1,v2):    return sum([v1[i]*v2[i] for i in range(len(v1))])#向量长度def veclength(v):    return sum([p**2 for p in v])#线性分类器,avgs[1]匹配的平均向量,avgs[0]不匹配的平均向量def dpclassify(point,avgs):    #猜测,应该计算point向量离avgs[1]近还是avgs[0],来判定最终分类    b=(dotproduct(avgs[1],avgs[1])-dotproduct(avgs[0],avgs[0]))/2    y=dotproduct(point,avgs[0])-dotproduct(point,avgs[1])+b    if y>0: return 0    else: return 1

数据处理

#将枚举类型转换为数值def yesno(v):    if v=='yes': return 1    elif v=='no': return -1 #    else: return 0 #缺省值#相同兴趣def matchcount(interest1,interest2):    l1=interest1.split(':')    l2=interest2.split(':')    x=0    for v in l1:        if v in l2: x+=1    return x    #因为向量有多个维度,每个维度数据绝对值大小不一,需要在此做归一化处理def scaledata(rows):    low=[999999999.0]*len(rows[0].data)#最小值    high=[-999999999.0]*len(rows[0].data)#最大值    #最大、最小值    for row in rows:        d=row.data        for i in range(len(d)):            if d[i]<low[i]: low[i]=d[i]            if d[i]>high[i]: high[i]=d[i]    #内部方法,归一化处理,(当前值-最小值)/(最大值-最小值),返回值在0~1之间    def scaleinput(d):        return [(d.data[i]-low[i])/(high[i]-low[i])             for i in range(len(low))]    newrows=[matchrow(scaleinput(row.data)+[row.match])           for row in rows]    return newrows,scaleinput

核方法



在图一中很难找到一条直线来划分,此时就需要将数据转换为另外一个空间上结果如图二,转换后,就可以容易找到一条直线了来划分了。

核方法:是采用一中映射的方法将数据映射到一个高纬度空间上。

#当为了找到一条直线,将数据转换到成千个维度上,通常是不实际的,我们可以用核方法来替代dot-products#核方法def rbf(v1,v2,gamma=20):    dv=[v1[i]-v2[i] for i in range(len(v1))]    l=veclength(dv)    return math.e**(-gamma*l)#非线性分类def nlclassify(point,rows,offset,gamma=10):    sum0=0.0    sum1=0.0    count0=0    count1=0    #计算匹配的rbf总和和不匹配的rbf总和    for row in rows:        if row.match==0:            sum0+=rbf(point,row.data,gamma)            count0+=1        else:            sum1+=rbf(point,row.data,gamma)            count1+=1        y=(1.0/count0)*sum0-(1.0/count1)*sum1+offset    if y<0: return 0    else: return 1#偏移量    def getoffset(rows,gamma=10):    l0=[]    l1=[]    for row in rows:        if row.match==0: l0.append(row.data)        else: l1.append(row.data)    sum0=sum(sum([rbf(v1,v2,gamma) for v1 in l0]) for v2 in l0)    sum1=sum(sum([rbf(v1,v2,gamma) for v1 in l1]) for v2 in l1)    return (1.0/(len(l1)**2))*sum1-(1.0/(len(l0)**2))*sum0

支持向量机



    图1中的线是average classify计算出来的分割线,图中的两点离分割线很近,大多数数据都远离分割线,支持向量机就是为解决此类问题的一些创建分类器的方法。其核心思想:尝试找到尽可能离类别远的线,此线成为最大空白超平面。

    1)分割线选择平行线,是为了尽可能远触摸每个类

    2)确定新的数据点拟合到哪个类

    3)只有在空白边上的点需要决定分割线的放置位置,可以去掉在同一位置上的其他所有数据和线

    在分割线附件的点称为支持向量,寻找支持向量,使用它们找到分割线的算法就是支持向量机。

def svm_func():#svm使用demo    from svm import *    answers,inputs=[r.match for r in scaledset],[r.data for r in scaledset]    param = svm_parameter(kernel_type = RBF)    prob = svm_problem(answers,inputs)    m=svm_model(prob,param)    newrow=[28.0,-1,-1,26.0,-1,1,2,0.8]    m.predict(scaledata(newrow))


原创粉丝点击