这阵子跟着老师和一班兄弟搞数据挖掘,一心想找个实用的系统案例分析一下,以便对今后所期望开发出来的应用系统有个大概的把握。傍晚洗澡时突来灵感,想起了坐车网(www.zuoche.com),这的确是一个数据挖掘大显神通的好舞台,起码我这么认为。
就我菜鸟级的见解,数据挖掘这种技术主要针对的是海量数据——从海量数据中抽象出一个模型,根据输入的参数,模型经过分析得到一个期望的输出。而“坐车网”,显而易见,需要包涵全国各地的每条公交线路信息、每条公交线路上的每个站点信息,如此数据量,够得上海量了。“坐车网”的主要功能就是在B/S架构下,用户通过提交一份表单(用户必须输入的信息很简单:出发地、目的地,仅此而已,当然,如果你喜欢的话还可以进行一些高级设置,比如期望搜索到白天还是夜里的公交线路),服务器通过get方式获得用户输入参数(之所以如此肯定为get方式,请看下面解释),通过某种未知的手段(实话实说,迄今为止我还没有确切的证据证明是通过什么手段实现的,话说回来,假如我知道了,那还得了,哈哈),返回由出发地到达目的地的各种交通线路转乘方式。
打开 www.zuoche.com 随便输入一个出发地和一个目的地,可以看到浏览器的地址栏上出现了这么一个URL:
“http://www.zuoche.com/traffic/?si=00c4538e_2369515150&di=2708569b_3584974491&time=1&stgy=0&peop=0&c1=%E4%B8%8A%E6%B5%B7&c2=%E4%B8%9C%E8%8E%9E&x=40&y=9”,
再点击“返回首页”的超链接,发现URL为“http://www.zuoche.com/traffic/index.jspx”。由第二个URL后面的index.jspx可以得知这个网站用的是java web快速开发框架,本质上是java。对于第一个UTL,http://www.zuoche.com/traffic/ 部分是域名,“?”后面跟着的很长一串东西就是所谓的传递参数,这也是上面断定get方式的依据,其中“si”应该是出发地,“di”是目的地,“time”自然是时间,“time=1”表示的是白天,假如选择夜车的话“time=2”;“stgy=0&peop=0”应该分别对应“尽量少走路和尽量少乘车”“C1、C2”是出发地和目的地的城市,比如广州,对应“%E5%B9%BF%E5%B7%9E”。
上述是网站的功能实现,很简单,给用户一个傻瓜式的界面,让用户输入参数,当用户点击查询时,浏览器把参数传回给服务器,服务器经过一系列的功能实现后把线路信息返还回来,在浏览器上呈现给浏览者。
下面是重点了,我要对比一下在非“数据挖掘”思想指导下的功能实现和“数据挖掘”思想指导下的实现优劣。当然,由于本人初学数据挖掘,不免有很多认识误区,高手发现了,还望不吝赐教。
先说说完全不用数据挖掘思想实现线路的查询:
我想到的是首先应该把某个城市,比如广州的各个公众比较熟悉的地名还有标志性的建筑所在地点的经度纬度和地名对应起来存储在数据库中。
然后建一张名为station的表,key为station,就是每个公交或者地铁站点(未免混乱,地铁就权当公交算了,事实上实现起来应该是一致的),这个表还应有一个字段“place”,用来存放在每个站点下车后步行能够到达的地点,还必须有一个字段“path”用来存储每个站点上经过的公交线路。
再建一张“path”表,用来存放每条线路经过的站点。key为path,即线路,用一个字段station存储线路上的每个站点名。
当用户输入出发地和目的地时,首先要在一堆混乱的地名中查找到离出发地和目的地所在位置最近的车站名称,这个过程的时间复杂度是难以估量的,假如运气不好的话或许要遍历整个城市公交站点组成的数据表,发生这种情况只能说:悲剧。当然,采用地域分区和地点索引的方式能显著提高检索的效率,做法是存储地点的经纬信息时先依照一定的规则(人为划区或者是地域划区都可以)把地点信息存放到不同的数据单元中,当用户输入查询参数时要求用户同时输入出发地和目的地的大致所在分区(这种情况下选用下拉选单或单项按钮,用户体验会更好),这样做可以把需要检索的数据范围大大缩小。
找到离出发地和目的地最近的站点A和B后,以出发地站点A为参数,在station表中查找经过这个站点的所有公交路线,以这些路线为参数,在path表中查找B站点,同理,如果运气好的话,刚好A和B在同一条线路上,这时能很快的返回线路信息;假如所有线路都无法搜到站点B,则必须以每条线路上经过的站点为参数再在station表中搜索此站点对应的线路,再以这些线路为参数在path表中搜索这些线路是否经过B站点……如此循环往复,总有一个机会能查询到B站点,这时需要根据记录下来的线路信息依次排好,统计出中间需要经过的站点数和转乘的次数,再用一个函数算出出发地到A站点,目的地到B站点的大概距离(还记得我们存了所有地名的经纬度吗?这时派上用场了),当然,这个距离是相当大概的,因为用经纬度算出来的距离只能是直线的,假如出发地与A点间有建筑物挡住的话,那就不得不用曲线绕过了,这时算出来的距离就只能说是很大概的。
由上面的过程不难发现,站点B在第一、二步搜索中,搜索的复杂度是比较低的,假如在这前几步搜索中没能找到B,那后面的搜索量几乎是以指数级增大的。众所周知,查询数据库本身就是一件很耗费资源的事,当有大量数据需要查询时,困难程度无法想象。
所以非数据挖掘的这种线路查询系统虽说有实现的可能,但是在现实中估计不会有人那么无聊去开发,即使开发出来,最多也只能用在很小的局部地区,城市越大,平均需要的搜索时间将越长。这时很不实用的。
所以我们不得不采用数据挖掘的思想来解决这个问题。
我们要做的是训练出一个神经网络,这个网络的功能是可以根据输入的出发地和目的地智能地提供中间的线路换乘信息。
要训练这么一个神经网络我想到的解决方案是:把全市所有的公交线路以某种特定的方式(矩阵也好、指针也罢)存储起来,使所有公交线路形成一个网状的数据结构。建立一个模型,给其权赋一个任意初值,使用出发地、目的地、中间线路这样的参数对不断去改变测验模型,修改其权值……最后得到的一个模型将是最接近于我们需要的智能模型。
当然,真正实现起来或许没这么简单,但思路应该大抵如此。
注意到坐车网查询出来的坐车方式中一般还有一条出租车的方式,比如:乘坐出租车,共行驶19.2公里,费用约55元。这个用数据挖掘实现起来还是比较有保证的,方法是收集尽可能多的出租车发票作为模型的训练参数。假如不训练出一个模型的话,能做的估计也就是依据两个地点的经纬度用算法算出两点间的距离——可见这个距离是相当不具有参考性的,因为世界上的道路不总是直来直去的。
通过以上对比,不难看出采用数据挖掘的方式的确可以提高工作效率,在信息高度膨胀的今天,掌握效率无疑掌握了经济的咽喉,所以不难推测,这种技术在未来若干年内还是有发展前景的,诸君算是找对门路了。奋斗吧!!哈哈……

