1. 程式人生 > >室內定位系列(三)——位置指紋法的實現(KNN)

室內定位系列(三)——位置指紋法的實現(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$\times$1m的網格,每個網格是看作一個類別,用網格標號代替,對k個網格標號計數投票,選擇票數做多的網格作為定位結果。

kNN是一種lazy式的學習方法,在上面的過程中不需要使用訓練資料進行“學習”,在定位的時候直接在訓練資料中搜索就可以。一些工具包中的kNN演算法的訓練過程中會建立一個kd樹(一種資料結構),有利於線上預測時的搜尋。

具體實現

匯入資料

# 匯入資料
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/
關於作者:目前主要研究領域為機器學習與無線定位技術,歡迎討論與指正!
版權宣告:本文版權歸作者和部落格園共有,轉載請註明出處。

相關推薦

室內定位系列——位置指紋實現KNN

位置指紋法中最常用的演算法是k最近鄰(kNN):選取與當前RSS最鄰近的k個指紋的位置估計當前位置,簡單直觀有效。本文介紹kNN用於定位的基本原理與具體實現(matlab、python)。 基本原理 位置指紋法可以看作是分類或迴歸問題(特徵是RSS向量,標籤是位置),監督式機器學習方法可以從資料中訓練出一

室內定位系列——位置指紋實現測試各種機器學習分類器

位置指紋法中最常用的演算法是k最近鄰(kNN)。本文的目的學習一下python機器學習scikit-learn的使用,嘗試了各種常見的機器學習分類器,比較它們在位置指紋法中的定位效果。 匯入資料 # 匯入資料 import numpy as np import scipy.io as scio offl

室內定位系列——WiFi位置指紋

目錄 摘要 GPS難以解決室內環境下的一些定位問題,大部分室內環境下都存在WiFi,因此利用WiFi進行定位無需額外部署硬體裝置,是一個非常節省成本的方法。然而WiFi並不是專門為定位而設計的,傳統的基於時間和角度的定位方法並不適用於WiFi。近十年來,在室內WiFi場景下的定位中,位置指紋法被廣泛研究

室內定位系列——目標跟蹤粒子濾波

進行目標跟蹤時,先驗知識告訴我們定位軌跡是平滑的,目標當前時刻的狀態與上一時刻的狀態有關,濾波方法可以將這些先驗知識考慮進來得到更準確的定位軌跡。本文簡單介紹粒子濾波及其使用,接著卡爾曼濾波寫,建議先閱讀室內定位系列(五)——目標跟蹤(卡爾曼濾波)。 原理 這裡跟卡爾曼濾波進行對比來理解粒子濾波。 目標

室內定位系列——模擬獲取RSS資料

很多情況下大家都採用實際測量的資料進行定位演算法的效能分析和驗證,但是實際測量的工作量太大、資料不全面、靈活性較小,採用模擬的方法獲取RSS資料是另一種可供選擇的方式。本文介紹射線跟蹤技術的基本原理,以及如何得到用於定位模擬的RSS資料。在此基礎上得到位置指紋庫與一組測試資料,用於以後定位演算法的驗證。(本

室內定位系列——目標跟蹤卡爾曼濾波

進行目標跟蹤時,先驗知識告訴我們定位軌跡是平滑的,目標當前時刻的狀態與上一時刻的狀態有關,濾波方法可以將這些先驗知識考慮進來得到更準確的定位軌跡。本文簡單介紹卡爾曼濾波及其使用。 原理 這裡僅從目標定位跟蹤的角度做一個簡化版的介紹。 定位跟蹤時,可以通過某種定位技術(比如位置指紋法)得到一個位置估計(

Python培訓知識總結系列- 第章 Python3文件操作

readline new socket 總結 排序 tin strip() list 是否 open 123456789f = open(‘filename‘,‘r‘) # 讀模式f = open(‘filename‘,‘w‘) # 寫模式f = open(‘filenam

充值系列——充值系統業務邏輯層實現

上一篇文章主要說明充值的執行邏輯和控制層的設計,這篇文章主要討論充值業務層的具體實現。 正如上一篇文章所說到的,生成訂單需要如下幾個步驟: (1)例項化操作人 (操作人) (2)例項化產品模型 (獲取產品的詳細資訊) (3)例項化訂單模型 (生成一筆狀態為“交易中”的訂單)

python教程系列.2.1、time&Calendar模組

在Python中,通常有這幾種方式來表示時間: 時間戳(timestamp):通常來說,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。我們執行“type(time.time())”,返回的是float型別。 格式化的時間字串(Format S

江西偉人系列篇:唐宋八大家歐陽修

青春 logs body 指導 文學家 分享 itl 1年 html 歐陽修(1007年8月1日-1072年9月22日),字永叔,號醉翁,晚號六一居士, 漢族,吉州永豐(今江西省吉安市永豐縣)人,北宋政治家、文學家,且在政治上負有盛名。因吉州原屬廬陵郡,以“

JavaScript、DOM文檔對象模型

文檔 mod 允許 ima ges 所有 以及 修改 聯盟 一、什麽是DOM DOM 是 Document Object Model(文檔對象模型)的縮寫。 DOM 是 W3C(萬維網聯盟)的標準。 DOM 定義了訪問 HTML 和 XML 文檔的標準: “W3C 文檔對象

快速排序數中值

package sort; public class QuickSort {//快速排序 public static void main(String[] args) { int[] array = {39,44,1,0,8,66,23,67,9,15,100,70,22,3,6,54

【隨堂筆記】unity中socket用法,伺服器端執行緒的使用

手機專案,最好不要使用執行緒,因為unity專門提供了協程,枝執行緒不能訪問主執行緒(ui) 手機使用執行緒,容易導致硬體出問題 執行緒測試程式碼 /// <summary> /// 執行緒的測試方法 /// </summary>

Java中List集合的遍歷種遍歷方式效率的比較

public static void main(String args[]){ compare(); } public static void compare() { List<String> list = new ArrayList

Windows下AirSIM的環境搭建、Build Unity示例專案及資源

文章目錄 Unity Build Windridge City 示例專案 Usage Operation 事實上,在原始碼裡,我沒找到怎麼控制無人機,這裡暫時留個坑不填,需要準備一下畢業開題的事情

Python求最長迴文字串重迴圈遍歷所有字串 新

前兩天自己寫了下,雖然對了,但是思路不太好,網上看了遍歷的思路,瞬間感覺之前好蠢,雖然本質上我的程式碼也是遍歷,但是思路不好。 正確思路就是先遍歷出所有長度大於等於2的字串,然後在逐一判斷這些字串是不是迴文字串就行了,思路清晰了,程式碼就簡單多了,10分鐘就寫完了。 d

資料結構篇:校園最短路徑導航:地圖影象顯示以及完整程式

首先是地圖的顯示,因為控制檯限制,只能通過外部程式來顯示圖片 如果你使用的是VC6.0或者Dev C++將準備好的圖片放在工程根目錄,命名為SchoolMap.png 如果有小夥伴和我一樣使用的是CLion的話,就把圖片放到cmake-build-debug下面 ) 在ma

MySQL學習、分組查詢和多表查詢

一、分組查詢1.MySQL查詢函式    函式的分類:    1,單行函式:將每條資料進行獨立的計算,然後每條資料得到一條結果。    2,多行函式:多條資料同時計算,最終得到一條結果資料。也成為聚集函式、分組函式, 主要用於完成一些統計功能。2.什麼是分組?    針對於班

種簡單排序的實現氣泡排序,選擇排序,插入排序

氣泡排序: public static void main(String[] args) { int[] a = {1, 7, 4, 3, 8, 2, 9, 6, 5}; for(int j = a.length; j > 0; j--

Nested loops、Hash join、Sort merge join種連線型別原理、使用要點

nested loop 巢狀迴圈(原理): oracle從較小結果集(驅動表、也可以被稱為outer)中讀取一行,然後和較大結果集(被偵查表,也可以叫做inner)中的所有資料逐條進行比較(也是等值連線,也可以是非等值連線),如果符合規則,就放在結果集中,然後取驅動表的下一