回顧近期開發推薦演算法的心得。目前在服飾電商服務,就以服飾的推薦算法為場景舉例。本文談論的內容包含為何要開發推薦系統、推薦模型基本架構,以及在設計算法過程中要考慮的細節。

想像一個陽光普照春日下午,剛結束跟姐妹下午茶約會的你,在回家的路上偶然走進一間服飾店逛逛,也順便吹冷氣休息一下。看到店內有數百件各類型衣服,首先可能會大致瀏覽一下自己喜歡的類型、款式、顏色,也許拿幾件自己感興趣的洋裝出來比試一番,順便欣賞鏡中的自己。這時一旁的帥哥店員會簡單的跟你閒聊,同時根據你先前從衣架上拿下的商品的特徵來推薦當季的最新款、或更合你心意的洋裝款式。這位帥哥店員便是推薦系統了。

開發推薦系統的目的

推薦系統想解決的問題是,如何幫助使用者在資訊超載的情況下,高效率地獲得感興趣的商品資訊。以目前工作的電商網站為例,站上使用者能接觸的商品超過十萬檔,當這麼多商品一次擺在你面前,如何在短時間內找到自己適合的商品就會是個困擾使用者的問題。

站在公司角度,推薦系統產品是用來吸引使用者、提升用戶留存率與使用者黏性,進一步達到商業目標增長的目的。不同公司根據其商業模式,推薦系統的最佳化目標也不同。比方說,串流影音平台,注重的是使用者的觀看時長﹔新聞網站注重使用者的點擊率﹔電商公司更注重使用者的轉換率(Conversion Rate,CVR)。最終都是要達成公司的商業目標,增加公司收益。

從工程面看,推薦系統是利用使用者在站上過往的歷史紀錄⎡猜測⎦使用者可能會喜歡的內容。

推薦模型架構概述

推薦系統架構圖示

完整的推薦模型由上圖的幾個抽象單元組成。

  • 候選物品庫(candidate items):可用來推薦的所有站上商品。
  • 召回層(recall layer):從巨量的候選品中利用規則、演算法、簡單的模型,先過濾出一群使用者可能有興趣的物品組成候選物品集。實作方式可以是商品的熱門度計算,例如商品的點擊率、加車率等。
  • 排序層(sorting layer):前一層篩選出的物品,帶有的各種評價指標,進行細部重組、排序,得到將出現在推薦清單的先後次序。
  • 推薦清單(recommendation list):最終輸出給使用者的推薦清單。

上圖架構是個簡單的示例。實務上根據需求,及算法的設計考量,每個算法間的模型架構、計算方法也可能有很大的差異。

根據商業目標決定推薦算法的開發方向吧

這次的應用場景是app 推播服務,有別於過往電商的app推播對所有用戶都推送一致內容,這次想要製作客製化推播內容來增加用戶的對服務的黏著度與轉換率。

換句話說,就是要開發一個個人化的商品推薦模型,讓每個不同的使用者都會得到一份符合自身偏好的商品推薦清單。而這份推薦清單至少要包含兩個面向:

  • 挑選商品需滿足商品的多樣性、新鮮度、與即時性
  • 貼近用戶偏好的推薦

多樣性、新鮮度、與即時性

一個及格的推薦模型,推薦結果大多要包含上面標題中的三個面向。也是在開發算法時首先要考慮的問題。

  • 多樣性:代表推薦商品在類別上、風格上或其它商品特徵上,希望保持多樣性,讓使用者感覺豐富、不無聊。比如說,給看過許多件上衣的用戶,推薦可做搭配的短褲或其他熱門類別。但換個角度想,是否每個用戶都喜歡多樣化的推薦清單呢?也許該用戶只有購買上衣的需求,若同時推薦的品項、類別用戶完全沒興趣,就可能浪費了一次推薦系統可帶來效益的機會。
  • 新鮮度:推薦最新上架商品為佳,或是一定比例包含有高點擊率的長春熱賣品呢?長春商品點擊率佳,容易滿足商業目標;但推薦新商品則有機會測試用戶當季偏好,進而創造下一個長春商品,並擴大推薦商品池。在不同考量下將影響到候選商品池的大小,候選商品池太小,隨後算出的推薦清單長度可能太短。另外,已經推薦過的商品要隔多久才能再次被推薦,這也是個考慮新鮮度的面向。
  • 即時性:也許用戶兩週前看了很多洋裝、但最近兩天的進站開始逛起T-shirt,是不是代表用戶這次想買T-shirt呢?若希望能及時反應用戶喜好,就要考慮多久更新一次推薦清單,是每週更新,每日更新、還是每小時更新?還有一次計算多久的user log(用戶日誌)能夠洽當的對用戶當下需求做反應,一次計算越多的user log 對模型來說可信度較高,但也有可能對使用著最近期的行為反應不佳。但只使用短期的user log做計算則無法得到足夠資訊計算用戶的行為偏好。

