计算用于在Java中选择训练集的互信息

时间:2010-01-04 21:54:39

标签: java machine-learning bayesian information-theory

方案


我正在尝试对Java GUI应用程序中的数据集实施有监督的学习。将向用户提供要检查的项目或“报告”的列表,并将基于一组可用标签对其进行标记。一旦监督学习完成,标记的实例将被给予学习算法。这将尝试订购其余项目用户想要查看它们的可能性。

为了充分利用用户的时间,我想预先选择能够提供有关整个报告集的最多信息的报告,并让用户对其进行标记。据我了解,为了计算这一点,有必要找到每个报告的所有互信息值的总和,并按该值排序。然后,来自监督学习的标记报告将用于形成贝叶斯网络,以查找每个剩余报告的二进制值的概率。

示例


在这里,一个人为的例子可能有助于解释,并且当我毫无疑问地使用错误的术语时可能会清除混淆:-)考虑一个应用程序向用户显示新闻故事的示例。它根据显示的用户偏好选择首先显示哪些新闻故事。具有相关性的新闻报道的特征是country of origincategorydate。因此,如果用户将来自苏格兰的单个新闻故事标记为有趣的话,它会告诉机器学习者,来自苏格兰的其他新闻故事对用户来说更有可能。类似于体育等类别,或类似于2004年12月12日的日期。

可以通过选择所有新闻报道的任何顺序(例如按类别,按日期)或随机排序它们,然后在用户进行时计算偏好来计算此偏好。我想做的是通过让用户查看少量特定新闻故事并说出他们是否对他们感兴趣(监督学习部分)来获得一种“先发制人”。要选择向用户展示哪些故事,我必须考虑整个故事集。这就是相互信息的来源。对于每个故事,我想知道当用户对其进行分类时,它能告诉我其他所有故事的内容。例如,如果有大量来自苏格兰的故事,我想让用户对其中一个进行分类(至少)。与其他相关功能类似,例如类别或日期。目标是找到报告的示例,这些报告在分类时提供有关其他报告的最多信息。

问题


因为我的数学有点生疏,而且我是机器学习的新手,我在将相互信息的定义转换为Java实现方面遇到了一些麻烦。维基百科将互信息的等式描述为:

mutual information equation

但是,我不确定当没有被分类时这是否真的可以使用,并且学习算法还没有计算任何东西。

在我的例子中,假设我有大量新的,未标记的此类实例:

public class NewsStory {
    private String countryOfOrigin;
    private String category;
    private Date date;
    // constructor, etc.
}

在我的特定场景中,字段/功能之间的相关性基于完全匹配,因此,例如,日期中的一天和10年差异在其不等式中是等效的。

相关因子(例如,日期与类别相关的日期更相关?)不一定相等,但它们可以是预定义的和不变的。这是否意味着函数p(x,y) 的结果是预定义的值,还是我混淆了术语?

问题 (最后)


如果给出这个(假的)新闻报道的例子,我怎样才能实现互信息计算?库,javadoc,代码示例等都是受欢迎的信息。此外,如果这种方法存在根本缺陷,那么解释为什么会出现这种情况将是一个有价值的答案。


PS。我知道像Weka和Apache Mahout这样的库,所以只提一下它们对我来说并不是很有用。我仍在搜索这些库的文档和示例,专门查找Mutual Information上的内容。真正帮助我的是指向资源(代码示例,javadoc),这些库有助于互信息。

2 个答案:

答案 0 :(得分:4)

我猜你的问题就像......

“给定一个未标记的示例列表,如果用户标记了示例并将其添加到训练集中,则按照模型的预测准确度提高的程度对列表进行排序。”

如果是这种情况,我不认为互信息是正确的,因为你不能在两个实例之间计算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 = 0
for 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,它只是没有这样定义。

答案 1 :(得分:1)

我知道信息只能与决策树(DT)相关联,在构建DT时,每个节点上的分割是最大化信息增益的分割。 DT在Weka中实现,因此您可以直接使用它,但我不知道Weka是否允许您计算DT节点下任何特定拆分的信息增益。

除此之外,如果我理解正确,我认为你要做的事情通常被称为active learning。在那里,您首先需要一些初始标记的训练数据,这些数据被输入您的机器学习算法。然后,您的分类器标签包含一组未标记的实例,并为每个实例返回置信度值。具有最低置信度值的实例通常是提供最多信息的实例,因此您将这些显示给人类注释器并手动将其标记为这些,将它们添加到您的训练集中,重新训练您的分类器,并完成整个过程。重复直到您的分类器具有足够高的准确度或直到满足其他一些停止标准。因此,如果这对您有用,您原则上可以使用在Weka或任何其他ML框架中实现的任何ML算法,只要您选择的算法能够返回置信度值(在贝叶斯方法的情况下,这将只是概率)


根据您编辑的问题,我想我会明白您的目标。如果你想要的是计算MI,那么在我看来,StompChicken的答案和伪代码就不那么清楚了。我也认为MI并不是你想要的,你正试图重新发明轮子。

让我们概括一下:您想要训练一个可由用户更新的分类器。这是积极学习的经典案例。但是为此,你需要一个初始分类器(你基本上可以给用户随机数据进行标记,但我认为这不是一个选项)并且为了训练你的初始分类器,你需要至少一些少量的标记训练监督学习的数据。但是,您拥有的只是未标记的数据。你能用这些做什么?

好吧,您可以使用Weka提供的标准群集算法或某些特定的群集工具(如cluster)将它们Cluto分成相关实例组。如果您现在采用每个群集的x个最核心实例(x取决于群集的数量和用户的耐心),并让用户将其标记为有趣或无趣,则可以将此标签用于其他实例那个集群(或者至少是中心集群)。 Voila,现在您有训练数据,您可以使用这些数据来训练您的初始分类器,并在每次用户将新实例标记为有趣或无效时更新分类器,从而启动主动学习过程。我认为你试图通过计算MI实现的目标基本相似,但可能只是错误的运费。

不知道您的场景的细节,我认为您可能根本不需要任何标记数据,除非您对标签本身感兴趣。只需对数据进行一次聚类,让用户从所有群集的中心成员中选择一个对他/她感兴趣的项目,并建议所选群集中的其他项目也可能是有趣的。还可以在这里和那里建议来自其他集群的一些随机实例,这样如果用户选择其中一个,您可能会认为相应的集群通常也很有趣。如果存在矛盾并且用户喜欢群集的某些成员但不喜欢同一群集中的某些成员,那么您尝试将数据重新聚类为更细粒度的群组,这些群体区分好的和坏的。通过在每个矛盾的用户输入原因中从一开始就使用层次聚类并沿着集群层次结构向下移动,甚至可以避免重新训练步骤。