Press "Enter" to skip to content

基于Wi-Fi指纹和深度神经网络的室内定位系统设计代码详解(二)

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

 

模型建立与训练

本次实验时使用的框架是keras,我们需要使用其中的“Sequential”构建模型。

 

然后定义输入层,利用循环根据输入参数定义隐藏层,最后定义输出层。

 

需要注意的是,这里使用的是全连接层,其中的激活函数是‘relu’,没有偏置。

 

然后使用输入优化器adam和损失函数mse对模型进行编译,最后对模型进行训练。需要注意的是,此时的输入和输出都是520维的Wi-Fi指纹数据,网络也是对称的结构,从而达到编码的目的(SAE)。

 

    # create a model based on stacked autoencoder (SAE)
    model = Sequential()
    model.add(Dense(sae_hidden_layers[0], name="sae-hidden-0", input_dim=INPUT_DIM, activation=SAE_ACTIVATION, use_bias=SAE_BIAS))
for i in range(1, len(sae_hidden_layers)):
        model.add(Dense(sae_hidden_layers[i], name="sae-hidden-"+str(i), activation=SAE_ACTIVATION, use_bias=SAE_BIAS))
    model.add(Dense(INPUT_DIM, name="sae-output", activation=SAE_ACTIVATION, use_bias=SAE_BIAS))
    model.compile(optimizer=SAE_OPTIMIZER, loss=SAE_LOSS)
# Show the structure of the model
    model.summary()
# train the model
    model.fit(x_train, x_train, batch_size=batch_size, epochs=epochs, verbose=VERBOSE)

 

假设我们使用默认参数,我们可以看到模型的结构如下,也可以看到输出的feature map大小。

 

例如,第一层的输出为(None, 256),其中None表示运行后的大小,网络模型中需要训练和更新的参数有348160个。

 

    ___________________________________________________________
    Layer (type)                 Output Shape           Param #   
    ===========================================================
    sae-hidden-0 (Dense)         (None, 256)            133120    
    ___________________________________________________________
    sae-hidden-1 (Dense)         (None, 128)            32768     
    ___________________________________________________________
    sae-hidden-2 (Dense)         (None, 64)             8192      
    ___________________________________________________________
    sae-hidden-3 (Dense)         (None, 128)            8192      
    ___________________________________________________________
    sae-hidden-4 (Dense)         (None, 256)            32768     
    ___________________________________________________________
    sae-output (Dense)           (None, 520)            133120    
    ===========================================================
    Total params: 348,160
    Trainable params: 348,160
    Non-trainable params: 0
    ___________________________________________________________

 

训练完成后,我们需要去掉SAE的解码器部分,添加分类器来估计建筑、楼层和位置。

删除解码器部分的代码如下所示。

 

    # remove the decoder part
    num_to_remove = (len(sae_hidden_layers) + 1) // 2
for i in range(num_to_remove):
        model.pop()

 

接着添加分类器。实验中,在使用上述编码器后,增加了激活函数为的全连接层,且无偏置,在每个全连接层后增加了dropout层,以防止模型过拟合。输出层也是全连接层,此时激活函数为无偏置。

 

然后使用输入优化器和损失函数编译模型,最后对模型进行训练。

 

需要注意的是这里使用了多标签分类器,结合sigmoid激活函数和二进制交叉熵损失来实现该方法。

 

此时输入520维Wi-Fi指纹,输出118维,其中0-2代表建筑物的标签,3-7代表楼层的标签,8-117代表位置的标签。

 

    model.add(Dropout(dropout))
for i in range(len(classifier_hidden_layers)):
        model.add(Dense(classifier_hidden_layers[i], name="classifier-hidden"+str(i), activation=CLASSIFIER_ACTIVATION, use_bias=CLASSIFIER_BIAS))
        model.add(Dropout(dropout))
    model.add(Dense(OUTPUT_DIM, name="activation-0", activation='sigmoid', use_bias=CLASSIFIER_BIAS))  # 'sigmoid' for multi-label classification
    model.compile(optimizer=CLASSIFIER_OPTIMIZER, loss=CLASSIFIER_LOSS, metrics=['accuracy'])
# Show the structure of the model
    model.summary()
# train the model
    startTime = timer()
    model.fit(x_train, y_train, validation_data=(x_val, y_val), batch_size=batch_size, epochs=epochs, verbose=VERBOSE)
    elapsedTime = timer() - startTime
    print("Model trained in %e s." % elapsedTime)

 

假设我们使用默认参数,我们可以看到模型的结构如下,也可以看到输出的特征图,网络模型中有213760个参数需要训练和更新。

 

    ___________________________________________________________
    Layer (type)                 Output Shape           Param #   
    ===========================================================
    sae-hidden-0 (Dense)         (None, 256)            133120    
    ___________________________________________________________
    sae-hidden-1 (Dense)         (None, 128)            32768     
    ___________________________________________________________
    sae-hidden-2 (Dense)         (None, 64)             8192      
    ___________________________________________________________
    dropout (Dropout)            (None, 64)             0         
    ___________________________________________________________
    classifier-hidden0 (Dense)   (None, 128)            8192      
    ___________________________________________________________
    dropout_1 (Dropout)          (None, 128)            0        
    ___________________________________________________________
    classifier-hidden1 (Dense)   (None, 128)            16384     
    ___________________________________________________________
    dropout_2 (Dropout)          (None, 128)            0         
    ___________________________________________________________
    activation-0 (Dense)         (None, 118)            15104     
    ===========================================================
    Total params: 213,760
    Trainable params: 213,760
    Non-trainable params: 0
    ___________________________________________________________  

 

