X-Intend[超级打算]
每个人都有自己的想法,哪怕仅仅一瞬间~!

AJBrige

2009年11月06日 作者: KingFo 开发者

My  Frist  Open  Source Project

 

Global:

 "AS do AS things (code), JS do JS things (code), only communicate with me (bridge)"

(AS and JS are doing their own things, only use bridge in communication.)

目标:
   “AS做AS的事(code),JS做JS的事(code),仅在沟通时用我(bridge)!"

project home :  http://code.google.com/p/ajbridge/

svn:  http://ajbridge.googlecode.com/svn/trunk/

 

被阅 233 次, 0 票  发表评论

HTML5处理音频说明

2010年03月10日 作者: KingFo 开发者

 

https://wiki.mozilla.org/Audio_Data_API

被阅 15 次, 0 票  发表评论

[转]Custom events in JavaScript

2010年03月10日 作者: KingFo 开发者

 

Custom events in JavaScript

Tags: , , ,

 

Without a doubt, the most often-used paradigm in JavaScript is events. Events are a manifestation of the observer pattern, a well-defined computer science design pattern for loose coupling. Loose coupling is incredibly important for creating maintainable, stable codebases. I talk a lot about loose coupling and its importance in my talk, Scalable JavaScript Application Architecture (video), so I won’t talk too much about it here. However, the concept is very important to grasp if you wish to progress as a software engineer.

Events

Unless you’ve never written any JavaScript before, you’ve used events at some point in time (admittedly, if you’ve never written JavaScript before, the chances of your reading my blog are probably pretty slim). Put quite simply: the way that you tie behavior to web pages is through events. Events are a way of letting interested parties know that an important moment has occurred in the lifecycle of the application. For instance:

  1. window.onload = function(){ 
  2.     Application.init(); 
  3. }; 

In this example, the load event is the interesting moment. I want to know when the window is fully loaded so that I can initialized the JavaScript application. The onload event handler is the location to where an event handler is assigned. The brilliant part is that window doesn’t care what web page is loaded or who is writing the code; it just knows that there’s a function to call when load occurs. This is the essence of loose coupling: when parts of an application have very limited knowledge of one another.

The Browser Object Model (BOM) and Document Object Model (DOM) publish events to allow developers access to the interesting moments of the browser and web page, respectively.

Custom events

It’s no surprise that most JavaScript libraries rely heavily on custom events since this is a pattern that web developers are familiar with. Every major JavaScript library provides its own events, components to enable easy custom event definition, or both. This makes sense, of course, since libraries want to be loosely-coupled to the execution environment, and therefore, to your code.

There’s nothing magic about custom events, though, and there’s no need to load an entire library if you’d like to experiment with custom events. An object that supports custom events needs to be able to do a small set of things:

  1. Assign an event handler for a particular event.
  2. Remove an event handler for a particular event.
  3. Fire an event and call all assigned event handlers.

