如何在 Java 中使用 LibSVM?

Posted

技术标签:

【中文标题】如何在 Java 中使用 LibSVM?【英文标题】:How to use LibSVM in Java? 【发布时间】:2013-02-20 13:28:42 【问题描述】:

我正在尝试使用蓝牙加密狗实现室内位置跟踪系统。这个想法是带着安卓设备四处走动,并根据房间周围蓝牙加密狗的信号强度计算你在房间中的位置。 为了做到这一点,我决定使用机器学习将 RSSI 尽可能地近似为距离,例如米。 我大学的一位讲师告诉我,LibSVM 是我正在寻找的东西,所以我一直在阅读。 我查看了这个tutorial,似乎无法理解训练系统所需的数据。 我将拥有的数据是:

保存在数据库中的每个加密狗的位置(连同 MAC 地址)、x 和 y 坐标 离我的 android 设备最近的加密狗的接收信号强度指示器 (RSSI) mac 地址将用于在数据库中查询某些加密狗

我了解数据必须采用 SVM 格式,但我有点不确定输入数据和输出数据应该是什么格式。下面的示例取自我提到的教程,表明男人是一个阶级,女人是一个阶级。那么在我的情况下,我只有一个类“加密狗”吗?并且所有值加密狗都应该反映我存储在数据库中的值吗?

男人声音:低身材:大收入:好

女声:高身材:苗条 收入:票价

    将特征值转换为其数字表示。假设,最好的薪水是 5,最差的薪水是 1(或没有薪水 = 0),与其他枚举变量相同。 我们有 2 个班级,男人和女人。将类转换为数值:man = 1,woman = -1 以 libsvm 数据格式保存:

[类/目标] 1:[firstFeatureValue] 2:[secondFeatureValue] 等例如: 一个薪水高、声音低、身材矮小的女性会被编码 喜欢: -1 1:5 2:1.5 3:1.8

一般来说SVM的输入文件格式是

[标签] [index1]:[value1] [index2]:[value2] ... [label] [index1]:[value1] [index2]:[value2] ...

谁能给我一个我应该瞄准的例子吗?

这对我来说都是全新的,所以任何有助于我前进的有用提示或技巧都会很棒。 提前致谢

【问题讨论】:

【参考方案1】:

我已经为室内定位实现了 WiFi 指纹识别,所以我知道这里的一些问题。

首先,要确定您的位置,您是在执行指纹识别还是信号强度三边测量(人们错误地称之为三角测量)?三边测量是使多个球体相交以在空间中找到位置的过程。另一方面,指纹识别是一个分类问题,它将信号解析到一个没有计算实际距离的位置。

由于多径衰落等无线问题,在室内进行三边测量非常困难。这些影响会导致您的信号衰减,进而导致您的距离估计值被关闭。

指纹只是一个分类问题。与三边测量一样,它假设加密狗的位置不会改变。但是,与三边测量不同,它根本不使用距离。

三边测量的优势在于,假设距离估计正确(实际上很难达到),您将能够在连续(非离散)范围内解析您的位置。由于指纹识别是一个分类问题,它必须分类到一组固定的离散位置中的一个;例如,如果您的蓝牙无线电沿房间周边布置,您最终可能会将房间内部离散化为 3x3 个可能的位置之一。

如果您要进行指纹识别,那么您需要收集具有如下特征向量的训练数据:

MAC_1:-87, MAC_2:-40, MAC_3:-91, class=location_A
MAC_1:-31, MAC_2:-90, MAC_3:-79, class=location_B

对于房间中的每个位置,您可以从所有可以感应到的可用蓝牙无线电中读取 RSSI。您应该为每个位置至少读取 10 个读数。对于 WiFi,RSSI 值是整数,以分贝为单位,范围为 -100 到 -1(例如,-20 dB 表示您非常靠近收音机)。

现在,当您尝试执行分类时,您将阅读如下内容:

MAC_1:-89, MAC_2:-71, MAC_3:-22, class=?

问题是将这些 RSSI 读数分类到其中一个位置。

在我之前的工作中,我使用了朴素贝叶斯分类器而不是支持向量机,因为朴素贝叶斯很容易适应缺失的特征(通过允许你给缺失的特征一个小概率质量)。另外,在朴素贝叶斯中,我使用高斯 PDF 函数来计算似然概率 P(location | MAC_i = RSSI_i),因为所有 RSSI 值都是数字。

【讨论】:

