WIFI定位实验K近邻算法 C# Python混合实现

前言

学校布置了WIFI室内定位相关作业,在网上查资料时候发现和自己有所了解的Python机器学习不谋而合。
网上很多介绍关于KNN最近邻Python机器学习的算法,但没有一个综合的解决方案,在篇文章意在记录与分享。谢谢大家了😊在这里求求一个赞!这对我真的很重要!❤️
实验中我负责的是上位机相关的开发 关于RSSI安卓开发可以参考其他程序。Android端可以通过/bin文件夹下offlinedatebase.txt进行操作 实现对接。

一、前期准备

Python对于深度学习可谓是轻车熟路,有很多相关的类可以进行机器学习。通过学习不同的视频与文章。还是选择了B站UP主帅器学习的视频为模板进行“二创” 加入C#进行可显示操作的Windows窗体工程。
代码主要会分为两块 : Python深度学习和C#窗口工程开发 并有一丢丢批处理文件(不足挂齿)
视频链接:https://www.bilibili.com/video/BV1L4411c7XF?p=6&spm_id_from=333.880.my_history.page.click

开发环境:

Visual Studio 2022 C# 窗体应用
Pycharm python 3.9环境

二、Python KNN深度学习 算法

1.库引用

引用 pandas标准化数据 尽量取消数据大小带来的差值
引用numpy进行txt文本处理 导入程序并处理
引用sklearn sklearn为深度学习模型 是一个python自带库可以直接引用 非常方便 用于处理一些小型的深度学习算法

代码显示如下:

import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn import metrics

附录:训练数据

训练数据

2.读入数据

在训练数据中 1-98表示进入模型训练的点,而99则表示“未知” 即我们所求的位置
相关代码:

#导入数据集 读进data.txt文件中的内容 间隔符为一个TAB
train_set = pd.read_csv('offlinedatebase.txt',sep = '\t')

由当前文件夹下的offlinedatebase.txt导入数据

3.预处理数据

#对数据进行分类 截提取数据特征
train = pd.concat([train_set['RSSI1'], train_set['RSSI2'], train_set['RSSI3'], train_set['RSSI4']],axis = 1)
#将特征数据转化成数组形式
train = np.array(train)
#将特征数据转标准化 train 储存特征
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
train = scaler.fit_transform(train)
print(train)
#将类别标签存入数组label
label = np.array(train_set['Label'])

我们首先将所有数据分成两部分
①标签部分(label)
②数据部分(RSSI 1~~4)并将这部分数据进行“训练模型标准化”(同时将未知的RSSI和训练数据一起标准化 确保模型训练后的结果准确性)
由于咱们的99位置位置也在数据部分中 我们需要把它们过滤出来⬇️

#将所求强度label与训练数据分离
ls = list(label)
for i in range(len(ls)):
    if label[i] == 99:
        del ls[i]
print(ls)
label = np.array(ls)
print(label)

过滤label 99 数据储存为numpy.array类型的数据 等待处理

#将所求强度 与训练数据分离
len_train = len(train)
X_exam = train[len_train-1,:]
X_exam_r = X_exam.reshape(1,4)
print(X_exam_r)
f_train = np.delete(train,len_train-1,0)
train = f_train

过滤RSSI数据 将最后一行的位置RSSI数据提取并保存 为X_exam_r
另一部分是要发送到模型学习的训练数据

三、Sklearn算法 创建模型

数据模型

1.调整模型参数

#分割数据集 既要测试既要模型 比率为0.9 0.1(可调)
X_train,X_test,y_train,y_test = train_test_split(f_train,label,train_size = 0.9,random_state=1)
#创建模型,放入训练数据 在这里 KNN 算法临近值设为5 关键参数为distance距离 根据场景不同可以适量调节
knn = KNeighborsClassifier(n_neighbors=5,weights = 'distance')
knn.fit(X_train,y_train)
#训练KNN算法模型 
y_pred = knn.predict(X_test)#测试
print('model accuracy:',metrics.accuracy_score(y_test,y_pred))
print('数据训练完毕')

应用Sklearn算法模型 因为既要兼顾 训练 与 测试 我们将训练数据分为 90%训练 10%测试
KNN 算法距离设为5 关键参数为distance距离

2.训练模型

可根据场景调整

ans = knn.predict(X_exam_r)
strans = str(ans)
strans = strans[1]
print(f"点的位置是{strans}")

3.为C#窗口应用铺路

将 位置的点送入 训练好的KNN算法模型 得到ANS

with open('ans.txt','w') as fff :
    fff.write(str(ans))
with open('model accuracy.txt','w') as ggg:
    ggg.write(str(metrics.accuracy_score(y_test,y_pred)))
