<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>数据挖掘</title>
    <description>讨论各种数据挖掘中使用的方法，交流数据挖掘经验！</description>
    <link>http://datamining.group.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
          <item>
        <title>维数 大家讨论下</title>
        <author>beyondsanli</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://beyondsanli.javaeye.com">beyondsanli</a>&nbsp;
                    链接：<a href="http://datamining.group.javaeye.com/group/blog/191739" style="color:red;">http://datamining.group.javaeye.com/group/blog/191739</a>&nbsp;
          发表时间: 2008年05月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p style="text-indent: 2em; text-align: justify;">我们现在来看由维数概念创造的世界。一个数学世界可以存在于一个点、一条线、一个平面、一个空间或一个超立方体（四维立方体）。每一个高维包含那些比它低的维，但是每一个低维本身就可以成为一个世界。设想你生活的世界是在一个平坦的面上。你不能向上或向下看。<span style="color: #ff0000;">三维生物只要从上面或下面进入你的领域，就能够在你根本不知道的情况下侵犯你的世界。</span>数学家、作家和艺术家曾经在他们的作品中运用各种不同思想试图捕捉不同维的本质。第三维以上的维一直在吸引着人们的兴趣。立方体是最早被用来通过变成超立方体而进入第四维的三维物体之一。左图显示了变成超立方体所经过的各个阶段。现在甚至已经设计出了一些计算机程序，可以利用超立方体各个面的三维透视图来一瞥第四维的视觉形象。</p>
