为约会网站的用户寻找配对;数据包含数值型、名词性和大量的非线性关系。
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(data)-1]
self.match=int(row[len(row)-1]))
def loadmatch(f,allnum=False):
rows=[]
for line in file(f):
rows.append(matchrow(line.split(','),allnum))
return rows
基本的线性分类
def lineartrain(rows):
averages={}
counts={}
for row in rows:
c1=row.match
averages.setdefault(c1,[0.0]*(len(row.data)))
counts,setdefault(c1,0)
for i in range(len(row.data)):
averages[c1][i]=float(row.data[i])
counts[c1]+=1
for c1,avg in averages.items():
for i in range(len(avg)):
avg[i]=avg[i]/counts[c1]
return averages
确定匹配和不匹配状态下的数据的平均值,显示在图上。
点积。class=sign((x-(m0+m1)/2)*(m0-m1)
def dotproduct(v1,v2):
return sum([v1[i]*v2[i] for i in range(len(v1))])
def dpclassify(point,avgs):
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
利用Yahoo! Maps来确定距离
略
构造新的数据集
def loadnumerical():
oldrows=loadmatch('matchmaker.csv')
newrows=[]
for row in oldrows:
d=row.data
data=[float(d[0]),yesno(d[1]),yesno(d[2]),float(d[5]),yesno(d[6]),yesno(d[7]),matchcount(d[3],d[8]),milesdistance(d[4],d[9]),
row.match]
newrows.append(matchrow(data))
return newrows
对数据进行缩放处理
将所有数据转化为0-1之间的值
def scaledata(rows):
low=[99999999]*len(rows[0].data)
high=[-9999999]*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]
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
理解核方法
我们可以预先的坐标点进行变换,构造一个用一条直线就可以进行划分的新数据集。
核技法
用一个新的函数来取代原来的点积函数,当借助某个映射函数将数据第一次变换到更高纬度的坐标空间时,新函数将会返回高纬度坐标空间的点积结果。————径向基函数。是非线性的。
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 getoffset(rows,gamma=10):
略
def nlclassify(point,rows,offset,gamma=10)
sum0=0
sum1=0
count1=0
count0=0
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/count0)*sum0-(1/count1)*sum1+offset
if y<0:return 0
else return 1 #将经过处理的数据进行判别(dpclassify)
支持向量机
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0QASFznE-1582534997725)(C1343EB5CB5D470ABFC26C3D334CCC9B)]
我们引入一个LIBSVM的开源库,它能够对SVM模型进行训练、给出预测。
from svm import *
prob=svm_problem([1,-1],[[1,0,1],[-1,0,-1]])
param=svm_parameter(kernel_type=LINEAR,C=10)
#训练
m=svm_model(prob,param)
#预测
m.predice([1,1,1])
用SVM用于婚介数据集,系统自带的函数
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)
m.predict(scalef(newrow))
#利用交叉验证函数来检验模型的质量...
g=cross_validation(prob,param,4)
n=sum([abs(answers[i]-g[i]) for i in range(len(g))
若n=116,由于初始集为500,则得到了384项正确匹配。