【原创】.NET平台机器学习组件-Infer.NET连载(二)贝叶斯分类器

            本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html

微软Infer.NET机器学习组件文章目录:http://www.cnblogs.com/asxinyu/p/4329742.html

关于本文档的说明

  本文档基于Infer.NET 2.6对Infer.NET User Guide进行中文翻译,但进行了若干简化和提炼,按照原网站的思路进行,但不局限与其顺序。

  欢迎传播分享,必须保持原作者的信息,但禁止将该文档直接用于商业盈利。

  本人正在研究基于Infer.NET组件,并计划将其应用于实际的预测之中,该组件功能强大,封装很完善,但也有很多难以理解的地方,同时官方也给出了大量的例子,限于个人精力有限,更新时间较慢,也希望有兴趣的朋友一起来完成该项工作。

     Email:asxinyu@qq.com

  本文章原始地址http://www.cnblogs.com/asxinyu/p/4255921.html

1.Infer.NET贝叶斯分类器介绍

  本教程提供了一个简短的,循序渐进的介绍如何使用C# API创建、训练和测试一个贝叶斯机分类器的过程。如果你只是想尝试使用贝叶斯机器分类器,你可以提供数据一个特定格式文本文件,不用担心最终的性能,可以参考一下命令行的使用。

  本项目使用的贝叶斯分类器是基于Infer.NET API构建的,源码等资料在本文最后的资源信息。

  该文章翻译的网址为:点击这里看英文原文

2.性别预测介绍

  本教程的目的,让我们假设我们要根据一组给人身高和体重的数据来预测一个人的性别。让我们进一步假设我们已经收集到的样本大小为N=1000,而我们知道的性别作为标签样本单独存放。下面图是样本数据可视化的结果:

  

  解决这类问题的一个方法是创建一个概率模型。Infer.NET允许您使用各种各样的模型。在描述了这个分类问题后,我们已经给你准备了一个完整和稳定的模型,所以你不需要做这个工作。然而,我们创建的贝叶斯机器(BPM)分类器,必须要有一些前提条件,这些你可能要搞清楚。如果这些假设不满足你的情况,你自己可以考虑创建一个更符合你实际情况的概率模型。样本数据中包含508名女性(红色)和508名男性(蓝色)。样本中的女性平均身高是162厘米,男性平均身高为175.2厘米。女性平均体重为70.1公斤,男性平均体重为83.8公斤。正如人们所预料的,该图的中,两组数据的显示有很大的重叠,这意味着给定一个人的身高和体重,并不能完全的区分为男性或者女性。现在,根据这些数据,那么一个身高183厘米,体重78公斤的人是一个女人的可能性大吗?

   使用Visual Studio创建项目,并添加下面几个dll引用:Infer.Learners.dll,Infer.Learners.Classifier.dll,Infer.Runtime.dll。这个过程比较简单,基本忽略。

3.数据和映射

  针对上述提供的数据。每个人的身高和体重是以向量实例存储在内存中的,相应的性别以字符串类型对象表示的,其值是“女性”或“男性”。因此整个样本,包含个数是1000的向量数组对象和1000个字符串类型对象。

相关说明:

  1.贝叶斯机器分类器模型并不显式地指定一个预期结果。然而,在许多分类问题中,添加一个预期结果是至关重要的,因为它使得贝叶斯分类器以固定的特性转换特征(决策边界不需要原始数据特征),从而显著的影响预测性能[翻译不太准确]。BPM可以实现添加预期值的功能,使其总有1这个值。如果你的分类数据还不包括这样一个常数特征值,你应该很想将它添加到特征向量中。

  2.如果特性(包括预期值)是高度相关的,贝叶斯机器分类器的训练可能出现收敛速度慢的情况。

  在上述性别预测的例子中,我们可以使用了一个增强的三维特征向量,不仅包含一个人的身高和体重,还有额外的特征值为1。此外,让我们在原始数据中减去平均身高和平均体重,这就消除身高、体重和预期值之间的相关性。

  数据可以存储在各种不同的格式中。通常的您的数据格式都和学习者Learner所预期要求的数据类型都不一致。这意味着您必须将原始数据转化为学习者的格式。这在一些小的用例测试中,当然是一个合理的选择,但对于大型的真实数据集,这种转换代价是非常大的。因此为了避免用户输入固定类型的数据,Infer.NET提供了一个灵活的机制,允许您指定学习者应该如何使用他们的输入数据。这种机制被称为映射。一个映射定义输入数据是如何传递到Infer.NET的学习者中的。因为它让你选择最方便的格式,它有助于避免不必要的数据转换。

  贝叶斯机器分类器中有两种不同类型的映射,详细可以参考Mappings类。在我们简单介绍的例子中,最简单的将输入数据映射到一个表单以便于贝叶斯分类器理解的方法是实现IClassifierMapping接口,如下所示:  

 1 /// <summary>
 2 /// A mapping for the Bayes Point Machine classifier tutorial.
 3 /// </summary>
 4 public class ClassifierMapping: IClassifierMapping<IList<Vector>, int, IList<string>, string, Vector>
 5 {
 6     public IEnumerable<int> GetInstances(IList<Vector> featureVectors)
 7     {
 8         for (int instance = 0; instance < featureVectors.Count; instance++)
 9         {
10             yield return instance;
11         }
12     }
13     public Vector GetFeatures(int instance, IList<Vector> featureVectors)
14     {
15         return featureVectors[instance];
16     }
17 
18     public string GetLabel(int instance, IList<Vector> featureVectors, IList<string> labels)
19     {
20         return labels[instance];
21     }
22 
23     public IEnumerable<string> GetClassLabels(IList<Vector> featureVectors = null, IList<string> labels = null)
24     {
25         return new[] { "Female", "Male" };
26     }
27 }