<p style="text-indent: 2em; text-align: justify;">&nbsp;</p>
<p style="text-indent: 2em; text-align: justify;"><img src="C:\Documents and Settings\new\My Documents\My Pictures\2007112205140287.GIF" alt="" /></p>
          <br/>
          <span style="color:red;">
            <a href="http://datamining.group.javaeye.com/group/blog/191739#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 10 May 2008 15:36:00 +0800</pubDate>
        <link>http://datamining.group.javaeye.com/group/blog/191739</link>
        <guid>http://datamining.group.javaeye.com/group/blog/191739</guid>
      </item>
          <item>
        <title>预测型挖掘</title>
        <author>ahuaxuan</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ahuaxuan.javaeye.com">ahuaxuan</a>&nbsp;
                    链接：<a href="http://datamining.group.javaeye.com/group/blog/184884" style="color:red;">http://datamining.group.javaeye.com/group/blog/184884</a>&nbsp;
          发表时间: 2008年04月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          5月份，我又有一个新的挖掘任务，就是根据历史销售记录来分析将来的销售情况。所以需要预先研究一下这个方面的挖掘，以下是我的学习笔记。<br /><br />预测型知识挖掘：<br /> 	顾名思义就是由历史数据和当前数据来推测出未来数据的一种挖掘方式。<br />从上面一句话中的历史，当前，未来三个关键字，我们可以看出时间概念在这次挖掘中将会起到非常重要的作用。 从预测的主要功能上来看，主要是对未来数据的分类和趋势的输出。<br /><br />	统计学中的回归方法等可以通过历史数据直接产生对未来数据的预测的连续值（这个应该就是我要的功能）<br /><br />预测型知识的挖掘可以借助于经典的统计方法，神经网络和机器学习技术。<br /><br />一般来说常见的预测应用模型由如下4种：<br /><br />1，	趋势预测模型<br />针对那些具有时序性的数据，比如销售记录，股票价格，发现长期的趋势变化。有许多来自于统计学的方法经过改造可以用于数据挖掘中，如基于n阶移动平均值，n阶加权（加权，又是加权，加权无处不在）移动平均值。还有一些研究较早的，比如分类（分类的方法太多了，之前我在文本分类中使用的是vsm，在这些纯数据的挖掘中，象bayes，decision等方法应该能比较有效果），关联规则等技术也被应用到趋势预测中。<br /><br />2，	周期分析模式<br />主要是针对那些数据分布和时间依赖性很强的数据进行周期模式的挖掘。例如，服装在某个季节或所有季节的销售周期。近年来这方面的研究备受注目，有比如快速傅立叶变换等统计方法及其改造算法。看来我要着重研究这个周期分析模式。<br /><br />3，	序列模式<br />主要针对历史事情发生的次序的分析形成预测模式来对未来行为进行预测。例如，预测“3年前购买计算机的客户有很大的概率会购买数字相机”。我怎么就觉得这个和推荐算法有千丝万缕的联系呢。<br /><br />4，	神经网络<br />在预测型知识挖掘中，神经网络也是很有用的一个模式结构。我一直觉得这个是最玄的一个东东，目前我也没有对它进行什么深入的研究。<br /><br />通过以上的一些权衡，我觉得周期分析模式应该是我这次任务的主攻方向，希望我能圆满完成任务。
          <br/>
          <span style="color:red;">
            <a href="http://datamining.group.javaeye.com/group/blog/184884#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 21 Apr 2008 13:11:18 +0800</pubDate>
        <link>http://datamining.group.javaeye.com/group/blog/184884</link>
        <guid>http://datamining.group.javaeye.com/group/blog/184884</guid>
      </item>
          <item>
        <title>通过对web日志的挖掘来实现内容推荐系统</title>
        <author>ahuaxuan</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ahuaxuan.javaeye.com">ahuaxuan</a>&nbsp;
                    链接：<a href="http://datamining.group.javaeye.com/group/blog/169512" style="color:red;">http://datamining.group.javaeye.com/group/blog/169512</a>&nbsp;
          发表时间: 2008年03月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          /**<br /><br />*作者：张荣华<br /><br />*日期：2008-3-9<br /><br />**/<br /><br />先说一说问题，不知道大家有没有这样的经验，反正我是经常碰到。<br /><br />        举例1，某些网站每隔几天就发邮件给我，每次发的邮件内容都是一些我根本不感兴趣的东西，我不甚其扰，对其深恶痛绝。<br />        举例2，添加具有某功能的一个msn机器人，每天都有几次突然蹦出一个窗口，推荐一堆我根本不想知道的内容，烦不烦啊， 我只好将你阻止掉。<br /><br />        每一个观众只想看他感兴趣的东西，而不是一下与之无关的事物，那么如何才能知道观众的兴趣所在呢，还是数据挖掘，经过一番思考，终于有点思路，即根据用户以往的浏览历史来预测用户将来的行为，也就是基于内容的推荐。<br />基于内容的推荐（Content-based Recommendation）是信息过滤技术的延续与发展，它是建立在项目的内容信息上作出推荐的，而不需要依据用户对项目的评价意见，更多地需要用机器学习的方法从关于内容的特征描述的事例中得到用户的兴趣资料。在基于内容的推荐系统中，项目或对象是通过相关的特征的属性来定义，系统基于用户评价对象的特征，学习用户的兴趣，考察用户资料与待预测项目的相匹配程度。用户的资料模型取决于所用学习方法，常用的有决策树、神经网络和基于向量的表示方法等。基于内容的用户资料是需要有用户的历史数据，用户资料模型可能随着用户的偏好改变而发生变化。<br /><br /><br />基于内容推荐方法的优点是：<br />1）不需要其它用户的数据，没有冷开始问题和稀疏问题。<br />2）能为具有特殊兴趣爱好的用户进行推荐。<br />3）能推荐新的或不是很流行的项目，没有新项目问题。<br />4）通过列出推荐项目的内容特征，可以解释为什么推荐那些项目。<br />5）已有比较好的技术，如关于分类学习方面的技术已相当成熟。<br /><br /><br />    缺点是要求内容能容易抽取成有意义的特征，要求特征内容有良好的结构性，并且用户的口味必须能够用内容特征形式来表达，不能显式地得到其它用户的判断情况。<br /><br />要实现内容推荐系统总体来说要经过4个大的步骤：<br />1 搜集数据，即搜集用户的行为资料，其中也包括很多方法，根据我找到的资料与以往的经验来看，web日志可以作为我们的切入点，即我们的数据来源。<br /><br />2 过滤数据，web日志中有很多无用的信息，我们要把这些无用的信息排除掉，而且要区分出用户和日志数据之间的联系。<br /><br />3 分析数据，利用分类聚类技术分析出这些日志数据之间的关联性，以及这些日志数据和用户之间的关联性，这也是最重要的一步。<br /><br />4 输出结果。<br /><br />    有了这个思路之后，我们可以着手做第一步，即日志数据的收集<br />我们知道，大多数的web服务器都是有自己的日志记录的，比如说apache安装之后有一个logs目录，其中就有它的日志文件，一般说来它有自己的一个格式，比如说：<br />1浏览器所在主机的 IP 地址(ip)； 2访问日期和时间(date-time)；3客户机与服务器通信所用的方法(methed，get or post)； 4客户机请求访问页面的 URL； 5服务器返回的状态(status)； 6客户端浏览器的类型；<br /><br />   <br />        但是这个日志文件有一些不能克服的问题，或者我不知道如何克服，那么我先说说我的疑问，首先，这个日志文件中记录的是ip地址，据了解，网络中有很多计算机的ip地址是相同的，因为他们在一个统一的路由后面，这个比例可能达到25%。那么我们就无法根据ip地址来唯一确定一个用户。其次，一般的web服务器中都会用多个应用，那么其他应用的访问信息对我们来说有可能是多余的。再者，web服务器的日志形式比较单一，灵活性不大，可定制的余地很小，在日志数据中有效数据所占的比例较小。还有，一些静态文件的请求也会被web服务器记录下来，比如说js文件，css文件，还有图片文件，等等这些东西对内容推荐来说都是无用的资源。<br /><br />        基于上面3点原因，我认为可以自定义日志数据。为了解决用户唯一性，我们让应用为每一个浏览器生成一个clientId保存在对应的浏览器上，这样该浏览器只要访问网站，我们就可以确定这个浏览器的唯一性，当然我们仍然不能确定浏览器使用者的唯一性，但是我们可以更进一步，如果浏览器的使用者登陆网站的话，我们就可以使用用户id来确定用户的唯一性，不过大多数网站用户可能在使用网站的时候并不会登陆，我也是这样，没有关系，即使使用clientId问题也不会太大，随着社会的发展，计算机的拥有量逐渐增加，一般来说一个人只会使用一台固定的电脑，在公司里尤其是这样。所以我认为clientId的方案是可行的，也许有人要问，别人的浏览器禁止了cookie怎么办，那么我只能说没有办法，不过还好事实是绝大多数人都没有这样做。<br /><br />接下来我们可以定义一下我们所需要的日志数据的格式，比如这样，<br />ip，clientId，userId，url，datetime，get or post等等。<br />这样数据有效性会大大提高。<br /><br />在得到较为有效的数据之后，我们还需要对这些数据进行再次过滤：<br />    1 去掉一些非内容的url，这些数据也是无效数据，这些非内容的url需要我们自己手工的统计出来，然后和日志数据中的数据进行比对，将这些非内容数据从日志数据中清除出去。<br />    2 同时我们也需要把post请求从日志数据中清除出去，或者我们在记录日志的时候根本不应该把post请求记录下来。<br /><br /><br />        经过以上步骤之后我们就可以开始第3个阶段了，统计每个用户的访问的url，对这些url进行访问，得到对应的html中所包含的数据，这些数据都是文本，将有用的文本提取出来，然后对这些有用的文本进行聚类。这样就可以得到每个用户喜欢的几个类别。<br /><br />        聚类完成之后我们就可以开始分类了，即把最新的文章或者内容和对应的类别进行匹配，匹配成功之后，我们可以认为这个新文章或者内容可以推荐给对应的用户。<br /><br />        问题：以上的流程只适用于没有使用缓存的系统，但是一般大型的网站都会使用varnish，squid等等，使用它们之后我们就无法得到用户访问的日志数据了，所以如果使用了varnish或者squid，我们不得不再次面对web服务器的日志数据。<br /><br />        在不考虑varnish或者squid的情况下，使用lucene+jamon+htmlparse基本就可以实现以上推荐系统。
          <br/>
          <span style="color:red;">
            <a href="http://datamining.group.javaeye.com/group/blog/169512#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 09 Mar 2008 12:29:44 +0800</pubDate>
        <link>http://datamining.group.javaeye.com/group/blog/169512</link>
        <guid>http://datamining.group.javaeye.com/group/blog/169512</guid>
      </item>
          <item>
        <title>数据挖掘之分类（kNN算法的描述及使用）</title>
        <author>ahuaxuan</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ahuaxuan.javaeye.com">ahuaxuan</a>&nbsp;
                    链接：<a href="http://datamining.group.javaeye.com/group/blog/164435" style="color:red;">http://datamining.group.javaeye.com/group/blog/164435</a>&nbsp;
          发表时间: 2008年02月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          /** <br /><br />*作者：张荣华 <br /><br />*日期：2008-2-23 <br /><br />**/<br /><br /><br />数据挖掘之分类系列文章<br /><br />之前说到分类的基本概念以及一个文本分类的实例，原文地址见：<a href="http://www.javaeye.com/topic/163285" target="_blank">http://www.javaeye.com/topic/163285</a> 现在我们就来改造之前的分类算法，本文主要介绍KNN算法在文本分类器中的使用。<br /><br />kNN算法简介：<br /> kNN(k Nearest Neighbors)算法又叫k最临近方法， 总体来说kNN算法是相对比较容易理解的算法之一，假设每一个类包含多个样本数据，而且每个数据都有一个唯一的类标记表示这些样本是属于哪一个分类， kNN就是计算每个样本数据到待分类数据的距离，取和待分类数据最近的k各样本数据，那么这个k个样本数据中哪个类别的样本数据占多数，则待分类数据就属于该类别。<br />	<br />	基于kNN算法的思想，我们必须找出使用该算法的突破点，本文的目的是使用kNN算法对文本进行分类，那么和之前的文章一样，关键还是项向量的比较问题，之前的文章中的分类代码仅使用的反余弦来匹配项向量，找到关键的“距离”，那么我们可以试想反余弦之后使用kNN的结果如何。<br /><br />	补充上一篇文章中没有详细讲解的反余弦匹配问题：<br />Lucene中有一个term vectors这个东东，它表示该词汇单元在文档中出现的次数，比如说这里有两篇文章，这两篇文章中都有hibernate和spring这两个单词，在第一篇文章中hibernate出现了10次，spring出现了20次，第二篇文章中hibernate出现15次，spring出现10次，那么对第一篇文章来说有两个项向量，分别是hibernate:10,spring:20，第二篇文章类似，hibernate:15,spring:10。然后我们就可以在二维空间的x，y组上表示出来，如图：<br /> <br />这样看来我们其实是要得到两者之间的夹角，计算两个向量之间夹角的公式为A*B/||A||*||B||。按照这个原理我们就可以得到新文章和样本文章之间的距离，代码如下，这个份代码在第一篇文章提供的代码下载中。<br /><pre name="code" class="java">public double caculateVectorSpace(Map&lt;String, Integer> articleVectorMap, Map&lt;String, Integer> classVectorMap) {
		if (articleVectorMap == null || classVectorMap == null) {
			if (logger.isDebugEnabled()) {
				logger.debug("itemVectorMap or classVectorMap is null");
			}
			
			return 20;
		}
		
		int dotItem = 0;
		double denominatorOne = 0;
		double denominatorTwo = 0;
		
		
		for (Entry&lt;String, Integer> entry : articleVectorMap.entrySet()) {
			String word = entry.getKey();
			double categoryWordFreq = 0;
			double articleWordFreq = 0;
			
			if (classVectorMap.containsKey(word)) {
				categoryWordFreq = classVectorMap.get(word).intValue() / classVectorMap.size();
				articleWordFreq = entry.getValue().intValue() / articleVectorMap.size();
			}
			
			dotItem += categoryWordFreq * articleWordFreq;
			denominatorOne += categoryWordFreq * categoryWordFreq;
			denominatorTwo += articleWordFreq * articleWordFreq;
		}
		
		double denominator = Math.sqrt(denominatorOne) * Math.sqrt(denominatorTwo);
		
		double ratio =  dotItem / denominator;
		
		return Math.acos(ratio);
	}