模型预测与评估

 

建筑预测与评估

 

首先,我们需要使用函数,得到预测的多标签结果。然后取下前0-2个标签,表示建筑物的预测标签。

 

然后使用函数获取最大值的索引,即为预测的建筑。最后,计算所有建筑预测结果的准确率。

 

    preds = model.predict(test_AP_features, batch_size=batch_size)
    n_preds = preds.shape[0]
    blds_results = (np.equal(np.argmax(blds, axis=1), np.argmax(preds[:, :3], axis=1))).astype(int)
    acc_bld = blds_results.mean()

 

楼层预测与评估

 

对于楼层的预测结果,我们只需要取模型预测结果的3-7位的值,然后使用函数得到索引的最大值,最后我们可以得到楼层的结果,并计算所有楼层预测结果的准确率。

 

     flrs_results = (np.equal(np.argmax(flrs, axis=1), np.argmax(preds[:, 3:8], axis=1))).astype(int)
    acc_flr = flrs_results.mean()

 

建筑-楼层预测与评估

 

对于建筑-楼层的预测准确率,我们只需要将建筑和楼层的预测结果结合起来,就可以得到最终的结果。

 

 acc_bf = (blds_results*flrs_results).mean()

 

位置预测与评估

 

由于测试位置是一个任意的位置,可能与训练集中给出的位置不同,我们不能直接取最大值的索引作为预测的结果。

 

mask代表的是所有建筑-楼层都预测正确的索引,即mask是bool型的数组,预测正确的为TRUE。通过mask取出测试数据对应的真实的经纬度坐标,建筑和楼层,以及预测的参考点的标签。

 

    # calculate positioning error when building and floor are correctly estimated
    mask = np.logical_and(blds_results, flrs_results)  # mask index array for correct location of building and floor
    x_test_utm = x_test_utm[mask]
    y_test_utm = y_test_utm[mask]
    blds = blds[mask]
    flrs = flrs[mask]
    rfps = (preds[mask])[:, 8:118]

 

然后我们需要取出每个测试数据对应的预测参考点标签的最大的N个值。

 

通过变量计算预测参考点标签的阈值,即一个预测参考点标签的最大值乘为阈值,前N个值只有大于阈值才认为有效。

 

idxs是前N个值的索引,需要注意的是idxs的行数代表的是成功预测建筑-楼层的数量,列数代表前N个值的索引。

 

    n_success = len(blds)  # number of correct building and floor location
    n_loc_failure = 0
    sum_pos_err = 0.0
    sum_pos_err_weighted = 0.0
    idxs = np.argpartition(rfps, -N)[:, -N:]  # (unsorted) indexes of up to N nearest neighbors
    threshold = scaling*np.amax(rfps, axis=1)

 

对于每一个预测成功的建筑-楼层,取出预测参考点标签最大的前N个值,并且分别假设每一个值为最大值时对应的参考点标签,取出该建筑-楼层-参考点在对应的训练集中的经纬度坐标,即代表对应的预测经纬度值。当大于阈值时,则取出预测参考点对应的经纬度坐标,加入到,中,其本身的预测值加入到中。

 

    for i in range(n_success):
        xs = []
        ys = []
        ws = []
for j in idxs[i]:
            rfp = np.zeros(110)
            rfp[j] = 1
            rows = np.where((train_labels == np.concatenate((blds[i], flrs[i], rfp))).all(axis=1)) # tuple of row indexes
if rows[0].size > 0:
if rfps[i][j] >= threshold[i]:
                    xs.append(train_df.loc[train_df.index[rows[0][0]], 'LONGITUDE'])
                    ys.append(train_df.loc[train_df.index[rows[0][0]], 'LATITUDE'])
                    ws.append(rfps[i][j])

 

然后将每个测试Wi-Fi指纹预测的N个坐标取平均值(np.mean(xs)),即预测的坐标结果。平均位置误差表示为平均坐标与实际坐标之间的欧氏距离。

 

N个预测参考点坐标也被加权平均(以元素的值作为权重,np.mean(xs, weights=ws)),计算到真实坐标的欧氏距离作为加权平均位置误差。

 

对于定位失败的点,我们用当前楼层的平均坐标和实际坐标计算欧式距离作为误差。

 

最后,计算所有试验数据的平均位置误差(mean_pos_err)、加权平均位置误差(mean_pos_err _weighted)、正确预测建筑物和楼层时定位的失败率(loc_failure)。

 

    if len(xs) > 0:
        sum_pos_err += math.sqrt((np.mean(xs)-x_test_utm[i])**2 + (np.mean(ys)-y_test_utm[i])**2)
        sum_pos_err_weighted += math.sqrt((np.average(xs, weights=ws)-x_test_utm[i])**2 + (np.average(ys, weights=ws)-y_test_utm[i])**2)
else:
        n_loc_failure += 1
        key = str(np.argmax(blds[i])) + '-' + str(np.argmax(flrs[i]))
        pos_err = math.sqrt((x_avg[key]-x_test_utm[i])**2 + (y_avg[key]-y_test_utm[i])**2)
        sum_pos_err += pos_err
        sum_pos_err_weighted += pos_err
mean_pos_err = sum_pos_err / n_success
mean_pos_err_weighted = sum_pos_err_weighted / n_success
loc_failure = n_loc_failure / n_success # rate of location estimation failure given that building and floor are correctly located

 

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.

 

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注