unit9 相亲匹配判别

2018-05-22  本文已影响0人  巴拉巴拉_9515

《集体智慧编程》第九单元“高阶分类”主要亮点是相亲人员的匹配判断。是有监督的分析,基于一定量的有结果的试验数据,从中获得规律实现预测。使用高阶分类:核方法与支持向量机(SVM)训练模型并对配对进行判断。

01数据集介绍

假设某网站的相亲记录如下:每一行代表一个配对试验,记录女性和男性的年龄、是否吸烟、是否有孩子、兴趣、住址,以及是否配对成功(0表示失败,1表示成功)。

单提取男女年龄一项,看看相亲市场上年龄的配对情况。散点分布如下图。

横轴为female年龄:年轻的姑娘(<25)和40岁以上男性基本配对失败;
25-40岁的女性在配对上,对象的年龄并没有那么大限制,40岁的女性和20几岁的男性成功配对数也比较多。
40-50岁的女性和25岁以下的男性配对成功的概率较低

02 数据预处理

(1)数值化
将原始数据转换为数值型,可以方便模型的使用。

是否吸烟?是否有孩子:是1;否-1,模糊或确实或不清楚的为0
兴趣爱好:显示男女相同爱好的个数
地址显示男女间地址距离

预处理后数据集变量为:女性年龄,是否吸烟,是否有孩子,男性年龄,是否吸烟,是否有孩子,相同爱好,地址距离。

[39.0, 1, -1, 43.0, -1, 1, 0, 105.66516194012885]
[23.0, -1, -1, 30.0, -1, -1, 0, 1.319127371884788]
[50.0, -1, -1, 49.0, 1, 1, 2, 106.48245828168044]
[46.0, -1, 1, 19.0, -1, -1, 0, 110.56632686422407]

(2)标准化
由于不同变量的数值范围不同,需要做标准化处理,使数据范围在同一水平,便于比较。标准化处理后,每个变量范围在0-1之间,数据集如下所示:

[0.65625, 1.0, 0.0, 0.78125, 0.0, 1.0, 0.0, 0.9556721737702848]
[0.15625, 0.0, 0.0, 0.375, 0.0, 0.0, 0.0, 0.011930642984140028]
[1.0, 0.0, 0.0, 0.96875, 1.0, 1.0, 1.0, 0.9630640838095432]
[0.875, 0.0, 1.0, 0.03125, 0.0, 0.0, 0.0, 1.0]

03 核方法

核方法kernel methods (KMs)是一类模式识别的算法,是解决非线性模式分析问题的一种有效途径。
径向基

def rbf(v1, v2, gamma=10):
    dv = [v1[i] - v2[i] for i in range(len(v1))]#点与点间的差
    l = veclength(dv)
    return math.e ** (-gamma * l)

偏移量
转换空间以后会发生改变。

def getoffset(rows, gamma=10):
    l0 = []
    l1 = []
    #匹配成功的都提出来放在L1中,失败的都放在L0中.
    for row in rows:
        if row.match == 0:
            l0.append(row.data)
        else:
            l1.append(row.data)
    #向量V1、V2偏移量计算
    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
ssoffset=getoffset(scaledset)#结果为0.05915809687556309

核方法
模型建立,基于径向量和偏移量,建立决策判断模型。

#输入:point(目标判断点), rows(数据集),offset(偏移量)
def nlclassify(point, rows, offset, gamma=10):
    sum0 = 0.0
    sum1 = 0.0
    count0 = 0
    count1 = 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.0 / count0) * sum0 - (1.0 / count1) * sum1 + offset
    if y > 0:
        return 0#配对失败
    else:
        return 1#配对成功
#判断[0.65625, 1.0, 0.0, 0.78125, 0.0, 1.0, 0.0, 0.9556721737702848]
nlclassify(scalef(numericalset[0].data),scaledset,ssoffset)#0;#scalef基于数据集的缩放函数

预测判断
例如有一组数据newrow=[23.0,-1,-1,30.0,-1,-1,0,1.3]。

女性23岁,不吸烟,无小孩;
男性30岁,不吸烟,无小孩;
无共同兴趣爱好,住址相距1.3

核方法判断结果为:配对成功(结果为:1)

nlclassify(scalef(newrow),scaledset,ssoffset)#1

04 SVM支持向量机

代码实现SVM很方便

from sklearn import svm
clf_linear = svm.SVC(kernel='linear').fit(inputs,answers)
clf_rbf = svm.SVC(kernel='rbf').fit(inputs,answers)
clf_sigmoid = svm.SVC(kernel='sigmoid').fit(inputs,answers)

训练号SVM模型以后,实现对未知分类的数据集预判。

a=scalef([23.0,-1,-1,30.0,-1,-1,0,1.3])
newrow=np.array([a])
clf_linear.predict(newrow)#array([0])

05 困难及问题

在对原始数据“地址”做处理计算两地间距离时,yahoo!map一直调试不出来无法获得地址的经纬度。数据集中的地址都是美国地址686 Avenue of the Americas New York NY,经过多次尝试最后使用geopy包实现。

from geopy.geocoders import Nominatim
def geocodeN(address):
    gps=Nominatim()
    location=gps.geocode(address)
    return location.longitude,location.latitude
geocodeN("220 W 42nd St New York NY")
#(-73.987958, 40.7563095),成功了

但问题是计算每一对距离都很耗时,实际操作中我只计算了20组数据的距离,造成核方法、SVM的训练数据太少,所以以上判断并不考虑准确性。

总之,模型实现其实还好,数据预处理花了很久折腾。

上一篇下一篇

猜你喜欢

热点阅读