</pre><br />	接着根据kNN的原理，我们记录下待分类数据和样本数据的距离，对每一个待分类数据都找出k个距离最小的样本，最后判断这些样本所在的分类， 这些样本所在的分类就是该新数据应该所在的分类。<br /><br />	那么根据以上的描述，我把结合使用反余弦匹配和kNN结合的过程分成以下几个步骤：<br />1，	计算出样本数据和待分类数据的距离<br />2，	为待分类数据选择k个与其距离最小的样本<br />3，	统计出k个样本中大多数样本所属的分类<br />4，	这个分类就是待分类数据所属的分类<br /><br />根据上面的步骤，我写出了以下代码，这些代码都包含在提供下载的代码里，我将不断的扩充这些代码，可以说一下代码是使用kNN比较核心的代码。<br /><br />MatchCondition这个类包括，待分类数据，样本数据，样本类别，和距离。<br /><pre name="code" class="java">
protected Map&lt;String, List&lt;MatchCondition>> analyse(Map&lt;String, Map&lt;String, Integer>> articleVectorMap, Map&lt;String, Map&lt;String, Integer>> categoryVectorMap) {
		
		Map&lt;String, List&lt;MatchCondition>> result = new HashMap&lt;String, List&lt;MatchCondition>>();
		
		for (Entry&lt;String, Map&lt;String, Integer>> categoryEntry : categoryVectorMap.entrySet()) {
			
			for (Entry&lt;String, Map&lt;String, Integer>> itemEntry : articleVectorMap.entrySet()) {
				double acos = caculateVector(itemEntry.getValue(), filterVectorMap(categoryEntry.getValue()));
				if (acos &lt; vectorGene) {
					if (result.get(itemEntry.getKey()) != null) {
						List&lt;MatchCondition> list = result.get(itemEntry.getKey());
						
						if (list.size() &lt; kNum) {
							list.add(new MatchCondition(itemEntry.getKey(), categoryEntry.getKey(), acos));
						} else {
							if (list.size() == kNum) {
								Collections.sort(list, new MatchConditionComparator());
							}
							
							int n = 0;
							for (MatchCondition condition : list) {
								if (acos &lt; condition.getAcos()) {
									list.set(n, new MatchCondition(itemEntry.getKey(), categoryEntry.getKey(), acos));
								}
								n++;
							}
						}
					} else {
						List&lt;MatchCondition> list = new LinkedList&lt;MatchCondition>();
						list.add(new MatchCondition(itemEntry.getKey(), categoryEntry.getKey(), acos));
						result.put(itemEntry.getKey(), list);
					}
					
				}
			}
			
		}
		
		return result;
	}</pre><br /><br />所有的代码在本文提供的下载代码中，以第一篇文章中的测试数据运行测试，所得的结果为：<br />2008-02-23 14:04:15,646 DEBUG ArticleKNNClassifierImpl:81 - ---------------- The article id is 3<br />2008-02-23 14:04:15,646 DEBUG ArticleKNNClassifierImpl:83 - categoryId : a | count : 1<br />2008-02-23 14:04:15,646 DEBUG ArticleKNNClassifierImpl:81 - ---------------- The article id is 2<br />2008-02-23 14:04:15,646 DEBUG ArticleKNNClassifierImpl:83 - categoryId : b | count : 2<br />2008-02-23 14:04:15,646 DEBUG ArticleKNNClassifierImpl:83 - categoryId : a | count : 3<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:81 - ---------------- The article id is 1<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:83 - categoryId : b | count : 1<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:83 - categoryId : a | count : 4<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:81 - ---------------- The article id is 5<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:83 - categoryId : b | count : 1<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:83 - categoryId : a | count : 4<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:81 - ---------------- The article id is 4<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:83 - categoryId : b | count : 3<br />2008-02-23 14:04:15,656 DEBUG ArticleKNNClassifierImpl:83 - categoryId : a | count : 2<br />从这里我们可以看出articleId为2的应该属于a分类，articleId为1的也属于a分类，articleId为5的也属于a分类，articleId为4的属于b分类。当然其实我们的样本数量太少了，并不能说明acos＋knn结合的的效果。<br /><br />也有人提出了一种结合kNN分类器的加权特征提取问题，该分类通过每次的分类结果不断的调整权值，具有较好的分类效果。所以说虽然kNN算法比较简单，但是事实上如果使用正确，应该也可以收到不错的效果。<br /><br />下一篇关于数据挖掘的文章还是分类问题，不过会使用另外一个算法，就是朴素贝叶斯分类。当然也希望有大家能够在这里交流一下自己的经验。
          <br/>
          <span style="color:red;">
            <a href="http://datamining.group.javaeye.com/group/blog/164435#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 23 Feb 2008 15:18:28 +0800</pubDate>
        <link>http://datamining.group.javaeye.com/group/blog/164435</link>
        <guid>http://datamining.group.javaeye.com/group/blog/164435</guid>
      </item>
          <item>
        <title>数据挖掘之分类</title>
        <author>ahuaxuan</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ahuaxuan.javaeye.com">ahuaxuan</a>&nbsp;
                    链接：<a href="http://datamining.group.javaeye.com/group/blog/163285" style="color:red;">http://datamining.group.javaeye.com/group/blog/163285</a>&nbsp;
          发表时间: 2008年02月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          /**<br /><br />*作者：张荣华<br /><br />*日期：2008-2-19<br /><br />**/<br />随着当代计算机硬件的发展，硬件功能越来越强大，价格越来越低，企业可以记录的数据也越来越多，这些因素就为数据挖掘的普及做了比较好的前提准备，树挖掘是未来信息处理的重要技术，而且就目前而言已经取得了决定性成功而且得到了比较广泛的应用。<br /><br />数据挖掘中有很多领域，分类就是其中之一，什么是分类，<br />分类就是把一些新得数据项映射到给定类别的中的某一个类别，比如说当我们发表一篇文章的时候，就可以自动的把这篇文章划分到某一个文章类别，一般的过程是根据样本数据利用一定的分类算法得到分类规则，新的数据过来就依据该规则进行类别的划分。<br /><br />	分类在数据挖掘中是一项非常重要的任务，有很多用途，比如说预测，即从历史的样本数据推算出未来数据的趋向，有一个比较著名的预测的例子就是大豆学习。再比如说分析用户行为，我们常称之为受众分析，通过这种分类，我们可以得知某一商品的用户群，对销售来说有很大的帮助。<br /><br />分类器的构造方法有统计方法，机器学习方法，神经网络方法等等。常见的统计方法有knn算法，基于事例的学习方法。机器学习方法包括决策树法和归纳法，上面讲到的受众分析可以使用决策树方法来实现。神经网络方法主要是bp算法，这个俺也不太了解。<br /><br /><br />文本分类， 所谓的文本分类就是把文本进行归类，不同的文章根据文章的内容应该属于不同的类别，文本分类离不开分词，要将一个文本进行分类，首先需要对该文本进行分词，利用分词之后的的项向量作为计算因子，再使用一定的算法和样本中的词汇进行计算，从而可以得出正确的分类结果。在这个例子中，我将使用庖丁分词器对文本进行分词。<br /><br />下面这个例子将使用反余弦进行词汇单元进行匹配，<br />第一步，训练样本：<br /><pre name="code" class="java">protected Map&lt;String, Map&lt;String, Integer>> getClassVector(List&lt;Category> categoryList) throws Exception {
		
		if (categoryList == null || categoryList.size() == 0) {
			if (logger.isDebugEnabled()) {
				logger.debug("The list of new categoryList which should be classified is null or size = 0");
			}
			return Collections.emptyMap();
		}
		
		Map&lt;String, Map&lt;String, Integer>> categoryMap = new HashMap&lt;String, Map&lt;String, Integer>>();
		
		Directory ramDir = new RAMDirectory();
		IndexWriter writer = new IndexWriter(ramDir, new PaodingAnalyzer(), true);
		
		for (Category cRc : categoryList) {
			for (Article item : cRc.getArticleList()) {
				
				Document doc = new Document();
				doc.add(new Field("description", item.getContent(), Field.Store.NO,
						Field.Index.TOKENIZED, TermVector.YES));
				doc.add(new Field("category", cRc.getId().toString(), Field.Store.YES, Field.Index.NO));
				writer.addDocument(doc);
			}
		}
		
		if (logger.isDebugEnabled()) {
			logger.debug("Generate the index in the memory, the size of categoryList list is " + categoryList.size());
		}
		
		writer.close();
		
		buildContentVectors(ramDir, categoryMap, "category", "description");
		return categoryMap;
		
	}