我想这就是我的目标。因此,我没有获得确切的位置(即(x,y)坐标,而是将房间划分为不同的区域,并根据这些 RSSI 值获得人们站在哪个区域......?我想这就是你的意思。在与今天在该领域工作的一些人交谈后,我被建议这样做。 是的,这是正确的理解。如果您在房间中创建区域,您将能够将您的位置分类到其中一个区域。但请注意,您的蓝牙无线电的数量和配置以及区域的大小和距离都会影响分类的准确性。 这正是我之前试图解释时对朋友所说的。为了获得准确的结果,必须有策略地放置加密狗。谢谢您的回答。很大的帮助。我也可以问一下,我现在正在创建一个小的 train.txt 和 test.txt 文件,我只在房子周围放置了 3 个加密狗。我将楼上分成 3 个区域(3 个不同的房间)。我为 train.txt 文件(共 30 个)的每个区域获得了 10 个 RSSI 读数,为 test.txt 文件的每个区域获得 4 个 RSSI 读数(共 12 个)。我是否将测试文件中的标签/类值留空? 加密狗需要有策略地放置,并且从您收集训练数据到您进行最终测试(也许您的课程有演示)期间,不得移动加密狗。 关于后面的问题,现在归结为机器学习最佳实践。对于训练和测试数据,您都需要拥有真实位置。您可以将训练和测试数据集分开,但由于您没有很多数据(很多通常意味着 100 或 1000 个实例),那么我建议您应用 10 折交叉验证,这是一种常见的方法方法。像 Weka 这样的机器学习工具包将为您执行交叉验证的详细信息。【参考方案2】:

由于您的输出是一个实数(距离),我们谈论的是回归问题,而不是分类问题。 我不清楚您要查找的值是离加密狗最近的距离还是您的 输出将是一组到所有加密狗的距离。这是你需要先弄清楚的。

有几种算法可以做到这一点,但既然你问的是支持向量机,我会考虑范围 这个答案就是这样。我假设你的输出只是一个代表距离的值,如果你是 期望有一个多维输出,并且假设 SVR(支持向量回归)只提供一维输出, 您需要按维度训练一个实例。

libsvm 的参数之一是 svm_type,因为问题是回归问题,你应该使用选项 3 - epsilon-SVR

对于内核类型,我建议考虑 RBF(选项 2 - 径向基函数)

至于您的数据,这是一种可能的安排:

| dongle 1           | dongle 2           | dongle 3           | desired output
| x    | y    | RSSI | x    | y    | RSSI | x    | y    | RSSI |   
---------------------------------------------------------------------------------
| 10.0 | 11.1 | 2.3  | 0.0  | 1.1  | 0.3  | 17.0 | 19.1 | 0.3  |     10.3
| 30.0 | 17.1 | 0.3  | 10.0 | 1.1  | 0.9  | 11.0 | 9.1  | 0.2  |     18.7

所以这将转化为(大括号只是为了清楚起见):

[10.3] [1]:[10.0] [2]:[11.1] [3]:[2.3] [4]:[0.0] [5]:[1.1] [6]:[0.3] [7]:[17.0] [8]:[19.1] [9]:[0.3]
[18.7] [1]:[30.0] [2]:[17.1] [3]:[0.3] [4]:[10.0] [5]:[1.1] [6]:[0.9] [7]:[11.0] [8]:[9.1] [9]:[0.2]

始终建议在 [-1, 1] 或 [0, 1] 之间缩放数据。 此外,您可以在这里找到一些示例数据http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/regression.html

希望对你有帮助

【讨论】:

【参考方案3】:

我认为您不能使用 SVM 来做您所说的事情(计算您在房间中的位置...) SVM 是一种有监督的二进制分类算法。也就是说,如果你给它一些数据和一些正/负类,它会学习一个分类器,可以告诉你新的、未观察到的数据点是正的还是负的。因此,您可以训练一个 SVM 来告诉您一个人是在房间的一侧还是在另一侧(南侧/北侧),而不是他们的实际位置。

看来你想做的事情根本不需要机器学习。请参阅以下帖子:

http://en.wikipedia.org/wiki/Trilateration Triangulation algorithm using signal strength Wifi Triangulation http://www.eetimes.com/design/microwave-rf-design/4019032/Wireless-triangulation-using-RSSI-signals

编辑:鉴于您的澄清,我建议使用k-nearest neighbors 回归。 SVM 绝对不适合您想做的事情;即使使用 SVM 进行回归,它也只适用于一维..

您想要做的是获取尽可能多的数据(数据 = RSSI,标签 = 距离)并将它们嵌入到度量空间中,可能在您拥有的加密狗数量的维度中。然后,给定一些新数据(RSSI 信号强度),找到空间中最近的邻居并计算距离上的某种平均值。

【讨论】:

我不是要计算房间中的位置,而是要教系统RSSI值给出的距离。这对三角测量/三边测量不太有效,因为障碍物会影响信号强度,但这不会影响距离。 k-NN 回归似乎是要走的路。我更新了我的帖子。

以上是关于如何在 Java 中使用 LibSVM?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中获取 LibSVM 分类器的权重?

如何在 libsvm (java) 中禁用控制台输出

如何使用 LIBSVM 的 Android Java 包装器正确设置 LIBSVM.scale() 的参数

如何在 Android 中设置 libsvm?

如何在 LibSVM 中使用“svm_toy”小程序示例?

java中使用LibSVM的一个例子