The following implements all of this basic functionality:

  1. //Copyright (c) 2010 Nicholas C. Zakas. All rights reserved. 
  2. //MIT License 
  3.  
  4. function EventTarget(){ 
  5.     this._listeners = {}; 
  6.  
  7. EventTarget.prototype = { 
  8.  
  9.     constructor: EventTarget, 
  10.  
  11.     addListener: function(type, listener){ 
  12.         if (typeof this._listeners[type] == "undefined"){ 
  13.             this._listeners[type] = []; 
  14.         } 
  15.  
  16.         this._listeners[type].push(listener); 
  17.     }, 
  18.  
  19.     fire: function(event){ 
  20.         if (typeof event == "string"){ 
  21.             event = { type: event }; 
  22.         } 
  23.         if (!event.target){ 
  24.             event.target = this
  25.         } 
  26.  
  27.         if (!event.type){  //falsy 
  28.             throw new Error("Event object missing 'type' property."); 
  29.         } 
  30.  
  31.         if (this._listeners[event.type] instanceof Array){ 
  32.             var listeners = this._listeners[event.type]; 
  33.             for (var i=0, len=listeners.length; i < len; i++){ 
  34.                 listeners[i].call(this, event); 
  35.             } 
  36.         } 
  37.     }, 
  38.  
  39.     removeListener: function(type, listener){ 
  40.         if (this._listeners[type] instanceof Array){ 
  41.             var listeners = this._listeners[type]; 
  42.             for (var i=0, len=listeners.length; i < len; i++){ 
  43.                 if (listeners[i] === listener){ 
  44.                     listeners.splice(i, 1); 
  45.                     break
  46.                 } 
  47.             } 
  48.         } 
  49.     } 
  50. }; 

The EventTarget type has three methods: addListener(), fire(), and removeListener.

The addListener() uses the private _listeners object to store event handlers for various events. When an event handler is added, the method first checks to see if there’s a named property for that event type on the _listeners object, and if not, creates one containing an array. The event handler function is then saved to the array for later.

The fire() method fires an event with a given name. In effect, this method’s only job is to execute each event handler for the given event type. The method accepts either an object, in which case it’s expected to have a type property, or a string, in which case a new object is created and the string is assigned as the value of type. Next, if the event object doesn’t have a target property assigned, it is set to the current instance. This effectively creates an event object similar to the one most are familiar with via the BOM and DOM. Once the event object is created, the _listeners object is checked for event handlers, and if found, they are executed. Note that in order to mimic the BOM/DOM approach, event handlers are executed in the scope of this via the call() method.

The last method, removeListener(), simply reverses the process of addListener(). It searches through the _listeners property for the given event type to locate the specified event handler. If found, the event handler is removed by using the array’s splice() method, and otherwise it exits without doing anything.

Basic usage:

  1. var target = new EventTarget(); 
  2. function handleEvent(event){ 
  3.     alert(event.type); 
  4. }; 
  5.  
  6. target.addListener("foo", handleEvent); 
  7. target.fire({ type: "foo" });    //can also do target.fire("foo") 
  8. target.removeListener("foo", handleEvent); 

Practically speaking, you’ll likely not want to use an instance of EventTarget directly, but rather inherit from it:

  1. function MyObject(){ 
  2.     EventTarget.call(this); 
  3.  
  4. MyObject.prototype = new EventTarget(); 
  5. MyObject.prototype.constructor = MyObject; 
  6. MyObject.prototype.foo = function(){ 
  7.     this.fire("foo"); 
  8. }; 
  9.  
  10. var o = new MyObject(); 
  11.  
  12. o.addListener("foo"function(){ 
  13.     alert("Foo just happened."); 
  14. }); 
  15.  
  16. o.foo(); 

Typically, events are fired in reaction to some other method call, as in this example (events are usually not fired external to the object that is publishing the events).

What about…?

This is a pretty barebones implementation of a custom event providing object, so inevitably someone will come along and ask why I didn’t include one feature or another. There are, of course, a lot of enhancements you can make to custom events if you so desire. Some enhancements others have implemented:

  • Bubbling of events
  • Continue to execute event handlers even if one throws an error
  • Allow event handlers to cancel further processing or default actions

Each of these can be built pretty easily on top of the base presented in this post.

Conclusion

Custom events are a very powerful and useful pattern in JavaScript programming, and your usage of them doesn’t have to rely on a large JavaScript library. Implementing your own custom events is easy. The implementation presented in this post is a minimum feature set that typically fulfills most requirements, but you can consider it as a starting point for more advanced functionality if your requirements are more complex.

 

被阅 16 次, 0 票  发表评论

阅读摘要:推荐算法介绍(隐性打分)

2010年03月01日 作者: KingFo 开发者

 来源:http://blog.csdn.net/liuzhenwen/archive/2009/04/22/4101003.aspx

推荐系统最早在亚马逊的网站上应用,根据以往用户的购买行为,推荐出购买某种产品同时可能购买的其他产品。

直接打分需要用户的参与程度比较高,很多网站都在内容页中留一个打分的按钮,从1~5选一 个,我可能喜欢这篇文章,可我哪里知道我喜欢的程度是几分啊,还要我去思考,而网站设计中一条很重要的原则是:Do not let me think!,于是我就胡打一个分数或者不打,而隐性的打分则不同,只有你喜欢的图书你才会购买,只有你喜欢的歌曲才会听多次。

最近邻搜索算法一般是皮尔森相关系数(Person Correlation Coefficient)、余弦相似性(Cosine-based Similarity)以及调整余弦相似性(Adjusted Cosine Similarity)。关于余弦定理在数据挖掘中的应用,google黑白报有过介绍,可以参考数学之美 系列 12 - 余弦定理和新闻的分类

 

基本原理

用户          对事物A打分 对事物B打分
X 3 4
Y 2 4
Z 4 ?

用户Z对事物B的打分可能是多少呢?股票上有个说法是平均值可以掩盖一切异常波动,所以股票上的各个技术指标收拾不同时间段的平均值的曲线图或者柱 状图等。同样的,Slope one算法也认为:平均值也可以代替某两个未知个体之间的打分差异,事物A对事物B的平均很差是:((3 - 4) + (2 - 4)) / 2 = -1.5,也就是说人们对事物B的打分一般比事物A的打分要高1.5,于是Slope one算法就猜测Z对事物B的打分是4 + 1.5 = 5.5

 

 

加权算法

有n个人对事物A和事物B打分了,R(A->B)表示这n个人对A和对B打分的平均差(A-B),有m个人对事物B和事物C打分 了,R(C->B)表示这m个人对C和对B打分的平均差(C-B),注意都是平均差而不是平方差,现在某个用户对A的打分是ra,对C的打分是 rc,那么A对B的打分可能是:

rb = (n * (ra - R(A->B)) + m * (rc - R(C->B)))/(m+n)

 

 

 

 

  1.  
  2. # This is the code in plain text out of the technical report. 
  3. # Daniel Lemire, Sean McGrath, Implementing a Rating-Based Item-to-Item 
  4. # Recommender System in PHP/SQL, Technical Report D-01, January 2005. 
  5. # http://www.ondelette.com/lemire/abstracts/TRD01.html 
  6. # This code is in the public domain, use at your own risks. 
  7. # It is assumed that you looked at the report and know some SQL and PHP. 
  8. # Daniel Lemire, February 3rd 2005 
  9. # First part is sample SQL code. 
  10. #########CUT HERE#################### 
  11.  
  12. CREATE TABLE rating ( 
  13.     userID INT PRIMARY KEY, 
  14.     itemID INT NOT NULL, 
  15.     ratingValue INT NOT NULL, 
  16.     datetimestamp TIMESTAMP NOT NULL 
  17. ); 
  18.  
  19.  
  20. CREATE TABLE dev ( 
  21.   itemID1 int(11) NOT NULL default '0'
  22.   itemID2 int(11) NOT NULL default '0'
  23.   count int(11) NOT NULL default '0'
  24.   sum int(11) NOT NULL default '0'
  25.   PRIMARY KEY  (itemID1,itemID2) 
  26. ); 
  27.  
  28.  
  29. # simple query to output 10 most liked items 
  30. # by people who rated item 1 
  31. SELECT itemID2, ( sum / count ) AS average 
  32. FROM dev 
  33. WHERE count > 2 AND itemID1 = 1 
  34. ORDER  BY ( sum / count ) DESC 
  35. LIMIT 10; 
  36.  
  37. # Next part is sample PHP code. 
  38. #########CUT HERE#################### 
  39.  
  40. // This code assumes $itemID is set to that of  
  41. // the item that was just rated.  
  42. // Get all of the user's rating pairs 
  43. $sql = "SELECT DISTINCT r.itemID, r2.ratingValue - r.ratingValue  
  44.             as rating_difference 
  45.             FROM rating r, rating r2 
  46.             WHERE r.userID=$userID AND  
  47.                     r2.itemID=$itemID AND  
  48.                     r2.userID=$userID;"; 
  49. $db_result = mysql_query($sql$connection); 
  50. $num_rows = mysql_num_rows($db_result); 
  51. //For every one of the user's rating pairs,  
  52. //update the dev table 
  53. while ($row = mysql_fetch_assoc($db_result)) { 
  54.     $other_itemID = $row["itemID"]; 
  55.     $rating_difference = $row["rating_difference"]; 
  56.     //if the pair ($itemID, $other_itemID) is already in the dev table 
  57.     //then we want to update 2 rows. 
  58.     if (mysql_num_rows(mysql_query("SELECT itemID1  
  59.     FROM dev WHERE itemID1=$itemID AND itemID2=$other_itemID", 
  60.     $connection)) > 0)  { 
  61.         $sql = "UPDATE dev SET count=count+1,  
  62.     sum=sum+$rating_difference WHERE itemID1=$itemID  
  63.     AND itemID2=$other_itemID"; 
  64.         mysql_query($sql$connection); 
  65.     //We only want to update if the items are different                 
  66.         if ($itemID != $other_itemID) { 
  67.             $sql = "UPDATE dev SET count=count+1,  
  68.         sum=sum-$rating_difference  
  69.         WHERE (itemID1=$other_itemID AND itemID2=$itemID)"; 
  70.             mysql_query($sql$connection); 
  71.         } 
  72.     } 
  73.     else { //we want to insert 2 rows into the dev table 
  74.         $sql = "INSERT INTO dev VALUES ($itemID$other_itemID
  75.         1, $rating_difference)"; 
  76.         mysql_query($sql$connection);  
  77.     //We only want to insert if the items are different        
  78.         if ($itemID != $other_itemID) {          
  79.             $sql = "INSERT INTO dev VALUES ($other_itemID,  
  80.         $itemID, 1, -$rating_difference)"; 
  81.             mysql_query($sql$connection); 
  82.         } 
  83.     }     
  84.  
  85.  
  86. function predict($userID$itemID) { 
  87.     global $connection;     
  88.     $denom = 0.0; //denominator 
  89.     $numer = 0.0; //numerator     
  90.     $k = $itemID;     
  91.     $sql = "SELECT r.itemID, r.ratingValue  
  92.     FROM rating r WHERE r.userID=$userID AND r.itemID <> $itemID"; 
  93.     $db_result = mysql_query($sql$connection);         
  94.     //for all items the user has rated 
  95.     while ($row = mysql_fetch_assoc($db_result))  { 
  96.         $j = $row["itemID"]; 
  97.         $ratingValue = $row["ratingValue"];         
  98.         //get the number of times k and j have both been rated by the same user 
  99.         $sql2 = "SELECT d.count, d.sum FROM dev d WHERE itemID1=$k AND itemID2=$j"
  100.         $count_result = mysql_query($sql2$connection);         
  101.         //skip the calculation if it isn't found 
  102.         if(mysql_num_rows($count_result) > 0)  { 
  103.             $count = mysql_result($count_result, 0, "count"); 
  104.             $sum = mysql_result($count_result, 0, "sum");             
  105.             //calculate the average 
  106.             $average = $sum / $count;             
  107.             //increment denominator by count 
  108.             $denom += $count;             
  109.             //increment the numerator 
  110.             $numer += $count * ($average + $ratingValue); 
  111.         }         
  112.     }     
  113.     if ($denom == 0) 
  114.         return 0; 
  115.     else 
  116.         return ($numer / $denom); 
  117.  
  118.  
  119. function predict_all($userID ) { 
  120.     $sql2 = "SELECT d.itemID1 as 'item', sum(d.countas 'denom',  
  121.     sum(d.sum + d.count*r.ratingValue) as 'numer' FROM item i, rating r, 
  122.     dev d WHERE r.userID=$userID  
  123.     AND d.itemID1<>r.itemID  
  124.     AND d.itemID2=r.itemID GROUP BY d.itemID1"; 
  125.     return mysql_query($sql2$connection); 

 

Java:

  1. import java.util.*; 
  2. /** 
  3. * Daniel Lemire 
  4. * A simple implementation of the weighted slope one 
  5. * algorithm in Java for item-based collaborative  
  6. * filtering.  
  7. * Assumes Java 1.5. 
  8. * 
  9. * See main function for example. 
  10. * 
  11. * June 1st 2006. 
  12. * Revised by Marco Ponzi on March 29th 2007 
  13. */ 
  14.  
  15. public class SlopeOne { 
  16.    
  17.   public static void main(String args[]){ 
  18.     // this is my data base 
  19.     Map<UserId,Map<ItemId,Float>> data = new HashMap<UserId,Map<ItemId,Float>>(); 
  20.     // items 
  21.     ItemId item1 = new ItemId("       candy"); 
  22.     ItemId item2 = new ItemId("         dog"); 
  23.     ItemId item3 = new ItemId("         cat"); 
  24.     ItemId item4 = new ItemId("         war"); 
  25.     ItemId item5 = new ItemId("strange food"); 
  26.      
  27.     mAllItems = new ItemId[]{item1, item2, item3, item4, item5}; 
  28.      
  29.     //I'm going to fill it in 
  30.     HashMap<ItemId,Float> user1 = new HashMap<ItemId,Float>(); 
  31.     HashMap<ItemId,Float> user2 = new HashMap<ItemId,Float>(); 
  32.     HashMap<ItemId,Float> user3 = new HashMap<ItemId,Float>(); 
  33.     HashMap<ItemId,Float> user4 = new HashMap<ItemId,Float>(); 
  34.     user1.put(item1,1.0f); 
  35.     user1.put(item2,0.5f); 
  36.     user1.put(item4,0.1f); 
  37.     data.put(new UserId("Bob"),user1); 
  38.     user2.put(item1,1.0f); 
  39.     user2.put(item3,0.5f); 
  40.     user2.put(item4,0.2f); 
  41.     data.put(new UserId("Jane"),user2); 
  42.     user3.put(item1,0.9f); 
  43.     user3.put(item2,0.4f); 
  44.     user3.put(item3,0.5f); 
  45.     user3.put(item4,0.1f); 
  46.     data.put(new UserId("Jo"),user3);     
  47.     user4.put(item1,0.1f); 
  48.     //user4.put(item2,0.4f); 
  49.     //user4.put(item3,0.5f); 
  50.     user4.put(item4,1.0f); 
  51.     user4.put(item5,0.4f); 
  52.     data.put(new UserId("StrangeJo"),user4);     
  53.     // next, I create my predictor engine 
  54.     SlopeOne so = new SlopeOne(data); 
  55.     System.out.println("Here's the data I have accumulated..."); 
  56.     so.printData(); 
  57.     // then, I'm going to test it out... 
  58.     HashMap<ItemId,Float> user = new HashMap<ItemId,Float>(); 
  59.     System.out.println("Ok, now we predict..."); 
  60.     user.put(item5,0.4f); 
  61.     System.out.println("Inputting..."); 
  62.     SlopeOne.print(user); 
  63.     System.out.println("Getting..."); 
  64.     SlopeOne.print(so.predict(user)); 
  65.     // 
  66.     user.put(item4,0.2f); 
  67.     System.out.println("Inputting..."); 
  68.     SlopeOne.print(user); 
  69.     System.out.println("Getting..."); 
  70.     SlopeOne.print(so.predict(user)); 
  71.   } 
  72.    
  73.   Map<UserId,Map<ItemId,Float>> mData; 
  74.   Map<ItemId,Map<ItemId,Float>> mDiffMatrix; 
  75.   Map<ItemId,Map<ItemId,Integer>> mFreqMatrix; 
  76.    
  77.   static ItemId[] mAllItems; 
  78.    
  79.   public SlopeOne(Map<UserId,Map<ItemId,Float>> data) { 
  80.     mData = data; 
  81.     buildDiffMatrix();     
  82.   } 
  83.    
  84.   /** 
  85.   * Based on existing data, and using weights, 
  86.   * try to predict all missing ratings. 
  87.   * The trick to make this more scalable is to consider 
  88.   * only mDiffMatrix entries having a large  (>1) mFreqMatrix 
  89.   * entry. 
  90.   * 
  91.   * It will output the prediction 0 when no prediction is possible. 
  92.   */ 
  93.   public Map<ItemId,Float> predict(Map<ItemId,Float> user) { 
  94.     HashMap<ItemId,Float> predictions = new HashMap<ItemId,Float>(); 
  95.     HashMap<ItemId,Integer> frequencies = new HashMap<ItemId,Integer>(); 
  96.     for (ItemId j : mDiffMatrix.keySet()) { 
  97.       frequencies.put(j,0); 
  98.       predictions.put(j,0.0f); 
  99.     } 
  100.     for (ItemId j : user.keySet()) { 
  101.       for (ItemId k : mDiffMatrix.keySet()) { 
  102.         try { 
  103.         float newval = ( mDiffMatrix.get(k).get(j).floatValue() + user.get(j).floatValue() ) * mFreqMatrix.get(k).get(j).intValue(); 
  104.         predictions.put(k, predictions.get(k)+newval); 
  105.         frequencies.put(k, frequencies.get(k)+mFreqMatrix.get(k).get(j).intValue()); 
  106.         } catch(NullPointerException e) {} 
  107.       } 
  108.     } 
  109.     HashMap<ItemId,Float> cleanpredictions = new HashMap<ItemId,Float>(); 
  110.     for (ItemId j : predictions.keySet()) { 
  111.         if (frequencies.get(j)>0) { 
  112.           cleanpredictions.put(j, predictions.get(j).floatValue()/frequencies.get(j).intValue()); 
  113.         } 
  114.     } 
  115.     for (ItemId j : user.keySet()) { 
  116.          cleanpredictions.put(j,user.get(j)); 
  117.     } 
  118.     return cleanpredictions; 
  119.   } 
  120.    
  121.   /** 
  122.   * Based on existing data, and not using weights, 
  123.   * try to predict all missing ratings. 
  124.   * The trick to make this more scalable is to consider 
  125.   * only mDiffMatrix entries having a large  (>1) mFreqMatrix 
  126.   * entry. 
  127.   */ 
  128.   public Map<ItemId,Float> weightlesspredict(Map<ItemId,Float> user) { 
  129.     HashMap<ItemId,Float> predictions = new HashMap<ItemId,Float>(); 
  130.     HashMap<ItemId,Integer> frequencies = new HashMap<ItemId,Integer>(); 
  131.     for (ItemId j : mDiffMatrix.keySet()) { 
  132.       predictions.put(j,0.0f); 
  133.       frequencies.put(j,0); 
  134.     } 
  135.     for (ItemId j : user.keySet()) { 
  136.       for (ItemId k : mDiffMatrix.keySet()) { 
  137.         //System.out.println("Average diff between "+j+" and "+ k + " is "+mDiffMatrix.get(k).get(j).floatValue()+" with n = "+mFreqMatrix.get(k).get(j).floatValue()); 
  138.         float newval = ( mDiffMatrix.get(k).get(j).floatValue() + user.get(j).floatValue() ) ; 
  139.         predictions.put(k, predictions.get(k)+newval); 
  140.       } 
  141.     } 
  142.     for (ItemId j : predictions.keySet()) { 
  143.         predictions.put(j, predictions.get(j).floatValue()/user.size()); 
  144.     } 
  145.     for (ItemId j : user.keySet()) { 
  146.       predictions.put(j,user.get(j)); 
  147.     } 
  148.     return predictions; 
  149.   } 
  150.  
  151.  
  152.   public void printData() { 
  153.         for(UserId user : mData.keySet()) { 
  154.           System.out.println(user); 
  155.           print(mData.get(user)); 
  156.         } 
  157.         for (int i=0; i<mAllItems.length; i++) { 
  158.             System.out.print("\n" + mAllItems[i] + ":"); 
  159.             printMatrixes(mDiffMatrix.get(mAllItems[i]), mFreqMatrix.get(mAllItems[i])); 
  160.         } 
  161.       } 
  162.  
  163.     private void printMatrixes(Map<ItemId,Float> ratings, 
  164.                 Map<ItemId,Integer> frequencies) {   
  165.             for (int j=0; j<mAllItems.length; j++) { 
  166.                 System.out.format("%10.3f", ratings.get(mAllItems[j])); 
  167.                 System.out.print(" "); 
  168.                 System.out.format("%10d", frequencies.get(mAllItems[j])); 
  169.             } 
  170.         System.out.println(); 
  171.     } 
  172.    
  173.   public static void print(Map<ItemId,Float> user) { 
  174.     for (ItemId j : user.keySet()) { 
  175.       System.out.println(" "+ j+ " --> "+user.get(j).floatValue()); 
  176.     } 
  177.   } 
  178.    
  179.   public void buildDiffMatrix() { 
  180.     mDiffMatrix = new HashMap<ItemId,Map<ItemId,Float>>(); 
  181.     mFreqMatrix = new HashMap<ItemId,Map<ItemId,Integer>>(); 
  182.     // first iterate through users 
  183.     for(Map<ItemId,Float> user : mData.values()) { 
  184.       // then iterate through user data 
  185.       for(Map.Entry<ItemId,Float> entry: user.entrySet()) { 
  186.         if(!mDiffMatrix.containsKey(entry.getKey())) { 
  187.           mDiffMatrix.put(entry.getKey(), new HashMap<ItemId,Float>()); 
  188.           mFreqMatrix.put(entry.getKey(), new HashMap<ItemId,Integer>()); 
  189.         } 
  190.         for(Map.Entry<ItemId,Float> entry2: user.entrySet()) { 
  191.           int oldcount = 0
  192.           if(mFreqMatrix.get(entry.getKey()).containsKey(entry2.getKey())) 
  193.             oldcount = mFreqMatrix.get(entry.getKey()).get(entry2.getKey()).intValue(); 
  194.           float olddiff = 0.0f; 
  195.           if(mDiffMatrix.get(entry.getKey()).containsKey(entry2.getKey())) 
  196.             olddiff = mDiffMatrix.get(entry.getKey()).get(entry2.getKey()).floatValue(); 
  197.           float observeddiff = entry.getValue() - entry2.getValue(); 
  198.           mFreqMatrix.get(entry.getKey()).put(entry2.getKey(),oldcount + 1); 
  199.           mDiffMatrix.get(entry.getKey()).put(entry2.getKey(),olddiff+observeddiff);           
  200.         } 
  201.       } 
  202.     } 
  203.     for (ItemId j : mDiffMatrix.keySet()) { 
  204.       for (ItemId i : mDiffMatrix.get(j).keySet()) { 
  205.         float oldvalue = mDiffMatrix.get(j).get(i).floatValue(); 
  206.         int count = mFreqMatrix.get(j).get(i).intValue(); 
  207.         mDiffMatrix.get(j).put(i,oldvalue/count); 
  208.       } 
  209.     } 
  210.   } 
  211.  
  212. class UserId  { 
  213.   String content; 
  214.   public UserId(String s) { 
  215.     content = s; 
  216.   } 
  217.    
  218.   public int hashCode() { return content.hashCode();} 
  219.   public String toString() { return content; } 
  220. class ItemId  { 
  221.   String content; 
  222.   public ItemId(String s) { 
  223.     content = s; 
  224.   } 
  225.   public int hashCode() { return content.hashCode();} 
  226.   public String toString() { return content; } 

 

Python:

  1. # Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>. 
  2. # 
  3. # This software may be used and distributed according to the terms 
  4. # of the GNU General Public License, version 2 or later, which is 
  5. # incorporated herein by reference. 
  6.  
  7. class SlopeOne(object): 
  8.     def __init__(self): 
  9.         self.diffs = {} 
  10.         self.freqs = {} 
  11.  
  12.     def predict(self, userprefs): 
  13.         preds, freqs = {}, {} 
  14.         for item, rating in userprefs.iteritems(): 
  15.             for diffitem, diffratings in self.diffs.iteritems(): 
  16.                 try
  17.                     freq = self.freqs[diffitem][item] 
  18.                 except KeyError: 
  19.                     continue 
  20.                 preds.setdefault(diffitem, 0.0
  21.                 freqs.setdefault(diffitem, 0
  22.                 preds[diffitem] += freq * (diffratings[item] + rating) 
  23.                 freqs[diffitem] += freq 
  24.         return dict([(item, value / freqs[item]) 
  25.                      for item, value in preds.iteritems() 
  26.                      if item not in userprefs and freqs[item] > 0]) 
  27.  
  28.     def update(self, userdata): 
  29.         for ratings in userdata.itervalues(): 
  30.             for item1, rating1 in ratings.iteritems(): 
  31.                 self.freqs.setdefault(item1, {}) 
  32.                 self.diffs.setdefault(item1, {}) 
  33.                 for item2, rating2 in ratings.iteritems(): 
  34.                     self.freqs[item1].setdefault(item2, 0
  35.                     self.diffs[item1].setdefault(item2, 0.0
  36.                     self.freqs[item1][item2] += 1 
  37.                     self.diffs[item1][item2] += rating1 - rating2 
  38.         for item1, ratings in self.diffs.iteritems(): 
  39.             for item2 in ratings: 
  40.                 ratings[item2] /= self.freqs[item1][item2] 
  41.  
  42. if __name__ == '__main__'
  43.     userdata = dict( 
  44.         alice=dict(squid=1.0
  45.                    cuttlefish=0.5
  46.                    octopus=0.2), 
  47.         bob=dict(squid=1.0
  48.                  octopus=0.5
  49.                  nautilus=0.2), 
  50.         carole=dict(squid=0.2
  51.                     octopus=1.0
  52.                     cuttlefish=0.4
  53.                     nautilus=0.4), 
  54.         dave=dict(cuttlefish=0.9
  55.                   octopus=0.4
  56.                   nautilus=0.5), 
  57.         ) 
  58.     s = SlopeOne() 
  59.     s.update(userdata) 
  60.     print s.predict(dict(squid=0.4)) 

 

 =-========================== 延伸文章===========================

来源 : http://my.donews.com/clickstone/2006/10/16/fktEQWUckzvGDyfjugcqcJjkaDpdjemooGTf/

 

本文是关于推荐系统的系列研究文章之一,其他内容将陆续发布。这些内容,大多数来自我在2004年底完成的一篇项目方案建议书。放在这里,抛砖引玉,供大家讨论之用。
-------------------------------------------------

在推荐系统简介中,我们给出了推荐系统的一般框架。很明显,推荐方法是整个推荐系统中最核心、最关键的部分,很大程度上决定了推荐系统性能的优劣。目前,主要的推荐方法包括:基于内容推荐、协同过滤推荐、基于关联规则推荐、基于效用推荐、基于知识推荐和组合推荐。

一、基于内容推荐

基于内容的推荐(Content-based Recommendation)是信息过滤技术的延续与发展,它是建立在项目的内容信息上作出推荐的,而不需要依据用户对项目的评价意见,更多地需要用机 器学习的方法从关于内容的特征描述的事例中得到用户的兴趣资料。在基于内容的推荐系统中,项目或对象是通过相关的特征的属性来定义,系统基于用户评价对象 的特征,学习用户的兴趣,考察用户资料与待预测项目的相匹配程度。用户的资料模型取决于所用学习方法,常用的有决策树、神经网络和基于向量的表示方法等。 基于内容的用户资料是需要有用户的历史数据,用户资料模型可能随着用户的偏好改变而发生变化。

基于内容推荐方法的优点是:
 1)不需要其它用户的数据,没有冷开始问题和稀疏问题。
 2)能为具有特殊兴趣爱好的用户进行推荐。
 3)能推荐新的或不是很流行的项目,没有新项目问题。
 4)通过列出推荐项目的内容特征,可以解释为什么推荐那些项目。
 5)已有比较好的技术,如关于分类学习方面的技术已相当成熟。

缺点是要求内容能容易抽取成有意义的特征,要求特征内容有良好的结构性,并且用户的口味必须能够用内容特征形式来表达,不能显式地得到其它用户的判断情况。

二、协同过滤推荐

协同过滤推荐(Collaborative Filtering Recommendation)技术是推荐系统中应用最早和最为成功的技术之一。它一般采用最近邻技术,利用用户的历史喜好信息计算用户之间的距离,然后 利用目标用户的最近邻居用户对商品评价的加权评价值来预测目标用户对特定商品的喜好程度,系统从而根据这一喜好程度来对目标用户进行推荐。协同过滤最大优 点是对推荐对象没有特殊的要求,能处理非结构化的复杂对象,如音乐、电影。

协同过滤是基于这样的假设:为一用户找到他真正感兴趣的内容的好方法是首先找到与此用户有相似兴趣的其他用户,然后将他们感兴趣的内容推荐给此用 户。其基本思想非常易于理解,在日常生活中,我们往往会利用好朋友的推荐来进行一些选择。协同过滤正是把这一思想运用到电子商务推荐系统中来,基于其他用 户对某一内容的评价来向目标用户进行推荐。

基于协同过滤的推荐系统可以说是从用户的角度来进行相应推荐的,而且是自动的,即用户获得的推荐是系统从购买模式或浏览行为等隐式获得的,不需要用户努力地找到适合自己兴趣的推荐信息,如填写一些调查表格等。

和基于内容的过滤方法相比,协同过滤具有如下的优点:
1) 能够过滤难以进行机器自动内容分析的信息,如艺术品,音乐等。
2) 共享其他人的经验,避免了内容分析的不完全和不精确,并且能够基于一些复杂的,难以表述的概念(如信息质量、个人品味)进行过滤。
3) 有推荐新信息的能力。可以发现内容上完全不相似的信息,用户对推荐信息的内容事先是预料不到的。这也是协同过滤和基于内容的过滤一个较大的差别,基于内容的过滤推荐很多都是用户本来就熟悉的内容,而协同过滤可以发现用户潜在的但自己尚未发现的兴趣偏好。
4) 能够有效的使用其他相似用户的反馈信息,较少用户的反馈量,加快个性化学习的速度。

虽然协同过滤作为一种典型的推荐技术有其相当的应用,但协同过滤仍有许多的问题需要解决。最典型的问题有稀疏问题(Sparsity)和可扩展问题(Scalability)。

三、基于关联规则推荐

基于关联规则的推荐(Association Rule-based Recommendation)是以关联规则为基础,把已购商品作为规则头,规则体为推荐对象。关联规则挖掘可以发现不同商品在销售过程中的相关性,在零 售业中已经得到了成功的应用。管理规则就是在一个交易数据库中统计购买了商品集X的交易中有多大比例的交易同时购买了商品集Y,其直观的意义就是用户在购 买某些商品的时候有多大倾向去购买另外一些商品。比如购买牛奶的同时很多人会同时购买面包。

算法的第一步关联规则的发现最为关键且最耗时,是算法的瓶颈,但可以离线进行。其次,商品名称的同义性问题也是关联规则的一个难点。

四、基于效用推荐

基于效用的推荐(Utility-based Recommendation)是建立在对用户使用项目的效用情况上计算的,其核心问题是怎么样为每一个用户去创建一个效用函数,因此,用户资料模型很大 程度上是由系统所采用的效用函数决定的。基于效用推荐的好处是它能把非产品的属性,如提供商的可靠性(Vendor Reliability)和产品的可得性(Product Availability)等考虑到效用计算中。

五、基于知识推荐

基于知识的推荐(Knowledge-based Recommendation)在某种程度是可以看成是一种推理(Inference)技术,它不是建立在用户需要和偏好基础上推荐的。基于知识的方法因 它们所用的功能知识不同而有明显区别。效用知识(Functional Knowledge)是一种关于一个项目如何满足某一特定用户的知识,因此能解释需要和推荐的关系,所以用户资料可以是任何能支持推理的知识结构,它可以 是用户已经规范化的查询,也可以是一个更详细的用户需要的表示。

六、组合推荐

由于各种推荐方法都有优缺点,所以在实际中,组合推荐(Hybrid Recommendation)经常被采用。研究和应用最多的是内容推荐和协同过滤推荐的组合。最简单的做法就是分别用基于内容的方法和协同过滤推荐方法 去产生一个推荐预测结果,然后用某方法组合其结果。尽管从理论上有很多种推荐组合方法,但在某一具体问题中并不见得都有效,组合推荐一个最重要原则就是通 过组合后要能避免或弥补各自推荐技术的弱点。

在组合方式上,有研究人员提出了七种组合思路:
1)加权(Weight):加权多种推荐技术结果。
2)变换(Switch):根据问题背景和实际情况或要求决定变换采用不同的推荐技术。
3)混合(Mixed):同时采用多种推荐技术给出多种推荐结果为用户提供参考。
4)特征组合(Feature combination):组合来自不同推荐数据源的特征被另一种推荐算法所采用。
5)层叠(Cascade):先用一种推荐技术产生一种粗糙的推荐结果,第二种推荐技术在此推荐结果的基础上进一步作出更精确的推荐。
6)特征扩充(Feature augmentation):一种技术产生附加的特征信息嵌入到另一种推荐技术的特征输入中。
7)元级别(Meta-level):用一种推荐方法产生的模型作为另一种推荐方法的输入。
七、主要推荐方法的对比

