很多人覺得機器學習高不可攀,認為這是一門隻有少數專業學者才了解的神秘技術。
畢竟,你是在讓運作在二進制世界裡的機器得出它自己對現實世界的認識。你正在教它們如何思考。然而,本文幾乎不是你所認為的晦澀難懂、複雜而充滿數學公式的文章。正如所有幫助我們認識世界的基本常識一樣(例如:牛頓運動定律、工作需要去完成、供需關系等等),機器學習最佳的方法和概念也應該是簡潔明了的。可惜的是,絕大多數關于機器學習的文獻都充斥着複雜難懂的符号、艱澀晦暗的數學公式和不必要的廢話。正是這給機器學習簡單基礎的思想圍上了一堵厚厚的牆。
現在看一個實際的例子,我們需要在一篇文章的末尾增加一個“你可能喜歡”的推薦功能,那麼我們該如何實作呢?

- 獲得目前文章的标題并将其分割成獨立的單詞(譯者注:原文是英文,隻需要依據空格分割即可,中文分詞需要用到分詞器)
- 擷取除目前文章以外的所有文章
- 将這些文章依據其内容與目前文章标題的重合程度進行排序
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
采用這種方法去找出與博文“支援團隊如何提高産品品質”相似的文章,我們由此得到下列相關度前十的文章:
- 如何着手實施一個經過驗證的方案
- 了解你的客戶是如何做決策的
- 設計首次運作界面以取悅你的使用者
- 如何招聘設計師
- 圖示設計的探讨
- 對歌手Ryan的采訪
- 通過内部交流對客戶進行積極支援
- 為什麼成為第一并不重要
- 對Joshua Porter的采訪
- 客戶留存、群組分析與可視化
正如你所看到的,标杆文章是關于如何有效率地進行團隊支援,而這與客戶群組分析、讨論設計的優點都沒有太大的關系,其實我們還可以采取更好的方法。
現在,我們嘗試用一種真正意義上的機器學習方法來解決這個問題。分兩步進行:
- 将文章用數學的形式表示;
- 用K均值(K-means)聚類算法對上述資料點進行聚類分析。
1.将文章用數學的形式表示
如果我們可以将文章以數學的形式展示,那麼可以根據文章之前的相似程度作圖,并識别出不同簇群:
如上圖所示,将每篇文章映射成坐标系上的一個坐标點并不難,可以通過如下兩步實作:
1. 找出每篇文章中的所有單詞;
2. 為每篇文章建立一個數組,數組中的元素為0或者1,用于表示某單詞在該文章中是否出現了,每篇文章數組元素的順序都是一樣的,隻是其值有差異。
Ruby代碼如下:
@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
假設@words 的值為:
[“你好”,”内部”,”内部交流”,”讀者”,”部落格”,”釋出”]
如果某篇文章的内容是“你好 部落格 釋出 讀者”,那麼其對應的數組即為:
[1,0,0,1,1,1]
當然,我們現在沒法使用簡單的工具像二維坐标系一樣展示這個六次元的坐标點,但是這其中涉及的基本概念,例如兩點之間的距離都是互通的,可以通過二維推廣到更高次元(是以使用二維的例子來說明問題還是行得通的)。
2.用K均值(K-means)聚類算法對資料點進行聚類分析
現在我們得到了一系列文章的坐标,可以嘗試找出相似文章的群簇。這裡我們采用使用一個相當簡單聚類算法-K均值算法,概括起來有五個步驟:
1. 設定一個數K,它表示群簇中對象的數目;
2. 從所有資料對象中随機選擇K個對象作為初始的K個群簇中心;
3. 周遊所有對象,分别将它們指派到離自己最近的一個群簇中;
4. 更新群簇中心,即計算每個群簇中對象的均值,并将均值作為該群簇的新中心;
5. 重複3、4步驟,直到每個群簇中心不再變化。
我們接下來用圖的形式形象化地展示這些步驟。首先我們從一系列文章坐标中随機選擇兩個點(K=2):
我們将每篇文章指派到離它最近的群簇中:
我們計算各個群簇中所有對象的坐标均值,作為該群簇新的中心。
這樣我們就完成了第一次的資料疊代,現在我們将文章根據新的群簇中心重新指派到對應的群簇中去。
至此,我們找到了每篇文章對應的群簇!很明顯,即使繼續進行疊代群簇中心不會改變,每篇文章對應的群簇也不會改變了。
上述過程的Ruby代碼如下:
@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
@cluster_centers = @clusters.map do |post|
average(posts)
下面是由這個方法得到的與博文“支援團隊如何提高産品品質”相似性排在前十位的文章:
- 你對此更了解了還是你更聰明了
- 客戶回報的三個準則
- 從客戶擷取你所要的資訊
- 産品傳遞隻是一個開始
- 你覺得功能擴充看起來像什麼
- 了解你的使用者群
- 在正确的資訊和正确的時間下轉換客戶
- 與你的客戶溝通
- 你的應用有消息推送安排嗎
- 你有試着與客戶溝通嗎
- 結果不言自明。
我們僅僅用了不到40行的代碼以及簡單的算法介紹就實作了這個想法,然而如果你看學術論文你永遠不會知道這本該有多簡單。下面是一篇介紹K均值算法論文的摘要(并不知道K均值算法是誰提出的,但這是首次提出“K均值”這個術語的文章)。
如果你喜歡以數學符号去表達思想,毫無疑問學術論文是很有用處的。然而,其實有更多優質的資源可以替換掉這些繁雜數學公式,它們更實際、更平易近人。
* Wiki百科(例如:潛在語義索引,聚類分析)
* 開源機器學習庫的源代碼(例如:
Scipy’s K-Means,
Scikit’s DBSCAN)
* 以程式員的角度編寫的書籍(例如:
集體智慧程式設計 黑客機器學習* 可汗學院
試一試
如何為你的項目管理應用推薦标簽?如何設計你的客戶支援工具?或者是社交網絡中使用者如何分組?這些都可以通過簡答的代碼、簡單的算法來實作,是練習的好機會!是以,如果你認為項目中面臨的問題可以通過機器學習來解決,那為什麼還要猶豫呢?
機器學習其實比你想象得更簡單!