基于Wi-Fi指纹和深度神经网络的室内定位系统设计代码详解(一)
本文講解的代碼可在GitHub上獲取
https://github.com/kyeongsoo/can405_indoor_localization
首先我們需要知道為什么要通過WIFI指紋實現室內定位,這是因為衛星定位系統在室內環境或高層建筑密集地區無法檢測到衛星信號,無法滿足人們對定位精度的要求。而良好的網絡穩定性、高速高質量的數據傳輸,以及Wi-Fi通信模塊在智能移動終端上的廣泛應用,使得室內使用WIFI無線定位轉變成一種低成本和易于實現技術。
話不多說,下面直接開始講解代碼。本文主要講解如何預處理數據,數據集采用的UJIIndoorLoc dataset http://archive.ics.uci.edu/ml/datasets/UJIIndoorLoc
先定義訓練與驗證集的路徑變量
path_train = '../data/UJIIndoorLoc/trainingData2.csv' path_validation = '../data/UJIIndoorLoc/validationData2.csv'用函數pd.read_csv讀取數據,其中header=0代表第一行是標題行
train_df = pd.read_csv(path_train, header=0) test_df = pd.read_csv(path_validation, header=0)下面是讀取數據集的結果。我們可以看到,該數據庫包括19937條訓練數據和1111條測試數據,實驗中將原來的驗證集作為測試集。一共有520個不同的無線接入點(WAP),每個無線接入點對應的接收信號強度(RSSI)范圍從負整數-104dBm(極差信號)到0dBm。在本實驗中,為了便于后續歸一化,使用負值-110表示未檢測到WAP。除了520個WiFi指紋,529個屬性還包含其他指紋采集坐標和其他有用信息。
在本實驗中,除了使用520個WiFi指紋外,還需要使用6個屬性,即Longitude (-7695.9388~ -7299.7865),Latitude (4864745.7450~4865017.3647),Floor (建筑物內樓層的高度,整數(0 ~ 4)),BuildingID(三棟樓(0~2)),SpaceID(用于識別位置空間(辦公室、走廊、教室)的內部ID號,整數),RelativePosition(相對于位置空間的相對位置(1-門內,2-門外))。
train_dfWAP001 WAP002 WAP003 ... USERID PHONEID TIMESTAMP 0 -110 -110 -110 ... 2 23 1371713733 1 -110 -110 -110 ... 2 23 1371713691... ... ... ... ... ... ... 19935 -110 -110 -110 ... 18 10 1371711049 19936 -110 -110 -110 ... 18 10 1371711025[19937 rows x 529 columns]test_dfWAP001 WAP002 WAP003 ... USERID PHONEID TIMESTAMP 0 -110 -110 -110 ... 0 0 1380872703 1 -110 -110 -110 ... 0 13 1381155054... ... ... ... ... ... ... 1109 -110 -110 -110 ... 0 13 1381247807 1110 -110 -110 -110 ... 0 13 1381247836[1111 rows x 529 columns]然后取出所有樣本的520個WiFi指紋(train_AP_features),轉換為float類型數組,使用函數scalescalescale對數據進行預處理。需要注意的是,這里是對每一行的數據進行標準化處理。
在此之后,添加一個新的列,它是SpaceIDSpaceIDSpaceID和RelativePositionRelativePositionRelativePosition的組合,也就是字符串內容相加。進行這一步是因為我們后面要對樓層的參考點進行編號。將SpaceIDSpaceIDSpaceID和RelativePositionRelativePositionRelativePosition結合,也就是說訓練集數據中,在一個樓層里,我們將出現的不同參考點(SpaceIDSpaceIDSpaceID,RelativePositionRelativePositionRelativePosition)分別進行編號。
train_AP_features = scale(np.asarray(train_df.iloc[:,0:520]).astype(float), axis=1) # convert integer to float and scale jointly (axis=1)train_df['REFPOINT'] = train_df.apply(lambda row: str(int(row['SPACEID'])) + str(int(row['RELATIVEPOSITION'])), axis=1) # add a new columntrain_AP_features.shape(19937, 520)train_df['REFPOINT']0 10621 1062...19935 113219936 1122Name: REFPOINT, Length: 19937, dtype: object對于數據集中一共有幾棟樓,每一棟樓有幾個樓層,雖然我們可以直接在數據集的介紹中找到,但是我們一般還是選擇自己從數據集中獲取。np.unique函數是可以查找數組的唯一元素,因此我們可以通過該函數得到數據集中一共有三棟樓,五個樓層。
blds = np.unique(train_df[['BUILDINGID']])flrs = np.unique(train_df[['FLOOR']])bldsarray([0, 1, 2], dtype=int64)flrsarray([0, 1, 2, 3, 4], dtype=int64)下面的代碼是將參考點映射到每個樓層,這里用到了前面的REFPOINT,即每個樓層的不同參考點用不同的id標記。然后計算各樓層的平均坐標,留著后面使用。cond代表當前選擇的樓層,train_df.loc[cond,′REFPOINT′]train\_df.loc[cond, 'REFPOINT']train_df.loc[cond,′REFPOINT′]是選取當前樓層的所有參考點的值,此時得到的idx代表的就是該樓層每一個參考點編號后的id值。
x_avg = {}y_avg = {}for bld in blds:for flr in flrs:# map reference points to sequential IDs per building-floor before building labelscond = (train_df['BUILDINGID']==bld) & (train_df['FLOOR']==flr)_, idx = np.unique(train_df.loc[cond, 'REFPOINT'], return_inverse=True) # refer to numpy.unique manualtrain_df.loc[cond, 'REFPOINT'] = idx# calculate the average coordinates of each building/floorx_avg[str(bld) + '-' + str(flr)] = np.mean(train_df.loc[cond, 'LONGITUDE'])y_avg[str(bld) + '-' + str(flr)] = np.mean(train_df.loc[cond, 'LATITUDE']) train_df['REFPOINT']0 131 13..19935 1519936 13Name: REFPOINT, Length: 19937, dtype: objectx_avg{'0-0': -7640.376350991143, '0-1': -7637.829042353956, '0-2': -7639.023285886209, '0-3': -7640.245117900643, '0-4': nan, '1-0': -7463.825569651152, '1-1': -7511.07230214694, '1-2': -7486.581783868335, '1-3': -7492.579508808194, '1-4': nan, '2-0': -7352.32452951861, '2-1': -7351.31601971969, '2-2': -7347.406288310243, '2-3': -7360.208989855721, '2-4': -7357.458888837215}y_avg{'0-0': 4864957.721957975, '0-1': 4864957.706202937, '0-2': 4864958.364463876, '0-3': 4864956.533051689, '0-4': nan, '1-0': 4864874.372386921, '1-1': 4864893.299521635, '1-2': 4864878.546449652, '1-3': 4864892.971830967, '1-4': nan, '2-0': 4864818.793817714, '2-1': 4864816.715084595, '2-2': 4864820.8762252545, '2-3': 4864806.658757386, '2-4': 4864822.315012857}通過上述的操作,對于每一組數據,我們得到了520個WiFi指紋,標簽就是對應的建筑,樓層,參考點的三個id,我們可以看出這是一個多標簽的分類問題。對于建筑,樓層,參考點,我們可以分別采用pd.get_dummies得到對應的獨熱編碼,然后將其合并為118位的label,其中前三位是代表建筑,接著的五位代表樓層,后面的110位是參考點。所以對于所有訓練數據的label就是19937 x 118大小。
# build labels for multi-label classificationlen_train = len(train_df)blds_all = np.asarray(pd.get_dummies(pd.concat([train_df['BUILDINGID'], test_df['BUILDINGID']]))) # for consistency in one-hot encoding for both dataframesflrs_all = np.asarray(pd.get_dummies(pd.concat([train_df['FLOOR'], test_df['FLOOR']]))) # dittoblds = blds_all[:len_train]flrs = flrs_all[:len_train]rfps = np.asarray(pd.get_dummies(train_df['REFPOINT']))train_labels = np.concatenate((blds, flrs, rfps), axis=1)# labels is an array of 19937 x 118# - 3 for BUILDINGID# - 5 for FLOOR,# - 110 for REFPOINTOUTPUT_DIM = train_labels.shape[1] train_labelsarray([[0, 1, 0, ..., 0, 0, 0],[0, 1, 0, ..., 0, 0, 0],[0, 1, 0, ..., 0, 0, 0],...,[0, 1, 0, ..., 0, 0, 0],[0, 1, 0, ..., 0, 0, 0],[0, 1, 0, ..., 0, 0, 0]], dtype=uint8)train_labels.shape(19937, 118)然后我們將訓練集分為訓練集和驗證集,其中training_ratiotraining\_ratiotraining_ratio表示訓練數據與整體數據的比率,默認值為0.9。
# split the training set into training and validation setstrain_val_split = np.random.rand(len(train_AP_features)) < training_ratio # mask index arrayx_train = train_AP_features[train_val_split]y_train = train_labels[train_val_split]x_val = train_AP_features[~train_val_split]y_val = train_labels[~train_val_split] x_train.shape(17955, 520)y_train.shape(17955, 118)x_val.shape(1982, 520)y_val.shape(1982, 118)對于從文件中讀取的驗證集,本次實驗是將其作為測試集,對WiFi指紋數據也需要進行相應的標準化。
然后得到測試集中建筑和樓層的標簽,緯度和經度。
# turn the given validation set into a testing settest_AP_features = scale(np.asarray(test_df.iloc[:,0:520]).astype(float), axis=1) # convert integer to float and scale jointly (axis=1)x_test_utm = np.asarray(test_df['LONGITUDE'])y_test_utm = np.asarray(test_df['LATITUDE'])blds = blds_all[len_train:]flrs = flrs_all[len_train:]至此我們已經將數據處理完畢,得到了訓練集,驗證集,測試集。其中訓練集的WiFi指紋大小為(17955, 520),標簽大小為(17955, 118)。驗證集的WiFi指紋大小為(1982, 520),標簽大小為(1982, 118)。測試集的WiFi指紋大小為(1111, 520),因為要評估模型的性能,因此當測試時,我們對于預測得到的標簽通過訓練集轉換標簽的對應關系得到對應預測的建筑,樓層,參考點(可以對應到經緯度坐標)與真實的相比較,評估模型的性能。
ref
- D. Dua and C. Graff, “UCI machine learning repository,” 2017. [Online]. Available:http://archive.ics.uci.edu/ml
- K. S. Kim, S. Lee, and K. Huang, “A scalable deep neural network architecture for multi-building and multi-floor indoor localization based on wi-fi fingerprinting,” Big Data Analytics, vol. 3, no. 1, p. 4, 2018.
本文僅供參考, 若有錯誤, 歡迎指出, 共同學習
歡迎關注 小玉lab 公眾號
總結
以上是生活随笔為你收集整理的基于Wi-Fi指纹和深度神经网络的室内定位系统设计代码详解(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux基础命令必知必会
- 下一篇: 量子计算机ai出现意识,人工智能到底会不