KNN算法的实现

Posted zhangyafei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KNN算法的实现相关的知识,希望对你有一定的参考价值。

K近邻(KNN)算法简介

  KNN是通过测量不同特征值之间的距离进行分类。它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别,其中K通常是不大于20的整数。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。

     下面通过一个简单的例子说明一下:如下图,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。

                      技术分享图片

由此也说明了KNN算法的结果很大程度取决于K的选择。

     在KNN中,通过计算对象间距离来作为各个对象之间的非相似性指标,避免了对象之间的匹配问题,在这里距离一般使用欧氏距离或曼哈顿距离:

                      技术分享图片

同时,KNN通过依据k个对象中占优的类别进行决策,而不是单一的对象类别决策。这两点就是KNN算法的优势。

   接下来对KNN算法的思想总结一下:就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类,其算法的描述为:

1)计算测试数据与各个训练数据之间的距离;

2)按照距离的递增关系进行排序;

3)选取距离最小的K个点;

4)确定前K个点所在类别的出现频率;

5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

Python实现

 

技术分享图片
import pandas as pddef maxminNormalization(data):
  """标准化
  data = (data - data.mean) / data.std
  :return data
  """
    mean_vals = data.mean(axis=0)
    std_val = data.std(axis=0)
    data = (data - mean_vals) / std_val
    return data


class KNN():
    def __init__(self,k=1):
        self.k = k

    def fit(self,x_train,y_train):
        self.x_train = x_train
        self.y_train = y_train

    def predict(self,x_test):
        dis_squar = (x_train - x_test)**2
        dis_squar_sum = dis_squar.sum(axis=1)
        distances = dis_squar_sum**0.5
        sortedIndics = distances.argsort()
        indices = sortedIndics[:self.k]
        labelCount = {}  # 存储每个label的出现次数
        for i in indices:
            label = self.y_train[i]
            labelCount[label] = labelCount.get(label, 0) + 1  # 次数加一
        # 排序方式一
        # sortedCount = list(zip(labelCount.values(),labelCount.keys()))
        # 对label出现的次数从大到小进行排序
        # sortedCount.sort()
        # return sortedCount[0][1]  # 返回出现次数最大的label
        # 排序方式二
        sortedCount = sorted(labelCount.items(), key=lambda k:k[1], reverse=True)
        return sortedCount[0][0]  # 返回出现次数最大的label


if __name__ == __main__:
    # data = np.arange(24).reshape(4,6)
    train = pd.DataFrame({age:[23,33,45],income:[5000,12000,13000],work:[1,2,3]})
    test = pd.DataFrame({age:[22,30,40],income:[9000,13000,14000],work:[2,1,2]})
    x_train = maxminNormalization(train[[age,work]])
    y_train = train[income]
    x_test = maxminNormalization(test[[age,work]])
    y_test = test[income]
    knn = KNN()
    knn.fit(x_train,y_train)
    y_predict = knn.predict(x_test)
    print(y_predict)
底层代码实现

 

技术分享图片
from sklearn.datasets import load_iris,fetch_20newsgroups,load_boston
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
import pandas as pd
from sklearn.metrics import classification_report

def knncls():
    """
    k-近邻预测用户签到位置
    :return None
    """
    #读取数据
    data = pd.read_csv(./data/FBlocation/train.csv)
    print(data.head(10))

    #处理数据
    #1.缩小数据,查询数据筛选
    data = data.query(x>1.0 & x<1.25 & y>2.5 & y<2.75)

    #处理时间的数据
    time_value = pd.to_datetime(data.time,unit=s)
    print(time_value)

    #把日期格式转化为字典参数
    time_value = pd.DatetimeIndex(time_value)

    #构造一些特征
    data.loc[:,day] = time_value.day
    data.loc[:,hour] = time_value.hour
    data.loc[:,weekday] = time_value.weekday

    #时间戳特征删除
    data.drop([time],axis=1)
    print(data)

    #把签到数量少于n个目标位置删除
    place_count = data.groupby(place_id).aggregate(np.count_nonzero)
    tf = place_count[place_count.row_id > 3].reset_index()
    data = data[data[place_id].isin(tf.place_id)]

    # 2.4 清理无效特征
    data = data.drop([row_id], axis=1)
    data = data.drop([accuracy], axis=1)

    #取出数据当中的特征值和目标值
    y = data[place_id]
    x = data.drop([place_id],axis=1)

    #进行数据的分割 训练集和测试集
    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)

    #特征工程(标准化)
    std = StandardScaler()

    #对训练集和测试机的特征值进行标准化
    x_train = std.fit_transform(x_train)
    x_test = std.fit_transform(x_test)

    #特征工程(‘标准化‘)

    #进行算法流程  #超参数
    knn = KNeighborsClassifier()
    # # fit,perdict,score
    # knn.fit(x_train,y_train)
    #
    # #得到预测结果
    # y_predict = knn.predict(x_test)
    # print(‘预测的目标签到位置为:‘,y_predict)
    # # #得到准确率
    # print(‘预测的准确率:‘,knn.score(x_test,y_test))

    #构造一些参数的值进行搜索
    param = {n_neighbors:[3,5,10]}

    gc = GridSearchCV(knn,param_grid=param,cv=2)
    gc.fit(x_train,y_train)

    #预测准确率
    print(在测试集上的准确率:,gc.score(x_test,y_test))

    print(在交叉验证中最好的结果:,gc.best_score_)
    print(选择最好的模型是:,gc.best_estimator_)
    print(每个超参数每次交叉验证的结果:,gc.cv_results_)

    return None


def knncls_iris():
    li = load_iris()

    x_train,x_test,y_train,y_test = train_test_split(li.data,li.target,test_size=0.25)
    """
    knn = KNeighborsClassifier(n_neighbors=5)
    knn.fit(x_train,y_train)
    y_predict = knn.predict(x_test)
    print(‘鸢尾花种类预测值为:‘,y_predict)
    print(‘准确率为:‘,knn.score(x_test,y_test))
    print(‘每个分类的精确率和召回率是:‘,classification_report(y_test,y_predict,target_names=li.target_names))
    """
    #模型选择与调优
    knn = KNeighborsClassifier()
    param = {n_neighbors:[3,5,10]}
    gc = GridSearchCV(knn,param_grid=param,cv=10)
    gc.fit(x_train,y_train)

    print(在测试集中的准确率:,gc.score(x_test,y_test))
    print(在交叉验证中的最好的结果:,gc.best_score_)
    print(最好的模型是:,gc.best_estimator_)
    print(每个超参数每次交叉验证的结果:,gc.cv_results_)


if __name__ == __main__:
    # knncls()
    knncls_iris()
sklearn实现

 

以上是关于KNN算法的实现的主要内容,如果未能解决你的问题,请参考以下文章

python实现简单knn算法

数据挖掘——KNN算法的实现

自己实现的简易的knn算法

2. KNN和KdTree算法实现

Python实现KNN算法

机器学习实战笔记(Python实现)-01-K近邻算法(KNN)