为了实现IClassifierMapping 接口,必须要实现以下几点:

1.哪个是要分批交给分类器的对象?(GetInstances);

2.如何获取给定实例的特征值? (GetFeatures);

3.如何获取给定实例实际的标签值? (GetLabel);

4.获取数据中所有不同类型标签值,相当于标签范围(GetClassLabels)。

4.创建贝叶斯分类器,并训练,预测和评估

4.1 创建分类器

有了手动创建的数据映射,就可以创建贝叶斯机器分类器,如下所示:

1 有了手动创建的映射,就可以创建贝叶斯机器分类器,如下所示:
2 // Create the Bayes Point Machine classifier from the mapping
3 var mapping = new ClassifierMapping();
4 var classifier = BayesPointMachineClassifier.CreateBinaryClassifier(mapping);

4.2 训练

这样,就可以使用分类器根据身高和体重去学习和预测性别。使用1000个样本去训练贝叶斯机器分类器,如下所示:

1 // Train the Bayes Point Machine classifier on the gender data
2 classifier.Train(trainingSet.FeatureVectors, trainingSet.Labels);

trainingSet.FeatureVectors是一个包括身高和体重测量数据的向量数组,trainingSet.Labels是一个代表性别的预期标签。

注意,训练贝叶斯我们并不需要设置任何参数,如前置分布权重。这是因为贝叶斯机器分类器是无需超参数的(hyper-parameter)。这不仅避免了一些错误的参数设置,还可以自动移除一些影响运行时间的参数。更厉害的是:它甚至不需要规范化的数据输入,贝叶斯机器分类器能够自己自动适应不同尺度的观察数据。这些都是通过heavy-tailed 前置分布权重设置的。

4.3 预测

  使用训练后的贝叶斯机器分类器,就能够预测那些只有身高和体重数据的人的性别。特别是,现在我们可以回答之前那个身高183厘米,体重178公斤的人是一个女人的可能性有多大。如下代码:

1 // Making predictions on previously unseen data
2 var predictions = classifier.PredictDistribution(testSet.FeatureVectors);

testSet.FeatureVectors是一个只包含身高,体重以及预期值的向量数组。

调用PredictDistribution在测试集中,给每个实例返回一个伯努利分布,这个事实说明给定一个人的身高和体重,我们通常并不能完全确定一个人的性别。例如:

1 P(gender = 'Female' | height = 183cm, weight = 78kg) = 0.07

根据训练集1000个样本的观测数据,这个身高183厘米,体重78公斤的人是女性的概率是7%。在许多情况下,您可能需要预测一个最终确定的答案,而不是调用PredictDistribution,然后简单地预测,给出概率,例如,我们可以这样写:

1 // Making decisions
2 string estimate = classifier.Predict(InstanceOfInterest, testSet.FeatureVectors);

结果是:Male

注意,这种精确的分类预测仍然需要计算预测分布作为一个中间步骤。此外,最佳的精确答案不一定是最有可能的类。

4.4 评估测试

为了评价分类器的预测情况,我们需要利用一些不同于训练集的有标签的数据,因此我们假定我们可以得到一组100个额外的真实性别,体重和身高的测量记录。一个评价过程要通过ClassifierEvaluator进行,如下:

1 // Create an evaluator for mapping
2 var evaluatorMapping = mapping.ForEvaluation();
3 var evaluator = 
4     new ClassifierEvaluator<IList<Vector>, int, IList<string>, string>(
5         evaluatorMapping);

结果:Accuracy = 0.85;AUC = 0.926

ClassifierEvaluator  also allows you to get the receiver operating characteristic curve itself (for "Female" as the designated positive class):

1 IEnumerable<Pair<double, double>> rocCurve = 
2     evaluator.ReceiverOperatingCharacteristicCurve(
3         "Female", testSet.FeatureVectors, predictions);

 

  我们将在后续的文章中分享关于基于Infer.NET组件构建的贝叶斯机器分类器更多的功能和相关细节。

5.资源

  本人手动制作了Infer.NET 2.6的帮助文档,CHM格式,还有贝叶斯分类器的相关代码,

  文件比较大,将通过邮箱与30日下午统一发送,需要的朋友留Email。 

  如果本文章资源下载不了,或者文章显示有问题,请参考 本文原文地址http://www.cnblogs.com/asxinyu/p/4255921.html

      如果您看完本篇文章感觉不错,请点击一下右下角的【推荐】来支持一下博主,谢谢!

 

posted @ 2015-01-29 08:08 数据之巅 阅读(...) 评论(...) 编辑 收藏