很多人覺得機(jī)器學(xué)習(xí)高不可攀,認(rèn)為這是一門只有少數(shù)專業(yè)學(xué)者才了解的神秘技術(shù)。
畢竟,你是在讓運行在二進(jìn)制世界里的機(jī)器得出它自己對現(xiàn)實世界的認(rèn)識。你正在教它們?nèi)绾嗡伎?。然而,本文幾乎不是你所認(rèn)為的晦澀難懂、復(fù)雜而充滿數(shù)學(xué)公式的文章。正如所有幫助我們認(rèn)識世界的基本常識一樣(例如:牛頓運動定律、工作需要去完成、供需關(guān)系等等),機(jī)器學(xué)習(xí)最佳的方法和概念也應(yīng)該是簡潔明了的。可惜的是,絕大多數(shù)關(guān)于機(jī)器學(xué)習(xí)的文獻(xiàn)都充斥著復(fù)雜難懂的符號、艱澀晦暗的數(shù)學(xué)公式和不必要的廢話。正是這給機(jī)器學(xué)習(xí)簡單基礎(chǔ)的思想圍上了一堵厚厚的墻。
現(xiàn)在看一個實際的例子,我們需要在一篇文章的末尾增加一個“你可能喜歡”的推薦功能,那么我們該如何實現(xiàn)呢?
為了實現(xiàn)這個想法,我們有一個簡單的解決方案:
1 2 3 4 5 6 7 8 9 | def similar_posts(post) title_keywords = post.title.split( ' ' ) Post.all.to_a.sort |post1, post2| post1_title_intersection = post1.body.split( ' ' ) & title_keywords post2_title_intersection = post2.body.split( ' ' ) & title_keywords post2_title_intersection.length <=> post1_title_intersection.length end [ 0 .. 9 ] end |
采用這種方法去找出與博文“支持團(tuán)隊如何提高產(chǎn)品質(zhì)量”相似的文章,我們由此得到下列相關(guān)度前十的文章:
正如你所看到的,標(biāo)桿文章是關(guān)于如何有效率地進(jìn)行團(tuán)隊支持,而這與客戶群組分析、討論設(shè)計的優(yōu)點都沒有太大的關(guān)系,其實我們還可以采取更好的方法。
現(xiàn)在,我們嘗試用一種真正意義上的機(jī)器學(xué)習(xí)方法來解決這個問題。分兩步進(jìn)行:
1.將文章用數(shù)學(xué)的形式表示
如果我們可以將文章以數(shù)學(xué)的形式展示,那么可以根據(jù)文章之前的相似程度作圖,并識別出不同簇群:
如上圖所示,將每篇文章映射成坐標(biāo)系上的一個坐標(biāo)點并不難,可以通過如下兩步實現(xiàn):
Ruby代碼如下:
1 2 3 4 5 6 7 8 9 10 11 | @posts = Post.all @words = @posts .map do |p| p.body.split( ' ' ) end .flatten.uniq @vectors = @posts .map do |p| @words .map do |w| p.body.include?(w) ? 1 : 0 end end |
假設(shè)@words 的值為:
[“你好”,”內(nèi)部”,”內(nèi)部交流”,”讀者”,”博客”,”發(fā)布”]
如果某篇文章的內(nèi)容是“你好 博客 發(fā)布 讀者”,那么其對應(yīng)的數(shù)組即為:
[1,0,0,1,1,1]
當(dāng)然,我們現(xiàn)在沒法使用簡單的工具像二維坐標(biāo)系一樣展示這個六維度的坐標(biāo)點,但是這其中涉及的基本概念,例如兩點之間的距離都是互通的,可以通過二維推廣到更高維度(因此使用二維的例子來說明問題還是行得通的)。
2.用K均值(K-means)聚類算法對數(shù)據(jù)點進(jìn)行聚類分析
現(xiàn)在我們得到了一系列文章的坐標(biāo),可以嘗試找出相似文章的群簇。這里我們采用使用一個相當(dāng)簡單聚類算法-K均值算法,概括起來有五個步驟:
我們接下來用圖的形式形象化地展示這些步驟。首先我們從一系列文章坐標(biāo)中隨機(jī)選擇兩個點(K=2):
我們將每篇文章指派到離它最近的群簇中:
我們計算各個群簇中所有對象的坐標(biāo)均值,作為該群簇新的中心。
這樣我們就完成了第一次的數(shù)據(jù)迭代,現(xiàn)在我們將文章根據(jù)新的群簇中心重新指派到對應(yīng)的群簇中去。
至此,我們找到了每篇文章對應(yīng)的群簇!很明顯,即使繼續(xù)進(jìn)行迭代群簇中心不會改變,每篇文章對應(yīng)的群簇也不會改變了。
上述過程的Ruby代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @cluster_centers = [rand_point(), rand_point()] 15 .times do @clusters = [[], []] @posts . each do |post| min_distance, min_point = nil , nil @cluster_centers . each .with_index do |center, i| if distance(center, post) < min_distance min_distance = distance(center, post) min_point = i end end @clusters [min_point] << post end @cluster_centers = @clusters .map do |post| average(posts) end end |
下面是由這個方法得到的與博文“支持團(tuán)隊如何提高產(chǎn)品質(zhì)量”相似性排在前十位的文章:
結(jié)果不言自明。
我們僅僅用了不到40行的代碼以及簡單的算法介紹就實現(xiàn)了這個想法,然而如果你看學(xué)術(shù)論文你永遠(yuǎn)不會知道這本該有多簡單。下面是一篇介紹K均值算法論文的摘要(并不知道K均值算法是誰提出的,但這是首次提出“K均值”這個術(shù)語的文章)。
如果你喜歡以數(shù)學(xué)符號去表達(dá)思想,毫無疑問學(xué)術(shù)論文是很有用處的。然而,其實有更多優(yōu)質(zhì)的資源可以替換掉這些繁雜數(shù)學(xué)公式,它們更實際、更平易近人。
試一試
如何為你的項目管理應(yīng)用推薦標(biāo)簽?如何設(shè)計你的客戶支持工具?或者是社交網(wǎng)絡(luò)中用戶如何分組?這些都可以通過簡答的代碼、簡單的算法來實現(xiàn),是練習(xí)的好機(jī)會!所以,如果你認(rèn)為項目中面臨的問題可以通過機(jī)器學(xué)習(xí)來解決,那為什么還要猶豫呢?
機(jī)器學(xué)習(xí)其實比你想象得更簡單!