机器学习用于加权调整
我正在尝试找出如何使用一些机器学习库,来帮助我确定每个参数的正确权重,以便做出好的决策。
具体来说:
背景:我想为HTML文件实现一个发布日期提取器。这是针对新闻网站的,所以我没有一个通用的日期格式可以使用。我在Python中使用dateutil库的解析器,它的效果还不错。最后我得到了一个可能的发布日期列表(HTML文件中的所有日期)。
根据一些参数,比如闭合标签、靠近日期子串的词等等,我会根据它们成为发布日期的可能性来对这个列表进行排序。每个参数的权重都是一些经过思考的猜测。
我想实现一个机器学习算法,在经过一个训练期(在这个期间提供实际的发布日期)后,它能够确定每个参数应该有的权重。
我已经阅读了Python中不同机器学习库的文档(如pyML、scikit-learn、pybrain),但没有找到任何有用的信息。我还看过这个,里面有一个类似的例子,讲的是如何判断蘑菇是否可食用。
注意:我正在使用Python。
我非常感谢你的帮助。
2 个回答
假设你需要用到机器学习(比如你的文档数量很大,新闻网站也很多,逐个网站写解析程序太麻烦,网址里没有明显的发布时间标记,HTTP的最后修改时间也不可靠等等),你可以考虑以下方法:
- 使用决策树、贝叶斯学习或者其他方法,把你的文本特征转化为“我认为这个日期是发布时间的概率有多大”这样的特征;
- 使用最大熵学习来计算权重(比如,http://www-i6.informatik.rwth-aachen.de/web/Software/YASMET.html这个工具会很有帮助)。
根据你描述的问题、数据特征,以及你的机器学习背景和个人偏好,我推荐你使用Orange。
Orange是一个成熟的、免费的开源项目,里面有很多机器学习算法,并且提供了很好的文档和培训材料。大多数用户可能会使用Orange自带的图形界面,但这个框架也可以用Python编写脚本。
使用这个框架,你可以快速尝试各种分类器,因为(i) 所有的算法都在一个地方;(ii) 每个算法都有一个统一的配置界面。Orange框架中的所有机器学习技术都可以在“演示”模式下运行,使用的是Orange安装包中提供的一个或多个示例数据集。Orange安装包中的文档非常优秀。此外,主页上还有很多教程链接,几乎涵盖了框架中包含的所有机器学习技术。
考虑到你的问题,或许可以先从决策树算法开始(可以选择C4.5或ID3实现)。最近的《Dr. Dobbs Journal》在线版上有一篇关于使用决策树的优秀文章,案例是关于网络服务器的数据(来自服务器访问日志)。
Orange提供了C4.5实现,可以通过图形界面(作为一个“小部件”)访问。如果觉得这太简单,使用Python编写一个大约只需要100行代码。这里有一个在Python中实现的源代码。
我推荐从决策树开始,有几个原因。
如果它能在你的数据上有效工作,你不仅会得到一个训练好的分类器,还会有一个整个分类结构的可视化表示(以二叉树的形式表示)。在这方面,决策树可能是机器学习技术中独特的。
你的数据特征与C4.5的最佳性能场景相符;数据可以是分类变量或连续变量(尽管这个技术在特征(列/字段)越离散时效果更好,这似乎符合你的数据);此外,决策树算法可以接受不完整的数据点,而无需任何预处理。
简单的数据预处理。 输入到决策树算法的数据不需要像大多数其他机器学习技术那样复杂的预处理;预处理通常是整个机器学习工作流程中最耗时的任务。这个过程的文档也很少,所以它也是最容易出错的地方。
你可以通过每个节点距离根节点的距离来推断每个变量的(相对)权重——换句话说,通过快速的可视检查训练好的分类器。记住,训练好的分类器只是一个二叉树(通常以这种方式呈现),其中节点对应于一个特征(变量或数据集中的列)的一个值;连接到该节点的两个边当然代表根据该特征的值将数据点分成两组(例如,如果特征是分类变量“HTML页面头中的发布日期?”那么左边的边会流入所有发布日期不在开头和结束头标签之间的数据点,而右边的节点则接收另一组)。这有什么意义呢?因为一个节点仅代表某个变量的状态或值,所以该变量在分类数据中的重要性(或权重)可以通过它在树中的位置推断出来——也就是说,离根节点越近,重要性越高。
从你的问题来看,似乎在将训练数据输入机器学习分类器之前,你有两个任务需要完成。
I. 确定合理的类别标签
你想要预测的是一个日期。除非你的精度要求特别严格(例如,精确到某一天),否则我建议建立一个分类模型(根据数据点返回一个类别标签),而不是回归模型(返回一个连续值)。
考虑到你的响应变量是一个日期,一个简单的方法是将最早的日期设为基准0,然后将所有其他日期表示为与该基准的距离的整数值。接下来,将所有日期离散化为少量的范围。一种非常简单的技术是计算响应变量的五个总结性描述统计(最小值、第一个四分位数、均值、第三个四分位数和最大值)。从这五个统计数据中,你可以得到四个合理选择的日期范围(虽然可能不是相等的跨度或相等的成员大小)。
这四个日期值范围就代表了你的类别标签——例如,类别I可能是所有响应变量(发布日期)在0到10天之间的数据点(网页,我想)。类别II是0之后11天到25天之间的数据点,等等。
[注意:根据提问者在此答案下的评论请求澄清,添加了下面的代码。]
# suppose these are publication dates
>>> pd0 = "04-09-2011"
>>> pd1 = "17-05-2010"
# convert them to python datetime instances, e.g.,
>>> pd0 = datetime.strptime(pd0, "%d-%m-%Y")
# gather them in a python list and then call sort on that list:
>>> pd_all = [pd0, pd1, pd2, pd3, ...]
>>> pd_all.sort()
# 'sort' will perform an in-place sort on the list of datetime objects,
# such that the eariest date is at index 0, etc.
# now the first item in that list is of course the earliest publication date
>>> pd_all[0]
datetime.datetime(2010, 5, 17, 0, 0)
# express all dates except the earliest one as the absolute differenece in days
# from that earliest date
>>> td0 = pd_all[1] - pd_all[0] # t0 is a timedelta object
>>> td0
datetime.timedelta(475)
# convert the time deltas to integers:
>>> fnx = lambda v : int(str(v).split()[0])
>>> time_deltas = [td0,....]
# d is jsut a python list of integers representing number of days from a common baseline date
>>> d = map(fnx, time_deltas)
II. 将你的原始数据转换为“机器学习可用”的形式。
对于C4.5分类器,这个任务比其他机器学习算法简单得多,步骤也更少。这里更倾向于将尽可能多的参数离散化为相对较少的值——例如,如果你的一个参数/变量是“发布日期字符串距离结束body标签的距离”,那么我建议将这些值离散化为范围,就像市场调查常常要求参与者在指定的一组范围内报告他们的年龄(18 - 35;36 - 50等),而不是作为一个单一的整数(41)。