機器學習專案完整流程
機器學習專案的完整流程
1 模型抽象
對於實際生活中的複雜事物來說,如果要使用機器學習方法來解決,對實際問題進行建模,將其抽象為數學問題是首要的工作。下面舉幾個簡單例子
預測本地明天的天氣
首先你需要利用生活常識和收集資料得到的專業知識,知道可能會對天氣有影響的因素;然後去收集資料,明確自己的目的。是想使用過去的天氣情況來預測明天的氣溫範圍呢,還是單純的想知道明天會不會下雨,會不會有霧霾。根據你的目標不同,前者是迴歸問題,而後者是分類問題。
決定要不要購買一件商品
首先你可能會檢視店鋪評分,判斷這是不是一家靠譜的店鋪;其次可能會檢視一些商品資訊,如品牌、商品的成交量、價格、評論、實物圖等等。這裡所有你可以蒐集到的資訊都可以作為是否購買這件商品的參考,同樣的這是一個分類問題。
簡而言之,在這個階段我們應該充分發掘複雜場景的內容,充分明確我們的目標。
2 資料處理
2.1 資料採集
- 選擇對最後結果預測有幫助的資訊:需要思考哪些資料有用
- 需要消除掉線下可以使用但是線上實時採集不到的資訊,如地理位置
- 考慮一些基於統計的需要耗時計算的資訊
- 例子:商品推薦,需要採集店家、商品、使用者(埋點)資訊
2.2 資料格式化
2.2.1 確定儲存格式
- 時間使用年月日or時間戳or第幾天or…
- 單個行為動作or一天行為聚合
- 其他
2.2.2 資料檔案關聯
- 大多數情況下,需要關聯非常多的
hive
表和叢集(如HDFS
)檔案
2.3 資料清洗
2.3.1 主要做的工作:去掉髒資料
資料和特徵決定了機器學習結果的上限,而演算法只是儘可能逼近這個上限。
2.3.2 示例、思考角度
- 違背常識的資料
- 組合或統計屬性判定:多個特徵之間相互矛盾的資料
- 補齊可對應的預設值:丟掉不可信的資料,預設值極多的欄位考慮不使用
2.4 資料取樣
大多數模型對於樣本分佈(如二分類任務中的正負樣本分佈)比較敏感,如LR、NN比較敏感,而基於樹的模型不是很敏感。當我們要處理海量資料時,一般沒有時間和精力在所有的資料上面進行特徵提取、模型訓練、尋找超引數等,需要對資料進行取樣處理。對原始資料集劃分為訓練集和測試集的過程也是一種資料取樣操作。
2.4.1 隨機取樣
可能會破壞掉原來資料中存在的結構(如性別比例等)
2.4.2 分層抽樣
在保持資料原有結構(如性別比例等)的情況下,進行取樣
2.4.3 正負樣本不平衡的處理辦法
這裡我們認為正樣本數量少,負樣本數量多,差距在一個數量級以上
2.4.3.1 情景
- 廣告點選率估計
- 商品購買率估計
- 是否患病估計
2.4.3.2 處理辦法
-
正負樣本資料量都很大的情況下:
下采樣(隨機取樣、分層抽樣)
-
正負樣本資料量都很小的情況下:
- 採集更多的資料
- 上取樣,資料增強,如對於影象的映象和旋轉
- 修改損失函式,使不同類別佔有的權重不同,引申為代價敏感學習
-
改變正負樣本權重
lightGBM
、xgboost
的模型中可以進行相關設定(balanced
,scale_pos_weight
)
3 特徵提取和特徵選擇
3.1 特徵工程的意義
特徵是指從資料中抽取出來的對預測結果有用的資訊
特徵工程指使用專業背景知識和技巧處理資料,使得特徵能夠在機器學習演算法中發揮更好作用地過程。更好地特徵意味著模型更高的上限,意味著使用簡單的模型就能達到好的效果,意味著更強的靈活度。
對於工業界來說,大部分複雜模型的演算法精進都是資深的資料科學家的任務,大部分人員的工作還是跑資料、map-reduce
,hive SQL
,資料倉庫搬磚,做一些業務分析、資料清洗、特徵工程(找特徵)的工作。
特徵工程的作用也很明顯,對於搜尋引擎廠、廣告部門、電商的商品推薦,阿里天池比賽經常出現上萬維的交叉特徵。
3.2 特徵處理
3.2.1 數值型特徵
- 二值化:根據給定的閾值threshold將特徵值變為0和1
>>> from sklearn.preprocessing import Binarizer
>>> X = [[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]]
>>> transformer = Binarizer().fit(X) # fit does nothing.
>>> transformer
Binarizer(copy=True, threshold=0.0)
>>> transformer.transform(X)
array([[1., 0., 1.],
[1., 0., 0.],
[0., 1., 0.]])
- 最大最小化:Transforms features by scaling each feature to a given range,幅度調整到給定的範圍內,預設範圍為(0,1),變換按照下式計算,其中(min,max)是給定的range。
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min
example:
>>> from sklearn.preprocessing import MinMaxScaler
>>>
>>> data = [[-1, 2],
... [-0.5, 6],
... [0, 10],
... [1, 18]]
>>> scaler = MinMaxScaler()
>>> print(scaler.fit(data))
MinMaxScaler(copy=True, feature_range=(0, 1))
>>> print(scaler.data_max_)
[ 1. 18.]
>>> print(scaler.transform(data))
[[0. 0. ]
[0.25 0.25]
[0.5 0.5 ]
[1. 1. ]]
>>> print(scaler.transform([[2, 2]]))
[[1.5 0. ]]
-
歸一化:均值為0,方差為1
-
標準化:
-
log、exp等變化:針對長尾分佈,將其轉換為類正態分佈
-
統計值max、min、mean、std:如考慮日最高氣溫、日最低氣溫來決定是否開空調
-
連續數值離散化:對於如使用者年齡、商品價格等離散化。等步長劃分:簡單、線上線下沒有區別。等頻劃分(等分位數、等樣本數),如min,25%,50%,75%,max:精準,線上應用時需要重新計算
-
hash分桶:如判斷新聞主題的時候,統計每句話中含有的政治、經濟、體育詞庫中詞的個數
-
每個類別下對應的變數統計值histohistogram(分佈狀況):如分別統計男生和女生對於所有愛好的比例,將其作為男生和女生的直方圖對映,如男:
[1/3,2/3,0]
,女:[1/3,0,2/3]
-
轉換為類別型
3.2.2 類別型特徵
- one-hot編碼:呼叫
sklearn.one-hot_encoder()
,對於user id
等數量很大的特徵,會先根據其歷史購物行為進行聚類,再按照其cluster id
進行one-hot編碼 - 啞編碼:與one-hot編碼相同,呼叫
pandas.get_dummies()
- hash與聚類處理:hash技巧,對文字分桶,記錄每個樣本含有的每個類別的詞的個數
- 直方圖對映:統計每個類別變數下各個target的比例,轉成數值型
3.2.3 時間類特徵
- 時間類特徵既可以看做連續值,也可以看做離散值
- 對於連續值來說,有持續時間,如使用者瀏覽一家商戶的時間;有間隔時間,如使用者上次登入(購買、點選等行為)距現在的時間
- 對於離散值來說,有如下特徵:一天中的哪個時間段、一週中的第幾天、一年中的第幾周、一年中的第幾個月、一年中的第幾個季度、工作日or週末、節假日or促銷節
3.2.4 文字型特徵
- 詞袋(word bag):指對於文字資料預處理後,去掉停用詞,剩下的片語成的list,在詞庫中對映的稀疏向量
- n元詞袋:將詞袋中的詞擴充套件到n-gram,分詞後相鄰的n個詞也進入詞袋
- TF-idf特徵:一種用來評估一個字詞對於一個檔案集或一個語料庫中的一份檔案的重要程度的統計方法。字詞的重要性與它在檔案中出現的次數成正比,與它在語料庫中出現的頻率成反比。TF(Term freqiency),
TF(t)=詞t在當前文中出現的次數/詞t在全部文件中出現的次數
,IDF(t)=ln(總文件數/含t的文件數)
,TF-IDF權重=TF(t)*IDF(t)
word2vec
:現有的工具有Google word2vec
、gensim
3.2.5 統計特徵
歷屆kaggle、天池比賽,天貓、京東排序和推薦業務線裡模型用到的特徵:
- 加減平均:如商品價格高於平均價格多少,使用者在某個品類下的消費超過平均水平多少,商戶評分超過平均評分多少
- 分位數:商品屬於售出商品價格的多少分位線處
- 次序型:商品銷量排在同品類商品的第幾位
- 比例型:電商中好、中、差評的比例
3.2.6 組合特徵
- 簡單組合特徵:拼接型,
user clustered id && category
,user clustered id && clothes style
- 模型特徵組合GBDT+LR:最早Facebook使用的方式,多家網際網路公司再用。gbdt訓練模型,從根節點到葉子結點的每一條路徑看做一個組合特徵,組合特徵和原有特徵一起放進LR訓練
3.3 特徵選擇
- 原因:1.冗餘:部分特徵的相關度太高,消耗計算效能;2.噪聲:部分特徵對預測結果無影響或有負影響
- 特徵選擇vs降維:特徵選擇只踢掉原本特徵中和結果預測關係不大的,後者做特徵的計算組合構成新特徵;SVD或PCA也能解決一定的高維度問題
- 良好的資料要能夠提取出良好的特徵才能真正發揮效力。
3.3.1 filter過濾型
- 評估單個特徵和結果值之間的相關程度,排序留下top相關的特徵部分
- 可能對線性模型有用
- pearson相關係數、互資訊、距離相關度
- 缺點:沒有考慮到特徵之間的關聯作用,可能把有用的關聯特徵誤踢掉
3.3.2 wrapper包裹型
- 把特徵選擇看做一個特徵子集搜尋問題,篩選各種特徵子集,用模型評估效果
- 典型的包裹型演算法:遞迴特徵刪除演算法,recursive feature elimination algorithm,RFE
- 舉個例子:如邏輯迴歸,1.用全量特徵跑一個模型;2.根據線性模型的係數(體現相關性),刪掉5%-10%的弱特徵,觀察準確率的變化;3.逐步進行,直至準確率出現大的下滑停止
3.3.3 embedded嵌入型
- 根據模型來分析特徵的重要性
- 最常見的方式是用正則化做特徵選擇
- 最早在電商用LR作CTR預估,在3-5億維的係數特徵上用L1正則化的LR模型,剩餘2-3千萬的feature,意味著其他的feature重要度不夠
- L1正則化,截斷型效應,不重要的特徵權重會變為0
- L2正則化,縮放效應,特徵權重只會縮小
總結
- 特徵預處理、資料清洗是很關鍵的步驟,往往能夠使得演算法的效果和效能得到顯著提高。歸一化、離散化、因子化、缺失值處理、去除共線性等,資料探勘過程中很多時間就花在它們上面。這些工作簡單可複製,收益穩定可預期,是機器學習的基礎必備步驟。
篩選出顯著特徵、摒棄非顯著特徵,需要機器學習工程師反覆理解業務。這對很多結果有決定性的影響。特徵選擇好了,非常簡單的演算法也能得出良好、穩定的結果。這需要運用特徵有效性分析的相關技術,如相關係數、卡方檢驗、平均互資訊、條件熵、後驗概率、邏輯迴歸權重等方法。
4 訓練模型與調優
4.1 模型選擇
- 廣義的模型選擇:sklearn algorithm cheat-sheet
- 超引數選擇:交叉驗證,k折交叉驗證
4.2 模型訓練
直到這一步才用到我們上面說的演算法進行訓練。現在很多演算法都能夠封裝成黑盒供人使用。但是真正考驗水平的是調整這些演算法的超引數,使得結果變得更加優良。這需要我們對演算法的原理有深入的理解。理解越深入,就越能發現問題的癥結,提出良好的調優方案。
5 模型診斷
如何確定模型調優的方向與思路呢?這就需要對模型進行診斷的技術。
5.1 模型狀態判斷
過擬合、欠擬合判斷是模型診斷中至關重要的一步。常見的方法如交叉驗證,繪製學習曲線(如同時繪製訓練資料和驗證資料的損失,觀察其變化情況)等。過擬合的基本調優思路是增加資料量,降低模型複雜度(如進行特徵選擇)。欠擬合的基本調優思路是提高特徵數量和質量,增加模型複雜度。
5.2 特徵重要性分析
5.3 bad-case分析
誤差分析也是機器學習至關重要的步驟。通過觀察誤差樣本,全面分析誤差產生誤差的原因:是引數的問題還是演算法選擇的問題,是特徵的問題還是資料本身的問題……
診斷後的模型需要進行調優,調優後的新模型需要重新進行診斷,這是一個反覆迭代不斷逼近的過程,需要不斷地嘗試, 進而達到最優狀態。
6 模型融合
一般來說,模型融合後都能使得效果有一定提升,而且效果很好。
工程上,主要提升演算法準確度的方法是分別在模型的前端(特徵清洗和預處理,不同的取樣模式)與後端(模型融合)上下功夫。因為他們比較標準可複製,效果比較穩定。而直接調參的工作不會很多,畢竟大量資料訓練起來太慢了,而且效果難以保證。
7 上線執行
這一部分內容主要跟工程實現的相關性比較大。工程上是結果導向,模型在線上執行的效果直接決定模型的成敗。 不單純包括其準確程度、誤差等情況,還包括其執行的速度(時間複雜度)、資源消耗程度(空間複雜度)、穩定性是否可接受。
這些工作流程主要是工程實踐上總結出的一些經驗。並不是每個專案都包含完整的一個流程。這裡的部分只是一個指導性的說明,只有大家自己多實踐,多積累專案經驗,才會有自己更深刻的認識。
後記
後面會整理資料處理、特徵處理的例子,加入到文章中