• 室内定位系列(三)——位置指纹法的实现(KNN)


    位置指纹法中最常用的算法是k最近邻(kNN):选取与当前RSS最邻近的k个指纹的位置估计当前位置,简单直观有效。本文介绍kNN用于定位的基本原理与具体实现(matlab、python)。

    基本原理

    位置指纹法可以看作是分类或回归问题(特征是RSS向量,标签是位置),监督式机器学习方法可以从数据中训练出一个从特征到标签的映射关系模型。kNN是一种很简单的监督式机器学习算法,可以用来做分类或回归。

    对于在线RSS向量(s),分别计算它与指纹库中各个RSS向量{(s_1, s_2, ..., s_M)}的距离(比如欧氏距离),选取最近的(k)个位置指纹(一个指纹是一个RSS向量与一个位置的对应)。

    • 对于knn回归,标签是坐标x和坐标y,可以进行数值计算,使用这k个指纹的位置坐标取平均,得到作为定位结果。

    • 对于knn分类,将定位区域划分为1m$ imes$1m的网格,每个网格是看作一个类别,用网格标号代替,对k个网格标号计数投票,选择票数做多的网格作为定位结果。

    kNN是一种lazy式的学习方法,在上面的过程中不需要使用训练数据进行“学习”,在定位的时候直接在训练数据中搜索就可以。一些工具包中的kNN算法的训练过程中会建立一个kd树(一种数据结构),有利于在线预测时的搜索。


    具体实现

    Github地址,包括matlab版本和python版本
    数据来源说明:http://www.cnblogs.com/rubbninja/p/6118430.html

    导入数据

    # 导入数据
    import numpy as np
    import scipy.io as scio
    offline_data = scio.loadmat('offline_data_random.mat')
    online_data = scio.loadmat('online_data.mat')
    offline_location, offline_rss = offline_data['offline_location'], offline_data['offline_rss']
    trace, rss = online_data['trace'][0:1000, :], online_data['rss'][0:1000, :]
    del offline_data
    del online_data
    
    # 定位准确度
    def accuracy(predictions, labels):
        return np.mean(np.sqrt(np.sum((predictions - labels)**2, 1)))
    

    knn回归

    # knn回归
    from sklearn import neighbors
    knn_reg = neighbors.KNeighborsRegressor(40, weights='uniform', metric='euclidean')
    predictions = knn_reg.fit(offline_rss, offline_location).predict(rss)
    acc = accuracy(predictions, trace)
    print "accuracy: ", acc/100, "m"
    
    accuracy:  2.24421479398 m
    

    knn分类

    # knn分类,需要把坐标转换成网格标号,预测后将网格标号转换为坐标
    labels = np.round(offline_location[:, 0]/100.0) * 100 + np.round(offline_location[:, 1]/100.0)
    from sklearn import neighbors
    knn_cls = neighbors.KNeighborsClassifier(n_neighbors=40, weights='uniform', metric='euclidean')
    predict_labels = knn_cls.fit(offline_rss, labels).predict(rss)
    x = np.floor(predict_labels/100.0)
    y = predict_labels - x * 100
    predictions = np.column_stack((x, y)) * 100
    acc = accuracy(predictions, trace)
    print "accuracy: ", acc/100, 'm'
    
    accuracy:  2.73213398632 m
    

    定位算法分析

    加入数据预处理和交叉验证

    # 预处理,标准化数据(其实RSS数据还算正常,不预处理应该也无所谓,特征选择什么的也都不需要)
    from sklearn.preprocessing import StandardScaler
    standard_scaler = StandardScaler().fit(offline_rss)
    X_train = standard_scaler.transform(offline_rss)
    Y_train = offline_location
    X_test = standard_scaler.transform(rss)
    Y_test = trace
    
    # 交叉验证,在knn里用来选择最优的超参数k
    from sklearn.model_selection import GridSearchCV
    from sklearn import neighbors
    parameters = {'n_neighbors':range(1, 50)}
    knn_reg = neighbors.KNeighborsRegressor(weights='uniform', metric='euclidean')
    clf = GridSearchCV(knn_reg, parameters)
    clf.fit(offline_rss, offline_location)
    scores = clf.cv_results_['mean_test_score']
    k = np.argmax(scores) #选择score最大的k
    
    # 绘制超参数k与score的关系曲线
    import matplotlib.pyplot as plt
    %matplotlib inline
    plt.plot(range(1, scores.shape[0] + 1), scores, '-o', linewidth=2.0)
    plt.xlabel("k")
    plt.ylabel("score")
    plt.grid(True)
    plt.show()
    

    png

    # 使用最优的k做knn回归
    knn_reg = neighbors.KNeighborsRegressor(n_neighbors=k, weights='uniform', metric='euclidean')
    predictions = knn_reg.fit(offline_rss, offline_location).predict(rss)
    acc = accuracy(predictions, trace)
    print "accuracy: ", acc/100, "m"
    
    accuracy:  2.22455511073 m
    
    # 训练数据量与accuracy
    k = 29
    data_num = range(100, 30000, 300)
    acc = []
    for i in data_num:
        knn_reg = neighbors.KNeighborsRegressor(n_neighbors=k, weights='uniform', metric='euclidean')
        predictions = knn_reg.fit(offline_rss[:i, :], offline_location[:i, :]).predict(rss)
        acc.append(accuracy(predictions, trace) / 100)
    
    # 绘制训练数据量与accuracy的曲线
    import matplotlib.pyplot as plt
    %matplotlib inline
    plt.plot(data_num, acc, '-o', linewidth=2.0)
    plt.xlabel("data number")
    plt.ylabel("accuracy (m)")
    plt.grid(True)
    plt.show()
    

    png


    作者:[rubbninja](http://www.cnblogs.com/rubbninja/) 出处:[http://www.cnblogs.com/rubbninja/](http://www.cnblogs.com/rubbninja/) 关于作者:目前主要研究领域为机器学习与无线定位技术,欢迎讨论与指正! 版权声明:本文版权归作者和博客园共有,转载请注明出处。
  • 相关阅读:
    19. vue的原理
    18.jwt加密
    17.vue移动端项目二
    16.vue-cli跨域,swiper,移动端项目
    15.vue动画& vuex
    14.vue路由&脚手架
    13.vue组件
    12.vue属性.监听.组件
    11.vue 数据交互
    从尾到头打印链表
  • 原文地址:https://www.cnblogs.com/rubbninja/p/6134481.html
Copyright © 2020-2023  润新知