各种推荐方法都有其各自的优点和缺点,见表1。

表1 主要推荐方法对比

推荐方法 优点 缺点
基于内容推荐 推荐结果直观,容易解释;

 

不需要领域知识

新用户问题;

 

复杂属性不好处理;

要有足够数据构造分类器

协同过滤推荐 新异兴趣发现、不需要领域知识;

 

随着时间推移性能提高;

推荐个性化、自动化程度高;

能处理复杂的非结构化对象

稀疏问题;

 

可扩展性问题;

新用户问题;

质量取决于历史数据集;

系统开始时推荐质量差;

基于规则推荐 能发现新兴趣点;

 

不要领域知识

规则抽取难、耗时;

 

产品名同义性问题;

个性化程度低;

基于效用推荐 无冷开始和稀疏问题;

 

对用户偏好变化敏感;

能考虑非产品特性

用户必须输入效用函数;

 

推荐是静态的,灵活性差;

属性重叠问题;

基于知识推荐 能把用户需求映射到产品上;

 

能考虑非产品属性

知识难获得;

 

推荐是静态的

 

 

被阅 53 次, 0 票  发表评论

利用 StarUML 创建 AS3 代码

2010年02月27日 作者: KingFo 开发者

最近在搜寻轻量好用且免费的UML工具,且最好能产生AS3代码的。  于是 StrarUML 进入我的视野。