實務上根據不同的商品性質與商業模式,對多樣性、新鮮度、即時度的考量也會不同。

由上面的論述我們能了解到,如何定義以及正確理解用戶上站的意圖十分重要。若要做到個人化推薦,則要下更多功夫針對每個用戶去理解他們的喜好。

如何貼近用戶偏好

就像上面服飾店帥哥店員根據你的喜好推薦衣服給你,個人化推薦,換句話說即是人貨媒合。從使用者過往瀏覽紀錄提取使用者資訊,計算使用者特徵(使用者偏好)、再搭配商品特徵,同時考慮應用場景,來計算每個使用者(user)對每件商品(item)的偏好程度

這裡先說明什麼是商品特徵,商品特徵就像是使用者瀏覽陳列在架上的商品時,可能會在意的所有細節,包含:商品種類、價格、尺寸、顏色、衣長、裙長、風格….等等特徵。若你在擁有數萬檔商品的情況下,則會先請資料科學家對商品圖片訓練分類模型,讓模型自動化辨識全站商品的每個特徵,做商品自動化打標籤的工作。

--

--

轉眼間轉職資料科學領域已工作超過兩年。經歷了一段忙碌又充實的日子,也在這樣的生活中迅速成長起來。這次想整理爬梳這兩年的經歷,為此時此刻的自己下個註記。

自己的定位

目前待過兩間規模類似,但產業天差地遠的公司:一間公司提供資安技術服務,另一間是電商。在這兩間公司,工程師的定位是相似的:需要懂後端系統設計,也要能實作資料分析與開發模型,結合上述兩者,能夠設計並打造數據分析平台和數據產品

當然技術上需要跟前輩、同事相互討論與請教。但這樣的我,也獨立開發了數個影像分類、推薦系統等數據產品,並順利上線運行。

工作日常還包含了:產品開發後,持續追蹤成效指摽,並據此調整線上產品。使用者站上行為log 的分析,期望能從中找到有趣的insight 來做下一個產品。

相較於專注在研究演算法的機器學習工程師(或研究員),我更傾向將自己定位為資料工程師與數據產品的開發人員,未來也打算繼續往這方向走。

在開發產品的過程中,需要理解stackholder的想法、思考產品商業價值,也能更多機會跟其他部門的人合作。這些都是我有興趣的工作內容。心中的最終目標,是想成為一位兼顧技術面、商業思維、與溝通能力的工程師。

技術能力的突破點是怎麼出現的

就像炭治郎在與上弦之六的對戰中覺醒了斑紋。真正的突破都是在實戰中。再次感謝那個當初只自學了資料科學三個月,python剛入門,就有膽子去找工作的我。沒有浪費太多時間在自學與摸索,而是直接投入工作現場累積經驗。

這兩年技術的提升,靠的是一個接一個專案中解決各種工程問題。專案需要串接後端,就將Restful API 寫法學起來﹔需要操作百萬筆等級數據,就將Spark操作學起來。需要在AWS環境做開發,就學著在S3, DynamoDB, 存取非結構化資料、用lambda 寫邏輯單元,用tensorflow在SageMaker平台訓練部署深度學習模型….。

下班時間也沒閒著,有感於自己是非本科工程師,也花了不少時間補充關於後端開發、SQL、資結、演算法等知識,近期也開始練習LeetCode刷題。

雖說學無止境。但在目前這個階段,軟體工程與資料工程的技術知識上,目前已累積了一些經驗,而許多知識點狀散布在腦中,似乎還沒有串成線。為了避免消化不良,今年的學習策略,會轉為結構化的複習、整理這些已知的技術,希望將它們再次內化,由點串成線。

下一階段想把自己有興趣的技術或應用,嘗試掛鉤於公司內部專案,這需要更多的業務理解,以及將業務問題轉化為技術問題的能力,這也是邁向下一階段需要具備的能力之一。

Photo by Dylan Gillis on Unsplash

工程師的下個階段:硬功夫 vs 軟實力

技術上明顯感覺到自己與兩年前的成長,且對於自己的未來有更多渴望與想像,往往令人感覺興奮。為了更瞭解自己的市場價值,以及外面的世界,最近找了一位mentor做諮詢。這位mentor 是一位資深的外商資料科學家,已經從產品開發跨足技術顧問領域。得以跟這樣的高手對談真是非常幸運。

而我們的談話如果只能用一句話表達那就是:請更多的專注在軟實力的提升。身為軟體工程師,自學新技術是基本技能,只需投入時間,且一個人就可達成。軟實力則是需要更多的與人互動、在工作中思考除了技術問題外的細節。具備溝通力、影響力、社群參與,才能幫助你往更高一階的工程師邁進。也就是這番話讓我形成了今年的自我發展方向。

