我正在尝试弄清楚如何使用某个机器学习库来帮助我找出每个参数的正确权重,以便做出好的决策。
更详细地说:
背景:我正在尝试为HTML文件实现一个发布日期提取器。这适用于新闻网站,所以我没有一个通用的日期格式可以使用。我使用的是Python中的dateutil解析器,它的表现相当不错。我最终得到了一系列可能的发布日期(HTML文件中的所有日期)。
从一组参数出发,比如关闭标签、日期子字符串附近的单词等,我根据可能是发布日期的可能性对列表进行排序。每个参数的权重都是某种程度上的经验猜测。
我想实现一个机器学习算法,在经过一个训练期(在此期间提供实际的发布日期)后,它可以确定每个参数的权重应该是什么。
我已经阅读了Python中不同机器学习库的文档(pyML, scikit-learn, pybrain),但我没有找到任何有用的东西。我还阅读了这个,其中有一个关于判断蘑菇是否可食的接近例子。
注意:我使用的是Python。
我非常感谢你的帮助。
回答:
根据你的问题描述、数据特征以及你的机器学习背景和个人偏好,我推荐使用Orange。
Orange是一个成熟的、免费的开源项目,拥有大量的机器学习算法和优秀的文档及培训材料。大多数用户可能使用Orange提供的GUI,但该框架也可以用Python进行脚本编写。
因此,使用这个框架当然可以让你快速尝试各种分类器,因为(i)它们都集中在一个地方;(ii)每个分类器都通过一个通用的配置语法GUI访问。Orange框架内的所有机器学习技术都可以以“演示”模式运行,使用Orange安装时提供的一个或多个样本数据集。Orange安装中提供的文档非常优秀。此外,主页上还包括了指向众多教程的链接,这些教程可能涵盖了框架中包含的每一种机器学习技术。
鉴于你的问题,或许可以从决策树算法开始(使用C4.5或ID3实现)。最近一期的Dr. Dobbs Journal(在线版)包括了一篇关于使用决策树的优秀文章;用例是来自服务器访问日志的Web服务器数据。
Orange有一个C4.5实现,可从GUI(作为一个“小部件”)获得。如果这太简单了,大约100行代码就可以在Python中编写一个。这里是该语言中一个工作实现的源代码
我推荐从决策树开始有几个原因。
-
如果它在你的数据上有效,你不仅会得到一个训练好的分类器,你还会得到一个整个分类方案的可视化表示(以二叉树的形式表示)。在这一点上,决策树在机器学习技术中可能是独一无二的。
-
你的数据特征与C4.5的最佳性能场景相符;数据可以是分类变量或连续变量(尽管这种技术在特征(列/字段)更多是离散而不是连续时表现更好,这似乎描述了你的数据);此外,决策树算法可以接受未经预处理的、不完整的数据点
-
简单的数据预处理。输入决策树算法的数据不需要像大多数其他机器学习技术那样进行大量的数据预处理;预处理通常(通常?)是整个机器学习工作流程中最耗时的任务。它也很少被记录,因此可能是错误最可能的来源。
-
你可以从每个节点到根节点的距离中推断出每个变量的(相对)权重——换句话说,从对训练好的分类器的快速视觉检查中。回想一下,训练好的分类器只是一个二叉树(通常以这种方式呈现),其中节点对应于一个特征的一个值(变量,或数据集中的列);连接到该节点的两条边当然代表根据每个点对该特征的值将数据点分成两组(例如,如果特征是分类变量“HTML页面头部中的发布日期?”,那么通过左边的边将流动所有发布日期不在打开和关闭头部标签内的数据点,而右边的节点得到另一组)。这有什么意义?由于一个节点仅代表一个特定变量的状态或值,该变量在分类数据中的重要性(或权重)可以从它在树中的位置推断出来——即,它离根节点越近,它就越重要。
从你的问题来看,似乎在你可以将训练数据输入机器学习分类器之前,你有两个任务要完成。
I. 识别合理的类标签
你想要预测的是一个日期。除非你的分辨率要求非常严格(例如,分辨到单一日期),我会构建一个分类模型(给定一个数据点返回一个类标签),而不是回归模型(返回一个单一的连续值)。
鉴于你的响应变量是一个日期,一个直接的方法是将最早的日期设置为基线,0,然后将所有其他日期表示为从该基线的距离的整数值。接下来,将所有日期离散化为少量的范围。一种非常简单的方法是计算你的响应变量的五个描述性统计摘要(最小值、第一四分位数、均值、第三四分位数和最大值)。从这五个统计数据中,你可以得到四个合理选择的日期范围(尽管可能不是等距或等成员大小)。
这些日期值的四个范围然后代表你的类标签——例如,类I可能是所有数据点(我猜是网页)的响应变量(发布日期)在0到10天之后;类II是0之后11天到25天之后,等等。
[注意:根据OP在本回答下面的评论请求澄清,添加了下面的代码。]
# 假设这些是发布日期>>> pd0 = "04-09-2011" >>> pd1 = "17-05-2010"# 将它们转换为Python的datetime实例,例如, >>> pd0 = datetime.strptime(pd0, "%d-%m-%Y")# 将它们收集在一个Python列表中,然后对该列表调用sort:>>> pd_all = [pd0, pd1, pd2, pd3, ...]>>> pd_all.sort()# 'sort'将对datetime对象列表进行原地排序,# 使得最早的日期位于索引0,等等。# 现在该列表中的第一个项目当然是最早的发布日期>>> pd_all[0]datetime.datetime(2010, 5, 17, 0, 0)# 将除最早日期之外的所有日期表示为与该最早日期的绝对天数差异>>> td0 = pd_all[1] - pd_all[0] # t0是一个timedelta对象>>> td0datetime.timedelta(475) # 将时间差转换为整数:>>> fnx = lambda v : int(str(v).split()[0])>>> time_deltas = [td0,....]# d只是一个表示从公共基线日期的天数的Python整数列表>>> d = map(fnx, time_deltas)
II. 将你的原始数据转换为“机器学习可使用”的形式
对于C4.5分类器来说,这项任务要简单得多,并且需要的步骤比可能的其他机器学习算法都要少。这里更喜欢的是将尽可能多的参数离散化为相对较少的值——例如,如果你的一个参数/变量是“发布日期字符串与关闭body标签的距离”,那么我建议将这些值离散化为范围,就像市场调查通常要求参与者报告他们在一个指定的范围内(18 – 35;36 – 50等)的年龄,而不是作为一个单一的整数(41)。