</pre><br />第二步：对待分类的文章进行分词（原理和样本训练类似）：<br /><pre name="code" class="java">
protected Map&lt;String, Map&lt;String, Integer>> getArticleVector(List&lt;Article> articleList) throws Exception {
		if (articleList == null || articleList.size() == 0) {
			if (logger.isDebugEnabled()) {
				logger.debug("The list of articles which should be classified is null or size = 0");
			}
		}
		
		Map&lt;String, Map&lt;String, Integer>> articleMap = new HashMap&lt;String, Map&lt;String, Integer>>();
		
		Directory articleRamDir = new RAMDirectory();
//		IndexWriter writer = new IndexWriter(articleRamDir, new ChineseAnalyzer(), true);
		IndexWriter writer = new IndexWriter(articleRamDir, new PaodingAnalyzer(), true);
		
		for (Article article : articleList) {
			Document doc = new Document();
			doc.add(new Field("articleId", article.getId(),
					Field.Store.YES, Field.Index.NO));
			doc.add(new Field("description", article.getContent(), Field.Store.NO, Field.Index.TOKENIZED, TermVector.YES));
			writer.addDocument(doc);
		}
		
		writer.flush();
		writer.close();
		
		buildContentVectors(articleRamDir, articleMap, "articleId", "description");
		return articleMap;
	}
