场景
我正在尝试在一个Java GUI应用程序中对数据集进行监督学习。用户将被提供一份项目或“报告”列表进行检查,并根据一组可用的标签对其进行标记。一旦监督学习完成,标记的实例将被提供给学习算法。该算法将尝试根据用户可能希望查看它们的可能性来对其余项目进行排序。
为了最大限度地利用用户的时间,我想预先选择那些能提供关于整个报告集合最多信息的报告,并让用户对它们进行标记。据我了解,要计算这一点,需要找到每个报告的所有互信息值的总和,并根据该值对它们进行排序。然后,监督学习中标记的报告将被用来构建一个贝叶斯网络,以找到每个剩余报告的二元值概率。
示例
在这里,一个人造的例子可能会有助于解释,并且当我无疑使用了错误的术语时,可以消除混淆 🙂 考虑一个例子,其中应用程序向用户显示新闻故事。它根据用户显示的偏好选择首先显示哪些新闻故事。新闻故事的特征具有相关性,如来源国家
、类别
或日期
。因此,如果用户将一个来自苏格兰的新闻故事标记为有趣,这告诉机器学习者,其他来自苏格兰的新闻故事对用户来说可能更有趣。类似地,对于体育这样的类别,或2004年12月12日这样的日期也是如此。
这种偏好可以通过为所有新闻故事选择任何顺序(例如,按类别、按日期)或随机排序它们来计算,然后在用户进行过程中计算偏好。我希望做的就是通过让用户查看少量特定新闻故事并说出他们是否对它们感兴趣(监督学习部分)来对这种排序有一个“先发优势”。为了选择向用户展示哪些故事,我必须考虑整个故事集合。这就是互信息的作用所在。对于每个故事,我想知道当它被用户分类时,它能告诉我多少关于其他所有故事的信息。例如,如果有大量来自苏格兰的故事,我想让用户分类(至少)其中一个。类似地,对于其他相关特征,如类别或日期也是如此。目标是找到当分类时能提供关于其他报告最多信息的报告示例。
问题
因为我的数学有点生疏,而且我是机器学习的新手,我在将互信息的定义转换为Java实现时遇到了一些麻烦。维基百科描述了互信息的方程为:
然而,我不确定在没有任何东西被分类,学习算法尚未计算任何东西的情况下是否可以实际使用它。
如我的例子所示,假设我有大量新的、未标记的这个类的实例:
public class NewsStory { private String countryOfOrigin; private String category; private Date date; // 构造函数等}
在我的特定场景中,字段/特征之间的相关性基于精确匹配,因此,例如,一天和十年之差在日期上的不等性是等价的。
相关性的因素(例如,日期是否比类别更相关?)不一定是相等的,但它们可以是预定义的和恒定的。这是否意味着函数p(x,y)
的结果是预定义的值,还是我混淆了术语?
问题 (终于)
鉴于这个(假的)新闻故事的例子,我该如何实现互信息的计算?欢迎提供库、javadoc、代码示例等信息。此外,如果这种方法从根本上是错误的,解释为什么会这样同样是一个有价值的答案。
PS. 我知道像Weka和Apache Mahout这样的库,所以仅仅提到它们对我来说并没有多大用处。我仍在搜索这两个库的文档和示例,寻找关于互信息的具体内容。真正能帮助我的是指向这些库在互信息方面提供帮助的资源(代码示例、javadoc)。
回答:
我猜你的问题是类似于…
“给定一个未标记的示例列表,根据如果用户标记了示例并将其添加到训练集中,模型的预测准确性会提高多少来对列表进行排序。”
如果是这种情况,我认为互信息不是正确的使用方法,因为你不能在两个实例之间计算MI。MI的定义是关于随机变量的,而一个单独的实例不是随机变量,它只是一个值。
特征和类别标签可以被认为是随机变量。也就是说,它们在整个数据集上有一组值的分布。你可以计算两个特征之间的互信息,以了解一个特征在给定另一个特征的情况下有多“冗余”,或者计算一个特征与类别标签之间的互信息,以了解该特征可能对预测有多大帮助。这就是人们通常在监督学习问题中使用互信息的方式。
我认为ferdystschenko建议你查看主动学习方法是一个好建议。
响应Grundlefleck的评论,我将通过使用他的Java对象类比的想法更深入地探讨术语…
我们集体使用了“实例”、“事物”、“报告”和“示例”这些术语来指代被分类的事物。让我们把这些东西想象成Java类的实例(我省略了样板构造函数):
class Example{ String f1; String f2;}Example e1 = new Example("foo", "bar");Example e2 = new Example("foo", "baz");
在机器学习中的常用术语是,e1是一个示例,所有示例都有两个特征 f1和f2,并且对于e1,f1的值为’foo’,f2的值为’bar’。一组示例被称为数据集。
获取数据集中所有示例的f1的所有值,这是一个字符串列表,也可以被认为是一个分布。我们可以将特征视为一个随机变量,并且列表中的每个值都是从该随机变量中抽取的一个样本。因此,例如,我们可以计算f1和f2之间的MI。伪代码将是这样的:
mi = 0for each value x taken by f1:{ sum = 0 for each value y taken by f2: { p_xy = number of examples where f1=x and f2=y p_x = number of examples where f1=x p_y = number of examples where f2=y sum += p_xy * log(p_xy/(p_x*p_y)) } mi += sum}
然而,你不能在e1和e2之间计算MI,这不是这样定义的。