用意: 搞推薦系統或者數據挖掘的, 對數據要絕對的敏感和熟悉, 而且熱愛你的數據. 分析數據既要用統計分析那一套,又要熟悉業務發掘有趣的特徵(feature). 後者有意思的多,可是由於我業務作的很少,還不太熟悉, 跪求大牛們分析業務經歷. 聽豆瓣上的大神"懶惰啊我"說過,有一個Nokia的比賽,有一個團隊直接用陀螺儀參數就發現了性別分佈,由於男生手機都放在口袋裏, 而女生每每放在包裏面. 不知道記錯沒有. html
下面主要講些統計分析或者簡單的內容分析, 說說我本身的總結, 這個話題之後能夠常說. python
這部分不涉及Mahout的內容,主要是使用Python和Linux命令簡單處理數據. 不感興趣的朋友能夠直接跳到最後面看看一些不錯的數據集推薦. 算法
1. 打開你的數據,讀懂每一行的含義 數據庫
數據的行數 數據結構
item和user的數量 機器學習
rate的評分方式,是boolean仍是1-5分或者其它. 性能
數據稀疏仍是稠密 sparse or dense 學習
3. 找到合適的存儲方式存儲,DenseVector仍是SparseVector spa
如今國內的數據還比較少, 感謝下百度,提供了一些不錯的數據. excel
百度舉辦的電影推薦系統算法創新大賽提供的用戶數據. http://pan.baidu.com/s/1y15w4
1. 讀懂你的數據, 知道每一行的含義.
一共有五個文件:
movie_tag.txt 每行表示一個有效數據項, 下面相似. 每行由電影id以及tag的id, 用"\t"隔開; tag用","隔開.
training_set.txt 每行表示用戶id, 電影id, 評分, 用"\t"隔開.
user_social.txt 每行表示用戶id和用戶關注的好友id集合; 好友id集合用","隔開.
predict.txt 每行表示用戶id和電影id
user_history.txt 每行表示用戶id和用戶看過的電影id.
數據以下圖所示: head -n 2 *.txt
行數分析: wc -l *.txt
用戶(總數,平均值,標準差)=( 9722 129.884900226 223.778624272 )
電影(總數,平均值,標準差)=( 7889 160.063506148 360.171047305 )
評分範圍=( 1.0 5.0 )
簡要分析:
由數據可見,用戶數量和電影數量在10000左右級別, 因爲電影更少一些,使用item-based較合適;固然,因爲用戶和電影數量差距不大,最終仍是要用實驗來證實一下二者的性能優異.
另外:二者標準差分別爲223與336可見, 基本能夠斷定數據爲稀疏矩陣.
[比較: 我使用了movieLens上的1M數據集進行對比, 運行結果以下]
http://www.grouplens.org/datasets/movielens/
用戶(總數,平均值,標準差)=( 6040 165.597516556 192.731072529 )
電影(總數,平均值,標準差)=( 3706 269.889098759 383.996019743 )
評分範圍=( 1.0 5.0 )
評價: 平均值更大, 數據更加緻密一些. 每一個用戶和電影的數據推薦效果應該也會更好一些.
[吐槽點: 你給了id不給電影和標籤的真實名稱,看着一堆id, 推薦一大堆數字有個毛興趣啊. 可是movieLens給出了電影名稱,之後仍是使用movieLens來做爲預測數據更加有興趣一些.]
Python代碼以下:
# -*- coding: utf-8 -*- ''' Created on 2 Nov, 2013 @author: cool ''' import math #return user_num, movie_num, movie_mean, movie_variant def countData(filename): user_count = {} #the number of movie about every user movie_count = {} #the number of user about every movie max = -100 min = 100 #Assuming no duplicate data for line in open(filename): (user, movie, rating) = line.split("\t") #(user, movie, rating, xx) = line.split("::") rating = float(rating.replace(r"\r\r\n", "")) #print rating user_count.setdefault(user, 0) user_count[user] += 1 movie_count.setdefault(movie, 0) movie_count[movie] += 1 if (max < rating): max = rating if (min > rating): min = rating uSum = sum([user_count[user] for user in user_count]) uSqSum = sum([user_count[user]**2 for user in user_count]) user_mean = float(uSum) / len(user_count) user_variant = math.sqrt(float(uSqSum) / len(user_count) - user_mean**2) mSum = sum([movie_count[movie] for movie in movie_count]) mSqSum = sum([movie_count[movie]**2 for movie in movie_count]) movie_mean = float(mSum) / len(movie_count) movie_variant = math.sqrt(float(mSqSum) / len(movie_count) - movie_mean**2) return len(user_count), len(movie_count), user_mean, user_variant, movie_mean, movie_variant, min, max if __name__ == '__main__': (user_count, movie_count, user_mean, user_variant, movie_mean, movie_variant, min, max) \ = countData("../data/baidu/training_set.txt") #(user_count, movie_count, user_mean, user_variant, movie_mean, movie_variant, min, max) \ # = countData("../data/baidu/ratings.dat") print "用戶(總數,平均值,標準差)=(", user_count, user_mean, user_variant, ")" print "電影(總數,平均值,標準差)=(", movie_count, movie_mean, movie_variant, ")" print "評分範圍=(", min, max, ")"