</pre><br />分类的核心算法(下面这段代码的原理来自于lucene in action)：<br /><pre name="code" class="java">public double caculateVectorSpace(Map&lt;String, Integer> articleVectorMap, Map&lt;String, Integer> classVectorMap) {
		if (articleVectorMap == null || classVectorMap == null) {
			if (logger.isDebugEnabled()) {
				logger.debug("itemVectorMap or classVectorMap is null");
			}
			
			return 20;
		}
		
		int dotItem = 0;
		double denominatorOne = 0;
		double denominatorTwo = 0;
		
		
		for (Entry&lt;String, Integer> entry : articleVectorMap.entrySet()) {
			String word = entry.getKey();
			double categoryWordFreq = 0;
			double articleWordFreq = 0;
			
			if (classVectorMap.containsKey(word)) {
				categoryWordFreq = classVectorMap.get(word).intValue() / classVectorMap.size();
				articleWordFreq = entry.getValue().intValue() / articleVectorMap.size();
			}
			
			dotItem += categoryWordFreq * articleWordFreq;
			denominatorOne += categoryWordFreq * categoryWordFreq;
			denominatorTwo += articleWordFreq * articleWordFreq;
		}
		
		double denominator = Math.sqrt(denominatorOne) * Math.sqrt(denominatorTwo);
		
		double ratio =  dotItem / denominator;
		
		return Math.acos(ratio);
	}