# 按行读入,删除最后一行
file_old = open('offlinedatebase.txt', 'r', encoding="utf-8")
lines = [i for i in file_old]
del lines[-1]
file_old.close()
# 再覆盖写入
file_new = open('offlinedatebase.txt', 'w', encoding="utf-8")
file_new .write(''.join(lines))
file_new .close()

将ans答案写入ans.txt文本中存储
将model accuracy算法准确度
编辑offlinedatebase.txt将最后一行未知位置删除 保持数据库干净

三、C#窗口应用

窗口做的比较简朴 后续会对UI优化
预计增加TABLE可视化数据

UI界面

1.引用命名空间

using System;
using System.IO;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

2.框体设计

保持设计完整性 解释性代码作为注释写在程序中

namespace KNN_WindowsForm
{
    public partial class KNN : Form
    {
        //标题格式
        public static string beginning = "Label\tRSSI1\tRSSI2\tRSSI3\tRSSI4\t\n";
        class FileWriteAndOutput
        {
            //文件初始化函数
            public void FileWhitePaper()
            {
                StreamWriter sw = File.AppendText("offlinedatebase.txt");
                sw.Close();
                File.Delete("offlinedatebase.txt");
                FileStream F = File.Create("offlinedatebase.txt");
                F.Close();
                System.IO.File.WriteAllText("offlinedatebase.txt", beginning);
                sw = File.AppendText("offlinedatebase.txt");
                sw.Close();

            }
            //文件写入函数
            public void FileWrite(string n)
            {
                StreamWriter sw = File.AppendText("offlinedatebase.txt");
                sw.Close();
                sw = File.AppendText("offlinedatebase.txt");
                sw.WriteLine(n);
                sw.Close();
            }
            //文件读取函数
            public void FileRead()
            {
                Process processtemp = new Process();
                processtemp = System.Diagnostics.Process.Start("notepad.exe", "offlinedatebase.txt");
                processtemp.WaitForExit();
                processtemp.Close();
                
            }
        }
        //file write and output 类
        FileWriteAndOutput fwao = new FileWriteAndOutput();
        //初始化按下时候表示初始化offlinedatebase
        private void button4_Click(object sender, EventArgs e)
        {
            fwao.FileWhitePaper();
        }
        public KNN()
        {
            InitializeComponent();
        }
        //添加数据库按钮按下时 在offlinedatebase添加一条记录
        private void button1_Click(object sender, EventArgs e)
        {
            string StrOutput = "";
            if (LabelNum.Text!=""&& BRSSI1.Text.ToString()!= ""&& BRSSI2.Text.ToString() != ""&& BRSSI3.Text.ToString() != "" &&BRSSI4.Text.ToString() != "")
            {
                StrOutput = LabelNum.Text.ToString() + '\t' + BRSSI1.Text.ToString() + '\t' + BRSSI2.Text.ToString() + '\t' + BRSSI3.Text.ToString() + '\t' + BRSSI4.Text.ToString();
                fwao.FileWrite(StrOutput);
                BRSSI1.Clear();
                BRSSI2.Clear();
                BRSSI3.Clear();
                BRSSI4.Clear();
                LabelNum.Clear();
            }

        }
        //查看文件按钮按下时 用记事本只读方式打开offlinedatebase
        private void button3_Click(object sender, EventArgs e)
        {
            fwao.FileRead();
        }
        //运行python KNN算法处理
        private void button5_Click(object sender, EventArgs e)
        {
            this.RUNBAT();
        }
        public void RUNBAT()
        {
            Process proc = new Process();
            proc.StartInfo.FileName = @"RUNpython.bat";
            proc.StartInfo.Arguments = string.Format("10");//this is argument
            proc.StartInfo.CreateNoWindow = false;
            proc.Start();
            proc.WaitForExit();
            proc.Close();
        }
        //每一个计时器周期 更新位置id和算法准确率
        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                StreamReader reader = new StreamReader(@"ans.txt");
                label8.Text = reader.ReadToEnd();
                reader.Close();
            }
           
            catch (Exception)
            {
                label8.Text = "Unknow";
            }
            try
            {
                StreamReader reader2 = new StreamReader(@"model accuracy.txt");
                label10.Text = reader2.ReadToEnd();
                reader2.Close();
            }

            catch (Exception)
            {
                label10.Text = "Unknow";
            }

        }
    }
}

源文件:
链接:https://pan.baidu.com/s/1R6_oHxL32tDqKIvcerYlkg
提取码:8888

后续优化计划

更新 添加 KNNsf.py 参数可调功能
更新 使用SQL数据库 进行数据IO
更新 Android通过网络一键添加数据库
更新 优化窗口UI 增加table控件 使查看数据库更加直观

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2022年4月13日 下午5:29
下一篇 2022年4月15日 上午10:45

相关推荐