机器学习:kNN算法(二)—— 实战:改进约会网站的配对效果

一 利用KNN进行对象匹配

  某个在线约会网站对于注册用户推荐不同的对象,某个用户把他们分为不喜欢的人,喜欢的人,非常喜欢的人。现在希望通过之前一段时间此用户划分的对象数据,进行分析。然后自动判别新的对象是否为该用户所喜欢。

  • 收集数据。关于此用户的数据存放在某个文本文件中。
  • 准备数据。收集的数据主要包括以下三个特征:(1)每年获得的飞行里程数;(2)玩视频游戏所耗的时间百分比;(3)每周消费的冰淇淋公升数
    将特征输入到分类器前,必须将之处理成可以接受的格式。我们可以利用自己创建一个函数,函数输入为文件路径,输出特征矩阵与类别向量,代码如下。当然我们可以直接。
def file2matrix(filename):
    fr=open(filename)
    arrayOLines=fr.readlines()                
    numberOfLines=len(arrayOLines)         
    returnMat=np.zeros((numberOfLines,3))   
    classLabelVector=[]                      
    index=0
    for line in arrayOLines:
        line=line.strip()                     #去除每行前后空白换行符等
        listFromLine=line.split('	')      
        returnMat[index,:]=listFromLine[0:3]   #列表的三个元素给矩阵的每一行,生成包含各个实例的有三个特征的array。
        if listFromLine[-1] == 'didntLike':    #将类别表示成数字形式
            classLabelVector.append(1)
        elif listFromLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        elif listFromLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        index += 1
    return returnMat, classLabelVector
  • 对数据进行切分,划为训练集与数据集
  • 通过查看数据可以看出,数值差值很大的第一个特征对计算结果影响很大,需要进行标准化。
    40920 8.326976 0.953952 largeDoses
    14488 7.153469 1.673904 smallDoses
    26052 1.441871 0.805124 didntLike
    75136 13.147394 0.428964 didntLike
    38344 1.669788 0.134296 didntLike
    72993 10.141740 1.032955 didntLike
    35948 6.830792 1.213192 largeDoses
    42666 13.276369 0.543880 largeDoses
    67497 8.631577 0.749278 didntLike
  • 不进行标准化时进行分类,代码如下。
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn import preprocessing


X,y= file2matrix(r'D:data of MLdatingTestSet.txt')
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
knn = KNeighborsClassifier()
knn.fit(X_train,y_train)
y_pre = knn.predict(X_test)
score=knn.score(X_test,y_test,sample_weight=None)
print(score)
  • 此时分类精度为77.5%。可以看出明显效果不是很好,因为第一个特征数值差值较大,基本对距离度量起到了主导作用,从而影响分类结果。下面加入标准化代码,进行分类
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn import preprocessing

X,y= file2matrix(r'D:data of MLdatingTestSet.txt')
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 对实例各个特征进行标准化
min_max_scaler = preprocessing.MinMaxScaler()
X_train_minmax = min_max_scaler.fit_transform(X_train)
X_test_minmax = min_max_scaler.transform(X_test)
knn = KNeighborsClassifier()
knn.fit(X_train_minmax,y_train)
y_pre = knn.predict(X_test_minmax)
score=knn.score(X_test_minmax,y_test,sample_weight=None)
print(score)
  • 此时精度达到了97.6%。明显分类效果较好。

二 sklearn中KNN分类器参数与方法

  • class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights=’uniform’, algorithm=’auto’, leaf_size=30, p=2, metric=’minkowski’, metric_params=None, n_jobs=1, **kwargs)
  • n_neighbors:即k的取值
  • weights:默认是uniform,参数可以是uniform、distance,或用户自己定义的函数。uniform是均等的权重,所有的邻近点的权重都是相等的。distance是不均等的权重,距离近的点比距离远的点影响大。用户自定义的函数,接收距离的数组,返回一组维数相同的权重。
  • algorithm:选取k个最近点的算法选择。 ‘ball_tree’ 选择球树 ;‘kd_tree’ 选择 KDTree ; ‘brute’ 暴力搜索; ‘auto‘默认选项,自动选择。
  • leaf_size:只有ball_tree和kd_tree才有必要
  • p与metric:距离度量选择,p=1是曼哈顿距离,p=2是欧式距离。
  • 方法如下:
    机器学习:kNN算法(二)—— 实战:改进约会网站的配对效果

三 总结

优点:

  • 思想简单,理论成熟,既可以用来做分类也可以用来做回归;
  • 可用于非线性分类;
  • 训练时间复杂度为O(n);
  • 准确度高,对数据没有假设,对outlier不敏感;

缺点:

  • 需要计算比较较多的距离值(即使采用了kd树,球树等),计算量较大,比较耗时;
  • 样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
  • 必须保存全部数据集,当数据量很大时需要大量的存储空间;