</pre><br />效果：<br />测试数据：<br /><pre name="code" class="java">
public static List&lt;Category> prepareCategoryList() {
		List&lt;Category> categoryList = new ArrayList&lt;Category>();
		List&lt;Article> articleList = new ArrayList&lt;Article>();
		
		Category c = new Category();
		c.setArticleList(articleList);
		c.setId("1");
		categoryList.add(c);
		
		Article a1 = new Article();
		a1.setId("1");
		a1.setTitle("Hibernate初探");
		a1.setContent("开始看Hibernate reference,运行hibernate的test中的代码。 Environment是一个非常重要的类。它定义了很多常量，最重要的是hibernate的入口在这里。");
		
		Article a2 = new Article();
		a2.setId("2");
		a2.setTitle("Hibernate SQL方言");
		a2.setContent("PO的数据类型设置 int 还是Integer Integer 允许为 null Hibernate 既可以访问Field也可以访问Property");
		
		Article a3 = new Article();
		a3.setId("3");
		a3.setTitle("Hibernate 杂烩");
		a3.setContent("Hibernate 中聚合函数的使用 Criteria接口的Projections类主要用于帮助Criteria接口完成数据的分组查询和统计功能:");
		
		Article a4 = new Article();
		a4.setId("4");
		a4.setTitle("Hibernate映射类型");
		a4.setContent("Hibernate映射类型Hibernate映射类型,对应的基本类型及对应的标准SQL类型");
		
		
		articleList.add(a1);
		articleList.add(a2);
		articleList.add(a3);
		articleList.add(a4);
		
		return categoryList;
	}
	
	public static List&lt;Article> prepareArticleList() {
		List&lt;Article> articleList = new ArrayList&lt;Article>();
		Article a1 = new Article();
		a1.setId("1");
		a1.setTitle("Hibernate学习笔记(一)");
		a1.setContent("本笔记的内容: 分层体系结构 ORM介绍 Hibernate简介 Hibernate开发步骤 Hibernate核心API ");
		
		Article a2 = new Article();
		a2.setId("2");
		a2.setTitle("Hibernate的性能问题");
		a2.setContent("各位老大，使用hibernate做企业级别的应用，会不会有性能问题啊？比如大数据量的搜索或者客户端同时大量的请求，会不会严重影响性能啊？有没有什么好的解决办法? 谢了先!");
		
		Article a3 = new Article();
		a3.setId("3");
		a3.setTitle("Spring2.5全面支持JEE5的实现");
		a3.setContent("Spring 2.5 发布已经有一段时间了，一直没有时间研究一下，只是听说有很多方面的提升。有一点十分重要的就是全面支持JEE5风格的annotation。");
		
		Article a4 = new Article();
		a4.setId("4");
		a4.setTitle("谈谈Spring的SqlMapClientTemplate对SqlMapClientCallback");
		a4.setContent("谈谈Spring的SqlMapClientTemplate对SqlMapClientCallback的使用 ■记得以前在看SqlMapClientTemplate的源代码的时候，下面的这两段代码硬是没看懂当时我很疑惑：真的有必要用到内部匿名类这样诡异的手法么？");
		
		Article a5 = new Article();
		a5.setId("5");
		a5.setTitle("spring 2.0 学习笔记");
		a5.setContent("前几天学习hibernate!在mysql下都能正常跑出来.! 但是我一换成oracle就出现下面这种情况: 小弟不解呀..google了很多次也解决不了此问题::.希望老大门帮忙看一下哈.!!! 环境:MyEclipse5.5,hibernate2.0,spring2.0");
		
		articleList.add(a1);
		articleList.add(a2);
		articleList.add(a3);
		articleList.add(a4);
		articleList.add(a5);
		
		return articleList;
	}
