室内定位——位置指纹法(KNN、WKNN)

一、KNN算法

位置指纹法中最常用的算法是k最近邻(kNN):选取与当前RSS最邻近的k个指纹的位置估计当前位置,简单直观有效。

基本原理

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

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

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

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

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

具体实现(python)

回归(RSS向量+坐标):

import numpy as np
import time
start_time = time.time()
## 准备数据
train_data = train_arr3[:,0:(train_arr3.shape[1]-2)]
train_crd = train_arr3[:,(train_arr3.shape[1]-2):train_arr3.shape[1]]
test_data = test_arr3[:,0:(test_arr3.shape[1]-2)]
test_crd = test_arr3[:,(test_arr3.shape[1]-2):test_arr3.shape[1]]
## 2.定义准确度函数
def getAccuracy(pred_crd,test_crd):
    return np.mean(np.sqrt(np.sum((pred_crd-test_crd)**2,1)))
## 3.导入KNN模块
from sklearn.neighbors import KNeighborsRegressor
knn = KNeighborsRegressor(4, weights='uniform', metric='euclidean')
%time knn.fit(train_data, train_crd)
%time pred_crd = knn.predict(test_data)
accuracy = getAccuracy(pred_crd, test_crd)
print("accuracy: ", accuracy, "m")
print("--- Run time: %s mins ---" % np.round(((time.time() - start_time)/60),4))

分类(RSS向量+标签):

import numpy as np
import time
start_time = time.time()
## 准备数据
train_data = train_arr3[:,0:(train_arr3.shape[1]-2)]
train_label = train_arr3[:,train_arr3.shape[1]]
test_data = test_arr3[:,0:(test_arr3.shape[1]-2)]
test_label = test_arr3[:,test_arr3.shape[1]]
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(4, weights='uniform', metric='euclidean')
%time knn.fit(train_data, train_label)
%time pred_label = knn.predict(test_data)
sum = 0
for a, y in zip(pred_label, test_label.ravel()):
    if a == y:
        sum = sum + 1
print ("%s of %s test values correct.\ntest accuracy: %f" % (sum, len(test_label.ravel()), sum / len(test_label.ravel())))
print("test time:",round(time.time() - start_time, 3), "s")

二、WKNN算法(回归)

import pandas as pd
import numpy as np
import operator
##导入原始数据
train_file = pd.read_csv('E:\\wifi定位数据集\\library dataset\\dataset_all\\04\\train_floor3.csv',header=None)
test_file = pd.read_csv('E:\\wifi定位数据集\\library dataset\\dataset_all\\04\\test_floor3.csv',header=None)
train_file.replace(-105,-100,inplace=True)         # 缺失值用-100替换
test_file.replace(-105,-100,inplace=True)
train_arr0 = train_file.iloc[:,0:622].values        # DataFrame 转换成 array
test_arr0 = test_file.iloc[:,0:622].values
##1.定义计算欧式距离的函数
def euclideanDistance(instance1,instance2,length):
    dis0 = 0
    for i in range(0,length):
        dis0 += (instance1[i]-instance2[i])**2
    return dis0**0.5
##2.计算测试点到所有RP距离的函数,并取距离最小的K个
def getNeighbors(trainSet,testPoint,k):
    distance = []
    length = len(testPoint)-2
    for i in range(0,len(trainSet)):
        dis1 = euclideanDistance(testPoint,trainSet[i],length)
        distance.append((trainSet[i],dis1))
    distance.sort(key = operator.itemgetter(1))      ## 对距离按照第二个域排序
    neighbors = []
    for j in range(0,k):
        neighbors.append(distance[j])
    return neighbors
##3.计算KRP坐标的加权平均值
def getResponse(neighbors):
    add_weight = 0
    crd = 0
    for i in range(0,len(neighbors)):
        add_weight += 1/neighbors[i][1] 
    for j in range(0,len(neighbors)):
        crd += (neighbors[j][0][97:99]/neighbors[j][1])/add_weight
    return crd
##4.定义准确度的函数
def getAccuracy(pred_crd,test_crd):
    return np.mean(np.sqrt(np.sum((pred_crd-test_crd)**2,1)))
##5.主函数
train_file = train_arr0[:,0:620]
test_file = test_arr0[:,0:620]
test_crd = test_arr0[:,620:622]
k = 4
pred_crd = []
for i in range(0,len(test_file)):
    neighbors = getNeighbors(train_file, test_file[i], k)
    crd = getResponse(neighbors)
    pred_crd.append(crd)
accuracy = getAccuracy(pred_crd,test_crd)
print("accuracy:" + repr(accuracy) + "m")               ## print()内输出的内容格式必须一致
print("--- Run time: %s mins ---" % np.round(((time.time() - start_time)/60),4))

参考:http://www.indoorpress.com/shi-nei-ding-wei-4247.html

室内定位RSS(Received Signal Strength)位置指纹是一种常用的室内定位技术,它通过收集已知位置的Wi-Fi信号强度(RSS)数据来建立位置指纹数据库,并根据当前位置附近的Wi-Fi信号强度来进行定位。而KNN(K-Nearest Neighbors)是一种基本的分类算,可用于室内定位中的位置指纹匹配。 首先,我们需要收集一定数量的RSS位置指纹数据。这些数据包括Wi-Fi信号的MAC地址和对应的RSS值,并记录其所在的物理位置。收集完数据后,我们将其存储在数据库中。 在进行定位时,首先收集当前位置附近的Wi-Fi信号的RSS值,并提取出MAC地址。然后,从之前建立的位置指纹数据库中找出K个最相似的位置指纹数据。这里的相似度一般使用欧氏距离或余弦相似度来计算。 对于这K个最相似的位置指纹数据,我们可以采用加权平均来进行定位。即根据它们与当前位置指纹数据的相似度,对它们的物理位置进行加权平均。加权平均的权重可以由相似度计算得出。 最后,根据加权平均得到的物理位置,就可以实现室内定位。 需要注意的是,室内定位RSS位置指纹-KNN在实际应用时也面临一些问题。例如,Wi-Fi信号受到物理环境干扰的影响,如墙壁、家具等会减弱信号强度。此外,Wi-Fi信号的分布和传播并不均匀,也会导致定位的偏差。因此,在实际应用中,我们需要综合考虑这些问题,采用更加复杂的算和技术来提高室内定位的准确度和稳定性。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值