接着上一篇文章常見算法的mapreduce案例(1)繼續挖坑,本文涉及到算法的基本原理,文中會大概講講,但具體有關公式的推導還請你們去查閱相關的文獻文章。下面涉及到的數據挖掘算法會有:Logistict 迴歸,SVM算法,關聯規則apriori算法,SlopeOne推薦算法,二度人脈社交
推薦算法
logistict regression的
map-reduce
邏輯迴歸做爲經典的分類算法,工業界也是應用的很是普遍(
點擊率預估,廣告投放等
),貌似大部分互聯網公司都會用吧,關於logistict regression的應用研究主要分兩塊:1)用什麼樣的正則(L2,L1); 2)使用什麼優化算法;關於第一點,若是維度超級多選L1較好,L1自然具備特徵選擇的優點,另外經常使用的優化算法有:梯度降低,LBFGS、隨機梯度降低,以及微軟針對L1提出的OWLQN算法;本來的logisitc迴歸,是針對線性可分的的,業界的一淘企業的工程師擴展了Logistic迴歸,用它來處理非線性的問題。
針對多種優化算法,梯度降低,LBFGS,OWLQN都是能夠無損的並行化(執行結果與串行的同樣),而基於隨機梯度降低的只能進行有損的並行化。
以梯度降低爲例:梯度降低的核心步驟
,每一次迭代的個過程能夠轉換成一個map-reduce過程,按行或者按列拆分數據,分配到N各節點上,每一個節點再經過計算,最後,輸出到reduce,進行合併更新W權重係數,完成一次迭代過程。下圖文獻1中也提到LR的並行,不過用的優化方法是
Newton-Raphson,節點須要計算海森矩陣。
針對隨機梯度的並行,下圖文獻2中提到
算法1是基本的SGD算法,算法2,3是並行的SGD,
能夠看出每臺worker分配T個數據,利用這些數據來SGD優化更新W,而後輸出W由reduce端進行歸約。
SVM的
map-reduce
支持向量機,最近十五年機器學習界的明星算法,學術界也是各類研究,現今已經達到一個瓶頸,屋漏偏逢連夜雨,隨着深度學習的雄起,SVM弄的一我的走茶涼的境遇(也許正是90年代神經網絡的感覺吧,呵呵),如今講一講關於SVM的並行,因爲原算法較難應用並行策略,而它的另外一個算法變種-pegasos 適合並行,下面是該算法的過程。
初始化W=0(向量形式)
for i in t:
隨機選擇K個樣本
for j in K:
if 第j個樣本分錯
利用該樣本更新權重
累加W的更新
end for
下面是基於mrjob的map-reduce版
1 class MRsvm(MRJob):
2
3 DEFAULT_INPUT_PROTOCOL = 'json_value'
4
5 #一些參數的設置
6
7 def __init__(self, *args, **kwargs):
8
9 super(MRsvm, self).__init__(*args, **kwargs)
10
11 self.data = pickle.load(open('data_path'))
12
13 self.w = 0
14
15 self.eta = 0.69 #學習率
16
17 self.dataList = [] #用於收集樣本的列表
18
19 self.k = self.options.batchsize
20
21 self.numMappers = 1
22
23 self.t = 1 # 迭代次數
24
25
26 def map(self, mapperId, inVals):
27
28 #<key,value> 對應着 <機器mapperID,W值或者樣本特徵跟標籤>
29
30 if False: yield
31
32 #判斷value是屬於W仍是樣本ID
33
34 if inVals[0]=='w':
35
36 self.w = inVals[1]
37
38 elif inVals[0]=='x':
39
40 self.dataList.append(inVals[1])
41
42 elif inVals[0]=='t': self.t = inVals[1]
43
44
45 def map_fin(self):
46
47 labels = self.data[:,-1]; X=self.data[:,0:-1]#解析樣本數據
48
49 if self.w == 0: self.w = [0.001]*shape(X)[1] #初始化W
50
51 for index in self.dataList:
52
53 p = mat(self.w)*X[index,:].T #分類該樣本
54
55 if labels[index]*p < 1.0:
56
57 yield (1, ['u', index])#這是錯分樣本id,記錄該樣本的id
58
59 yield (1, ['w', self.w]) #map輸出該worker的w
60
61 yield (1, ['t', self.t])
62
63
64 def reduce(self, _, packedVals):
65
66 for valArr in packedVals: #解析數據,錯分樣本ID,W,迭代次數
67
68 if valArr[0]=='u': self.dataList.append(valArr[1])
69
70 elif valArr[0]=='w': self.w = valArr[1]
71
72 elif valArr[0]=='t': self.t = valArr[1]
73
74 labels = self.data[:,-1]; X=self.data[:,0:-1]
75
76 wMat = mat(self.w); wDelta = mat(zeros(len(self.w)))
77
78 for index in self.dataList:
79
80 wDelta += float(labels[index])*X[index,:] #更新W
81
82 eta = 1.0/(2.0*self.t) #更新學習速率
83
84 #累加對W的更新
85
86 wMat = (1.0 - 1.0/self.t)*wMat + (eta/self.k)*wDelta
87
88 for mapperNum in range(1,self.numMappers+1):
89
90 yield (mapperNum, ['w', wMat.tolist()[0] ])
91
92 if self.t < self.options.iterations:
93
94 yield (mapperNum, ['t', self.t+1])
95
96 for j in range(self.k/self.numMappers):
97
98 yield (mapperNum, ['x', random.randint(shape(self.data)[0]) ])
99
100
101 def steps(self):
102
103 return ([self.mr(mapper=self.map, reducer=self.reduce,
104
105 mapper_final=self.map_fin)]*self.options.iterations)
關聯規則Apriori的
map-reduce
啤酒跟尿布的傳奇案例,相信你們都應該很是熟悉了,可是很悲劇的是這個案例貌似是假的,呵呵,超市的管理者通常會把這兩個放在相差很遠的位置上擺放,拉長顧客光顧時間,或許就不止買尿布跟啤酒了。前段時間看到一個東北笑話也許會更容易理解關聯規則,「一天,一隻小雞問小豬說:主人去哪了? 小豬回答說:去買蘑菇去了;小雞聽完後,立馬撒腿就跑了,小豬說你走這麼急幹啥,小雞回頭說:主人若是買粉條回來,你也照樣急。。。。」很形象生動的講述了關聯規則,好了,又扯遠了了,如今回到關聯規則的並行上來吧,下面以一個例子簡述並行的過程。
假設有一下4條數據
id,交易記錄
1,[A,B]
2,[A,B,C]
3,[A,D]
4,[B,D]
首先,把數據按行拆分,搞到每一個worker上面,key=交易id,value=交易記錄(假設1,2在第一個mapper上,3,4在第二個mapper上)
其次,每一個worker,計算頻次(第一個mapper生成<A,1>,<B,1>,<A,1>,<B,1>,<C,1> ;第二個mapper 就會生成<A,1>,<D,1>,<B,1>,<D,1>)
接着,進行combine操做(減輕reduce的壓力)
(第一個mapper生成<A,2>,<B,2>,<C,1> ;第二個mapper 就會生成<A,1>,<B,1>,<D,2>)
最後,送到reduce上面進行歸約,獲得1-頻繁項集
而後再重複上面的動做,知道K-頻繁項集
總結:這是對
Apriori的並行實現,可是該算法的一個缺點是須要屢次掃描數據,性能是個問題,對此,韓教授設計了另一個更巧妙的數據結構fp-tree,這個在mahout裏面是有實現的(0.9的版本里面貌似把這算法給kill了。。),整體來講關聯規則這個算法是一個聽起來是一個很實用的算法,實際操做過程當中要仔細調節支持度、置信度等參數,否則會挖掘出不少不少的價值低的規則。
SlopeOne推薦算法的
map-reduce
例如一個評分矩數據(用戶,物品,評分)以下所示
A,one ,2
A,two ,3
A,three,1
B,one ,3
B,two ,5
C,one ,4
C,three,2
首先把該數據集打成{用戶,[(物品1,評分),(物品2,評分),....,(物品n,評分)]}形式,很簡單的一個map-reduce操做
物品one
物品two
物品three
用戶A 2 3 1
用戶B 3 5 ?
用戶C 4 ? 2
固然真是的數據集確定是很是稀疏的,這裏只爲講清原理,接着對數據分片,分到不一樣的worker裏面,這裏假設3個,輸入是[A,(one,2)
,(two,3)
,(three,1)
],
[B,(one,3)
,(two,5)
],
[C,(one,4)
,
(three,2)
]。
每個map的操做輸出<key,value> 對應了<(物品1,物品2),(評分1-評分2,1)> 最後面的1,是爲了對
(物品1,物品2)
計數1,上面第1個節點<(one,two),(-1,1)>,
<(one,three),(1,1)>,
<(two,three),(1,1)>;
第2個節點
<(one,two),(-2,1)>,
<(one,
three
),(2,3,1)>;
第3個節點
<(one,
three
),(2,1)>。
接着能夠進行一下combine操做,把key相同的value,評分差值相加,計數相加
最後進行reduce操做,獲得物品跟物品之間的評分差
總結:slopeone在mahout0.9版本里面也被kill掉了,悲劇,難道太簡單啦??關於該算法有另一個變種就是weighted
slopeone,其實就是在計算物品跟物品之間評分差的時候,進行了加權平均。
人脈二度推薦的
map-reduce
最近社交類網站很是流行的給你推薦朋友/感興趣的人,利用好社交關係,就不愁找不到好的推薦理由了,舉個例子,假設A的好友是B,C,D,然而B的好友有E,C的好友有F,D的好友有E,那麼若是要給A推薦好友的話,那麼就會首推E了,由於B,C跟E都是好友,而F只是和C好友(有點關聯規則裏面支持度的味道)。OK,下面詳解給A用戶推薦好友的map-reduce過程
首先輸入文件每行是兩個id1,id2,假設id1認識id2,可是id2不認識id1,若是是好友的話,得寫兩行記錄(方便記錄單項社交關係)
A,B //A認識B
B,A //B認識A
A,C
C,A
A,D
D,A
B,E
E,B
C,F
F,C
D,E
E,D
第一輪map-reduce(爲簡單書寫,下面只對與A有關的行爲進行演示)
輸入上面數據,輸出<id,[(該id認識的人集合),(認識該id的人集合)]>
輸出:<B,[(A),(E)]>,
<C,[(A),(E)]>,
<D,[(A),(F)]>
第二輪map-reduce
map輸入上面數據,輸出<[
(該id認識的人),(認識該id的人)],id
>
輸出:
<[(A),(E)],B>,
<[(A),(E)],C>,
<[(A),(F)],D>
reduce輸入上面數據,輸出
<[
(該id認識的人),(認識該id的人)],[id集合]
>
輸出:
<[(A),(E)],[B,C]>
,
<[(A),(F)],[D]>
OK這樣算法挖完了,id集合的長度做爲二度人脈的支持度,能夠從上面看到,A認識E,比A認識F更靠譜一點。
總結:還有不少其餘的推薦算法諸如基於近鄰的CF,模型的CF(矩陣分解),關於矩陣分解的,前段時間,LibSvm團隊發表的Libmf,針對矩陣分解的並行化方面作出了很是好的貢獻
參考資料:
1,《Parallelized Stochastic Gradient Descent》Martin A. Zinkevich、Markus Weimer、Alex Smola and Lihong Li
2,《Map-Reduce for Machine Learning on Multicore NG的一篇nips文章》
5,Pegasos:primal estimated sub-gradient solver for svm
6,machine learning in action
7,http://my.oschina.net/BreathL/blog/60725