在此处可以找到原文阐述如何使用此款软件: http://www.senocular.com/flash/tutorials/starumltoas3/

关键安装方式是:

  1. 下载 StrarUML http://www.staruml.com/ 。
  2. 下载 AS3 代码生成模板  http://www.senocular.com/flash/tutorials/starumltoas3/downloads/StarUML_ActionScript3_Export.zip
  3. 进入 StrarUML   所在的安装目录下 \modules\staruml-generator\templates 处将 模板中 ActionScript 3.0 整个文件夹放入到这里。
    最后可以得到如下2个路径: 
    <StarUML 安装目录>\modules\staruml-generator\templates\ActionScript 3.0\template description.tdf
    <StarUML 安装目录>\modules\staruml-generator\templates\ActionScript 3.0\template.cot

关键使用方式:

  1. 启动StarUML 并打开你要导出代码的 UML 视图。
  2. 选择  Tools > StarUML Generator
  3. 勾上 模板列表(list of template)中文档名(Document Name)为 ActionScript 3.0 选项。
  4. 点下 next
  5. 此时面板会让你选择导出路径。自己选择吧,比如直接可以倒入到 Src中。
  6. 选择完毕后点下 next
  7. 此时,会等待你决定是否立即产出代码
  8. 点Generate 即可。

StarUML AS3例子:
http://www.senocular.com/flash/tutorials/starumltoas3/downloads/Gallery.uml

 

另外再提供UML学习指南:http://www.uml.org.cn/oobject/OObject.asp

 

被阅 63 次, 0 票  发表评论
1 / 14 / 70 | « 1 2 3 4 » |

 
Google 网上论坛
订阅 XIntend
电子邮件:
访问此论坛

PageRank Checking Icon

文章分类

站点统计

  • 文章总数: 137 篇
  • 评论总数: 11 条
  • 附件总数: 64 个
  • 留言总数: 0 份
  • 建站日期: 2008-1-1
  • 访问总数: 309725 人次

最新留言

赞助商

友情链接

Design by Free CSS Templates & TiSkin, Powered by Roclog v3.2.15

浙ICP备09082105号, Copyright © 2007 X-Intend[超级打算]. All rights reserved.