Fake it till you make it

剛入行,總擔心自己不夠格從事這份工作。即使已經在這個領域工作了兩年多,偶而還是會出現冒牌者心態,畢竟資料科學目前還是挺競爭的領域。我應對這種自我懷疑的策略是:那就假裝吧,假裝我夠格,裝久了就變成真的。

若你喜歡這篇文章,多拍兩下吧

--

--

對跨領域轉職為軟體工程師的你,提供我認為有效的學習策略 — 我是Sean,過去曾經是半導體工程師,沒有資工背景,也不懂程式語言。2019年從零學習寫程式,跨領域轉職為資料科學家。目前在新創電商服務,協助訓練影像辨識模型及推薦系統開發。從事軟體開發工作約兩年多。 在這篇文章中我想回顧這兩年學習的過程,並且問自己一個問題:假如能重來一遍,我會如何學習寫程式?要是回到兩年前,我會怎麼調整我的學習策略呢? 以下會聚焦在學習策略,而不是學習心態。心得有以下兩點。 不要學太多 開始工作後,我習慣在下班時間泡在Udemy或 Coursera的線上課程來補充需要的知識。線上課程的主要目的:可讓我在短時間有組織架構的學習一套新的技術知識,更可以在往後隨自己需求作延伸學習。 另一方面,通常在線上課程學習的過程,會是一種正向的體驗。你跟著課程演進,練習課程中的程式碼,看著程式碼跑起來,你會得到成就感,並且最後會得到一張數位結業證書,看起來真不錯!不知不覺你會迷上這種正向體驗,你會感覺到你付出的時間得到立即的反饋。兩年中,我上了不少線上課程。覺得晚上的線上課程,比起白天的程式開發還要輕鬆愉快,沒有時間壓力,不需要debug,也更容易有成就感。

假如能重來一遍,我會如何學習寫程式
假如能重來一遍,我會如何學習寫程式

我是Sean,過去曾經是半導體工程師,沒有資工背景,也不懂程式語言。2019年從零學習寫程式,跨領域轉職為資料科學家。目前在新創電商服務,協助訓練影像辨識模型及推薦系統開發。從事軟體開發工作約兩年多。

在這篇文章中我想回顧這兩年學習的過程,並且問自己一個問題:假如能重來一遍,我會如何學習寫程式?要是回到兩年前,我會怎麼調整我的學習策略呢?

以下會聚焦在學習策略,而不是學習心態。心得有以下兩點。

不要學太多

開始工作後,我習慣在下班時間泡在Udemy或 Coursera的線上課程來補充需要的知識。線上課程的主要目的:可讓我在短時間有組織架構的學習一套新的技術知識,更可以在往後隨自己需求作延伸學習。

另一方面,通常在線上課程學習的過程,會是一種正向的體驗。你跟著課程演進,練習課程中的程式碼,看著程式碼跑起來,你會得到成就感,並且最後會得到一張數位結業證書,看起來真不錯!不知不覺你會迷上這種正向體驗,你會感覺到你付出的時間得到立即的反饋。兩年中,我上了不少線上課程。覺得晚上的線上課程,比起白天的程式開發還要輕鬆愉快,沒有時間壓力,不需要debug,也更容易有成就感。

但太認真的學習,是一種陷阱,特別是過度專注細節。有些程式初學者,為了想把知識完整學習。會花時間研究困難的知識點,例如想精通Recursion的各種使用方式,但實務上程式開發很少用到Recursion 。過度專注細節,是個性認真的初學者特別容易踩中的陷阱。

學習技術的目的除了吸收知識外,更重要的是要將學到的東西輸出,也就是在未來的專案中實現出來。換句話說,學習的方向與深度是根據你手上任務的需要,學太多或學得完整沒有太大的助益。我自己也有上過不少線上課程的內容,因為後來工作上沒有用到這些技術,很快就淡忘了。

所以,對初學者而言,只學有必要的知識技術就好。只要盡力理解基本觀念,並且動手將這些概念實踐出來,不用太專注在細節。

現在一樣習慣在下班時間或通勤路上學習,但已經不會堅持將一門線上課程完整練習過,而是只專注在我需要的部分。

Photo by AltumCode on Unsplash

以專案為主

進行side project,是能讓程式初學者快速成長的好方法。從一開始的專案題目發想,接著搜集資料,學習需要用到的技術,嘗試解決過程中會遇到的所有問題。雖然單純上線上課程也可以學到不少東西,但自己完成一個小專案能帶來的價值是更高的。

通常一開始會從其他人的專案開始模仿。當然重製他人專案也是好方法,當你被bug卡住時,可以有個參考範例幫你度過難關。許多市面上的線上課程,也是帶你從頭到尾製作一個完整專案。只是要確保自己並不是只把程式碼複製貼上喔。

