<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>标点符 &#187; 网站开发</title>
	<atom:link href="http://www.biaodianfu.com/category/web-development/feed" rel="self" type="application/rss+xml" />
	<link>http://www.biaodianfu.com</link>
	<description>编译自己的互联网生活</description>
	<lastBuildDate>Wed, 08 Feb 2012 08:42:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>基于综合兴趣度的协同过滤推荐算法</title>
		<link>http://www.biaodianfu.com/collaborative-filtering-recommendation-algorithm.html</link>
		<comments>http://www.biaodianfu.com/collaborative-filtering-recommendation-algorithm.html#comments</comments>
		<pubDate>Wed, 08 Feb 2012 08:42:34 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[协同过滤]]></category>
		<category><![CDATA[推荐算法]]></category>
		<category><![CDATA[推荐系统]]></category>
		<category><![CDATA[综合兴趣度]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4634</guid>
		<description><![CDATA[1 概述 电子商务推荐系统最大的优点在于它能收集用户的兴趣资料和个人信息，根据用户兴趣偏好主动为用户做出个性化推荐。推荐技术指的是如何找出用户感兴趣的商品并列出推荐清单，在用户信息获取差别不大的情况下，推荐技术成为决定一个推荐系统性能的关键，其中推荐算法是推荐技术的核心[1]。 协同过滤技术是实际应用中使用最广泛的推荐技术，包括Amazon.com 在内许多网上书店都在使用协同过滤技术。协同过滤是一种基于用户间关联性的推荐算法，该推荐方法将购买习惯或兴趣相同的用户归类在同一个群体中，同群体内的用户彼此之间可以分享信息，互相推荐商品。应用协同过滤技术的著名的推荐系统包括GroupLens/NetPerceptions[2], Ringo/Firefly[3], Tapestry[4]等。协同过滤技术存在的不足主要表现为最近邻居的准确性问题，即在客户对商品评分数据比较少的时候，单纯地使用客户的注册兴趣信息和评分数据难以准确地确定最近邻居，从而导致推荐质量降低，这种问题是协同过滤技术本身无法克服的，需要对其进行改进。 本文针对协同过滤算法中的最近邻居判断准确性问题，综合显性兴趣度、隐形兴趣度和预测兴趣度3 种用户兴趣指标提出了综合兴趣度的概念，并将这种基于综合兴趣度的协同过滤方法应用于一种图书推荐系统中。实验结果表明，该方法提高了计算用户最近邻居的准确性，进而对推荐系统的推荐质量起到了明显的优化作用。 2 基于综合兴趣度的协同过滤方法 协同过滤方法的关键在于确定用户的最近邻居，确定最近邻居的基础是计算用户之间的相似性，兴趣度是计算用户相似性的重要指标。一般来说，用户相似性计算方法包括余弦相似性、修正的余弦相似性、相关相似性等[5]。传统的兴趣度计算方法主要考虑用户提供的注册信息和显性商品评分，即显性兴趣度，由于显性兴趣不能完整地体现用户真实兴趣，因此上述3 种方法在单纯采用显性兴趣度计算用户相似性方面均存在一定的缺陷[6]。采用余弦相似性度量时，对于未评分商品的兴趣评分都设为0，即兴趣度相同，但事实上用户对未评商品类的兴趣度不可能完全相同。修正的余弦相似性采取了对未评分项目设置平均评分值的改良措施，但仍未有效解决问题。 相关相似性度量仅对都有评分的项目进行度量，这在有共同评分项目较多的情况下较为准确，若在共同评分项目较少时，则偏差可能较大。 在心理学中，人的兴趣包括主观的表述、客观的描述及基于知识和经验有可能发生的兴趣预期。具体到推荐系统中，主观的兴趣表述可以理解为用户在兴趣调查表中主动提供本人的兴趣倾向，这种表述相对固定，属于显性兴趣度。用户的浏览行为反映了用户的实际需要，浏览的行为不断变动往往表示原有兴趣的调整，这是用户兴趣的客观描述，属于隐性兴趣度。 在用户的未评分项目中，用户未来的评分可通过分析项目的特性和用户的兴趣规律进行预测，这是根据已有资料对用户兴趣的合理预期，属于预测兴趣度。一些学者在研究中提到了利用用户浏览行为计算用户隐性兴趣度[7]或用商品间的关联信息预测用户对某些商品的评分情况[8]的思想，但这些方法仅考虑了用户兴趣中的一部分，并没有完整地描述用户兴趣。 因此，本文提出了结合显性兴趣度、隐性兴趣度(统称为已有兴趣度)和预测兴趣度的综合兴趣度的概念，综合兴趣度能使用户间的相似性度量更为准确，更完整地反映用户的兴趣倾向。基于综合兴趣度的协同过滤方法包括以下步骤： 获取用户对商品的兴趣评分，结合对用户浏览行为的分析得到已有兴趣度； 结合已有兴趣度和预测兴趣度，分析用户之间兴趣的相似程度，选取一群与用户有相近兴趣的最近邻居； 从最近邻居感兴趣的商品中，预测用户对某一商品的喜好，最终产生推荐结果。 2.1 已有兴趣度的获取 很多早期的协同过滤系统往往只采用显性兴趣度产生推荐，显性评分的信息一般较为准确，但由于用户注册时一般填写的项目不多，用户有共同显性评分的项目更为稀少，若单独以此进行用户相似程度的比较，误差较大，因此需要综合隐性评分，提高用户间相似程度判定的准确性。已有兴趣度的获取包括显性兴趣度获取和隐性兴趣度获取2 部分。 显性兴趣度来源于用户的显式评分，需要用户有意识地表达自己对商品信息的认同程度。一般的协同过滤推荐方法常用整数值(如1~9 等级)来表示喜欢的不同程度，本算法以规范化成0~1 的兴趣度表示。设Re(i,j)为用户i 对全部n 个商品类中的商品类j 的显性兴趣度，1 表示全部显性兴趣，则有： 隐性兴趣度来源于用户对商品的浏览行为信息。在用户-商品矩阵中，评分数据为用户浏览过该商品的次数，0 表示尚未发生兴趣，次数越多则兴趣越高。隐性兴趣度的获取方法较为简单，可从用户的浏览记录库中得到隐性兴趣度。对于某个商品类的隐性兴趣评分，可用用户浏览的该商品类在其整个浏览记录中的比例表示。设Ri(i,j)表示用户i 对全部n个商品类中的类j 的隐性兴趣度，1 表示全部隐性兴趣，则有： 通过上述的方法得到显性兴趣度和隐性兴趣度后，将两者结合，形成用户的已有兴趣度，以线性关系结合这2 个兴趣度，得到用户i 对商品类j 的已有兴趣度： 其中，α 为显性兴趣度的比重参数，α 取值越大则显性兴趣度越为重要；m 表示在浏览记录数据库中该用户浏览商品的总数。 2.2 综合兴趣度的获取与最近邻居的形成 在获取综合兴趣度之前，首先必须获得预测兴趣度，本文利用商品的属性分类关系和顾客所购物的关联性，建立商品的属性向量表达式和顾客的兴趣向量表达式，从而预测用户对某未评分商品的兴趣度。首先将所有的商品分类，建成一个有阶层的分类树，每个商品属于分类树的最底层中的其中一类，最底层的每一类对应一个商品属性，然后将所有属性构成每个商品的属性向量。属性权重的设定根据商品在分类树中所在的类别与其他类别的分类关系，及类别之间的关联规则。其中，关联规则是根据顾客的购买记录在各层类别中的分布，挖掘每一层中同层类别之间的关联规则。假设在全部n 个商品类中，每个商品类作为特征项，则任一商品类j 可以表示为一个n 维特征向量： 其中， Ps, j 为第s 个特征项的权重，本系统将Ps, [...]]]></description>
			<content:encoded><![CDATA[<p align="left"><strong>1 概述</strong></p>
<p align="left">电子商务推荐系统最大的优点在于它能收集用户的兴趣资料和个人信息，根据用户兴趣偏好主动为用户做出个性化推荐。推荐技术指的是如何找出用户感兴趣的商品并列出推荐清单，在用户信息获取差别不大的情况下，推荐技术成为决定一个推荐系统性能的关键，其中推荐算法是推荐技术的核心[1]。</p>
<p align="left">协同过滤技术是实际应用中使用最广泛的推荐技术，包括Amazon.com 在内许多网上书店都在使用协同过滤技术。协同过滤是一种基于用户间关联性的推荐算法，该推荐方法将购买习惯或兴趣相同的用户归类在同一个群体中，同群体内的用户彼此之间可以分享信息，互相推荐商品。应用协同过滤技术的著名的推荐系统包括GroupLens/NetPerceptions[2], Ringo/Firefly[3], Tapestry[4]等。协同过滤技术存在的不足主要表现为最近邻居的准确性问题，即在客户对商品评分数据比较少的时候，单纯地使用客户的注册兴趣信息和评分数据难以准确地确定最近邻居，从而导致推荐质量降低，这种问题是协同过滤技术本身无法克服的，需要对其进行改进。</p>
<p align="left">本文针对协同过滤算法中的最近邻居判断准确性问题，综合显性兴趣度、隐形兴趣度和预测兴趣度3 种用户兴趣指标提出了综合兴趣度的概念，并将这种基于综合兴趣度的协同过滤方法应用于一种图书推荐系统中。实验结果表明，该方法提高了计算用户最近邻居的准确性，进而对推荐系统的推荐质量起到了明显的优化作用。</p>
<p align="left"><strong>2 基于综合兴趣度的协同过滤方法</strong></p>
<p align="left">协同过滤方法的关键在于确定用户的最近邻居，确定最近邻居的基础是计算用户之间的相似性，兴趣度是计算用户相似性的重要指标。一般来说，用户相似性计算方法包括余弦相似性、修正的余弦相似性、相关相似性等[5]。传统的兴趣度计算方法主要考虑用户提供的注册信息和显性商品评分，即显性兴趣度，由于显性兴趣不能完整地体现用户真实兴趣，因此上述3 种方法在单纯采用显性兴趣度计算用户相似性方面均存在一定的缺陷[6]。采用余弦相似性度量时，对于未评分商品的兴趣评分都设为0，即兴趣度相同，但事实上用户对未评商品类的兴趣度不可能完全相同。修正的余弦相似性采取了对未评分项目设置平均评分值的改良措施，但仍未有效解决问题。</p>
<p align="left">相关相似性度量仅对都有评分的项目进行度量，这在有共同评分项目较多的情况下较为准确，若在共同评分项目较少时，则偏差可能较大。</p>
<p align="left">在心理学中，人的兴趣包括主观的表述、客观的描述及基于知识和经验有可能发生的兴趣预期。具体到推荐系统中，主观的兴趣表述可以理解为用户在兴趣调查表中主动提供本人的兴趣倾向，这种表述相对固定，属于显性兴趣度。用户的浏览行为反映了用户的实际需要，浏览的行为不断变动往往表示原有兴趣的调整，这是用户兴趣的客观描述，属于隐性兴趣度。</p>
<p align="left">在用户的未评分项目中，用户未来的评分可通过分析项目的特性和用户的兴趣规律进行预测，这是根据已有资料对用户兴趣的合理预期，属于预测兴趣度。一些学者在研究中提到了利用用户浏览行为计算用户隐性兴趣度[7]或用商品间的关联信息预测用户对某些商品的评分情况[8]的思想，但这些方法仅考虑了用户兴趣中的一部分，并没有完整地描述用户兴趣。</p>
<p align="left">因此，本文提出了结合显性兴趣度、隐性兴趣度(统称为已有兴趣度)和预测兴趣度的综合兴趣度的概念，综合兴趣度能使用户间的相似性度量更为准确，更完整地反映用户的兴趣倾向。基于综合兴趣度的协同过滤方法包括以下步骤：</p>
<ol>
<li>
<div align="left">获取用户对商品的兴趣评分，结合对用户浏览行为的分析得到已有兴趣度；</div>
</li>
<li>
<div align="left">结合已有兴趣度和预测兴趣度，分析用户之间兴趣的相似程度，选取一群与用户有相近兴趣的最近邻居；</div>
</li>
<li>
<div align="left">从最近邻居感兴趣的商品中，预测用户对某一商品的喜好，最终产生推荐结果。</div>
</li>
</ol>
<p align="left"><strong>2.1 已有兴趣度的获取</strong></p>
<p align="left">很多早期的协同过滤系统往往只采用显性兴趣度产生推荐，显性评分的信息一般较为准确，但由于用户注册时一般填写的项目不多，用户有共同显性评分的项目更为稀少，若单独以此进行用户相似程度的比较，误差较大，因此需要综合隐性评分，提高用户间相似程度判定的准确性。已有兴趣度的获取包括显性兴趣度获取和隐性兴趣度获取2 部分。</p>
<p align="left">显性兴趣度来源于用户的显式评分，需要用户有意识地表达自己对商品信息的认同程度。一般的协同过滤推荐方法常用整数值(如1~9 等级)来表示喜欢的不同程度，本算法以规范化成0~1 的兴趣度表示。设<em>Re</em>(<em>i</em>,<em>j</em>)为用户<em>i </em>对全部<em>n </em>个商品类中的商品类<em>j </em>的显性兴趣度，1 表示全部显性兴趣，则有：</p>
<p align="left"><img class="alignnone size-full wp-image-4635" title="xianxin" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/xianxin.png" alt="" width="280" height="41" /></p>
<p align="left">隐性兴趣度来源于用户对商品的浏览行为信息。在用户-商品矩阵中，评分数据为用户浏览过该商品的次数，0 表示尚未发生兴趣，次数越多则兴趣越高。隐性兴趣度的获取方法较为简单，可从用户的浏览记录库中得到隐性兴趣度。对于某个商品类的隐性兴趣评分，可用用户浏览的该商品类在其整个浏览记录中的比例表示。设Ri(i,j)表示用户i 对全部n个商品类中的类j 的隐性兴趣度，1 表示全部隐性兴趣，则有：</p>
<p align="left"><img class="alignnone size-full wp-image-4636" title="yinxin" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/yinxin.png" alt="" width="268" height="45" /></p>
<p align="left">通过上述的方法得到显性兴趣度和隐性兴趣度后，将两者结合，形成用户的已有兴趣度，以线性关系结合这2 个兴趣度，得到用户i 对商品类j 的已有兴趣度：</p>
<p align="left"><img class="alignnone size-full wp-image-4637" title="xinqudu" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/xinqudu.png" alt="" width="349" height="45" /></p>
<p align="left">其中，α 为显性兴趣度的比重参数，α 取值越大则显性兴趣度越为重要；m 表示在浏览记录数据库中该用户浏览商品的总数。</p>
<p align="left"><strong>2.2 综合兴趣度的获取与最近邻居的形成</strong></p>
<p align="left">在获取综合兴趣度之前，首先必须获得预测兴趣度，本文利用商品的属性分类关系和顾客所购物的关联性，建立商品的属性向量表达式和顾客的兴趣向量表达式，从而预测用户对某未评分商品的兴趣度。首先将所有的商品分类，建成一个有阶层的分类树，每个商品属于分类树的最底层中的其中一类，最底层的每一类对应一个商品属性，然后将所有属性构成每个商品的属性向量。属性权重的设定根据商品在分类树中所在的类别与其他类别的分类关系，及类别之间的关联规则。其中，关联规则是根据顾客的购买记录在各层类别中的分布，挖掘每一层中同层类别之间的关联规则。假设在全部n 个商品类中，每个商品类作为特征项，则任一商品类j 可以表示为一个n 维特征向量：</p>
<p align="left"><img class="alignnone size-full wp-image-4638" title="pj" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/pj.png" alt="" width="213" height="31" /></p>
<p align="left">其中， Ps, j 为第s 个特征项的权重，本系统将Ps, j 的取值规定为</p>
<p align="left"><img class="alignnone size-full wp-image-4639" title="psj" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/psj.png" alt="" width="231" height="153" /></p>
<p align="left">其中，C(s)和C( j ) 表示商品类s 和j 的父类；s⇒j 表示s和j 之间存在强关联关系。得到每个类的特征向量后，就得到类间的一种关联关系，通过这种关系，可以利用已评分类预测未评分类。设经用户i 已评分的类集合用Ai 表示，k ∈Ai，未评分商品类m∉Ai，Ri,k 表示用户i 对已评分类k 的兴趣度，那么用户i 对未评分的类j 的预期值Pri,j 为</p>
<p align="left"><img class="alignnone size-full wp-image-4640" title="prij" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/prij.png" alt="" width="335" height="69" /></p>
<p align="left">规范化处理使全部的预期兴趣度为 1，则用户i 对未评类j 的预期兴趣度i, j Rp 为</p>
<p align="left"><img class="alignnone size-full wp-image-4641" title="rpij" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/rpij.png" alt="" width="112" height="63" /></p>
<p align="left">为了结合已有兴趣度和预期兴趣度，设定系数β (0≤β ≤1)以平衡已有兴趣度与预期兴趣度的比例，得到综合兴趣度：</p>
<p align="left"><img class="alignnone size-full wp-image-4642" title="zonghexinqudu" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/zonghexinqudu.png" alt="" width="216" height="59" /></p>
<p align="left">判别 2 个用户是否是邻居需要比较这2 个用户的兴趣相似性，相似性度量方法常用的有余弦相似性、修正的余弦相似性和相关相似性等。</p>
<p align="left">由于按照本文的方法可得到较为完整的兴趣评分，因此本文采用余弦相似性作为度量方法。设用户i 和用户j 在n维类上的兴趣度分别表示为向量i 和j，则用户i 和用户j 之间的相似性sim(i,j)为</p>
<p align="left"><img class="alignnone size-full wp-image-4643" title="simij" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/simij.png" alt="" width="333" height="87" /></p>
<p align="left">其中， &#8216;Ri,d 和&#8217;Rj,d 分别表示用户i 和用户j 对类d 的兴趣度。</p>
<p align="left">寻找最近邻居的目标就是对每一个用户u，在整个用户空间中查找用户集合D=(d1,d2,…,dk)，使得u ∉D，并且d1 与u 的相似性sim(u,d1)最高，d2 与u 的相似性sim(u,d2)次之，依此类推。</p>
<p align="left"><strong>2.3 推荐结果的产生</strong></p>
<p align="left">通过上述的相似性度量方法得到目标用户的最近邻居 后，需要利用最近邻居的观点为目标用户产生相应的商品推荐 。常用的预测目标用户未评分项目评分的方法是综合最近邻居对未评分项目的评分，作为目标用户对预测项目的评分。</p>
<p align="left">本文采用最频项推荐为目标用户产生Top-N 推荐：在浏览记录库中，扫描目标用户每个最近邻居的浏览记录，对其浏览的商品进行计数，选择出现频率最高且目标用户尚未浏览过的前N 个商品作为推荐内容。设目标用户u 浏览商品的集合为A，最近邻居浏览商品的集合为D，候选推荐商品的集合<br />
C=D-A，候选商品b ∈A，那么候选商品b 对于用户u 的推荐度Recb,u 为</p>
<p align="left"><img class="alignnone size-full wp-image-4644" title="recbu" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/recbu.png" alt="" width="185" height="82" /></p>
<p align="left">其中， d ,bd CCount∈ Σ为浏览过商品b 的的最近邻居的数目；Sumc为最近邻居总数。</p>
<p align="left"><strong>3 实验及结果分析</strong></p>
<p align="left">为了验证本系统的推荐效果，在小范围内进行了实验，用平均绝对偏差作为测量标准对协同过滤推荐的实验结果进行了度量，并通过对比分析验证了基于综合兴趣度的方法的有效性。</p>
<p align="left"><strong>3.1 实验过程与评价标准</strong></p>
<p align="left">为了方便测试，实验前系统录入了约 1 000 本计算机书籍，邀请了某公司82 个员工参与实验，实验期为1 个月。实验的前20 天为用户自由浏览时间，系统不产生推荐，要求实验用户进行注册及填写显性评分，实验的后10 天系统为注册用户产生推荐清单，并要求用户对每个推荐书目进行满意程<br />
度反馈。</p>
<p align="left">本文评价协同过滤推荐效果时，采用平均绝对偏差(Mean Absolute Error, MAE)作为测量推荐系统满意度的公式，MAE 用于测量推荐值与实际评价值之间的偏差，可以直观地度量推荐质量，MAE 越小，推荐质量越高[9]。本实验用户u 的平均绝对偏差为</p>
<p align="left"><img class="alignnone size-full wp-image-4645" title="MAEu" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/MAEu.png" alt="" width="175" height="68" /></p>
<p align="left">其中，n 为Top-N 的推荐总数； pu,i 为实际评分； qu,i为相应的预测评分。</p>
<p align="left"><strong>3.2 实验结果分析</strong></p>
<p align="left">系统得到实验数据后，分别在推荐 Top-10, Top-20 和Top-30 的范围内，将实验用户的推荐结果及其反馈的满意度进行比较，然后分别利用平均绝对偏差公式对基于综合兴趣度的方法和传统的基于显性兴趣度的方法进行计算。计算的结果如表1 所示，对比分析如图1 所示。</p>
<p align="left"><img class="alignnone size-full wp-image-4646" title="MAE" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/MAE.png" alt="" width="443" height="222" /></p>
<p align="left">从图1 可知，MAE 值在0.12~0.17 之间，表明系统能起到较好的推荐效果，随着Top-N 数量增多，MAE 值呈下降趋势，表明了Top-N 中N 值较大时用户满意度高。</p>
<p align="left"><img class="alignnone size-full wp-image-4647" title="top-n" src="http://www.biaodianfu.com/wp-content/uploads/2012/02/top-n.png" alt="" width="334" height="307" /></p>
<p align="left">传统的协同过滤方法仅使用显性兴趣度作为用户相似性的计算指标，其计算最近邻居的准确度较低，从实验结果可看出其MAE 值较高，推荐质量不高。</p>
<p align="left">本文的推荐方法使用了综合兴趣度作为用户相似度的计算指标，实验表明在相同条件下MAE 值有了明显的降低，可见基于综合兴趣度的推荐方法能够有效地提高协同推荐系统的推荐质量。</p>
<p align="left">参考文献<br />
[1] Varian R. Recommender Systems[J]. Communications of the ACM,1997, 40(3): 56-58.<br />
[2] Resnick P, Iacovou N, Suchak M. Grouplens: An Open Architecturefor Collaborative Filtering of Netnews[C]//Proc. of the Conference on Computer Supported Cooperative Work. Chapel Hill, NC, USA: [s. n.], 1994: 175-186.<br />
[3] Shardanand U, Maes P. Social Information Filtering: Algorithms for Automating “Word of Mouth”[C]//Proc. of the ACM CHI Conference. Denver, Colorado, USA: [s. n.], 1995.<br />
[4] Goldbergd N D, Oki B M. Using Collaborative Filtering to Weave an Information Apestry[J]. Communications of the ACM, 1992, 35(12): 61-70.<br />
[5] Sarwar B M, karypis G, Konstan J A, et al. Item-based Collaborative Filtering Recommendation Algorithms[C]//Proc. of the 10th International World Wide Web Conf.. Hong Kong, China: [s. n.], 2001: 285-295.<br />
[6] 邓爱林, 朱扬勇, 施伯乐. 基于项目评分预测的协同过滤推荐算法[J]. 软件学报, 2003, 14(9): 1621- 1628.<br />
[7] 陈东林, 聂规划. 基于商品属性隐性评分的协同过滤算法研究[J]. 计算机应用, 2006, 26(4): 966-968.<br />
[8] 白丽君, 刘君强. 一种解决协作过滤中矩阵稀疏性问题的算法[J]. 情报学报, 2005, 24(2): 199-202.<br />
[9] Breese J S, Kadie C. Empirical Analysis of Predictive Algorithms forCollaborative Filtering[C]//Proc. of the Conference on Uncertainty in Artificial Intelligence. Madison, Wisconsin, USA: [s. n.], 1998.</p>
<p align="left"><strong>本文作者：秦光洁，张颖 (长安大学信息工程学院，西安 710064)</strong></p>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/comparison-study-of-internet-recommendation-system.html' rel='bookmark' title='互联网推荐系统比较研究'>互联网推荐系统比较研究</a></li>
<li><a href='http://www.biaodianfu.com/serve-keymatch.html' rel='bookmark' title='Google Search Appliance 关键字匹配'>Google Search Appliance 关键字匹配</a></li>
<li><a href='http://www.biaodianfu.com/rfm-model.html' rel='bookmark' title='电子商务与RFM模型'>电子商务与RFM模型</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/collaborative-filtering-recommendation-algorithm.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用Python来连接MySQL</title>
		<link>http://www.biaodianfu.com/python-mysql.html</link>
		<comments>http://www.biaodianfu.com/python-mysql.html#comments</comments>
		<pubDate>Tue, 31 Jan 2012 01:07:39 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4625</guid>
		<description><![CDATA[本来以为使用Python安装MySQL是件容易的事，但是发现，不管怎样每次安装编译都不通过。强大的pip install mysql-python 不再管用。报错内容为： Traceback (most recent call last): File &#34;setup.py&#34;, line 15, in &#60;module&#62; metadata, options = get_config() File &#34;D:\MySQL-python-1.2.3\setup_windows.py&#34;, li ne 7, in get_config serverKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, options[&#039;registry_ke y&#039;]) WindowsError: [Error 2] 在网上找了很久都没有找到解决方案，于是在QQ群里问了下，找到了一个做好的安装包，迅速的解决了此问题。 安装包下载地址：http://code.google.com/p/soemin/downloads/list 以下为一个简单的使用python向MySQL插入数据的代码，仅供参考： import MySQLdb db = MySQLdb.connect(host=&#34;localhost&#34;, user=&#34;root&#34;, passwd=&#34;root&#34;,db=&#34;slopeone&#34;) cursor = db.cursor() f = open(&#34;sample.data&#34;, &#34;r&#34;) for line in f: [...]]]></description>
			<content:encoded><![CDATA[<p>本来以为使用Python安装MySQL是件容易的事，但是发现，不管怎样每次安装编译都不通过。强大的pip install mysql-python 不再管用。报错内容为：</p>
<pre class="brush: shell; gutter: false">Traceback (most recent call last):
  File &quot;setup.py&quot;, line 15, in &lt;module&gt;
    metadata, options = get_config()
  File &quot;D:\MySQL-python-1.2.3\setup_windows.py&quot;, li
ne 7, in get_config
    serverKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, options[&#039;registry_ke
y&#039;])
WindowsError: [Error 2]</pre>
<p>在网上找了很久都没有找到解决方案，于是在QQ群里问了下，找到了一个做好的安装包，迅速的解决了此问题。</p>
<p>安装包下载地址：<a href="http://code.google.com/p/soemin/downloads/list">http://code.google.com/p/soemin/downloads/list</a></p>
<p>以下为一个简单的使用python向MySQL插入数据的代码，仅供参考：</p>
<pre class="brush: python; gutter: false">import MySQLdb
db = MySQLdb.connect(host=&quot;localhost&quot;, user=&quot;root&quot;, passwd=&quot;root&quot;,db=&quot;slopeone&quot;)
cursor = db.cursor()
f = open(&quot;sample.data&quot;, &quot;r&quot;)
for line in f:
    content = line.rstrip(&#039;\n&#039;).split(&quot;\t&quot;)
    user_id = content[0]
    item_id = content[1]
    rating = content[2]
    print user_id,item_id,rating
    cursor.execute(&quot;insert into oso_user_ratings values(%s,%s,%s)&quot;,(user_id,item_id,rating))
f.close()
print &quot;over!&quot;
cursor.close()</pre>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/python-mssql.html' rel='bookmark' title='使用Python连接MSSQL方法'>使用Python连接MSSQL方法</a></li>
<li><a href='http://www.biaodianfu.com/dbexportdoc-for-mysql.html' rel='bookmark' title='MySQL数据库表结构导出工具'>MySQL数据库表结构导出工具</a></li>
<li><a href='http://www.biaodianfu.com/learn-python-the-hard-way-study-notes.html' rel='bookmark' title='《Learn Python The Hard Way》学习笔记'>《Learn Python The Hard Way》学习笔记</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/python-mysql.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>使用Python连接MSSQL方法</title>
		<link>http://www.biaodianfu.com/python-mssql.html</link>
		<comments>http://www.biaodianfu.com/python-mssql.html#comments</comments>
		<pubDate>Sun, 29 Jan 2012 14:35:39 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4618</guid>
		<description><![CDATA[由于公司目前使用的都是MS SQL Server 2008，由于一些特殊需要，要使用python来解决一些简单繁琐的SQL查询，Python本身是不支持连接MSSQL的，需要特殊的组件才行。网上找了一个pymssql的扩展，据说很好。安装这个组件花了我好长时间。下面就来看看他的安装过程，好让后面使用的人少找一些弯路。 如果直接使用pip install pymssql安装的话，会直接有问题，具体报错如下： C:\Program Files (x86)\PowerCmd&#62;pip install pymssql Downloading/unpacking pymssql   Downloading pymssql-2.0.0b1-dev-20111019.tar.gz (5.0Mb): 5.0Mb downloaded   Running setup.py egg_info for package pymssql Traceback (most recent call last):   File &#34;&#60;string&#62;&#34;, line 14, in &#60;module&#62;   File &#34;C:\Program Files (x86)\PowerCmd\build\pymssql\setup.py&#34;, line 41, in &#60;module&#62;     from Cython.Distutils import build_ext as _build_ext [...]]]></description>
			<content:encoded><![CDATA[<p>由于公司目前使用的都是MS SQL Server 2008，由于一些特殊需要，要使用python来解决一些简单繁琐的SQL查询，Python本身是不支持连接MSSQL的，需要特殊的组件才行。网上找了一个pymssql的扩展，据说很好。安装这个组件花了我好长时间。下面就来看看他的安装过程，好让后面使用的人少找一些弯路。</p>
<p>如果直接使用pip install pymssql安装的话，会直接有问题，具体报错如下：</p>
<pre class="brush: shell; gutter: true">C:\Program Files (x86)\PowerCmd&gt;pip install pymssql
Downloading/unpacking pymssql
  Downloading pymssql-2.0.0b1-dev-20111019.tar.gz (5.0Mb): 5.0Mb downloaded
  Running setup.py egg_info for package pymssql
Traceback (most recent call last):
  File &quot;&lt;string&gt;&quot;, line 14, in &lt;module&gt;
  File &quot;C:\Program Files (x86)\PowerCmd\build\pymssql\setup.py&quot;, line 41, in &lt;module&gt;
    from Cython.Distutils import build_ext as _build_ext
ImportError: No module named Cython.Distutils
    Complete output from command python setup.py egg_info:
----------------------------------------
Command python setup.py egg_info failed with error code 1
Storing complete log in C:\Users\ThinkPad\AppData\Roaming\pip\pip.log</pre>
<p>从上面的报错中发现，原来是少了Cython这个扩展。Cython其实就是一个python的C编译器。安装起来也非常的简单。只要pip install Cython 即可。中间安装的时间会比较长。安装完Cython后再次安装pymssql发现还是不成功。具体的报错内容为：</p>
<pre class="brush: shell; gutter: true">cl: 命令行 error D8021 :无效的数值参数“/Wl,-allow-multiple-definition”
error: command &#039;&quot;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\cl.exe&quot;&#039; failed with exit status 2</pre>
<p>网上找了下，发现解决这个问题方法有很多种，但是都很烦，就是因为很烦，牛肉直接做了个非常牛X的安装包。</p>
<p>安装包下载地址： <a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/#pymssql">http://www.lfd.uci.edu/~gohlke/pythonlibs/#pymssql</a></p>
<p>安装安装完成以后我们就需要使用Python来连接数据库了，具体的连接方法官方网站上有详细的描述，这里只做一下简单的介绍：</p>
<p><a href="http://code.google.com/p/pymssql/wiki/PymssqlExamples">http://code.google.com/p/pymssql/wiki/PymssqlExamples</a></p>
<p>以下为我使用的Python语句:</p>
<pre class="brush: python; gutter: true">import pymssql
urllist = [&#039;www.baidu.com&#039;,&#039;www.google.com&#039;]
date = [&#039;2011-01-01&#039;,&#039;2012-01-02&#039;]
conn = pymssql.connect(host=&#039;localhost:1433&#039;, user=&#039;test&#039;, password=&#039;test&#039;, database=&#039;MyTestDB&#039;)
cur = conn.cursor()
for url in urllist:
    cur.execute(&quot;SELECT COUNT(DISTINCT CookieID) FROM [MyTestDB].[dbo].[VisitLog] WITH (NOLOCK) WHERE ComeDate &gt; %s AND ComeDate &lt; %s AND ReferrerDomain = %s&quot;,(date[0],date[1],url))
    for row in cur:
        print &quot;%s,%d&quot; % (url,row[0])
conn.close()</pre>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/python-today-dir.html' rel='bookmark' title='Python小程序：每天一个文件夹'>Python小程序：每天一个文件夹</a></li>
<li><a href='http://www.biaodianfu.com/google-analytics-data-export-api.html' rel='bookmark' title='Google Analytic 数据导出API接口'>Google Analytic 数据导出API接口</a></li>
<li><a href='http://www.biaodianfu.com/install-scrapy-on-windows.html' rel='bookmark' title='Scrapy在Windows上的安装笔记'>Scrapy在Windows上的安装笔记</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/python-mssql.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Facebook图片存储架构的学习</title>
		<link>http://www.biaodianfu.com/facebook-efficient-storage-of-billions-of-photos.html</link>
		<comments>http://www.biaodianfu.com/facebook-efficient-storage-of-billions-of-photos.html#comments</comments>
		<pubDate>Wed, 25 Jan 2012 15:07:24 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4606</guid>
		<description><![CDATA[分享照片是Facebook上最流行的的功能之一。截至目前，用户已经上传超过15亿张照片，这使得Facebook成为最大的照片共享网站。对于每一个上传的照片，Facebook都生成并存储四个大小不同的图像，从而转化为共60亿张照片，总容量超过1.5PB。目前以每周220万新照片的速度增长，相当于每周要额外增加25TB存储。在高峰期每秒需要传输55万照片。这些数字对Facebook的照片存储基础设施的一个重大的挑战。 旧的 NFS 照片架构 老的照片系统架构分以下几个层： 上传层接收用户上传的照片并保存在 NFS 存储层。 照片服务层接收 HTTP 请求并从 NFS 存储层输出照片。 NFS存储层建立在商业存储系统之上。 因为每张照片都以文件形式单独存储，这样庞大的照片量导致非常庞大的元数据规模，超过了 NFS 存储层的缓存上限，导致每次请求上传都包含多次I/O操作。庞大的元数据成为整个照片架构的瓶颈。这就是为什么 Facebook 主要依赖 CDN 的原因。为了解决这些问题，他们做了两项优化： 因为每张照片都以文件形式单独存储，大量为目录及文件在NFS 存储层上产生了大量的元数据， 这个规模的元数据量远远超过了超过了NFS 存储层的缓存上限，导致每次招聘请求会上传都包含多次I/O操作。庞大的元数据成为整个照片架构的瓶颈。这就是为什么 Facebook主要依赖 CDN 的原因。为了解决这些问题，他们做了两项优化： Cachr: 一个缓存服务器，缓存 Facebook 的小尺寸用户资料照片。 NFS文件句柄缓存：部署在照片输出层，以降低 NFS 存储层的元数据开销。 新的 Haystack 照片架构 新的照片架构将输出层和存储层合并为一个物理层，建立在一个基于HTTP 的照片服务器上，照片存储在一个叫做haystack 的对象库，以消除照片读取操作中不必要的元数据开销。新架构中，I/O 操作只针对真正的照片数据（而不是文件系统元数据）。haystack 可以细分为以下几个功能层： HTTP 服务器 照片存储 Haystack 对象存储 文件系统 存储空间 在下面的介绍中，我们会对于上述的每个功能层做详细的讲述。 存储空间 Haystack 部署在商业存储刀片服务器上，典型配置为一个2U的服务器，包含： 两个4核CPU 16GB [...]]]></description>
			<content:encoded><![CDATA[<p>分享照片是Facebook上最流行的的功能之一。截至目前，用户已经上传超过15亿张照片，这使得Facebook成为最大的照片共享网站。对于每一个上传的照片，Facebook都生成并存储四个大小不同的图像，从而转化为共60亿张照片，总容量超过1.5PB。目前以每周220万新照片的速度增长，相当于每周要额外增加25TB存储。在高峰期每秒需要传输55万照片。这些数字对Facebook的照片存储基础设施的一个重大的挑战。</p>
<p><strong>旧的 NFS 照片架构</strong></p>
<p>老的照片系统架构分以下几个层：</p>
<ol>
<li>上传层接收用户上传的照片并保存在 NFS 存储层。</li>
<li>照片服务层接收 HTTP 请求并从 NFS 存储层输出照片。</li>
<li>NFS存储层建立在商业存储系统之上。</li>
</ol>
<p>因为每张照片都以文件形式单独存储，这样庞大的照片量导致非常庞大的元数据规模，超过了 NFS 存储层的缓存上限，导致每次请求上传都包含多次I/O操作。庞大的元数据成为整个照片架构的瓶颈。这就是为什么 Facebook 主要依赖 CDN 的原因。为了解决这些问题，他们做了两项优化：</p>
<p>因为每张照片都以文件形式单独存储，大量为目录及文件在NFS 存储层上产生了大量的元数据， 这个规模的元数据量远远超过了超过了NFS 存储层的缓存上限，导致每次招聘请求会上传都包含多次I/O操作。庞大的元数据成为整个照片架构的瓶颈。这就是为什么 Facebook主要依赖 CDN 的原因。为了解决这些问题，他们做了两项优化：</p>
<ul>
<li>Cachr: 一个缓存服务器，缓存 Facebook 的小尺寸用户资料照片。</li>
<li>NFS文件句柄缓存：部署在照片输出层，以降低 NFS 存储层的元数据开销。</li>
</ul>
<p><strong>新的 Haystack 照片架构</strong></p>
<p>新的照片架构将输出层和存储层合并为一个物理层，建立在一个基于HTTP 的照片服务器上，照片存储在一个叫做haystack 的对象库，以消除照片读取操作中不必要的元数据开销。新架构中，I/O 操作只针对真正的照片数据（而不是文件系统元数据）。haystack 可以细分为以下几个功能层：</p>
<ul>
<li>HTTP 服务器</li>
<li>照片存储</li>
<li>Haystack 对象存储</li>
<li>文件系统</li>
<li>存储空间</li>
</ul>
<p>在下面的介绍中，我们会对于上述的每个功能层做详细的讲述。</p>
<p><strong>存储空间</strong></p>
<p>Haystack 部署在商业存储刀片服务器上，典型配置为一个2U的服务器，包含：</p>
<ul>
<li>两个4核CPU</li>
<li>16GB – 32GB 内存</li>
<li>硬件 RAID，含256-512M NVRAM 高速缓存</li>
<li>超过12个1TB SATA 硬盘</li>
</ul>
<p>每个刀片服务器提供大约10TB的存储能力，使用了硬件 RAID-6, RAID 6在保持低成本的基础上实现了很好的性能和冗余。不佳的写性能可以通过RAID控制器和NVRAM缓存回写解决，写由于读取大多是随机的，NVRAM缓存是完全用于写入的。</p>
<p><strong>文件系统</strong></p>
<p>Haystack 对象库是建立在10TB容量的单一文件系统之上。</p>
<p>图片读取请求需要在读取系统调用这些文件的位置偏移，但是为了执行读取操作，文件系统必须先找到实际物理卷上的数据。文件系统中的每个文件都被一个叫做inode结构标识。inode包含了一个磁盘上逻辑文件偏移和物理区块偏移的映射。在使用的特殊类型文件系统时大文件块映射可能相当大。</p>
<p>基于文件系统的区块为给个逻辑区块和大文件保存映射。这些信息通常不适合保存在inode的缓存中，而是存储在在间接地址块。所以在读取文件的时候必须按照特定的流程。这里可以多个是间接地址块，所以一个读取会产生多个I/O取决于是否间接地址块被缓存。</p>
<p>该系统只为连续范围的区块保持映射。一个连续的大文件的块映射可以只由一个范围的标识，这样是适应inode的系统需求的。但是，如果该文件是一个被切割的不连续的块的话，他的块地图可能非常的大。以上可以通过文件系统主动为大的物理文件分配大块的空间来减少碎片。</p>
<p>目前使用的文件系统为XFS，一个很大程度提供高效的文件预分配系统。</p>
<p><strong>Haystack 对象存储</strong></p>
<p>Haystack 是一个简单的日志结构（只能追加），存储着其内部数据对象的指针。一个 Haystack 包括两个文件，包括指针和索引。下面的图片将描述haystack存储文件的布局：</p>
<p><img class="alignnone size-full wp-image-4607" title="haystack-store-layout" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/haystack-store-layout.jpg" alt="" width="604" height="279" /></p>
<p>haystack最前面的8K存储是被超级块占用。紧随超级块是针，每针组成的一个头部，数据和尾部：</p>
<p><img class="alignnone size-full wp-image-4608" title="needles" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/needles.jpg" alt="" width="576" height="267" /></p>
<p>一个针被他的&lt;offset key=”" alternate=”" cookie=”"&gt;元组标识，其中的偏移量为其在haystack存储的偏移。Haystack不在任何健值上做限制，即允许可以有重复键针。下图显示了索引文件的布局：</p>
<p><img class="alignnone size-full wp-image-4609" title="tuple" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/tuple.jpg" alt="" width="604" height="215" /></p>
<p>在haystack存储文件中有每针相应的的索引记录，并且包含针索引记录的顺序必须和haystack存储文件相关的针的顺序相匹配。按照规定索引文件的最低需求是找到一个特定的针在haystack存储文件的元数据。载入和组织索引记录到一个有效的查找数据结构是Haystack程序的责任。索引文件是不是很关键，因为如果需要它可以从haystack存储文件重建。索引的主要职责是让针元数据无需通过较大的Haystack存储文件，快速加载到内存中。原因是其可以让索引编程原来存储的1%。</p>
<p><strong>Haystack 写操作</strong></p>
<p>Haystack 写操作同步将指针追加到 haystack 存储文件，当指针积累到一定程度，就会生成索引写到索引文件。由于索引文件是不是很关键，为了能有更快的性能所以采用异步的方式进行写入。</p>
<p>为了降低硬件故障带来的损失，索引文件还会定期写到存储空间中。在崩溃或突然断电的情况下，将haystack恢复处理器存储中任何残缺的针和截断haystack存储中最后一个有效的针。接下来，它会把丢失的针的索引记录 写到haystack文件的最后。</p>
<p>Haystack不允许重写现有的针偏移，如果一个针数据需要被重写，那么新版本必须使用相同的&lt;key alternate=”" key=”" cookie=”"&gt;元组。应用程序会自动分辨出这两个相同的键，有最大偏移的便是最新的那一个。</p>
<p><strong>Haystack 读操作</strong></p>
<p>传到 haystack 读操作的参数包括指针的偏移量，健，备用键，Cookie 以及数据大小。Haystack为数据大小添加头部和尾部的长度，然后根据数据尺寸从文件中读取整个指针。读取操作成功的关键就是作为参数传递的健，备用键，Cookie是否匹配，数据是否通过了校验，并且针没有被删除掉。（见下文）</p>
<p><strong>Haystack 删除操作</strong></p>
<p>删除操作比较简单 &#8211; 只需要在 Haystack 存储的指针字段中的“删除”位标记一下即可。并且，相关的索引记录不会做任何的修改。是最终的应用程序引用到的是一个删除的针。像这样一个读取删除针的操作将会返回一个相应的错误给应用程序。空间对已删除的针不做任何的回收，只有这样，才能使 haystack 的空间非常的紧凑。（见下文）</p>
<p><strong>照片存储服务器</strong></p>
<p>照片存储服务器负责接受 HTTP 请求，并转换成相应的 Haystack 操作。为了尽量减少服务器检索照片时的I/O操作，该服务器维护着全部 Haystack 中文件索引的缓存。服务器启动时，系统就会将这些索引读到缓存中。由于每个节点都有数百万张照片，必须保证索引的容量不会超过服务器的物理内存。在内存中仅需要保存查找照片所需的少量元数据即可。</p>
<p>对于用户上传的图片，系统分配一个64位的独立ID，照片接着被缩放成4种不同尺寸，每种尺寸的图像拥有相同的随机 Cookie 和64位的密钥，图片尺寸描述（大，中，小，缩略图）被存在代用key 中。接着上传服务器通知照片存储服务器将这些资料连同图片存储到 haystack 中。</p>
<p>每张图片的索引缓存包含以下数据：</p>
<p><img class="alignnone size-full wp-image-4614" title="photo-key" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/photo-key.jpg" alt="" width="604" height="215" /></p>
<p>由于Google的开源 sparse hash data 结构对于每个条目只有2bit的开销，所以Haystack使用它来保证内存中的索引缓存尽可能小。</p>
<p><strong>照片存 储的写/修改操作</strong></p>
<p>写操作将照片数据写到 Haystack 存储并更新内存中的索引。如果该索引记录中包含了相同的键，那么这是一次对现有的照片进行修改的操作。并且只要修改索引记录中的偏移来反应新图像在haystack存储文件的位置。照片存储始终假定，如果有重复的图像（图像具有相同的键），有较大的偏移量的那个存储是有效的。</p>
<p><strong>照片存储的读操作</strong></p>
<p>传递给一个读操作的参包括Haystack ID，照片的 Key, 尺寸以及 Cookie。服务器事先在缓存中按照照片的Key和所需文件的偏移进行查找。如果找到了它，并向haystack发出读取词图像的请求。按照上面说的，haystack的删除操作并不更新它的索引记录，因此添加到内存中的索引可以包含以前删除的照片的内容。当阅读以前的删除的照片失败后，系统将在内存的索引中色绘制词图片的偏移量为0.</p>
<p><strong>照片存储的删除操作</strong></p>
<p>通知 Haystack 执行删除操作之后，内存中的索引缓存会被更新，将偏移量设置为0，表示照片已被删除。</p>
<p><strong>重新整理（压缩）</strong></p>
<p>重新整理（压缩）是一种回收删除和重复的针（针使用相同的Key）的在线操作。它会通过复制针跳过任何重复或删除的条目创建一个新的 haystack。一旦此操作完成它就回去替换掉内存中的文件和结构。</p>
<p><strong>HTTP 服务器</strong></p>
<p>Http 框架使用的是简单的基于开源的libevent库的 evhttp 服务器。使用多线程，每个线程都可以单独处理一个 HTTP 请求。因为我们的系统消耗大多是I/O操作，HTTP服务器的性能并不很重要。</p>
<p><strong>结束语</strong></p>
<p>Haystack 是一个基于 HTTP 的对象存储，包含指向实体数据的指针，该架构消除了文件系统元数据的开销，并实现将全部索引直接存储到缓存，以最小的 I/O 操作实现对照片的存储和读取。</p>
<p>本文作者为Facebook的工程师Peter Vajgel, Doug Beaver 和 Jason Sobel， 由<a href="http://www.biaodianfu.com/">标点符</a>进行翻译。</p>
<p>原文链接（E文）：<a href="http://www.facebook.com/note.php?note_id=76191543919&amp;ref=mf">http://www.facebook.com/note.php?note_id=76191543919&amp;ref=mf</a></p>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/facebook-xhp.html' rel='bookmark' title='Facebook XHP:让PHP成为模板引擎'>Facebook XHP:让PHP成为模板引擎</a></li>
<li><a href='http://www.biaodianfu.com/facebook-hiphop.html' rel='bookmark' title='Facebook HipHop 源代码发布'>Facebook HipHop 源代码发布</a></li>
<li><a href='http://www.biaodianfu.com/startssl.html' rel='bookmark' title='StartSSL免费的HTTPS证书颁发机构'>StartSSL免费的HTTPS证书颁发机构</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/facebook-efficient-storage-of-billions-of-photos.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>互联网推荐系统比较研究</title>
		<link>http://www.biaodianfu.com/comparison-study-of-internet-recommendation-system.html</link>
		<comments>http://www.biaodianfu.com/comparison-study-of-internet-recommendation-system.html#comments</comments>
		<pubDate>Fri, 20 Jan 2012 04:18:01 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[推荐系统]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4590</guid>
		<description><![CDATA[互联网规模和覆盖面的迅速增长带来了信息超载（information overload）的问题：过量信息同时呈现使得用户无法从中获取对自己有用的部分，信息使用效率反而降低。现有的很多网络应用，比如门户网站、搜索引擎和专业数据索引本质上都是帮助用户过滤信息的手段。然而这些工具只满足主流需求，没有个性化的考虑，仍然无法很好地解决信息超载的问题。推荐系统（recommender system）作为一种信息过滤的重要手段，是当前解决信息超载问题的非常有潜力的方法。推荐系统与以搜索引擎为代表的信息检索（information retrieval）系统最大的区别在于： 搜索注重结果（如网页）之间的关系和排序,推荐还研究用户模型（user profile）和用户的喜好，基于社会网络(social network)进行个性化的计算（personalization）； 搜索的进行由用户主导，包括输入查询词和选择结果，结果不好用户会修改查询再次搜索。而推荐是由系统主导用户的浏览顺序，引导用户发现需要的结果。高质量的推荐系统会使用户对该系统产生依赖。 因此，推荐系统不仅能够为用户提供个性化的服务，而且能够与用户建立长期稳定的关系，提高用户忠诚度，防止用户流失。 推荐系统最典型的应用是在B2C电子商务领域，具有良好的发展和应用前景，商家根据用户的兴趣、爱好推荐顾客可能感兴趣或满意的商品（如书籍、音像等）。顾客的需求通常是不明确的、模糊的，如果商家能够把满足用户模糊需求的商品推荐给用户，就可以把用户的潜在需求转化为现实需求，从而达到提高产品销售量的目的。目前，几乎所有的大型电子商务系统，如Amazon、eBay等，都不同程度地使用了各种形式的推荐系统。其中Amazon研究电子商务的推荐系统长达10年时间.各种提供个性化服务的Web站点，如电影、音乐网站，也需要推荐系统的大力支持。表1中按照应用领域分类列举了一些典型的商用推荐系统。 在学术界，自20世纪90年代中期出现第一批关于协同过滤的文章[1−3]以来，推荐系统在电子商务、网络经济学和人类社会学等领域一直保持很高的研究热度并逐渐成为一门独立的学科。各种推荐算法涵盖包括认知科学、近似性理论、信息检索[4]、管理科学[5]、市场营销建模[6]等在内的众多研究领域[7].近几年来，国际学术界针对计算机网络信息整合的推荐相关的研究大量出现： ACM设立推荐系统年会（ACM recommender systems）； 计算机领域的人机交互、数据挖掘和机器学习顶级会议（SIGCHI、KDD、SIGIR、WWW等）中,推荐算法的文章逐年增加； 国际数据分析领域的高阶期刊（如IEEE Trans. on Knowledge and Data Engineering,ACM Trans. on Information System等）刊载数篇推荐系统方面的文章。 信息领域做推荐系统领先的研究单位（学者）包括：纽约大学（Alexander Tuzhilin）、明尼苏达州立大学的GroupLens研究小组（Joseph A. Konstan,John Riedl等）、美国密歇根大学（Paul Resnick）、卡内基梅隆大学（Jaime Callan）、微软研究院（Ryen W. White）等。其中，美国密歇根大学在2006年开授了由Paul Resnick主讲的推荐系统的课程。推荐系统，结合社会网络和语义网络的研究，面向互联网发展中出现的新问题和新技术需求，具有广泛的研究和应用前景。 本研究调研了推荐系统在计算机网络和信息领域的主流研究与应用进展。本文第1节中给出推荐系统的形式化定义。第2节根据推荐算法的类别分类陈述最新的学术进展。第3节讨论使用的数据集以及实验评测方法，对当前推荐系统的研究难点进行归纳并对比各种推荐方法的优、缺点。第4节对推荐系统有待深入的研究点和发展趋势进行初步预测。 1 推荐系统概念和形式化定义 目前被广泛引用的推荐系统的非形式化概念是Resnick和Varian在1997年[8]给出的：“它是利用电子商务网站向客户提供商品信息和建议，帮助用户决定应该购买什么产品，模拟销售人员帮助客户完成购买过程”。推荐有3个组成要素：推荐候选对象、用户、推荐方法。通用的推荐系统模型流程如图1所示。用户可以向推荐系统主动提供个人偏好信息或推荐请求，或者用户不提供，而是推荐系统主动采集。推荐系统可以使用不同的推荐策略进行推荐，如将采集到的个性化信息和对象数据进行计算得到推荐结果，或者直接基于已建模的知识数据库进行推荐。推荐系统将推荐结果返回给用户使用。 此外，文献[7]给出了推荐系统的形式化定义：设C是所有用户(user)的集合，S是所有可以推荐给用户的对象（object）的集合。实际中，C和S集合的规模通常很大，如上百万的顾客以及上亿种歌曲等。设效用函数u()可以计算对象s对用户c的推荐度（如提供商的可靠性（vendor reliability）和产品的可得性（product availability）等），即u: C×S→R，R是一定范围内的全序的非负实数，推荐要研究的问题就是找到推荐度R最大的那些对象s*，如式(1)。 用户和对象的度量与采样可以使用不同的属性和特征，这根据实际面对的问题不同而不同。推荐算法研究的中心问题是效用度u的计算，并非遍历整个C×S的整个空间，而是分布到一个流形子空间（manifold）上。对于某个数据集而言，必须先对u进行外推（extrapolation），也就是说，对象必须具备用户以前作的评分（rating），未评定（unrated）的对象的评分必须先根据已标注的对象进行标注外推后才可以使用。各类推荐算法在外推和评分预测（rating propagation）上采用了不同的策略，设计了不同的效用函数，这些将在下一节中分类介绍。 2 现有的推荐算法 推荐算法是整个推荐系统中最核心和关键的部分，在很大程度上决定了推荐系统类型和性能的优劣。目前，对推荐系统的分类并没有统一的标准，很多学者从不同角度对推荐方法进行了不同的划分[9−11]。但主流的推荐方法基本包括以下几种：基于内容推荐、协同过滤推荐、基于知识推荐和组合推荐。本节我们将分类讨论推荐算法的研究成果，下一节我们将讨论这几类推荐算法各自的优、缺点和推荐系统研究的重点、难点问题。 2.1 基于内容的推荐 基于内容的推荐（content-based recommendation）是指根据用户选择的对象，推荐其他类似属性的对象作为推荐，属于Schafer划分中[10]的Item-to-Item Correlation方法。这类算法源于一般的信息检索方法[4]。不需要依据用户对对象的评价意见。对象使用通过特征提取方法得到的对象内容特征来表示，系统基于用户所评价对象的特征，学习用户的兴趣，从而考察用户资料与待预测项目相匹配的程度。对象内容特征（Content(s)）的选取在目前的研究中以对象的文字描述为主，比如信息检索中最经典的文本特征是词频-倒排文档频率（term frequency–inverse [...]]]></description>
			<content:encoded><![CDATA[<p>互联网规模和覆盖面的迅速增长带来了信息超载（information overload）的问题：过量信息同时呈现使得用户无法从中获取对自己有用的部分，信息使用效率反而降低。现有的很多网络应用，比如门户网站、搜索引擎和专业数据索引本质上都是帮助用户过滤信息的手段。然而这些工具只满足主流需求，没有个性化的考虑，仍然无法很好地解决信息超载的问题。推荐系统（recommender system）作为一种信息过滤的重要手段，是当前解决信息超载问题的非常有潜力的方法。推荐系统与以搜索引擎为代表的信息检索（information retrieval）系统最大的区别在于：</p>
<ol>
<li>搜索注重结果（如网页）之间的关系和排序,推荐还研究用户模型（user profile）和用户的喜好，基于社会网络(social network)进行个性化的计算（personalization）；</li>
<li>搜索的进行由用户主导，包括输入查询词和选择结果，结果不好用户会修改查询再次搜索。而推荐是由系统主导用户的浏览顺序，引导用户发现需要的结果。高质量的推荐系统会使用户对该系统产生依赖。</li>
</ol>
<p>因此，推荐系统不仅能够为用户提供个性化的服务，而且能够与用户建立长期稳定的关系，提高用户忠诚度，防止用户流失。</p>
<p>推荐系统最典型的应用是在B2C电子商务领域，具有良好的发展和应用前景，商家根据用户的兴趣、爱好推荐顾客可能感兴趣或满意的商品（如书籍、音像等）。顾客的需求通常是不明确的、模糊的，如果商家能够把满足用户模糊需求的商品推荐给用户，就可以把用户的潜在需求转化为现实需求，从而达到提高产品销售量的目的。目前，几乎所有的大型电子商务系统，如Amazon、eBay等，都不同程度地使用了各种形式的推荐系统。其中Amazon研究电子商务的推荐系统长达10年时间.各种提供个性化服务的Web站点，如电影、音乐网站，也需要推荐系统的大力支持。表1中按照应用领域分类列举了一些典型的商用推荐系统。</p>
<p><img class="alignnone size-full wp-image-4593" title="Mainstream-commercialized-recommender-systems" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/Mainstream-commercialized-recommender-systems.png" alt="" width="608" height="149" /></p>
<p>在学术界，自20世纪90年代中期出现第一批关于协同过滤的文章[1−3]以来，推荐系统在电子商务、网络经济学和人类社会学等领域一直保持很高的研究热度并逐渐成为一门独立的学科。各种推荐算法涵盖包括认知科学、近似性理论、信息检索[4]、管理科学[5]、市场营销建模[6]等在内的众多研究领域[7].近几年来，国际学术界针对计算机网络信息整合的推荐相关的研究大量出现：</p>
<ol>
<li>ACM设立推荐系统年会（ACM recommender systems）；</li>
<li>计算机领域的人机交互、数据挖掘和机器学习顶级会议（SIGCHI、KDD、SIGIR、WWW等）中,推荐算法的文章逐年增加；</li>
<li>国际数据分析领域的高阶期刊（如IEEE Trans. on Knowledge and Data Engineering,ACM Trans. on Information System等）刊载数篇推荐系统方面的文章。</li>
</ol>
<p>信息领域做推荐系统领先的研究单位（学者）包括：纽约大学（Alexander Tuzhilin）、明尼苏达州立大学的GroupLens研究小组（Joseph A. Konstan,John Riedl等）、美国密歇根大学（Paul Resnick）、卡内基梅隆大学（Jaime Callan）、微软研究院（Ryen W. White）等。其中，美国密歇根大学在2006年开授了由Paul Resnick主讲的推荐系统的课程。推荐系统，结合社会网络和语义网络的研究，面向互联网发展中出现的新问题和新技术需求，具有广泛的研究和应用前景。</p>
<p>本研究调研了推荐系统在计算机网络和信息领域的主流研究与应用进展。本文第1节中给出推荐系统的形式化定义。第2节根据推荐算法的类别分类陈述最新的学术进展。第3节讨论使用的数据集以及实验评测方法，对当前推荐系统的研究难点进行归纳并对比各种推荐方法的优、缺点。第4节对推荐系统有待深入的研究点和发展趋势进行初步预测。</p>
<p><strong>1 推荐系统概念和形式化定义</strong></p>
<p>目前被广泛引用的推荐系统的非形式化概念是Resnick和Varian在1997年[8]给出的：“它是利用电子商务网站向客户提供商品信息和建议，帮助用户决定应该购买什么产品，模拟销售人员帮助客户完成购买过程”。推荐有3个组成要素：推荐候选对象、用户、推荐方法。通用的推荐系统模型流程如图1所示。用户可以向推荐系统主动提供个人偏好信息或推荐请求，或者用户不提供，而是推荐系统主动采集。推荐系统可以使用不同的推荐策略进行推荐，如将采集到的个性化信息和对象数据进行计算得到推荐结果，或者直接基于已建模的知识数据库进行推荐。推荐系统将推荐结果返回给用户使用。</p>
<p><img class="alignnone size-full wp-image-4594" title="Recommendation-system-general-model" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/Recommendation-system-general-model.png" alt="" width="560" height="379" /></p>
<p>此外，文献[7]给出了推荐系统的形式化定义：设C是所有用户(user)的集合，S是所有可以推荐给用户的对象（object）的集合。实际中，C和S集合的规模通常很大，如上百万的顾客以及上亿种歌曲等。设效用函数u()可以计算对象s对用户c的推荐度（如提供商的可靠性（vendor reliability）和产品的可得性（product availability）等），即u: C×S→R，R是一定范围内的全序的非负实数，推荐要研究的问题就是找到推荐度R最大的那些对象s*，如式(1)。</p>
<p><img class="alignnone size-full wp-image-4595" title="argmax" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/argmax.png" alt="" width="516" height="33" /></p>
<p>用户和对象的度量与采样可以使用不同的属性和特征，这根据实际面对的问题不同而不同。推荐算法研究的中心问题是效用度u的计算，并非遍历整个C×S的整个空间，而是分布到一个流形子空间（manifold）上。对于某个数据集而言，必须先对u进行外推（extrapolation），也就是说，对象必须具备用户以前作的评分（rating），未评定（unrated）的对象的评分必须先根据已标注的对象进行标注外推后才可以使用。各类推荐算法在外推和评分预测（rating propagation）上采用了不同的策略，设计了不同的效用函数，这些将在下一节中分类介绍。</p>
<p><strong>2 现有的推荐算法</strong></p>
<p>推荐算法是整个推荐系统中最核心和关键的部分，在很大程度上决定了推荐系统类型和性能的优劣。目前，对推荐系统的分类并没有统一的标准，很多学者从不同角度对推荐方法进行了不同的划分[9−11]。但主流的推荐方法基本包括以下几种：基于内容推荐、协同过滤推荐、基于知识推荐和组合推荐。本节我们将分类讨论推荐算法的研究成果，下一节我们将讨论这几类推荐算法各自的优、缺点和推荐系统研究的重点、难点问题。</p>
<p><strong>2.1 基于内容的推荐</strong></p>
<p>基于内容的推荐（content-based recommendation）是指根据用户选择的对象，推荐其他类似属性的对象作为推荐，属于Schafer划分中[10]的Item-to-Item Correlation方法。这类算法源于一般的信息检索方法[4]。不需要依据用户对对象的评价意见。对象使用通过特征提取方法得到的对象内容特征来表示，系统基于用户所评价对象的特征，学习用户的兴趣，从而考察用户资料与待预测项目相匹配的程度。对象内容特征（Content(s)）的选取在目前的研究中以对象的文字描述为主，比如信息检索中最经典的文本特征是词频-倒排文档频率（term frequency–inverse document frequency,简称TF-IDF）[8].。另一方面，用户的资料模型ContentBasedProfile(c)取决于所用机器学习方法，常用的有决策树、贝叶斯分类算法[12,13]、神经网络、基于向量的表示方法等，数据挖掘领域的众多算法都可以应用。结合对象内容特征和用户资料模型，最终的效用函数可以定义为[7]</p>
<p><img class="alignnone size-full wp-image-4596" title="content-score" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/content-score.png" alt="" width="604" height="27" /></p>
<p>Score的计算有不同的方法，比如使用最简单的向量夹角余弦的距离计算方法：</p>
<p><img class="alignnone size-full wp-image-4597" title="ucs" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/ucs.png" alt="" width="631" height="49" /></p>
<p>最后得到的u数值用于排序对象，将最靠前的若干个对象作为推荐。基于内容推荐的其他研究还包括自适应过滤[14,15]和阈值设定[16,17]等，前者关注如何通过不断到来的对象增量地计算ContentBasedProfile(c)，使其更加准确；后者研究用户查询文字和对象特征的匹配方法，从而更精确地计算Content(c)。</p>
<p><strong>2.2 协同过滤推荐</strong></p>
<p>协同过滤推荐（collaborative filtering recommendation）技术是推荐系统中最为成功的技术之一，它于20世纪90年代开始研究并促进了整个推荐系统研究的繁荣。大量论文和研究都属于这个类别。</p>
<p>协同过滤的基本思想是:找到与当前用户ccur相似（比如兴趣和口味相似）的其他用户cj，计算对象s对于用户的效用值u(cj,s)，利用效用值对所有s进行排序或者加权等操作，找到最适合ccur的对象s*。其基本思想非常易于理解，在日常生活中，我们往往会利用好朋友的推荐来进行一些选择。协同过滤正是把这一思想运用到推荐系统中来，即基于其他用户对某一内容的评价向目标用户进行推荐。</p>
<p>基于协同过滤的推荐系统可以说是从用户的角度进行推荐的，并且是自动的，也就是说，用户所获得的推荐是系统从用户购买或浏览等行为中隐式获得的，不需要用户主动去查找适合自己兴趣的推荐信息，如填写一些调查表格等。其另外一个优点是对推荐对象没有特殊的要求（而基于内容的推荐需要对推荐对象进行特征分析），能够处理非结构化的复杂对象，如音乐、电影等。同时，研究用户之间的关系需要大量的用户访问行为的历史数据，与社会网络研究有交叉点，有丰富的研究基础和广阔的前景。对协同过滤最早的研究有Grundy system[18]，后来的研究成果包括Tapestry system[19],GroupLens[20],Ringo[1],PHOAKS system[21],Jester system[22]等。总体而言，此类推荐算法可以分为两类[7]：启发式（heuristic-based or memory-based）方法和基于模型（model-based）的方法。</p>
<p>1) 启发式方法</p>
<p>启发式方法[23,24]的基本思想是使用与新用户c相似的用户c′对一个对象s的评价来预测s对新用户c的效用，进而判断是否推荐s给c。显然,，启发式方法的研究主要包括两点：(1) 计算用户之间的相似度；(2) 对所有与用户c相似的用户c′对对象s的评分进行聚合计算，以得到s对新用户c的效用的统计预测方法。</p>
<p>在用户相似度sim(c,c′)这个研究点上,主流的思路是根据用户对同一对象的评分的差异来判断用户兴趣的相似性。评分属于用户的浏览历史行为，可以是打分、观看次数、停留时间等。最基本的两种计算sim(c,c′)的方法是基于关联的(correlation-based)和基于余弦距离的(cosine-based)方法.基于关联的方法研究用户c和c′共同评分过的所有对象的评分相似度来计算关联[1,3]。而基于余弦距离的方法直接把评分作为向量来计算余弦距离，进而得到用户相似度[23,25]。</p>
<p>统计预测方法的计算公式可以形式化地表示如下[7]：</p>
<p><img class="alignnone size-full wp-image-4598" title="aggrr" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/aggrr.png" alt="" width="499" height="23" /></p>
<p>之前的研究设计了很多计算aggr的启发式函数，几个比较典型的例子是：</p>
<p><img class="alignnone size-full wp-image-4599" title="rcs" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/rcs.png" alt="" width="480" height="137" /></p>
<p>这3类aggr函数都是利用以前用户的评价和用户之间的相似度来启发式地计算效用值。其中，式(5)是最简单的形式；式(6)简单地引入用户相似度加权，是应用最广的方法；考虑到不同的用户在不同情况下作的评分可能有不同的尺度，式(7)提出进行平均归一化的操作以消除这种尺度影响。</p>
<p>除了这两个研究点之外，近年来一些学者同时也发展了其他启发式方法，以提高启发式推荐的性能，如缺省投票(default voting)、用户倒排评分(inverse user frequency)、实例扩展(case amplification)[23]和主流加权预测(weighted-majority prediction)[24]等。</p>
<p>2) 基于模型的方法</p>
<p>这类方法利用用户c对众多对象的评分来学习一个c的模型(model)[26−30]，然后使用概率方法对新的对象s的推荐效用进行预测。文献[7]对这种方法的形式化描述如式(8)所示：</p>
<p><img class="alignnone size-full wp-image-4600" title="ercs" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/ercs.png" alt="" width="568" height="46" /></p>
<p>这样，基于模型的方法把一个用户归类到一种模型下或者一个类型中。其他的算法还包括利用机器学习方法[26]和统计模型[30]、贝叶斯模型[31]、概率相关模型[27]、线性回归模型[25]和最大熵模型[32]。Shani在文献[33]中还把推荐选择看作序列决策问题(sequential decision problem)，使用马尔可夫决策过程方法(Markov decision processes)加以解决。图模型方法，包括概率隐形语义分析(probabilistic latent semantic analysis)[28]和LDA(latent dirichlet allocation)[29]，也应用于协同过滤推荐算法的研究。</p>
<p><strong>2.3 基于知识的推荐</strong></p>
<p>基于知识的推荐(knowledge-based recommendation)[34]在某种程度上可以看成是一种推理(inference)技术。它不是建立在用户需要和偏好基础上推荐的，而是利用针对特定领域制定规则(rule)来进行基于规则和实例的推理(case-based reasoning)。例如，文献[34]中利用饭店的菜式方面的效用知识，推荐饭店给顾客。效用知识(functional knowledge)是一种关于一个对象如何满足某一特定用户的知识,因而能够解释需求和推荐的关系，用于推荐系统。效用知识在推荐系统中必须以机器可读的方式存在(ontology本体知识库)，例如quickstep and foxtrot systems[35]使用关于学术论文主题的ontology本体知识库向读者作推荐。</p>
<p><strong>2.4 组合推荐</strong></p>
<p>组合推荐(hybrid recommendation)的一个最重要原则就是通过组合后应能避免或弥补各自推荐技术的弱点(见第3.4节)。研究和应用最多的是内容推荐和协同过滤推荐的组合[9,36−38]。尽管从理论上有很多种推荐组合方法，但不同的组合思路适用于不同的应用场景。我们将研究人员提出的组合思路大致分为如下3类：</p>
<ol>
<li>后融合：融合两种或两种以上的推荐方法各自产生的推荐结果。如使用基于内容的方法和协同过滤方法分别得到推荐列表，融合列表的结果决定最后推荐的对象。</li>
<li>中融合：以一种推荐方法为框架，融合另一种推荐方法。如以基于内容的方法为框架，融合协同过滤的方法，或者以协同过滤的方法为框架，融合基于内容的方法。</li>
<li>前融合：直接融合各种推荐方法。如将基于内容和协同过滤的方法整合到一个统一的框架模型下。</li>
</ol>
<p>2.4.1 后融合组合推荐</p>
<p>在后融合组合推荐中，最简单的做法就是分别用基于内容的方法和协同过滤推荐方法去产生一个推荐预测结果，然后用某种方法组合其结果。文献[37]使用了评分结果的线性组合，而文献[38]使用了投票机制来组合这些推荐结果。除此之外，也可以分别考察两个推荐列表，判断使用其中的哪个推荐结果。比如，Daily Learner system[39]计算推荐结果的可信度，然后选择一个列表的结果。这种结果层次上的融合我们称为后融合组合推荐。</p>
<p>2.4.2 中融合组合推荐</p>
<p>目前，中融合的组合推荐主要有两种，以基于内容的方法为框架,融合协同过滤的方法和以协同过滤的方法为框架，融合基于内容的方法。前者利用降维技术把基于内容的对象特征进行精简化。例如，文献[40]使用了LSI(latent semantic indexing)算法，在基于内容的框架中使用精化的用户特征向量。后者为了克服协同过滤的稀疏问题（详见第3.3节），把用户当作对象，使用基于内容的特征提取方法把用户本身的特征（如年龄、工作情况等人口统计学特征(demographic features)）使用到相似度计算中，而不是仅仅依赖用户的点击行为。Good等人在文献[41]中引入多种不同的用户描述符来归类用户，挖掘用户的内在联系，从而得到更好的推荐效果。文献[42]使用独立的基于内容的特征来补偿用户提供的简单的rating，也属于此类方法。</p>
<p>2.4.3 前融合组合推荐</p>
<p>近年来，这类推荐方法最受学者的关注。在文献[36]中，研究者把用户的年龄和电影的类型放到一个统一的分类器中训练学习。另外一种方法[43]使用了贝叶斯混合效果回归模型,，并通过马尔可夫蒙特卡洛方法得到这个模型的参数。文献[43]将用户和对象的特征都放到一个统计模型下来计算效用函数，研究者使用用户属性z、对象属性w及其交互关系(如选择关系)x来计算效用r。对象j对于用户i的效用值rij计算式可以表示为</p>
<p><img class="alignnone size-full wp-image-4601" title="rij" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/rij.png" alt="" width="607" height="29" /></p>
<p>这其中的3种正态分布的变量分别用于描述数据的噪声、用户属性的异质性和对象属性的异质性。式(9)表述效用值是由这几个因素共同决定的。这3种分布的3个参数由马尔可夫蒙特卡洛方法估算得到。</p>
<p>近年来,一些方法比较的工作[9,42,38]讨论并实验了各种方法与组合策略，得出结论：组合策略能够取得比纯基于内容或协同过滤方法更好的效果。这种在方法层次上融合的方法我们称为前融合组合推荐。</p>
<p><strong>3 推荐系统的重点、难点问题和主流算法对比</strong></p>
<p><strong>3.1 推荐系统的评测标准数据集</strong></p>
<p>推荐系统学术研究常用的数据集包括：</p>
<ol>
<li>MovieLens[44]，MovieLens数据集中，用户对自己看过的电影进行评分，分值为1~5。MovieLens包括两个不同大小的库，适用于不同规模的算法。小规模的库是943个独立用户对1 682部电影作的10 000次评分的数据；大规模的库是6 040个独立用户对3 900部电影作的大约100万次评分。</li>
<li>EachMovie[45]，HP/Compaq的DEC研究中心曾经在网上架设EachMovie电影推荐系统对公众开放。之后，这个推荐系统关闭了一段时间，其数据作为研究用途对外公布，MovieLens的部分数据就是来自于这个数据集的。这个数据集有72 916个用户对1 628部电影进行的2 811 983次评分。早期大量的协同过滤的研究工作都是基于这个数据集的。2004年HP重新开放EachMovie，这个数据集就不提供公开下载了。</li>
<li>BookCrossing[46]，这个数据集是网上的Book-Crossing图书社区的278 858个用户对271 379本书进行的评分，包括显式和隐式的评分。这些用户的年龄等人口统计学属性(demographic feature)都以匿名的形式保存并供分析。这个数据集是由Cai-Nicolas Ziegler使用爬虫程序在2004年从Book-Crossing图书社区上采集的。</li>
<li>Jester Joke[22]，Jester Joke是一个网上推荐和分享笑话的网站。这个数据集有73 496个用户对100个笑话作的410万次评分。评分范围是−10~10的连续实数。这些数据是由加州大学伯克利分校的Ken Goldberg公布的。</li>
<li>Netflix[47]，这个数据集来自于电影租赁网址Netflix的数据库。Netflix于2005年底公布此数据集并设立百万美元的奖金(netflix prize[47])，征集能够使其推荐系统性能上升10%的推荐算法和架构。这个数据集包含了480 189个匿名用户对大约17 770部电影作的大约10亿次评分。</li>
<li>Usenet Newsgroups[48]，这个数据集包括20个新闻组的用户浏览数据。最新的应用是在KDD 2007上的论文[49]。新闻组的内容和讨论的话题包括计算机技术、摩托车、篮球、政治等。用户们对这些话题进行评价和反馈。</li>
<li>UCI知识库[50]，UCI知识库是Blake等人在1998年开放的一个用于机器学习和评测的数据库，其中存储大量用于模型训练的标注样本，在文献[49]中被用于推荐系统的性能测试数据。</li>
</ol>
<p><strong>3.2 推荐系统的性能评测方法</strong></p>
<p>推荐系统的性能指标一般有推荐的效果/精确度(effectiveness)和推荐的效率(efficiency)，使用的指标有mean absolute error(MAE)，root mean squared error(RMSE)和correlation。由于不同的研究工作针对不同的问题，使用不同的数据集，所以具体评测方法变化很大。比较普遍的评测方法来自于机器学习等领域的一般方法，比如数据集被分割为训练集(probe set)和测试集(quiz set)。推荐算法的模型在训练集上进行学习和参数调整，然后在测试集合上计算精确度和运行效率，从而达到评测目的。文献[23]使用两种评测方法来比较几种协同过滤的算法性能，第1种评测得到每次推荐绝对误差的平均值，第2种评测计算整个推荐列表的推荐精度。</p>
<p><strong>3.3 推荐系统的重点、难点问题</strong></p>
<p>随着近年来对推荐系统研究的开展，很多研究中的重点、难点问题得到研究者的关注和共识[7]，主要包括：</p>
<p>1）特征提取问题</p>
<p>虽然在信息检索中，文本等对象特征的提取技术已经很成熟，但是推荐系统的对象不一定具有文本特征或者文本不足以作为描述[1]，此时特征的选择出现了问题。尤其是网络上广泛存在的多媒体数据如音乐、视频、图像等，自动化的特征提取方法需要结合多媒体内容分析领域的相关技术。另一个问题是特征的区分性问题，大规模数据情况下不同对象的特征错配会影响系统性能。</p>
<p>2）模型过拟合问题（可扩展性问题）</p>
<p>推荐系统中推荐算法无法完全掌握用户每个方面的兴趣和需求，因为用户之前没有对足够多类别的对象进行评价。过拟合现象是指系统推荐给用户的对象与用户刚刚看过的不是太相似，就是太不相关。模型过拟合(过学习)的问题本质上来自于数据的不完备性，这在实际应用中是无法完全避免的。在信息检索领域这类问题广泛存在，解决的主要方法是引入随机性，使算法收敛到全局最优或者逼近全局最优。随机方法包括遗传算法[51]等。Daily Learner相关的文献[15,39]针对这个问题考察了被推荐的对象的相关性(relevant)和冗余性(redundancy)，认为被推荐的对象首先不能与用户看过的对象重复(冗余)，其次必须有相关性以相互联系.推荐的多样性是必不可缺的。</p>
<p>3）新用户问题</p>
<p>系统没有存储或者存储很少新用户的信息，包括查看对象的历史记录和新用户对对象的评分，基于模型的方法无法获得训练数据而基于规则的方法难以进行推理。近期一些研究特别针对这个问题提出了解决方法。文献[52,53]利用对象熵(entropy)、受欢迎程度(popularity)、用户个性属性等来改进效果。</p>
<p>4）新对象问题</p>
<p>新用户和新对象问题都属于冷启动问题。在推荐系统尤其是协同过滤系统中，新对象加入数据库后必须等待一段时间才有用户查看并进行评价（点击、打分、评论等都是评价的手段）。在评价达到一定数量之前无法对此对象进行分析和推荐。不同于新用户问题，这类问题一般考虑使用组合推荐的方法来应对。</p>
<p>5）稀疏问题</p>
<p>在任何大型的推荐系统中，对于一个用户，总有大量的对象没有经过用户的评价或者查看，而且这类数据常常比已经有此用户评价的数据量更大[7]。用户之间由于选择的差异性非常大造成稀疏情况，即任意两个用户的评分差别都非常大。文献[38]提出初步的解决方法，将用户的年龄、国籍、性别等个人信息增加作为用户相似度计算的根据，称为基于人口统计学的过滤方法(demographic filtering)。文献[26,54]使用主分量分析(SVD)降维方法尝试把稀疏的关系矩阵降维到低维，以得到用户之间潜在的关系。</p>
<p><strong>3.4 各类推荐方法的对比</strong></p>
<p>各类推荐方法都有其各自的优、缺点，针对不同的数据集，效果也有所不同。每种方法因为算法本身的特征可能不适合在所有数据集上作推荐。如在基于内容的推荐方法中，自动化的特征提取方法很难应用于多媒体数据，即使在容易提取特征的文本数据的情况下，也无法仅仅通过词频统计的方式区分文档质量[4]。除此之外，为用户推荐的内容仅限于与该用户曾经选择的对象相似的对象，结果多样性差。而对于没有选择过任何对象的新用户，推荐尤其困难。协同过滤的方法从某种程度上克服了基于内容方法自动化程度低、推荐结果不丰富等弊端。但是，协同过滤是基于大量历史数据集的，因而存在稀疏问题和冷启动问题。在冷启动方面，由于协同过滤是依靠人与人之间选择内容的相似度进行推荐的，因此。与基于内容的方法相比，不但存在新用户问题[53]，而且还存在新对象问题，即刚刚加入的对象如果没有被任何人选择过，就很难被推荐[7]。基于知识的推荐是一种静态的推荐方法，不存在冷启动和稀疏问题，但知识很难建模。组合推荐策略由于组合方式不同，其性能特点差异很大，故不在此讨论范围内。几种推荐方法的优、缺点具体比较见表2。</p>
<p><img class="alignnone size-full wp-image-4602" title="Comparison-of-typical-recommendation-algorithms" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/Comparison-of-typical-recommendation-algorithms.png" alt="" width="651" height="238" /></p>
<p><strong>4 推荐系统研究发展的热点方向</strong></p>
<p>推荐系统的研究发展多年，曾经一度进入低潮期。近年来，机器学习、大规模网络应用需求和高性能计算的发展推动了这个研究领域的新进展，可以深入并可能取得成果的方向很多，主要包括：</p>
<p>1）引入更精确适用的用户和对象特征(new profiles of user and item)[7]</p>
<p>针对特定问题适用的用户和对象特征通常可以作为模型训练的样本。典型的协同过滤方法[1−3]并没有使用用户和对象特征，而是利用用户的评分。文献[13,55]只是使用简单的特征，如对象描述的关键词和用户的人口统计学特征等。而结合数据挖掘的高层特征一般是基于网络上下文的分析的[56]，比如发现用户浏览网页和对象的时序模式。这类方法需要精准的用户浏览历史数据和先进的数据挖掘算法，尚未在基于内容和协同过滤的研究中广泛采用。</p>
<p>2）推荐的多维度研究[7]</p>
<p>当前的大部分研究都是基于对象-用户的二维度量空间的，未考虑相关信息(contextual information)。然而，用户对对象的评价和选择常常由很多环境因素来决定，比如某个对象在特定时段很流行，用户在某个地方浏览对象的时候偏向于选择某类对象等。环境因素是无法从用户和对象的自有特征得到的，正如文献[57,58]所指出的，推荐使用的特征维度有必要根据具体问题来增加。文献[57]提出在多维度量空间上来定义效用函数u()，以电影推荐为例:除了看电影的人的特性和电影本身的固有描述特征以外，还有环境因素d来决定如何计算效用函数u()，d包括:1) 是一个人看电影还是和其他人一起看;2) 是去电影院看还是在网上看等;3) 看电影的时间段。基于这种多维特征的思想，文献[43]提出使用贝叶斯模型的方法进一步扩展了这个思路。问题在于，维度的扩展与应用场景相关，其可扩展性还有待进一步改进。</p>
<p>3）推荐系统安全问题</p>
<p>协同过滤类别的推荐算法必须使用用户的行为历史记录，但用户出于保护隐私的考虑常常无法提交完整而正确的信息给推荐系统。文献[59，60]认为良好的隐私保护机制是推荐系统获取优质数据和忠实用户的关键之一，并提出了相应的算法。同时，用户的信用度(reputation)也是推荐算法的重要参考数据。文献[61]提出两种信用计算模型并用于提高推荐精度。另外，熟悉推荐算法的攻击者恶意利用捏造的评分和对象属性等数据欺骗推荐系统，达到被频繁推荐的目的。文献[62,63]中定义这类行为为用户欺诈(shilling attack)，并设计算法监控评分的时序模式，去除不正常的对象与用户。</p>
<p>4）相关反馈研究(relevance feedback)与侵袭性问题</p>
<p>一般的推荐系统大多需要用户依据自身对推荐对象的喜好程度，提供适当的评比反馈信息，这种评比方式称为相关反馈(relevance feedback)。相关反馈可以分为显性反馈(explicit feedback)和隐性反馈(implicit feedback)。目前部分推荐系统主要使用显性反馈的方式，即需要用户每次查看对象都进行评分或者其他操作。一些研究[20,35,64]中使用的用户反馈的方法也属于显性反馈。使用这种方式来取得评价的方法对于用户不是很友好，具有很大的侵袭性。隐性反馈使用无须用户评价的用户数据采集方法。在文献[65]的研究中列举了12种用户在网络上的浏览行为，Oard和Kim[66]延伸了文献[65]的研究，进一步将这些行为分为3类，并增加了一种新的行为类型。文献[67]针对隐性反馈的可靠性进行了实验，结果显示“使用者的阅览时间”和“使用者是否喜欢该文章”有正向潜在关系。解决侵袭性问题的另一个研究方向是研究用户能够接受的评价方式是什么，比如能够有耐心进行几次评分。MovieLens系统[44]利用固定负担模型这种最简单的算法来计量用户评价的负担，将侵袭性问题转化为最优化问题来研究。</p>
<p>5）推荐算法的评价准则[7]</p>
<p>有效性和时间消耗作为推荐系统的重要指标，其评价准则的设计一直是一个热点，但是没有统一的结论。文献[55,68−70]都研究过评测推荐系统性能的准则，包括查全率(coverage)和查准率(accuracy)的评测。另外，信息检索领域使用的F-measure和ROC(receiver operating characteristic)指标也可以用于评测。第4。2节给出了部分研究工作中使用过的推荐效果度量方法。然而这些基于用户评分的数据和评测的方法存在固有的缺陷，比如用户的评分常常是针对他喜欢的对象，而其他对象被访问的概率则很小。评价准则必须考虑到人类行为的特点。同时，如果召集若干志愿者来做实时的实验，不仅样本量小，而且耗费的时间、人力也很昂贵。这是一个很有研究意义的方向。</p>
<p>6）基于复杂网络理论及图方法的推荐系统</p>
<p>近年来，机器学习、理论物理和复杂网络系统的研究者从图和动态复杂网络(graph and dynamic network)的视角，开始关注推荐系统中的大规模网络智能挖掘。文献[71]将网络视频推荐问题转化为热量散播平衡态网络上的谱图分割(spectral graph partitioning)问题，通过设计长尾发现(long tail discovering)的推荐策略引导用户发现潜在的感兴趣的网络视频。</p>
<p>7）社会分化和推荐逻辑空间的巴尔干化现象(balkanization)</p>
<p>以Internet为代表的信息和通信技术消除了地理壁垒，即传统的地理空间巴尔干(即局域性限制)。然而却不可避免地生成了逻辑空间巴尔干[72]。在推荐系统中根据个体兴趣、学科专业、社会地位以及观点进行推荐时尤其容易导致这种局域性限制和社会分化的出现。本质上，个体偏好关系是导致生成逻辑空间巴尔干的原因。推荐和个性化技术所产生的一系列社会学问题，也是很重要的一个研究方向。网络推荐中体现的其他社会学问题还包括从众心理和行为研究，推荐与主流兴趣形成的相互作用等。</p>
<p><strong>5 结论 </strong></p>
<p>在互联网的迅猛发展下，随着信息过载问题的逐年升温,互联网用户对信息需求的日益膨胀，推荐系统在各个领域的数字化进程中扮演着越来越重要的角色。在过去的数十年中，推荐系统在学术研究、工业界各种应用上取得了长足的进步。然而，现有的推荐算法仍然存在特征提取、冷启动、过拟合、稀疏问题，需要不断完善和解决。同时，多维度推荐、相关反馈、评价准则、安全性以及推荐社会学等仍然是当前进行深入研究和扩展的热点方向。伴随着这些问题的逐渐解决，推荐系统将在互联网领域为用户提供更加便捷、有效的用户信息获取体验。</p>
<p><strong>References:</strong><br />
[1]Shardanand U, Maes P. Social information filtering: Algorithms for automating “Word of Mouth”. In: Proc. of the Conf. on Human Factors in Computing Systems. New York: ACM Press, 1995. 210−217.<br />
[2]Hill W, Stead L, Rosenstein M, Furnas G. Recommending and evaluating choices in a virtual community of use. In: Proc. of the Conf. on Human Factors in Computing Systems. New York: ACM Press, 1995. 194−201.<br />
[3]Resnick P, Iakovou N, Sushak M, Bergstrom P, Riedl J. GroupLens: An open architecture for collaborative filtering of netnews. In: Proc. of the Computer Supported Cooperative Work Conf. New York: ACM Press, 1994. 175−186.<br />
[4]Baeza-Yates R, Ribeiro-Neto B. Modern Information Retrieval. New York: Addison-Wesley Publishing Co., 1999.<br />
[5]Murthi BPS, Sarkar S. The role of the management sciences in research on personalization. Management Science, 2003,49(10): 1344−1362.<br />
[6]Smith SM, Swinyard WR. Introduction to marketing models. 1999.http://marketing.byu.edu/htmlpages/courses/693r/modelsbook/preface.html<br />
[7]Adomavicius G, Tuzhilin A. Toward the next generation of recommender systems: A survey of the state-of-the-art and possible extensions. IEEE Trans. on Knowledge and Data Engineering, 2005,17(6):734−749.<br />
[8]Resnick P, Varian HR. Recommender systems. Communications of the ACM, 1997,40(3):56−58.<br />
[9]Balabanovic M, Shoham Y. Fab: Content-Based, collaborative recommendation. Communications of the ACM, 1997,40(3):66−72.<br />
[10]Schafer JB, Konstan J, Riedl J. Recommender systems in e-commerce. In: Proc. of the 1st ACM Conf. on Electronic Commerce. New York: ACM Press, 1999. 158−166.<br />
[11]Terveen L, Hill W. Beyond recommender systems: Helping people help each other. In: Carroll J, ed. HCI in The New Millennium. New York: Addison-Wesley Publishing Co., 2001. 1−21.<br />
[12]Mooney RJ, Bennett PN, Roy L. Book recommending using text categorization with extracted information. In: Proc. of the AAAI’98/ICML’98 Workshop on Learning for Text Categorization. Madison: AAAI Press, 1998. 49−54.<br />
[13]Pazzani M, Billsus D. Learning and revising user profiles: The identification of interesting Web sites. Machine Learning, 1997, 27(3):313−331.<br />
[14]Somlo G, Howe A. Adaptive lightweight text filtering. In: Proc. of the 4th Int’l Symp. on Intelligent Data Analysis. Berlin, Heidelberg: Springer-Verlag, 2001. 319−329.<br />
[15]Zhang Y, Callan J, Minka T. Novelty and redundancy detection in adaptive filtering. In: Proc. of the 25th Annual Int’l ACM SIGIR Conf. New York: ACM Press, 2002. 81−88.<br />
[16]Robertson S. Threshold setting and performance optimization in adaptive filtering. Information Retrieval, 2002,5(2-3):239−256.<br />
[17]Zhang Y, Callan J. Maximum likelihood estimation for filtering thresholds. In: Proc. of the 24th Annual Int’l ACM SIGIR Conf. New York: ACM Press, 2001. 294−302.<br />
[18]Rich E. User modeling via stereotypes. Cognitive Science, 1979,3(4):329−354.<br />
[19]Goldberg D, Nichols D, Oki BM, Terry D. Using collaborative filtering to weave an information tapestry. Communications of the ACM, 1992,35(12):61−70.<br />
[20]Konstan JA, Miller BN, Maltz D, Herlocker JL, Gordon LR, Riedl J. GroupLens: Applying collaborative filtering to usenet news. Communications of the ACM, 1997,40(3):77−87.<br />
[21]Terveen L, Hill W, Amento B, McDonald D, Creter J. PHOAKS: A system for sharing recommendations. Communications of the ACM, 1997,40(3):59−62.<br />
[22]Goldberg K, Roeder T, Gupta D, Perkins C. Eigentaste: A constant time collaborative filtering algorithm. Information Retrieval, 2001,4(2):133−151.<br />
[23]Breese JS, Heckerman D, Kadie C. Empirical analysis of predictive algorithms for collaborative filtering. Technical Report, MSR-TR-98-12, Redmond: Microsoft Research, 1998.<br />
[24]Delgado J, Ishii N. Memory-Based weighted-majority prediction for recommender systems. In: Proc. of the ACM SIGIR’99 Workshop Recommender Systems: Algorithms and Evaluation. New York: ACM Press, 1999.<br />
[25]Sarwar B, Karypis G, Konstan J, Riedl J. Item-Based collaborative filtering recommendation algorithms. In: Proc. of the 10th Int’l WWW Conf. New York: ACM Press, 2001. 285−295.<br />
[26]Billsus D, Pazzani M. Learning collaborative information filters. In: Proc. of Int’l Conf. on Machine Learning. San Francisco: Morgan Kaufmann Publishers Inc., 1998. 46−54.<br />
[27]Getoor L, Sahami M. Using probabilistic relational models for collaborative filtering. In: Proc. of the Workshop Web Usage Analysis and User Profiling. 1999.<br />
[28]Hofmann T. Collaborative filtering via Gaussian probabilistic latent semantic analysis. In: Proc. of the 26th Int’l ACM SIGIR Conf. New York: ACM Press, 2003. 259−266.<br />
[29]Marlin B. Modeling user rating profiles for collaborative filtering. In: Proc. of the 17th Annual Conf. on Neural Information Processing Systems. Cambridge: MIT Press, 2003. 627−634.<br />
[30]Ungar LH, Foster DP. Clustering methods for collaborative filtering. In: Proc. of the Workshop on Recommendation Systems. Menlo Park: AAAI Press, 1998. 112−125.<br />
[31]Chien YH, George EI. A Bayesian model for collaborative filtering. In: Proc. of the 7th Int’l Workshop on Artificial Intelligence and Statistics. San Francisco: Morgan Kaufmann, 1999.<br />
[32]Pavlov D, Pennock D. A maximum entropy approach to collaborative filtering in dynamic, sparse, high-dimensional domains. In: Proc. of the 16th Annual Conf. on Neural Information Processing Systems. 2002.<br />
[33]Shani G, Brafman R, Heckerman D. An MDP-based recommender system. The Journal of Machine Learning Research, 2005,6:1265−1295.<br />
[34]Burke R. Knowledge-Based recommender systems. Encyclopedia of Library and Information Systems, 2000,69(32):180−200.<br />
[35]Middleton SE, Shadbolt NR, de Roure DC. Ontological user profiling in recommender systems. ACM Trans. on Information Systems, 2004,22(1):54−88.<br />
[36]Basu C, Hirsh H, Cohen W. Recommendation as classification: Using social and content-based information in recommendation. In: Proc. of the AAAI’98. Menlo Park: AAAI Press. 1998. 714−720.<br />
[37]Claypool M, Gokhale A, Miranda T, Murnikov P, Netes D, Sartin M. Combining content-based and collaborative filters in an online newspaper. In: Proc. of the ACM SIGIR’99 Workshop Recommender Systems: Algorithms and Evaluation. New York: ACM Press, 1999.<br />
[38]Pazzani M. A framework for collaborative, content-based, and demographic filtering. Artificial Intelligence Review, 1999,13(5-6): 393−408.<br />
[39]Billsus D, Pazzani M. User modeling for adaptive news access. User Modeling and User-Adapted Interaction, 2000,10(2-3): 147−180.<br />
[40]Soboroff I, Nicholas C. Combining content and collaboration in text filtering. In: Proc. of the Int’l Joint Conf. on Artificial Intelligence Workshop: Machine Learning for Information Filtering. Stockholm, 1999. 86−91.<br />
[41]Good N, Schafer JB, Konstan JA, Borchers A, Sarwar B, Herlocker JL, Riedl J. Combining collaborative filtering with personal agents for better recommendations. In: Proc. of the 16th National Conf. on Artificial Intelligence. Menlo Park: AAAI Press, 1999. 439−446.<br />
[42]Melville P, Mooney RJ, Nagarajan R. Content-Boosted collaborative filtering for improved recommendations. In: Proc. of the 18th National Conf. on Artificial Intelligence. Menlo Park: American Association for Artificial Intelligence, 2002. 187−192.<br />
[43]Ansari A, Essegaier S, Kohli R. Internet recommendations systems. Journal of Marketing Research, 2000,37(3):363−375.<br />
[44]Miller BN, Albert I, Lam SK, Konstan JA, Riedl J. MovieLens unplugged: Experiences with an occasionally connected recommender system. In: Proc. of the Int’l Conf. on Intelligent User Interfaces. New York: ACM Press, 2003. 263−266.<br />
[45]EachMovie. EachMovie collaborative filtering data set. 1997. http://research.compaq.com/SRC/eachmovie<br />
[46]http://www.bookcrossing.com/</p>
<p><strong>本文作者：中国科学院计算机网络信息中心 许海玲 吴潇 李晓东</strong></p>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/google-user-centered-metrics.html' rel='bookmark' title='Google 用户体验指标衡量方案：HEART'>Google 用户体验指标衡量方案：HEART</a></li>
<li><a href='http://www.biaodianfu.com/amazon-com-recommendations.html' rel='bookmark' title='Amazon.com的推荐:从商品到商品的协同过滤'>Amazon.com的推荐:从商品到商品的协同过滤</a></li>
<li><a href='http://www.biaodianfu.com/google-news-model-and-techmeme-model-in-scientific-news-feeds.html' rel='bookmark' title='新闻聚合之Google news模式与 Techmeme模式'>新闻聚合之Google news模式与 Techmeme模式</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/comparison-study-of-internet-recommendation-system.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>基于增强学习的旅行计划推荐系统</title>
		<link>http://www.biaodianfu.com/recommender-system-for-travel-plan-based-on-reinforcement-learning.html</link>
		<comments>http://www.biaodianfu.com/recommender-system-for-travel-plan-based-on-reinforcement-learning.html#comments</comments>
		<pubDate>Thu, 12 Jan 2012 03:40:49 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[推荐系统]]></category>
		<category><![CDATA[旅行计划]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4566</guid>
		<description><![CDATA[1 概述 推荐系统是一种智能化电子商务应用，可以协助用户搜索信息，为用户提供个性化的产品推荐。旅游推荐系统的目的是支持旅行者在旅游前和旅游中面临的重要旅行规划决定。此类系统明确(通过问)或暗示(通过挖掘用户的在线活动日志)获取用户需求，并提供各种产品和服务，如前往目的地、兴趣点、事件或活动。近年来，研究者设计了很多旅游推荐系统，某些已经运行于主要的旅游门户网站。 传统推荐系统支持很简单的非交互检索流程：在旅行者交互的各个阶段，仅支持一种活动类型，例如，决定推荐给用户哪种产品。为了支持更真实的互动过程，人们提出了会话推荐系统。该系统支持对话，在每个阶段，系统能从可得的系统活动中选择一个行动。例如，推荐一些产品或向用户询问一些信息。系统选取的特别活动由推荐策略指定。例如，查询会话系统得到适合用户偏好的旅馆。可以采用以下2 种策略： 详细询问用户偏好，利用这些信息提取一个小的产品子集； 为用户推荐一系列产品，利用用户的反馈意见改进今后的建议。 这2 个会话策略最初应用于DieToRecs系统中，现在是Trip@dvice 技术的一部分。会话系统通常采用刚性策略，即在设计阶段已经确定而且在系统中使用严格编码。例如，Trip@dvice 允许用户选择这2 个策略中的任意一个，但必须严格遵照已选取策略中的步骤。该方法的主要局限在于，对于一个推荐任务可能有大量会话而不是刚性策略，如多种服务类型的旅游计划。此外，选取策略的过程基于直觉和系统设计者的先前经验，不一定适合用户。因此，设计者必须评估策略以发现最优策略，但考虑到必要开支、预算、精力、时间等，这不可行的。上述限制要求会话系统能自己确定最佳策略以协助用户。 文献提出一种新型基于会话的推荐系统来解决上述问题，而不是遵循硬性交互设计，提供了广泛的信息和决策支持功能，在交互过程中能改善最初的策略并采取最优策略。最优策略基本上可以最大化受益功能，用户能从每个交互步 骤中获益。笔者还基于人机模拟详细讨论了该方法的技术细节，并对评价结果进行描述。在评价中，当查询旅游服务(如旅馆)返回太多建议时，系统应当能决定是否向用户询问额外的服务特征以获取较小的服务集，或者让用户自动决定或手动更改查询。结果表明，推荐系统能改善最初的建议，严格地说，仅当结果集大于给定范围时才向用户询问以获取额外特征。但上述结果是在有限条件下得到的，即在一种情况下 系统必须做出决定，系统行为集只包含2 种行为。为了解决这些限制，本文提出一种基于会话推荐系统的自适应推荐系 统一般模型，将该模型用于旅行计划(Travel Planning, TP)工具中并描述了评价计划。 2 学习个性化的会话推荐互动策略 本文提出的推荐模型如图 1 所示，包含2 个实体，即信息系统IS 和推荐代理RA。信息系统是非自适应实体，功能完全由用户控制，可以提供简单的用户请求，如显示查询结果、热门搜索等。推荐代理是自适应实体，能自动协助用户，在交互过程的适当阶段为用户提供相关信息，这一协助过程基于系统的优化推荐策略。 在模型中，利用基于马尔可夫决策进程数学框架中的加固学习RL 技术学习最佳政策。马尔可夫决策过程是指决策者周期地或连续地观察具有马尔可夫性的随机动态系统，序贯地做出决策，即根据每个时刻观察到的状态，从可用的行动集合中选用一个行动做出决策。系统下一步(未来)的状态是随机的，且其状态转移概率具有马尔可夫性。决策者根据新观察到的状态，做新的决策，依此反复地进行。加固学习技术以此为基础，通过交互过程达到学习最优政策的目的。本文使用术语最优政策而不是最佳策略，策略只是政策规定如何根据系统行为选择规则实施策略。为通过RL 学习最优政策，认为RA 是决策制定代理必须实现的一个目标，即最优政策。通过与用户执行一些试错互动来实现，这些用户是代理环境的一部分。具体来说，在每个阶段，用户采取一些措施后，代理人指出当前形势或系统的状态(如图1 所示)。被观察的系统状态可能包括当前用户的状态信息(如目标和偏好)、正在进行的交互(如有多少产品用户已经浏览)、甚至代理自身的状态(如是否已经执行了一项推荐)。为学习最佳政策，这是代理必须具备的信息。 在一个或多个系统状态下，多系统行为可提供给代理执行(会话步骤)。例如，可能有这样的情形，系统不确定是提供旅馆建议更好还是其他选择更好。本文把这些状态标记为系统决策点(System Decision Point, SDP)。在系统决策点，代理尝试交互过程中不同的系统行为。对于每一个行为的执行，代理从环境中收到加强信号，通知它用户是否已接收先前行为。信号的大小由用户接收水平决定，例如，大的正信号(+10)可能标志最受欢迎的行为(如用户接收建议)，大的副信号(-10)可能标志最不受欢迎的行为(如用户退出)。在交互进行中，代理利用收到的反馈避免不能接受的行为，并采取可以接受的行为。这在政策迭代算法中执行，最大化立即回报和下一个阶段预期贴现值的行为定义该阶段的新最优行为。为计算下一阶段的预期贴现值，使用交互过程中学习到的状态转换概率。RL 政策迭代过程确保这一进程将最终导致代理学习每个系统决策点的最佳行为，即学习最佳政策。在非系统决策点状态，只有一个单一的行动可以执行，本文认为这是最佳行动。 3 自适应旅游计划建议 本节将上述方法采用旅游计划工具合并自适应推荐方法，并将该方法应用于奥地利门户网站，为用户提供多种旅行推荐方案。旅游计划工具由Trip@dvice 技术支持。Trip@dvice 允许用户从目录中选择旅行组件(旅馆、景点、活动)，将其绑定到一个新的计划中，或选择一个现有的旅行计划根据具体要求定制(删除或添加旅行组件)。如上所述，本文做法是基于学习一个或多个系统决策点的最佳行动，当用户在交互过程中通过系统浏览时，代理可能遇到这些系统决策点。用户导航流图基本模型如图2 所示。一个浏览状态代表用户交互中可能浏览的任意一个网页(如一个查询输入表单)。在每个浏览状态中，用户可以采取一个或多个用户行动导航到系统状态(如提交一个查询或返回到先前的交互状态)。 系统状态可能是 SDP 或非SDP 状态，因此，可用于选择下一个系统行为，其结果在下一个新的网页中呈现给用户。例如，假设在查询输入浏览状态，用户提交一个查询。为确保系统状态是SDP，此处系统必须决定如何继续会话以及下一个浏览状态需要呈现什么信息，如询问更多的偏好或执行查询。目前使用 Trip@dvice CBR 方法计算相关产品建议(如在相似过程中选择更高档次的产品)。提供2 种产品查询功能： 寻求启示，为用户循环提供建议产品清单直到用户选择一些产品； 查询搜索，用户限制逻辑查询产品目录以便搜索。 Trip@dvice 严格的会话政策决定了当前非自适应用户导航流图必须采用TP。流程图由单一的SDP 构成，该SDP [...]]]></description>
			<content:encoded><![CDATA[<p>1 概述</p>
<p>推荐系统是一种智能化电子商务应用，可以协助用户搜索信息，为用户提供个性化的产品推荐。旅游推荐系统的目的是支持旅行者在旅游前和旅游中面临的重要旅行规划决定。此类系统明确(通过问)或暗示(通过挖掘用户的在线活动日志)获取用户需求，并提供各种产品和服务，如前往目的地、兴趣点、事件或活动。近年来，研究者设计了很多旅游推荐系统，某些已经运行于主要的旅游门户网站。</p>
<p>传统推荐系统支持很简单的非交互检索流程：在旅行者交互的各个阶段，仅支持一种活动类型，例如，决定推荐给用户哪种产品。为了支持更真实的互动过程，人们提出了会话推荐系统。该系统支持对话，在每个阶段，系统能从可得的系统活动中选择一个行动。例如，推荐一些产品或向用户询问一些信息。系统选取的特别活动由推荐策略指定。例如，查询会话系统得到适合用户偏好的旅馆。可以采用以下2 种策略：</p>
<ol>
<li>详细询问用户偏好，利用这些信息提取一个小的产品子集；</li>
<li>为用户推荐一系列产品，利用用户的反馈意见改进今后的建议。</li>
</ol>
<p>这2 个会话策略最初应用于DieToRecs系统中，现在是Trip@dvice 技术的一部分。会话系统通常采用刚性策略，即在设计阶段已经确定而且在系统中使用严格编码。例如，Trip@dvice 允许用户选择这2 个策略中的任意一个，但必须严格遵照已选取策略中的步骤。该方法的主要局限在于，对于一个推荐任务可能有大量会话而不是刚性策略，如多种服务类型的旅游计划。此外，选取策略的过程基于直觉和系统设计者的先前经验，不一定适合用户。因此，设计者必须评估策略以发现最优策略，但考虑到必要开支、预算、精力、时间等，这不可行的。上述限制要求会话系统能自己确定最佳策略以协助用户。</p>
<p>文献提出一种新型基于会话的推荐系统来解决上述问题，而不是遵循硬性交互设计，提供了广泛的信息和决策支持功能，在交互过程中能改善最初的策略并采取最优策略。最优策略基本上可以最大化受益功能，用户能从每个交互步<br />
骤中获益。笔者还基于人机模拟详细讨论了该方法的技术细节，并对评价结果进行描述。在评价中，当查询旅游服务(如旅馆)返回太多建议时，系统应当能决定是否向用户询问额外的服务特征以获取较小的服务集，或者让用户自动决定或手动更改查询。结果表明，推荐系统能改善最初的建议，严格地说，仅当结果集大于给定范围时才向用户询问以获取额外特征。但上述结果是在有限条件下得到的，即在一种情况下<br />
系统必须做出决定，系统行为集只包含2 种行为。为了解决这些限制，本文提出一种基于会话推荐系统的自适应推荐系<br />
统一般模型，将该模型用于旅行计划(Travel Planning, TP)工具中并描述了评价计划。</p>
<p><strong>2 学习个性化的会话推荐互动策略</strong></p>
<p>本文提出的推荐模型如图 1 所示，包含2 个实体，即信息系统IS 和推荐代理RA。信息系统是非自适应实体，功能完全由用户控制，可以提供简单的用户请求，如显示查询结果、热门搜索等。推荐代理是自适应实体，能自动协助用户，在交互过程的适当阶段为用户提供相关信息，这一协助过程基于系统的优化推荐策略。</p>
<p><img class="alignnone size-full wp-image-4567" title="Recommender-System" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/Recommender-System.png" alt="" width="511" height="353" /></p>
<p>在模型中，利用基于马尔可夫决策进程数学框架中的加固学习RL 技术学习最佳政策。马尔可夫决策过程是指决策者周期地或连续地观察具有马尔可夫性的随机动态系统，序贯地做出决策，即根据每个时刻观察到的状态，从可用的行动集合中选用一个行动做出决策。系统下一步(未来)的状态是随机的，且其状态转移概率具有马尔可夫性。决策者根据新观察到的状态，做新的决策，依此反复地进行。加固学习技术以此为基础，通过交互过程达到学习最优政策的目的。本文使用术语最优政策而不是最佳策略，策略只是政策规定如何根据系统行为选择规则实施策略。为通过RL 学习最优政策，认为RA 是决策制定代理必须实现的一个目标，即最优政策。通过与用户执行一些试错互动来实现，这些用户是代理环境的一部分。具体来说，在每个阶段，用户采取一些措施后，代理人指出当前形势或系统的状态(如图1 所示)。被观察的系统状态可能包括当前用户的状态信息(如目标和偏好)、正在进行的交互(如有多少产品用户已经浏览)、甚至代理自身的状态(如是否已经执行了一项推荐)。为学习最佳政策，这是代理必须具备的信息。</p>
<p>在一个或多个系统状态下，多系统行为可提供给代理执行(会话步骤)。例如，可能有这样的情形，系统不确定是提供旅馆建议更好还是其他选择更好。本文把这些状态标记为系统决策点(System Decision Point, SDP)。在系统决策点，代理尝试交互过程中不同的系统行为。对于每一个行为的执行，代理从环境中收到加强信号，通知它用户是否已接收先前行为。信号的大小由用户接收水平决定，例如，大的正信号(+10)可能标志最受欢迎的行为(如用户接收建议)，大的副信号(-10)可能标志最不受欢迎的行为(如用户退出)。在交互进行中，代理利用收到的反馈避免不能接受的行为，并采取可以接受的行为。这在政策迭代算法中执行，最大化立即回报和下一个阶段预期贴现值的行为定义该阶段的新最优行为。为计算下一阶段的预期贴现值，使用交互过程中学习到的状态转换概率。RL 政策迭代过程确保这一进程将最终导致代理学习每个系统决策点的最佳行为，即学习最佳政策。在非系统决策点状态，只有一个单一的行动可以执行，本文认为这是最佳行动。</p>
<p><strong>3 自适应旅游计划建议</strong></p>
<p>本节将上述方法采用旅游计划工具合并自适应推荐方法，并将该方法应用于奥地利门户网站，为用户提供多种旅行推荐方案。旅游计划工具由Trip@dvice 技术支持。Trip@dvice 允许用户从目录中选择旅行组件(旅馆、景点、活动)，将其绑定到一个新的计划中，或选择一个现有的旅行计划根据具体要求定制(删除或添加旅行组件)。如上所述，本文做法是基于学习一个或多个系统决策点的最佳行动，当用户在交互过程中通过系统浏览时，代理可能遇到这些系统决策点。用户导航流图基本模型如图2 所示。一个浏览状态代表用户交互中可能浏览的任意一个网页(如一个查询输入表单)。在每个浏览状态中，用户可以采取一个或多个用户行动导航到系统状态(如提交一个查询或返回到先前的交互状态)。</p>
<p><img class="alignnone size-full wp-image-4568" title="user-visit-model" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/user-visit-model.png" alt="" width="404" height="110" /></p>
<p>系统状态可能是 SDP 或非SDP 状态，因此，可用于选择下一个系统行为，其结果在下一个新的网页中呈现给用户。例如，假设在查询输入浏览状态，用户提交一个查询。为确保系统状态是SDP，此处系统必须决定如何继续会话以及下一个浏览状态需要呈现什么信息，如询问更多的偏好或执行查询。目前使用 Trip@dvice CBR 方法计算相关产品建议(如在相似过程中选择更高档次的产品)。提供2 种产品查询功能：</p>
<ol>
<li>寻求启示，为用户循环提供建议产品清单直到用户选择一些产品；</li>
<li>查询搜索，用户限制逻辑查询产品目录以便搜索。</li>
</ol>
<p>Trip@dvice 严格的会话政策决定了当前非自适应用户导航流图必须采用TP。流程图由单一的SDP 构成，该SDP 决定用户提交的产品查询以及系统得到的大量产品。Trip@dvice 的政策规定，当结果集大于某一阈值时系统建议给用户更多的功能。为了更好地学习最优政策，研究者提议增设3 个SDP纳入到非自适应流和更详细的系统设置。本文只展示导航流图的4 个SDP(见图3 和图4)，而不是完整的自适应导航流图。</p>
<p><img class="alignnone size-full wp-image-4569" title="decision-point" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/decision-point.png" alt="" width="522" height="317" /></p>
<p><img class="alignnone size-full wp-image-4570" title="SuggTight" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/SuggTight.png" alt="" width="346" height="276" /></p>
<p>在图 3 中，用户通过欢迎页面输入系统。在此页面中，如果选择QrySrch 功能(用户行为SlctQrySrch)，系统在SDP1输入，SDP1 应当决定是否在浏览状态ViewSrchOpts(系统行为ShowOpts)向用户显示不同的查找目录(目的地、事件等)或是在显示各种服务类别之前询问用户一些旅行特点(系统行为AskChars)。具体来说，用户在浏览状态SpecChars 输入自己的特点(用户行为EnterChars)。系统进入非SDP 系统状<br />
态(黑色圆圈1)，在此唯一可能的系统行为执行ShowOpts。此外，如果用户选择Seeklnsp 功能(用户行为Slct Seeklmp)，则系统在SDP2 输入，SDP2 应当决定是否在浏览状态ViewProposals(系统行为ShowProps)向用户显示产品建议列表或在显示完整的旅行计划建议前询问用户一些旅行特点(系统行为AskChars)。一旦用户在SpecChars 输入自己的特点，系统便进入非SDP 状态(黑色圆圈2)。其中，唯一可能的系统行为是ShowProps。</p>
<p>如果用户限制条件并提交了具体的搜索查询(如旅馆)，则系统进入SDP(见图4)。在浏览状态ViewTightFtrs(系统行为SuggTight)，如果查询的结果集大小大于一定阈值，则系统应决定是否提出产品特性以减小结果集或执行查询并显示所有检索(系统行为Exec)。另外，如果查询结果集为空，即没有旅馆满足条件，系统也应决定是否建议用户在浏览状态ViewRelaxFtrs(系统行为SuggRelax)放宽一些条件或从查询(系统行为autoRelax)自动放宽一个条件(由系统而不是用户选择)以便产生一个结果集。在产品列表准备显示给用户的情形下，系统达到SDP4(见图4)，必须决定如下页面之一：</p>
<ol>
<li>ShowRP1，显示页面ViewRP1，系统简单显示推荐产品列表；</li>
<li>ShowRP2，显示页面ViewRP2，系统除了显示产品列表外还要求用户输入一些旅行特色；</li>
<li>ShowRP3，显示页面ViewRP3，系统除了显示产品列表外还推动用户提出一些其他类型产品相关的搜索；</li>
<li>ShowRP，显示页面ViewRP4，系统除了显示产品列表外还推动用户向他们的购物篮添加顶级产品，并提出其他产品类型的一些相关搜索。</li>
</ol>
<p>在完整的自适应导航流图中，本文以20 个浏览状态和4 个系统决策点为示范，同时按照图形化的系统规范Petri 网来执行流程。模仿Petri 网中的术语，本文称浏览状态、用户行为、系统状态、系统行为分别为地点、输入、过渡、输出。这种表示对于通过图形挖掘工具(如ProM 框架)跟踪用户的导航流(评估过程中产生)以及获取不同信息(用户的一般导航模型、用户采取的独特导航路径、最常见的路径)非常有用。</p>
<p><strong>4 系统设计与评价</strong></p>
<p>根据图 1 所示推荐模型，系统架构包括2 个主要实体，即学习最佳政策功能的推荐代理和环境。环境表示用户和信息系统，包含API，允许推荐代理及其内部之外的对象进行交互以获取学习最优政策必须的数据，例如在某些互动阶段用户采取的行为、系统到达的状态等。系统架构如图5 所示。</p>
<p><img class="alignnone size-full wp-image-4571" title="system-architecture" src="http://www.biaodianfu.com/wp-content/uploads/2012/01/system-architecture.png" alt="" width="532" height="330" /></p>
<p>在环境里，用户请求推荐系统以满足一个或多个导航/信息目标。这些请求传递给系统的对话管理器组件，对话管理器组件处理这些请求并根据系统的业务逻辑(从产品目录提取数据)和应用服务组件进行交互。状态管理器在每个用户请求后计算系统状态，在每个SDP 向推荐代理询问应用系统行为。此外，它通知推荐代理状态的改变，使代理可以在用户会话的每个阶段获取和存储(在日志数据组件)用户采取的行为、确保系统状态的相关信息、在此状态执行的系统行为、由对话管理器生成的结果浏览状态(页面)。在推荐代理中，决策管理器是在SDP 要求执行的系统行为的信息系统界面。它与用于存储当前代理政策的政策管理器组件交互。此外，决策管理器还记录每个阶段的所有相关数据(日志管理器)，此类数据被学习管理器再利用以学习最优政策。</p>
<p>上述旅行推荐创新办法需要一个新的具体评价方法。本文基于旅行推荐系统的2 个替代变量设计了一种方法：非自适应和自适应版本。第1 个变量基本遵循缺省的交互政策集，为用户提供设计好的严格编码逻辑建议。第2 个变量遵循学习过程的结果交互政策。本文基于一系列可靠措施对这些变量的性能进行假设测试，假设基于用户的搜索和产品选择行为以及对系统行为的满意度。评价中必须选择一组参与者(满足特定要求)，他们将随机分配到2 组实验，每组要求评价推荐系统中的变量。评价分2 个阶段进行。在训练阶段，首先进行的是第1 组实验，推荐变量采用替代的手工政策集。此变量构成基准系统。在此阶段，日志管理器记录所有相关序列数据的日志(用户行为、系统状态信息、系统行为、浏览状态)，然后被学习管理器组件利用，以学习TP 自适应流图的最优政策。在测试阶段、训练阶段之后执行第2 组实验，评估所采用的最优政策的推荐变量。</p>
<p>在每个阶段，要求参与者在蒂罗尔、奥地利地区规划度假的一般范围内执行一些任务。必须记录一系列操作步骤，在交互过程中(通过日志数据组件)一些会被自动记录，另一些则要求用户在交互后填写一张调查问卷。评价的目的是通过确定这些措施从训练阶段到测试阶段的改善来测验本文假设。主要测量由推荐代理获得的总回报(使用一种特殊政策)和系统的成功率，从而在系统评价中发现更有助于找到最优政策的状态变量。根据模拟实验，学习政策依赖用户和会话<br />
模型，即最佳交互政策受用户知识的影响，在人-机交互中获取，并由推荐代理使用。</p>
<p><strong>5 结束语</strong></p>
<p>本文对旅行和旅游业应用推荐系统的概念设计提出了一些意见。提出的模型已由一系列离线实验验证，但还需要进一步分析。本文方法需要模拟应包含在系统状态表示的用户相关信息(人口统计、用户目标等)。信息可显性(询问用户)或隐性(从交互日志中)获取。隐性获取方法是强制性的，因为用户通常对系统问题都不作答复。但考虑到在线用户行为通常是不可预测的或错误的，这些隐性信息的质量可能是可疑的。因此，需要可靠的研究方法确定哪些信息在系统状态是相关的。这将扩大基于模拟提出的结果。此外，需要更好的方法来评价由推荐代理分配给新状态的数值回报价值，这是用户响应的结果。这些值应该尽可能接近用户的满意度，而这一般通过观察用户活动来推断。尽管存在诸多困难，离线评价的结果证明，使用本文提出的模型和方法可以改善系统性能，有利于加快会话旅行推荐系统的开发。</p>
<p><strong>本文作者：刘小燕，陈艳丽，贾宗璞，沈记全 (河南理工大学计算机科学与技术学院，河南焦作 454003)</strong></p>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/conversion-rate-way.html' rel='bookmark' title='提升网站转化率的六种方法'>提升网站转化率的六种方法</a></li>
<li><a href='http://www.biaodianfu.com/sina-twitter-2.html' rel='bookmark' title='新浪微博客试用体会'>新浪微博客试用体会</a></li>
<li><a href='http://www.biaodianfu.com/mobile-soft.html' rel='bookmark' title='手机客户端开发定位'>手机客户端开发定位</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/recommender-system-for-travel-plan-based-on-reinforcement-learning.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为什么国内还有那么多网站使用.NET架构？</title>
		<link>http://www.biaodianfu.com/why-use-net-framework.html</link>
		<comments>http://www.biaodianfu.com/why-use-net-framework.html#comments</comments>
		<pubDate>Fri, 06 Jan 2012 09:13:03 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[京东]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4560</guid>
		<description><![CDATA[一、目前使用.NET 的国内大型网站有哪些？ 卓越http://www.amazon.cn/ 当当http://www.dangdang.com/ 京东http://www.360buy.com/ 凡客http://www.vancl.com/ 携程http://www.ctrip.com/ 二、为什么这么多网站使用Windows/.NET? 创业初期，创始人非技术背景出身，对Unix/Linux存在恐惧心理或对使用何种平台和框架没有想法。 创业初期，创始人技术出身，选择了自己擅长的语言。 创业初期，创始人对语言没有什么要求，唯一的要求就是省钱、快速上线。 三、使用Win/.NET的好处有哪些？ 人员：招聘比较快，各大高校和培训机构都有教.NET的。初级程序员工资要求比较低。 开发：入门简单，开发效率高。 维护：Windows Server 界面操作简单，便于维护，有现成的商业监控维护工具可用。 服务：提供了整体解决方案，如SQL Server提供了统计计算、数据挖掘、事务支持等。 四、使用Win/.NET有哪些不好的地方？ 使用.NET基本上被强制捆绑到了Windows上，虽然Linux机器上也有.NET支持的Mono（ http://www.mono-project.com/ ），但是性能并没有Windows系统上的那么好。.NET程序员在整个网站基础架构的优化改良上课选择的东西比较少。微软的东西一般不太会出现问题，但是如果出现问题，很难快速的找到解决方案。 最新的技术不能及时的应用到Windows平台，只能期望微软的早日更新。比如Windows对snmp协议的支持目前只能到2c，不能到3。许多无数的开源、高端服务器组件只有Linux/Unix版本。许多优化技术、高性能分布式缓存、数据库、NoSQL解决方案等等，仅针对Linux/Unix。 Windows Server的授权费比较贵（对于大型网站可能不太在乎）。如果有上百台服务器就需要购买上百份授权，如果一台服务器上安装N个虚拟机，就需要购买N份授权。 五、京东商城选择.NET的原因是什么？ 刘强东之前有.net程序员背景， 一开始的版本由他进行开发。.NET的人也比较容易招，创业初期有很多公司都是使用盗版的Windows Server的，不需要支付授权费用（不知道京东商城是不是）。 京东商城不是一家技术公司，它只是一个建立在电子商务平台上的销售公司。早期更偏向后端的物流仓储管理，后端进销存体系就是.net基础的。京东现在用的内部ERP，一开始是刘强东自己开发的。 六、京东商城为什么一做活动就宕机？ 管理不到位，管理者急功近利，要求员工超、快、猛，貌似每个公司都这样。项目的进度较少了设计和思考的时间。 运维不到位，没有提前对每次活动会带来的流量进行合理的评估，为活动提供服务器资源等。 这个猜想貌似不靠谱，貌似用堆服务器的方法无法解决性能问题。     架构不到位，前后台的依赖比较高。比如前台的库存要直接依赖后台库存数据等，这些不知道京东是如何处理的。 原开发不到位，开发者的能力没有到登峰造极的地步（这个比较困难啊），貌似除了微软自身的网站可以做到，其他网站的程序员很难做到。 七、京东商城用.NET架构合适吗？ 目前京东商城已经停止招.NET程序员了，进而转向JAVA。这是京东商城对目前出现问题的一个响应。但是开发程序的转变仅仅是第一步。系统性能的瓶颈主要集中在操作系统、网络和数据库上。京东商城在改变目前架构的时候肯定会遇到很多阻力和问题。比较典型的会有： 人员问题：目前掌权的，为京东商城立下汗马功劳的都是.NET会程序员，不可能把其撤掉。要让其领导新招的JAVA程序员，下属也会认为不妥。目前大量的.NET后期将何去何从，辞退或转型都不太好处理。 程序问题：现在的版本是通过不断的迭代才稳定下来的，如果需要同步无可避免的还会遇到很多问题。时间成本和人员成本都比较高。 数据问题：对原有架构的调整需要保证原来系统中的业务流、资金流，、数据流的整体平移。如供货商的管理，供应商考核，采购管理，退货管理等数据。 现实问题：没有像F1赛车那样的设计（现在的京东确实没有），无法对高速行驶的车辆更换主要零部件。京东也不可能会停下来。 八、如果真的遇到上述问题改如何去解决？（来看下实例） Stack Overflow 现在他们使用越来越多的Linux服务器，比如HAProxy(负载均衡), Redis(NoSQL数据库), Bacula(数据备份系统), Nagios(远程监控软件), 日志, 路由器都运行于Linux系统，几乎所有需要并行处理的功能都是由Linux处理。 当当目前已经渐渐转到Linux + PHP + [...]]]></description>
			<content:encoded><![CDATA[<p><strong>一、目前使用.NET 的国内大型网站有哪些？</strong></p>
<ul>
<li>卓越<a href="http://www.amazon.cn/">http://www.amazon.cn/</a></li>
<li>当当<a href="http://www.dangdang.com/">http://www.dangdang.com/</a></li>
<li>京东<a href="http://www.360buy.com/">http://www.360buy.com/</a></li>
<li>凡客<a href="http://www.vancl.com/">http://www.vancl.com/</a></li>
<li>携程<a href="http://www.ctrip.com/">http://www.ctrip.com/</a></li>
</ul>
<p><strong>二、为什么这么多网站使用Windows/.NET?</strong></p>
<ul>
<li>创业初期，创始人非技术背景出身，对Unix/Linux存在恐惧心理或对使用何种平台和框架没有想法。</li>
<li>创业初期，创始人技术出身，选择了自己擅长的语言。</li>
<li>创业初期，创始人对语言没有什么要求，唯一的要求就是省钱、快速上线。</li>
</ul>
<p><strong>三、使用Win/.NET的好处有哪些？</strong></p>
<ul>
<li>人员：招聘比较快，各大高校和培训机构都有教.NET的。初级程序员工资要求比较低。</li>
<li>开发：入门简单，开发效率高。</li>
<li>维护：Windows Server 界面操作简单，便于维护，有现成的商业监控维护工具可用。</li>
<li>服务：提供了整体解决方案，如SQL Server提供了统计计算、数据挖掘、事务支持等。</li>
</ul>
<p><strong>四、使用Win/.NET有哪些不好的地方？</strong></p>
<ul>
<li>使用.NET基本上被强制捆绑到了Windows上，虽然Linux机器上也有.NET支持的Mono（ <a href="http://www.mono-project.com/">http://www.mono-project.com/</a> ），但是性能并没有Windows系统上的那么好。.NET程序员在整个网站基础架构的优化改良上课选择的东西比较少。微软的东西一般不太会出现问题，但是如果出现问题，很难快速的找到解决方案。</li>
<li>最新的技术不能及时的应用到Windows平台，只能期望微软的早日更新。比如Windows对snmp协议的支持目前只能到2c，不能到3。许多无数的开源、高端服务器组件只有Linux/Unix版本。许多优化技术、高性能分布式缓存、数据库、NoSQL解决方案等等，仅针对Linux/Unix。</li>
<li>Windows Server的授权费比较贵（对于大型网站可能不太在乎）。如果有上百台服务器就需要购买上百份授权，如果一台服务器上安装N个虚拟机，就需要购买N份授权。</li>
</ul>
<p><strong>五、京东商城选择.NET的原因是什么？</strong></p>
<ul>
<li>刘强东之前有.net程序员背景， 一开始的版本由他进行开发。.NET的人也比较容易招，创业初期有很多公司都是使用盗版的Windows Server的，不需要支付授权费用（不知道京东商城是不是）。</li>
<li>京东商城不是一家技术公司，它只是一个建立在电子商务平台上的销售公司。早期更偏向后端的物流仓储管理，后端进销存体系就是.net基础的。京东现在用的内部ERP，一开始是刘强东自己开发的。</li>
</ul>
<p><strong>六、京东商城为什么一做活动就宕机？</strong></p>
<ul>
<li>管理不到位，管理者急功近利，要求员工超、快、猛，貌似每个公司都这样。项目的进度较少了设计和思考的时间。</li>
<li>运维不到位，没有提前对每次活动会带来的流量进行合理的评估，为活动提供服务器资源等。 这个猜想貌似不靠谱，貌似用堆服务器的方法无法解决性能问题。    </li>
<li>架构不到位，前后台的依赖比较高。比如前台的库存要直接依赖后台库存数据等，这些不知道京东是如何处理的。</li>
<li>原开发不到位，开发者的能力没有到登峰造极的地步（这个比较困难啊），貌似除了微软自身的网站可以做到，其他网站的程序员很难做到。</li>
</ul>
<p><strong>七、京东商城用.NET架构合适吗？</strong></p>
<p>目前京东商城已经停止招.NET程序员了，进而转向JAVA。这是京东商城对目前出现问题的一个响应。但是开发程序的转变仅仅是第一步。系统性能的瓶颈主要集中在操作系统、网络和数据库上。京东商城在改变目前架构的时候肯定会遇到很多阻力和问题。比较典型的会有：</p>
<ul>
<li>人员问题：目前掌权的，为京东商城立下汗马功劳的都是.NET会程序员，不可能把其撤掉。要让其领导新招的JAVA程序员，下属也会认为不妥。目前大量的.NET后期将何去何从，辞退或转型都不太好处理。</li>
<li>程序问题：现在的版本是通过不断的迭代才稳定下来的，如果需要同步无可避免的还会遇到很多问题。时间成本和人员成本都比较高。</li>
<li>数据问题：对原有架构的调整需要保证原来系统中的业务流、资金流，、数据流的整体平移。如供货商的管理，供应商考核，采购管理，退货管理等数据。</li>
<li>现实问题：没有像F1赛车那样的设计（现在的京东确实没有），无法对高速行驶的车辆更换主要零部件。京东也不可能会停下来。</li>
</ul>
<p><strong>八、如果真的遇到上述问题改如何去解决？（来看下实例）</strong></p>
<p>Stack Overflow 现在他们使用越来越多的Linux服务器，比如HAProxy(负载均衡), Redis(NoSQL数据库), Bacula(数据备份系统), Nagios(远程监控软件), 日志, 路由器都运行于Linux系统，几乎所有需要并行处理的功能都是由Linux处理。</p>
<p>当当目前已经渐渐转到Linux + PHP + Mysql，搜索、推荐等C++的后台也从Windows转为Linux版了。现在订单等后台作业依然采用C#跑着。</p>
<p>本文整理自知乎：<a href="http://www.zhihu.com/question/19818863">http://www.zhihu.com/question/19818863</a></p>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/smarty.html' rel='bookmark' title='Smarty 最近一直在学习的模板引擎'>Smarty 最近一直在学习的模板引擎</a></li>
<li><a href='http://www.biaodianfu.com/smsniff.html' rel='bookmark' title='网络抓包工具推荐：SmartSniff'>网络抓包工具推荐：SmartSniff</a></li>
<li><a href='http://www.biaodianfu.com/ipad-backup.html' rel='bookmark' title='iPad备份软件推荐：tinyumbrella'>iPad备份软件推荐：tinyumbrella</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/why-use-net-framework.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>协同过滤推荐系统的那些不足点</title>
		<link>http://www.biaodianfu.com/problems-of-recommender-systems.html</link>
		<comments>http://www.biaodianfu.com/problems-of-recommender-systems.html#comments</comments>
		<pubDate>Thu, 29 Dec 2011 04:34:33 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4557</guid>
		<description><![CDATA[类目（种类）推荐杂很多情境下行不通，因为有太多的产品属性，而每个属性（比如价钱，颜色，风格，面料，等等）在不同的时候对于消费者的重要程度都是不一样的。取而代之的是协同过滤推荐系统。但是协同过滤推荐系统也不是那么完美无缺，他或多或少的会有那么一些问题~ 1、数据稀疏问题 协同过滤的精度主要取决于用户数据的多少。如果一个系统有很多用户的历史数据，他就能更好的对用户的喜欢做出预测。所以，目前推荐系统做的最好的都是那些有着很大量用户数据的公司，比如Google, Yahoo, Netflix, Amazon等等。一个好的推荐系统首先需要类目（种类）数据（从目录或者其它形式得到），然后系统必须捕获并且分析这些用户数据（用户行为），然后，再应用神奇的算法工作。分析越多的类目（种类）和用户数据，系统越有可能生产好的推荐。但是，这又是一个蛋和鸡的问题：要形成好的推荐，首先需要有大量的用户，这样才能得到大量的推荐数据。 2、新用户问题（新产品问题） 这个问题和数据稀疏问题有一些相似性，他是指如何对新用户做出推荐。当一个新用户进入一个站点时，我们对他的兴趣爱好还一无所知，这时如何做出推荐是一个很重要的问题。一般在这个时候，我们只是向用户推荐那写普遍反映比较好的物品，也就是说，推荐完全是基于物品的。对于新的产品，同样存在如上的问题。 3、长尾问题（长尾用户/长尾商品） 新用户问题还有一个变种就是长尾(long tail)问题，在Amazon中，不是所有的用户都对很多书给出了评分，很多用户只给少数的书给出了评分，这些用户就处在一个长尾中，如何处理那些不太表露自己兴趣的用户，也是推荐系统的一个主要问题。除此之外，图书的长尾也是一个不可忽视的问题。 4、不断变化的用户喜好 用户的兴趣不是永远不变的，随着年龄和阅历的变化，用户的行为会发生变化。协同过滤其实还应该加入一个时间因子。今天自己浏览amazon时是会有特定意图的，明天或许会有另一个特定意图。举个典型的例子：有可能某天我会上amazon为自己买本书，但第二天我到amazon的原因可能是要为姐姐找一份生日礼物。对于用户喜好，推荐系统也可能错误的标注。 5、隐性喜好难处理 在现在的推荐系统中，用户的喜欢是通过用户对某些物品进行评分获得的。这种获得用户兴趣的方法是一种很直接的方法。但在实际的互联网中，用户有很多隐性的方法表露他们的喜欢。比如用户的文字评论，我们可以通过自然语言处理从用户的评论中获得用户的兴趣；或者是用户的浏览行为，比如用户长时间的浏览一个物品，或者用户经常浏览一个物品，或者用户 购买了一个物品，这些行为都可以作为模式识别系统中的特征。  6、偏激的用户和另类的产品 世界上有一些用户是很偏激的。他们和大多数人的观点是相反的。对于这种用户，现有的推荐系统做出的预测往往是很差的。如何处理偏激的用户，是推荐系统中的一个重要问题。和偏激用户相对应的，是颠覆性的产品。比如一些古怪（特别）的电影会有一些问题，有一些电影观众对它又爱又恨，这种类型的电影是很难去做推荐的，因为用户对它们会有各种反映而且无法预计。 7、马太效应的影响 在互联网中，物品实在是太多了，而推荐系统只能推荐有限的物品。被推荐系统所推荐的物品将会越来越热门，这就导致了大量很好的物品可能会被推荐系统所淹没。解决这个问题的主要方法是增加推荐系统的多样性，比如一个推荐系统发现一个用户非常喜欢吃德芙巧克力，那么他给这个用户推荐10个产品，不需要都是德芙巧克力，也可以推荐别的一些巧克力，或者一些和巧克力相似的甜品。在推荐时，不仅要推荐用户喜欢的东西，而且要通过推荐让用户喜欢一些东西，有的时候，用户自己也不知道他喜欢什么，通过推荐系统，他可能会发现一些新东西他比较喜欢。  8、推荐系统的作弊行为 只要涉及到经济利益，就有人作弊。搜索引擎作弊是一个被研究了很久的问题，因为在搜索引擎中，自己的网站排名越高，就能获得越多的经济利益。在推荐系统中也是如此，比如在淘宝中，如果一个卖家的物品经常被推荐，他就可能获得很多经济利益。很多电子商务的推荐系统都遭受到了作弊的干扰，一些人通过一些技术手段，对自己卖的物品给出非常高的评分，这就是一种作弊行为。作弊行为相当于人为的向系统中注入了噪声。目前解决作弊的算法主要是基于信任度和信用的。现在很多电子商务网站都引入了信用系统，比如淘宝等等。如何设计信用系统和推荐系统更好的融合，是一个重要的研究问题。 No related posts.]]></description>
			<content:encoded><![CDATA[<p>类目（种类）推荐杂很多情境下行不通，因为有太多的产品属性，而每个属性（比如价钱，颜色，风格，面料，等等）在不同的时候对于消费者的重要程度都是不一样的。取而代之的是协同过滤推荐系统。但是协同过滤推荐系统也不是那么完美无缺，他或多或少的会有那么一些问题~</p>
<p><strong>1、数据稀疏问题</strong></p>
<p>协同过滤的精度主要取决于用户数据的多少。如果一个系统有很多用户的历史数据，他就能更好的对用户的喜欢做出预测。所以，目前推荐系统做的最好的都是那些有着很大量用户数据的公司，比如Google, Yahoo, Netflix, Amazon等等。一个好的推荐系统首先需要类目（种类）数据（从目录或者其它形式得到），然后系统必须捕获并且分析这些用户数据（用户行为），然后，再应用神奇的算法工作。分析越多的类目（种类）和用户数据，系统越有可能生产好的推荐。但是，这又是一个蛋和鸡的问题：要形成好的推荐，首先需要有大量的用户，这样才能得到大量的推荐数据。</p>
<p><strong>2、新用户问题（新产品问题）</strong></p>
<p>这个问题和数据稀疏问题有一些相似性，他是指如何对新用户做出推荐。当一个新用户进入一个站点时，我们对他的兴趣爱好还一无所知，这时如何做出推荐是一个很重要的问题。一般在这个时候，我们只是向用户推荐那写普遍反映比较好的物品，也就是说，推荐完全是基于物品的。对于新的产品，同样存在如上的问题。</p>
<p><strong>3、长尾问题（长尾用户/长尾商品）</strong></p>
<p>新用户问题还有一个变种就是长尾(long tail)问题，在Amazon中，不是所有的用户都对很多书给出了评分，很多用户只给少数的书给出了评分，这些用户就处在一个长尾中，如何处理那些不太表露自己兴趣的用户，也是推荐系统的一个主要问题。除此之外，图书的长尾也是一个不可忽视的问题。</p>
<p><strong>4、</strong><strong>不断变化的用户喜好</strong></p>
<p>用户的兴趣不是永远不变的，随着年龄和阅历的变化，用户的行为会发生变化。协同过滤其实还应该加入一个时间因子。今天自己浏览amazon时是会有特定意图的，明天或许会有另一个特定意图。举个典型的例子：有可能某天我会上amazon为自己买本书，但第二天我到amazon的原因可能是要为姐姐找一份生日礼物。对于用户喜好，推荐系统也可能错误的标注。</p>
<p><strong>5、隐性喜好难处理</strong></p>
<p>在现在的推荐系统中，用户的喜欢是通过用户对某些物品进行评分获得的。这种获得用户兴趣的方法是一种很直接的方法。但在实际的互联网中，用户有很多隐性的方法表露他们的喜欢。比如用户的文字评论，我们可以通过自然语言处理从用户的评论中获得用户的兴趣；或者是用户的浏览行为，比如用户长时间的浏览一个物品，或者用户经常浏览一个物品，或者用户<br />
购买了一个物品，这些行为都可以作为模式识别系统中的特征。</p>
<p><strong> 6、偏激的用户和另类的产品</strong></p>
<p>世界上有一些用户是很偏激的。他们和大多数人的观点是相反的。对于这种用户，现有的推荐系统做出的预测往往是很差的。如何处理偏激的用户，是推荐系统中的一个重要问题。和偏激用户相对应的，是颠覆性的产品。比如一些古怪（特别）的电影会有一些问题，有一些电影观众对它又爱又恨，这种类型的电影是很难去做推荐的，因为用户对它们会有各种反映而且无法预计。</p>
<p><strong>7、<strong>马太效应的影响</strong></strong></p>
<p>在互联网中，物品实在是太多了，而推荐系统只能推荐有限的物品。被推荐系统所推荐的物品将会越来越热门，这就导致了大量很好的物品可能会被推荐系统所淹没。解决这个问题的主要方法是增加推荐系统的多样性，比如一个推荐系统发现一个用户非常喜欢吃德芙巧克力，那么他给这个用户推荐10个产品，不需要都是德芙巧克力，也可以推荐别的一些巧克力，或者一些和巧克力相似的甜品。在推荐时，不仅要推荐用户喜欢的东西，而且要通过推荐让用户喜欢一些东西，有的时候，用户自己也不知道他喜欢什么，通过推荐系统，他可能会发现一些新东西他比较喜欢。</p>
<p> 8、<strong>推荐系统的作弊行为</strong></p>
<p>只要涉及到经济利益，就有人作弊。搜索引擎作弊是一个被研究了很久的问题，因为在搜索引擎中，自己的网站排名越高，就能获得越多的经济利益。在推荐系统中也是如此，比如在淘宝中，如果一个卖家的物品经常被推荐，他就可能获得很多经济利益。很多电子商务的推荐系统都遭受到了作弊的干扰，一些人通过一些技术手段，对自己卖的物品给出非常高的评分，这就是一种作弊行为。作弊行为相当于人为的向系统中注入了噪声。目前解决作弊的算法主要是基于信任度和信用的。现在很多电子商务网站都引入了信用系统，比如淘宝等等。如何设计信用系统和推荐系统更好的融合，是一个重要的研究问题。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/problems-of-recommender-systems.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python小程序：每天一个文件夹</title>
		<link>http://www.biaodianfu.com/python-today-dir.html</link>
		<comments>http://www.biaodianfu.com/python-today-dir.html#comments</comments>
		<pubDate>Thu, 22 Dec 2011 10:16:48 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4549</guid>
		<description><![CDATA[这个程序的功能非常的简单，就是每天在系统中新建一个文件夹。文件夹即当前的时间。此代码是在同事那边看到的，为了锻炼下自己薄弱的Python能力，所以花时间重新写了一个。具体代码如下： import time,os basePath = &#039;F:\\work\\&#039; thisYear = str(time.localtime()[0]) thisMonth = str(time.localtime()[1]) thisDay = time.strftime(&#34;%Y-%m-%d&#34;, time.localtime()) yearPath = basePath + thisYear monthPath = basePath  + thisYear + &#039;\\&#039; +thisMonth dayPath = basePath + thisYear + &#039;\\&#039; +thisMonth + &#039;\\&#039; + thisDay if not os.path.exists(yearPath):     os.mkdir(yearPath) if not os.path.exists(monthPath):     os.mkdir(monthPath) if not os.path.exists(dayPath):     [...]]]></description>
			<content:encoded><![CDATA[<p>这个程序的功能非常的简单，就是每天在系统中新建一个文件夹。文件夹即当前的时间。此代码是在同事那边看到的，为了锻炼下自己薄弱的Python能力，所以花时间重新写了一个。具体代码如下：</p>
<pre class="brush: python; gutter: true">import time,os
 basePath = &#039;F:\\work\\&#039;
 thisYear = str(time.localtime()[0])
 thisMonth = str(time.localtime()[1])
 thisDay = time.strftime(&quot;%Y-%m-%d&quot;, time.localtime())
 yearPath = basePath + thisYear
 monthPath = basePath  + thisYear + &#039;\\&#039; +thisMonth
 dayPath = basePath + thisYear + &#039;\\&#039; +thisMonth + &#039;\\&#039; + thisDay
 if not os.path.exists(yearPath):
     os.mkdir(yearPath)
 if not os.path.exists(monthPath):
     os.mkdir(monthPath)
 if not os.path.exists(dayPath):
     os.mkdir(dayPath)
 os.popen(&quot;explorer.exe&quot; + &quot; &quot; + dayPath)
 os.popen(&quot;exit&quot;)</pre>
<p>刚开始写的时候我使用的os.system()来调用windows程序，但发现每次执行是都会弹出一个python窗口，很是麻烦。问了下高人，说解决方案是把.py文件后缀改为.pyw后缀即可。但是试了下还是不行。在高人的指导下，才得知原来值需要将os.system()修改为os.popen()即可。</p>
<p>.py和.pyw有什么不同？</p>
<p>严格来说，它们之间的不同就只有一个：视窗运行它们的时候调用不同的执行档案。视窗用python.exe 运行.py ，用pythonw.exe 运行.pyw 。这纯粹是因为安装视窗版Python 时，扩展名.py 自动被登记为用python.exe 运行的文件，而.pyw 则被登记为用pythonw.exe 运行。.py 和.pyw 之间的“其它差别”全都是python.exe 和pythonw.exe 之间的差别。</p>
<p>跟 python.exe 比较起来，pythonw.exe 有以下的不同：</p>
<ol>
<li>执行时不会弹出控制台窗口（也叫 DOS 窗口）</li>
<li>所有向原有的 stdout 和 stderr 的输出都无效</li>
<li>所有从原有的 stdin 的读取都只会得到 EOF</li>
</ol>
<p>.pyw 格式是被设计来运行开发完成的纯图形界面程序的。纯图形界面程序的用户不需要看到控制台窗口。开发纯图形界面程序的时候，你可以暂时把.pyw 改成 .py ，以便运行时能调出控制台窗口，看到所有错误信息。</p>
<p>os.system()和os.popen()有什么不同？</p>
<ol>
<li>os.system(command)  在一个子shell中运行command命令，并返回command命令执行完毕后的退出状态。这实际上是使用C标准库函数system()实现的。这个函数在执行command命令时需要重新打开一个终端，并且无法保存command命令的执行结果。</li>
<li>os.popen(command,mode)  打开一个与command进程之间的管道。这个函数的返回值是一个文件对象，可以读或者写(由mode决定，mode默认是&#8217;r')。如果mode为&#8217;r'，可以使用此函数的返回值调用read()来获取command命令的执行结果。</li>
</ol>
<p>&nbsp;</p>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/install-scrapy-on-windows.html' rel='bookmark' title='Scrapy在Windows上的安装笔记'>Scrapy在Windows上的安装笔记</a></li>
<li><a href='http://www.biaodianfu.com/learn-python-the-hard-way-study-notes.html' rel='bookmark' title='《Learn Python The Hard Way》学习笔记'>《Learn Python The Hard Way》学习笔记</a></li>
<li><a href='http://www.biaodianfu.com/web-log-format.html' rel='bookmark' title='WEB日志格式及分析工具'>WEB日志格式及分析工具</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/python-today-dir.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>【教程】使用PHP开发自己的MVC框架</title>
		<link>http://www.biaodianfu.com/write-your-own-php-mvc-framework.html</link>
		<comments>http://www.biaodianfu.com/write-your-own-php-mvc-framework.html#comments</comments>
		<pubDate>Sun, 11 Dec 2011 08:27:31 +0000</pubDate>
		<dc:creator>标点符</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[程序设计]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.biaodianfu.com/?p=4452</guid>
		<description><![CDATA[一、什么是MVC MVC模式（Model-View-Controller）是软件工程中的一种软件架构模式，把软件系统分为三个基本部分：模型（Model）、视图（View）和控制器（Controller）。 MVC模式的目的是实现一种动态的程序设计，使后续对程序的修改和扩展简化，并且使程序某一部分的重复利用成为可能。除此之外，此模式通过对复杂度的简化，使程序结构更加直观。软件系统通过对自身基本部份分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组： （控制器Controller）- 负责转发请求，对请求进行处理。 （视图View） &#8211; 界面设计人员进行图形界面设计。 （模型Model） &#8211; 程序员编写程序应有的功能（实现算法等等）、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。 模型（Model） “数据模型”（Model）用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力，例如对数据库的访问。“模型”不依赖“视图”和“控制器”，也就是说，模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制，那些用于监视此模型的视图必须事先在此模型上注册，从而，视图可以了解在数据模型上发生的改变。 视图（View） 视图层能够实现数据有目的的显示（理论上，这不是必需的）。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能，视图需要访问它监视的数据模型（Model），因此应该事先在被它监视的数据那里注册。 控制器（Controller） 控制器起到不同层面间的组织作用，用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。 二、为什么要自己开发MVC框架 网络上有大量优秀的MVC框架可供使用，本教程并不是为了开发一个全面的、终极的MVC框架解决方案，而是将它看作是一个很好的从内部学习PHP的机会，在此过程中，你将学习面向对象编程和设计模式，并学习到开放中的一些注意事项。 更重要的是，你可以完全控制你的框架，并将你的想法融入到你开发的框架中。虽然不一定是做好的，但是你可以按照你的方式去开发功能和模块。 三、开始开发自己的MVC框架 在开始开发前，让我们先来把项目建立好，假设我们建立的项目为todo，那么接下来的第一步就是把目录结构先设置好。 虽然在这个教程中不会使用到上面的所有的目录，但是为了以后程序的可拓展性，在一开始就把程序目录设置好使非常必要的。下面就具体说说每个目录的作用： application – 存放程序代码 config – 存放程序配置或数据库配置 db – 用来存放数据库备份内容 library – 存放框架代码 public – 存放静态文件 scripts – 存放命令行工具 tmp – 存放临时数据 在目录设置好以后，我们接下来就要来顶一下一些代码的规范： MySQL的表名需小写并采用复数形式，如items,cars 模块名（Models）需首字母大写，并采用单数模式，如Item,Car 控制器（Controllers）需首字母大写，采用复数形式并在名称中添加“Controller”，如ItemsController, CarsController 视图（Views）采用复数形式，并在后面添加行为作为文件，如：items/view.php, cars/buy.php 上述的一些规则是为了能在程序钟更好的进行互相的调用。接下来就开始真正的编码了。 第一步将所有的的请求都重定向到public目录下，解决方案是在todo文件下添加一个.htaccesss文件，文件内容为： &#60;IfModule mod_rewrite.c&#62; [...]]]></description>
			<content:encoded><![CDATA[<p><strong>一、什么是MVC</strong></p>
<p><strong>MVC</strong><strong>模式</strong>（Model-View-Controller）是软件工程中的一种软件架构模式，把软件系统分为三个基本部分：模型（Model）、视图（View）和控制器（Controller）。</p>
<p><strong>MVC</strong><strong>模式</strong>的目的是实现一种动态的程序设计，使后续对程序的修改和扩展简化，并且使程序某一部分的重复利用成为可能。除此之外，此模式通过对复杂度的简化，使程序结构更加直观。软件系统通过对自身基本部份分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组：</p>
<ul>
<li>（控制器Controller）- 负责转发请求，对请求进行处理。</li>
<li>（视图View） &#8211; 界面设计人员进行图形界面设计。</li>
<li>（模型Model） &#8211; 程序员编写程序应有的功能（实现算法等等）、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。</li>
</ul>
<p><img class="alignnone size-full wp-image-4453" title="mvc" src="http://www.biaodianfu.com/wp-content/uploads/2011/11/mvc.png" alt="" width="321" height="151" /><br />
<strong>模型（Model）</strong> “数据模型”（Model）用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力，例如对数据库的访问。“模型”不依赖“视图”和“控制器”，也就是说，模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制，那些用于监视此模型的视图必须事先在此模型上注册，从而，视图可以了解在数据模型上发生的改变。</p>
<p><strong>视图（View）</strong> 视图层能够实现数据有目的的显示（理论上，这不是必需的）。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能，视图需要访问它监视的数据模型（Model），因此应该事先在被它监视的数据那里注册。</p>
<p><strong>控制器（Controller）</strong> 控制器起到不同层面间的组织作用，用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。</p>
<p><strong>二、为什么要自己开发MVC框架</strong></p>
<p>网络上有大量优秀的MVC框架可供使用，本教程并不是为了开发一个全面的、终极的MVC框架解决方案，而是将它看作是一个很好的从内部学习PHP的机会，在此过程中，你将学习面向对象编程和设计模式，并学习到开放中的一些注意事项。</p>
<p>更重要的是，你可以完全控制你的框架，并将你的想法融入到你开发的框架中。虽然不一定是做好的，但是你可以按照你的方式去开发功能和模块。</p>
<p><strong>三、开始开发自己的MVC框架</strong></p>
<p>在开始开发前，让我们先来把项目建立好，假设我们建立的项目为todo，那么接下来的第一步就是把目录结构先设置好。</p>
<p><img class="alignnone size-full wp-image-4533" title="todo" src="http://www.biaodianfu.com/wp-content/uploads/2011/12/todo.png" alt="" width="217" height="264" /></p>
<p>虽然在这个教程中不会使用到上面的所有的目录，但是为了以后程序的可拓展性，在一开始就把程序目录设置好使非常必要的。下面就具体说说每个目录的作用：</p>
<ul>
<li>application – 存放程序代码</li>
<li>config – 存放程序配置或数据库配置</li>
<li>db – 用来存放数据库备份内容</li>
<li>library – 存放框架代码</li>
<li>public – 存放静态文件</li>
<li>scripts – 存放命令行工具</li>
<li>tmp – 存放临时数据</li>
</ul>
<p>在目录设置好以后，我们接下来就要来顶一下一些代码的规范：</p>
<ol>
<li>MySQL的表名需小写并采用复数形式，如items,cars</li>
<li>模块名（Models）需首字母大写，并采用单数模式，如Item,Car</li>
<li>控制器（Controllers）需首字母大写，采用复数形式并在名称中添加“Controller”，如ItemsController, CarsController</li>
<li>视图（Views）采用复数形式，并在后面添加行为作为文件，如：items/view.php, cars/buy.php</li>
</ol>
<p>上述的一些规则是为了能在程序钟更好的进行互相的调用。接下来就开始真正的编码了。</p>
<p>第一步将所有的的请求都重定向到public目录下，解决方案是在todo文件下添加一个.htaccesss文件，文件内容为：</p>
<pre>&lt;IfModule mod_rewrite.c&gt;
RewriteEngine on
RewriteRule    ^$    public/    [L]
RewriteRule    (.*) public/$1    [L]
&lt;/IfModule&gt;</pre>
<p>在我们把所有的请求都重定向到public目录下以后，我们就需要将所有的数据请求都再重定向到public下的index.php文件，于是就需要在public文件夹下也新建一个.htaccess文件，文件内容为：</p>
<pre>&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
#如果文件存在就直接访问目录不进行RewriteRule
RewriteCond %{REQUEST_FILENAME} !-f
#如果目录存在就直接访问目录不进行RewriteRule
RewriteCond %{REQUEST_FILENAME} !-d
#将所有其他URL重写到 index.php/URL
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
&lt;/IfModule&gt;</pre>
<p>这么做的主要原因有：</p>
<ol>
<li>可以使程序有一个单一的入口，将所有除静态程序以外的程序都重定向到index.php上；</li>
<li>可以用来生成利于SEO的URL，想要更好的配置URL，后期可能会需要URL路由，这里先不做介绍了。</li>
</ol>
<p>做完上面的操作，就应该知道我们需要做什么了，没错！在public目录下添加index.php文件，文件内容为：</p>
<pre class="brush: php; gutter: true">&lt;?php
define('DS',DIRECTORY_SEPARATOR);
define('ROOT',dirname(dirname(__FILE__)));
$url = $_GET['url'];
require_once(ROOT.DS.'library'.DS.'bootstrap.php');</pre>
<p>注意上面的PHP代码中，并没有添加PHP结束符号”?&gt;”，这么做的主要原因是：对于只包含PHP代码的文件，结束标志(“?&gt;”)最好不存在，PHP自身并不需要结束符号，不添加结束符号可以很大程度上防止末尾被添加额外的注入内容，让程序更加安全。</p>
<p>在index.php中，我们对library文件夹下的bootstrap.php发起了请求，那么bootstrap.php这个启动文件中到底会包含哪些内容呢？</p>
<pre class="brush: php; gutter: true">&lt;?php
require_once(ROOT.DS.'config'.DS .'config.php');
require_once(ROOT.DS.'library'.DS .'shared.php');</pre>
<p>以上文件都可以直接在index.php文件中引用，我们这么做的原因是为了在后期管理和拓展中更加的方便，所以把需要在一开始的时候就加载运行的程序统一放到一个单独的文件中引用。</p>
<p>先来看看config文件下的config .php文件，该文件的主要作用是设置一些程序的配置项及数据库连接等，主要内容为：</p>
<pre class="brush: php; gutter: true">&lt;?php
 # 设置是否为开发状态
 define('DEVELOPMENT_ENVIRONMENT',true);
 # 设置数据库连接所需数据
 define('DB_HOST','localhost');
 define('DB_NAME','todo');
 define('DB_USER','root');
 define('DB_PASSWORD','root');</pre>
<p>应该说config.php涉及到的内容并不多，不过是一些基础数据的一些设置，再来看看library下的共用文件shared.php应该怎么写。</p>
<pre class="brush: php; gutter: true">&lt;?php
/* 检查是否为开发环境并设置是否记录错误日志 */
function setReporting(){
    if (DEVELOPMENT_ENVIRONMENT == true) {
        error_reporting(E_ALL);
        ini_set('display_errors','On');
    } else {
        error_reporting(E_ALL);
        ini_set('display_errors','Off');
        ini_set('log_errors','On');
        ini_set('error_log',ROOT.DS. 'tmp' .DS. 'logs' .DS. 'error.log');
    }
}

/* 检测敏感字符转义（Magic Quotes）并移除他们 */
function stripSlashDeep($value){
    $value = is_array($value) ? array_map('stripSlashDeep',$value) : stripslashes($value);
    return $value;
}
function removeMagicQuotes(){
    if (get_magic_quotes_gpc()) {
        $_GET = stripSlashDeep($_GET);
        $_POST = stripSlashDeep($_POST);
        $_COOKIE = stripSlashDeep($_COOKIE);
    }
}

/* 检测全局变量设置（register globals）并移除他们 */
function unregisterGlobals(){
    if (ini_get('register_globals')) {
        $array = array('_SESSION','_POST','_GET','_COOKIE','_REQUEST','_SERVER','_ENV','_FILES');
        foreach ($array as $value) {
            foreach ($GLOBALS[$value] as $key =&gt; $var) {
                if ($var === $GLOBALS[$key]) {
                    unset($GLOBALS[$key]);
                }
            }
        }
    }
}

/* 主请求方法，主要目的拆分URL请求 */
function callHook() {
    global $url;
    $urlArray = array();
    $urlArray = explode("/",$url);
    $controller = $urlArray[0];
    array_shift($urlArray);
    $action = $urlArray[0];
    array_shift($urlArray);
    $queryString = $urlArray;
    $controllerName = $controller;
    $controller = ucwords($controller);
    $model = rtrim($controller, 's');
    $controller .= 'Controller';
    $dispatch = new $controller($model,$controllerName,$action);
    if ((int)method_exists($controller, $action)) {
        call_user_func_array(array($dispatch,$action),$queryString);
    } else {
        /* 生成错误代码 */
    }
}

/* 自动加载控制器和模型 */
function __autoload($className) {
    if (file_exists(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php')) {
        require_once(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php');
    } else if (file_exists(ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php')) {
        require_once(ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php');
    } else if (file_exists(ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php')) {
        require_once(ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php');
    } else {
           /* 生成错误代码 */
    }
}

setReporting();
removeMagicQuotes();
unregisterGlobals();
callHook();</pre>
<p>接下来的操作就是在library中建立程序所需要的基类，包括控制器、模型和视图的基类。</p>
<p>新建控制器基类为controller.class.php，控制器的主要功能就是总调度，具体具体内容如下：</p>
<pre class="brush: php; gutter: true">&lt;?php
 class Controller {
 protected $_model;
 protected $_controller;
 protected $_action;
 protected $_template;
function __construct($model, $controller,$action) {
 $this-&gt;_controller = $controller;
 $this-&gt;_action = $action;
 $this-&gt;_model = $model;
$this-&gt;$model =&amp; new $model;
 $this-&gt;_template =&amp; new Template($controller,$action);
 }
function set($name,$value) {
 $this-&gt;_template-&gt;set($name,$value);
 }
function __destruct() {
 $this-&gt;_template-&gt;render();
 }
 }</pre>
<p>新建控制器基类为model.class.php，考虑到模型需要对数据库进行处理，所以可以新建一个数据库基类sqlquery.class.php，模型去继承sqlquery.class.php。</p>
<p>新建sqlquery.class.php，代码如下：</p>
<pre class="brush: php; gutter: true">&lt;?php
 class SQLQuery {
 protected $_dbHandle;
 protected $_result;
/** 连接数据库 **/
 function connect($address, $account, $pwd, $name) {
 $this-&gt;_dbHandle = @mysql_connect($address, $account, $pwd);
 if ($this-&gt;_dbHandle != 0) {
 if (mysql_select_db($name, $this-&gt;_dbHandle)) {
 return 1;
 }
 else {
 return 0;
 }
 }
 else {
 return 0;
 }
 }
/** 中断数据库连接 **/
 function disconnect() {
 if (@mysql_close($this-&gt;_dbHandle) != 0) {
 return 1;
 }  else {
 return 0;
 }
 }
/** 查询所有数据表内容 **/
 function selectAll() {
 $query = 'select * from `'.$this-&gt;_table.'`';
 return $this-&gt;query($query);
 }
/** 查询数据表指定列内容 **/
 function select($id) {
 $query = 'select * from `'.$this-&gt;_table.'` where `id` = \''.mysql_real_escape_string($id).'\'';
 return $this-&gt;query($query, 1);
 }
/** 自定义SQL查询语句 **/
 function query($query, $singleResult = 0) {
 $this-&gt;_result = mysql_query($query, $this-&gt;_dbHandle);
 if (preg_match("/select/i",$query)) {
 $result = array();
 $table = array();
 $field = array();
 $tempResults = array();
 $numOfFields = mysql_num_fields($this-&gt;_result);
 for ($i = 0; $i &lt; $numOfFields; ++$i) {
 array_push($table,mysql_field_table($this-&gt;_result, $i));
 array_push($field,mysql_field_name($this-&gt;_result, $i));
 }
 while ($row = mysql_fetch_row($this-&gt;_result)) {
 for ($i = 0;$i &lt; $numOfFields; ++$i) {
 $table[$i] = trim(ucfirst($table[$i]),"s");
 $tempResults[$table[$i]][$field[$i]] = $row[$i];
 }
 if ($singleResult == 1) {
 mysql_free_result($this-&gt;_result);
 return $tempResults;
 }
 array_push($result,$tempResults);
 }
 mysql_free_result($this-&gt;_result);
 return($result);
 }
 }
/** 返回结果集行数 **/
 function getNumRows() {
 return mysql_num_rows($this-&gt;_result);
 }
/** 释放结果集内存 **/
 function freeResult() {
 mysql_free_result($this-&gt;_result);
 }
/** 返回MySQL操作错误信息 **/
 function getError() {
 return mysql_error($this-&gt;_dbHandle);
 }
 }</pre>
<p>新建model.class.php，代码如下：</p>
<pre class="brush: php; gutter: true">&lt;?php
 class Model extends SQLQuery{
 protected $_model;
function __construct() {
 $this-&gt;connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
 $this-&gt;_model = get_class($this);
 $this-&gt;_table = strtolower($this-&gt;_model)."s";
 }
function __destruct() {
 }
 }</pre>
<p>新建视图基类为template.class.php，具体代码如下：</p>
<pre class="brush: php; gutter: true">&lt;?php
 class Template {
 protected $variables = array();
 protected $_controller;
 protected $_action;
function __construct($controller,$action) {
 $this-&gt;_controller = $controller;
 $this-&gt;_action =$action;
 }
/* 设置变量 */
 function set($name,$value) {
 $this-&gt;variables[$name] = $value;
 }
/* 显示模板 */
 function render() {
 extract($this-&gt;variables);
 if (file_exists(ROOT.DS. 'application' .DS. 'views' .DS. $this-&gt;_controller .DS. 'header.php')) {
 include(ROOT.DS. 'application' .DS. 'views' .DS. $this-&gt;_controller .DS. 'header.php');
 } else {
 include(ROOT.DS. 'application' .DS. 'views' .DS. 'header.php');
 }
 include (ROOT.DS. 'application' .DS. 'views' .DS. $this-&gt;_controller .DS. $this-&gt;_action . '.php');
 if (file_exists(ROOT.DS. 'application' .DS. 'views' .DS. $this-&gt;_controller .DS. 'footer.php')) {
 include (ROOT.DS. 'application' .DS. 'views' .DS. $this-&gt;_controller .DS. 'footer.php');
 } else {
 include (ROOT.DS. 'application' .DS. 'views' .DS. 'footer.php');
 }
 }
 }</pre>
<p>做完了以上这么多操作，基本上整个MVC框架已经出来了，下面就该制作我们的站点了。我们要做的站点其实很简单，一个ToDo程序。</p>
<p>首先是在我们的/application/controller/ 目录下面新建一个站点控制器类为ItemsController，命名为itemscontroller.php，内容为：</p>
<pre class="brush: php; gutter: true">&lt;?php
 class ItemsController extends Controller {
 function view($id = null,$name = null) {
 $this-&gt;set('title',$name.' - My Todo List App');
 $this-&gt;set('todo',$this-&gt;Item-&gt;select($id));
 }
function viewall() {
 $this-&gt;set('title','All Items - My Todo List App');
 $this-&gt;set('todo',$this-&gt;Item-&gt;selectAll());
 }
function add() {
 $todo = $_POST['todo'];
 $this-&gt;set('title','Success - My Todo List App');
 $this-&gt;set('todo',$this-&gt;Item-&gt;query('insert into items (item_name) values (\''.mysql_real_escape_string($todo).'\')'));
 }
function delete($id) {
 $this-&gt;set('title','Success - My Todo List App');
 $this-&gt;set('todo',$this-&gt;Item-&gt;query('delete from items where id = \''.mysql_real_escape_string($id).'\''));
 }
 }</pre>
<p>接下来就是先建站点的模型，在我们的/application/model/ 目录下面先建一个站点模型类为Item，内容直接继承Model，代码如下：</p>
<pre class="brush: php; gutter: true">&lt;?php
 class Item extends Model {
}</pre>
<p>最后一步是设置我们站点的视图部分，我们现在/application/views/目录下新建一个items的文件夹，再在items文件夹下建立与控制器重Action相同的文件，分别为view.php，viewall.php，add.php，delete.php，考虑到这么页面中可能需要共用页首和页尾，所以再新建两个文件，命名为header.php，footer.php，每个文件的代码如下：</p>
<p>view.php文件：查看单条待处理事务</p>
<pre class="brush: php; gutter: true">&lt;h2&gt;&lt;?php echo $todo['Item']['item_name']?&gt;&lt;/h2&gt;
 &lt;a href="../../../items/delete/&lt;?php echo $todo['Item']['id']?&gt;"&gt;
 &lt;span&gt;Delete this item&lt;/span&gt;
 &lt;/a&gt;</pre>
<p>viewall.php文件：查看所有待处理事务</p>
<pre class="brush: php; gutter: true">&lt;form action="../items/add" method="post"&gt;
 &lt;input type="text" value="I have to..." onclick="this.value=''" name="todo"&gt; &lt;input type="submit" value="add"&gt;
 &lt;/form&gt;
 &lt;br/&gt;&lt;br/&gt;
 &lt;?php $number = 0?&gt;
&lt;?php foreach ($todo as $todoitem):?&gt;
 &lt;a href="../items/view/&lt;?php echo $todoitem['Item']['id']?&gt;/&lt;?php echo strtolower(str_replace(" ","-",$todoitem['Item']['item_name']))?&gt;"&gt;
 &lt;span&gt;
 &lt;?php echo ++$number?&gt;
 &lt;?php echo $todoitem['Item']['item_name']?&gt;
 &lt;/span&gt;
 &lt;/a&gt;&lt;br/&gt;
 &lt;?php endforeach?&gt;</pre>
<p>add.php文件：添加待处理事务</p>
<pre class="brush: php; gutter: true">&lt;a href="../items/viewall"&gt;Todo successfully added. Click here to go back.&lt;/a&gt;&lt;br/&gt;</pre>
<p>delete.php文件：删除事务</p>
<pre class="brush: php; gutter: true">&lt;a href="../../items/viewall"&gt;Todo successfully deleted. Click here to go back.&lt;/a&gt;&lt;br/&gt;</pre>
<p>header.php：页首文件</p>
<pre class="brush: php; gutter: true">&lt;html&gt;
 &lt;head&gt;
 &lt;title&gt;&lt;?php echo $title?&gt;&lt;/title&gt;
 &lt;style&gt;
 .item {width:400px;}
 input {color:#222222;font-family:georgia,times;font-size:24px;font-weight:normal;line-height:1.2em;color:black;}
 a {color:#222222;font-family:georgia,times;font-size:24px;font-weight:normal;line-height:1.2em;color:black;text-decoration:none;}
 a:hover {background-color:#BCFC3D;}
 h1 {color:#000000;font-size:41px;letter-spacing:-2px;line-height:1em;font-family:helvetica,arial,sans-serif;border-bottom:1px dotted #cccccc;}
 h2 {color:#000000;font-size:34px;letter-spacing:-2px;line-height:1em;font-family:helvetica,arial,sans-serif;}
 &lt;/style&gt;
 &lt;/head&gt;
 &lt;body&gt;
 &lt;h1&gt;My Todo-List App&lt;/h1&gt;</pre>
<p>footer.php：页尾文件</p>
<pre class="brush: php; gutter: true">&lt;/body&gt;
 &lt;/html&gt;</pre>
<p>当然还有一个必不可少的操作就是在数据中中建立一张表，具体代码如下：</p>
<pre class="brush: sql; gutter: true">CREATE TABLE IF NOT EXISTS `items` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `item_name` varchar(255) NOT NULL,
 PRIMARY KEY (`id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=17 ;</pre>
<p>至此一个使用MVC开发的网站就开发完成了，你现在可以通过访问http://localhost/todo/items/viewall 查看新建的站点。</p>
<p>原文链接：<a href="http://anantgarg.com/2009/03/13/write-your-own-php-mvc-framework-part-1/">http://anantgarg.com/2009/03/13/write-your-own-php-mvc-framework-part-1/</a></p>
<p>Related posts:<ol>
<li><a href='http://www.biaodianfu.com/create-an-object-oriented-blog-using-php.html' rel='bookmark' title='使用PHP创建一个面向对象的博客'>使用PHP创建一个面向对象的博客</a></li>
<li><a href='http://www.biaodianfu.com/how-to-make-heatmap.html' rel='bookmark' title='网站点击热力图的技术实现'>网站点击热力图的技术实现</a></li>
<li><a href='http://www.biaodianfu.com/php-get-remote-pic.html' rel='bookmark' title='PHP自动保存文章中的外部图片'>PHP自动保存文章中的外部图片</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.biaodianfu.com/write-your-own-php-mvc-framework.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