</pre><br />以上测试代码中的数据来源于javaeye的文章。<br />输出：<br />2008-02-19 11:05:42,031 DEBUG ArticleClassifierImpl:74 - articleId=2---------acos value=1.412016112149136<br />2008-02-19 11:05:42,031 DEBUG ArticleClassifierImpl:74 - articleId=1---------acos value=1.3258176636680326<br />2008-02-19 11:05:42,031 DEBUG ArticleClassifierImpl:74 - articleId=5---------acos value=1.4244090675006476<br /><br />有此可见文章id号为1,2,5的文章符合hibernate分类，事实上我们还要更进一步，假设我们有两个分类，hibernate，spring，各有5各样本，那么最后的结果应该再次作最小符合判断，acos值最小的则认为该article属于该分类，同学们可以自己做一下实验。<br /><br />文本分类中有很多注意点，比如说噪音词去除（上面的代码中并包括最简单的噪音词去除功能）等，接下来我会使用knn算法改造以上代码，并使用相同的测试数据并比对测试结果。
          <br/>
          <span style="color:red;">
            <a href="http://datamining.group.javaeye.com/group/blog/163285#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 19 Feb 2008 11:21:03 +0800</pubDate>
        <link>http://datamining.group.javaeye.com/group/blog/163285</link>
        <guid>http://datamining.group.javaeye.com/group/blog/163285</guid>
      </item>
      </channel>
</rss>