舉幾個小專案範例:

你喜歡美食,可以嘗試做一個介紹美食的靜態網頁,從一個只有純文字的HTML開始,接著學如何放入圖片、連結,順便開始學習使用CSS調整排版,下一階段還能嘗試加入bootstrap的擴充元件來美化網頁。

若你對投資理財有興趣,可以把搜集來的股票價格放在陣列中,嘗試計算價格移動平均或波動性。接著來做一些邏輯計算,也許你認為超過某個價格就該買進,低於某個價格就該賣出,把這些判斷寫進程式碼。你或許會想說,能不能自動抓取股價呢?那麼你就會去研究爬蟲技術,甚至嘗試用資料庫來存取你的股價資訊。

我認為所有初學者都應該以專案為主,越簡單的專案越好。找一個你有興趣或著你認為有用的主題做開發。一開始不用做到60分,30分就好。先求有再求好,完成了一個簡要雛形後,再持續迭代,慢慢增加新功能。

我做的第一個專案是幫朋友寫的抽籤程式。當時使用python,引入random包,將要拿來抽籤的字串放在陣列中,使用random包裡面的choices()函式,瞧,一個簡單的專案就完成了。

過去並沒有刻意在下班後做side project的習慣,以專案為主的心態也是最近才建立起來,目前也正調整節奏,每週分配更多時間做小專案的開發。最近因為工作的關係,使用AWS的Chalice框架寫了隻遵循MVC架構的Restful API,以此為契機,在工作之餘順便學習了Flask框架,正嘗試使用Flask來架一個簡易小網站來展示機器學習模型。另外我還有出於個人興趣的線上課程學習,也希望能在課程結束後做一個簡單的side project 來實現課程中學到的技術。重點是,30分就好!

小結

對初學者來說,實踐比理論重要。

先掌握最基礎的資料結構與學會寫邏輯程式控制資料後,使用一點好奇心來發想專案題目,從一個小題目開始,接著再慢慢增加該專案的其他功能。且注意力放在專案開發必要的技術上,不要學太多。我想,這會是讓一個初學者快速成長的有效策略。

若你喜歡這篇文章,多拍兩下吧

--

--

機器學習模型建模過程中,作為訓練材料的特徵們會跟模型要預測的問題息息相關。比如著名的Kaggle房價預測,拿來做模型訓練的特徵包含有:內部坪數、房間個數、地段等等。我們還會使用特徵工程手法,一般來說是一些統計方法,從初始訓練資料中,創造對模型準確度更有益的特徵。

真實商業場域,拿來讓模型訓練的特徵,除了用特徵工程手法取得,也可能是前一個機器學習模型的輸出。或是其他程式運算的結果。

最近的專案中,需要從服飾類商品圖擷取該服飾主色系,作為下一階段模型的輸入特徵。這篇文章主要分享我怎麼從沒有頭緒到做出以下兩功能的過程:

顏色偵測:擷取商品實際顏色

色系分類:將商品實際顏色歸類到網站上的商品色系

Strategies:

首先以技術角度來理解此問題,功能的實踐分成以下四步驟:

  1. 將一張圖片(.jpg)輸入程式
  2. 程式從圖片中判斷商品主體於圖片中所在位置
  3. 擷取商品顏色
  4. 回傳結果給使用者

這隻功能主要在於步驟2. 與步驟3. 的實踐。經過一番資料蒐集與摸索嘗試。決定以Github上開源的影像去背模型(rembg )實踐步驟2.,步驟3.則是參考網路上Color Dection 的介紹文,使用K-means 來將擷取出的商品主體做分色。

調整後的開發步驟:

  1. 將一張圖片(.jpg)輸入程式
  2. 影像去背
  3. K-means 尋找商品主色碼
  4. 回傳結果給使用者

步驟2. 與步驟3. 是本篇文章主要討論的部分。

Process of Developing Color Detection(顏色偵測):

影像去背(Rembg)

  • 直接使用現成的github 開源工具 rembg 來做影像去背。
  • rembg 背後以CNN模型來做物件偵測,此模型會自動找出畫面中主體,並做切割。並不像其它模型會限定偵測特定物件(例如衣服或人臉),泛用性高,切割效果很不錯。(見下圖範例)

K-means 尋找商品主色碼

  • K-means 在機器學習中是一種非監督式的分群演算法。以下來自wiki的解釋:k-means的目的是:把 n個點(可以是樣本的一次觀察或一個實例)劃分到k個聚類中,使得每個點都屬於離他最近的均值(此即聚類中心)對應的聚類,以之作為聚類的標準。這個問題將歸結為一個把資料空間劃分為Voronoi cells的問題。
  • 首先透過去背後的圖片,我們擷取商品上每個點的RGB值,使其成為向量空間中的一個點,如下圖所示。

--

--