關於支持向量機,其原理講解不是本次博文記錄的主題,後面會用一篇文章專門記錄SVM的相關問題。這裏主要是對於天氣預測的問題,要怎樣處理數據,選取什麼核函數或模型,以及模型的調優和評估展開。這裏先貼一個 Notebook的筆記鏈接,在看完文章後可複製鏈接在瀏覽器中查看 python的詳細代碼,文中對就不贅述了。
Jupyter Notebook nbviewer 鏈接 |
---|
https://nbviewer.jupyter.org/github/lda188/my-data/blob/master/%E5%A4%A9%E6%B0%94%E9%A2%84%E6%B5%8B%EF%BC%9A2019.09.19.ipynb |
數據來源&業務需求
數據來源於Kaggle,是未經過預處理的澳大利亞天氣數據集,目標是在這個數據集上來預測明天是否會下雨。
數據初步探索
導入數據Kaggle後,並進行初步探索,我們發現該數據有142193行22列。個字段含義如下:
特徵/標籤 | 含義 |
---|---|
Date | 觀察日期 |
Location | 獲取該信息的氣象站的名稱 |
MinTemp | 以攝氏度爲單位的最低溫度 |
MaxTemp | 以攝氏度爲單位的最高溫度 |
Rainfall | 當天記錄的降雨量,單位爲mm |
Evaporation | 到早上9點之前的24小時的A級蒸發量(mm) |
Sunshine | 白日受到日照的完整小時 |
WindGustDir | 在到午夜12點前的24小時中的最強風的風向 |
WindGustSpeed | 在到午夜12點前的24小時中的最強風速(km / h) |
WindDir9am | 上午9點時的風向 |
WindDir3pm | 下午3點時的風向 |
WindSpeed9am | 上午9點之前每個十分鐘的風速的平均值(km / h) |
WindSpeed3pm | 下午3點之前每個十分鐘的風速的平均值(km / h) |
Humidity9am | 上午9點的溼度(百分比) |
Humidity3am | 下午3點的溼度(百分比) |
Pressure9am | 上午9點平均海平面上的大氣壓(hpa) |
Pressure3pm | 下午3點平均海平面上的大氣壓(hpa) |
Cloud9am | 上午9點的天空被雲層遮蔽的程度,這是以“oktas”來衡量的,這個單位記錄 了雲層遮擋天空的程度。0表示完全晴朗的天空,而8表示它完全是陰天。 |
Cloud3pm | 下午3點的天空被雲層遮蔽的程度 |
Temp9am | 上午9點的攝氏度溫度 |
Temp3pm | 下午3點的攝氏度溫度 |
RainTomorrow | 目標變量,我們的標籤:明天下雨了嗎? |
根據字段含義及數據原型,可以知道該數據是由一部分分類型數據、一部分連續型數據構成。那麼便可以根據不同的數據類型採用不同的數據處理技術。其中雲層遮蔽程度“Cloud9am”&“Cloud3pm”雖然 是以數字表示,但其本質是分類變量。且大部分特徵是採集的自然數據,如蒸發量,日照時間,等等,另外少部分特徵是人爲構成。還有一些單純表示樣本信息的變量,如採集信息的地點、採集的時間。當然,還得檢查一下樣本的不均衡問題。
知道數據的大致結構後,必須先分訓練集和測試集,再進行數據預處理。因爲測試集在現實中往往是(或者被假設爲是)不可獲得的。追求實用的我們不希望建模的任何過程受到測試集數據的影響,否則的話,就相當於提前告訴了模型一部分預測的答案。所以 採取了現實中所使用的這種方式:先分訓練集和測試集,再逐步進行預處理。這樣導致的結果是,我們對訓練集執行的所有操作,都必須對測試集執行一次,工作量是翻倍的(不過是值得的)。
數據探索&預處理
數據預處理需要逐步展開,本次大致有一下幾步(同時在訓練集測試集操作):
第一步
先對數據進行分離,包括分離特徵矩陣和標籤矩陣,訓練集與測試集的拆分,(拆分後的數據集要重置索引)拆分結果如下:
符號 | 含義 |
---|---|
X | 特徵數據 |
Y | 標籤數據 |
X_train | 訓練特徵數據 |
Y_train | 訓練標籤數據 |
X_test | 測試特徵數據 |
Y_test | 測試標籤數據 |
第二步
樣本均衡性檢查。對標籤數據(測試訓練同步)進行編碼處理。
編碼前 | 編碼後 |
---|---|
NO | 0 |
Yes | 1 |
第三步
數據的異常值檢查與處理,通常超過變量3倍標準差的數據被認爲是異常值。異常值比例<10%的時候,通常做刪除處理。刪除異常值後要重置個數據集的索引。
第四步
對於日期和當日下雨量兩個變量對明天是否下雨的影響是不定的,可以將其處理後保留:
處理前變量名 | 處理後變量名 | 處理後值 |
---|---|---|
Date | Mounth | 1,2,……12. |
Rainfall | Raintody | Yes|No |
第五步
對於缺失值,分類變量的缺失值處理一般用衆數填充,連續型變量一般用均值填充。這裏要注意一定要將分類數據和連續型數據區分開。
第六步
前面解決了數據缺失值問題和異常值問題後,數據基本上是完整的,這裏再次進行數據缺失的檢驗。之後,需要將分類變量進行編碼處理。然後對連續型數據做標準化處理。
第七步
數據預處理完成後,一定記得將整理好的乾淨數據導出。
模型探索
建模選擇自然是我們的支持向量機SVM,先用核函數的學習曲線來選擇核函數 。我們希望同時觀察精確性,recall以及AUC分數 。因爲SVM是計算量很大的模型,所以我們需要時刻監控我們的模型運行時間。
SVM有四個核函數:“linear”,“poly”,“rbf”,“sigmoid”。那麼,核函數的選擇可能成爲模型優化的一個方向。下面截圖是四個函數的建模耗時:
我們注意到,模型的準確度和auc面積還是勉勉強強,但是每個核函數下的recall都不太高。相比之 下,其實線性模型的效果是最好的。那現在我們可以開始考慮了,在這種狀況下,我們要向着什麼方向 進行調參呢?我們最想要的是什麼?
我們可以有不同的目標:
一,我希望不計一切代價判斷出少數類,得到最高的recall。 二,我們希望追求最高的預測準確率,一切目的都是爲了讓accuracy更高,我們不在意recall或者 AUC。
三,我們希望達到recall,ROC和accuracy之間的平衡,不追求任何一個也不犧牲任何一個。
如果我們希望模型的recall指標高一些。那麼,SVM的class_weight參數可能成爲模型優化的一個方向。下面截圖是class_weight = "balanced"的建模耗時:
隨着recall地無節制上升,我們的精確度下降得十分厲害,不過看起來AUC面積卻還好,穩定保持在 0.86左右。如果此時我們的目的就是追求一個比較高的AUC分數和比較好的recall,那我們的模型此時 就算是很不錯了。雖然現在,我們的精確度很低,但是我們的確精準地捕捉出了每一個雨天。
我們來調節線性核函數的C值,試試能否有效果:
首先,我們注意到,隨着C值逐漸增大,模型的運行速度變得越來越慢。對於SVM這個本來運行就不 快的模型來說,巨大的C值會是一個比較危險的消耗。所以正常來說,我們應該設定一個較小的C值範圍 來進行調整。
其次,C很小的時候,模型的各項指標都很低,但當C到1以上之後,模型的表現開始逐漸穩定,在C 逐漸變大之後,模型的效果並沒有顯著地提高。可以認爲我們設定的C值範圍太大了,然而再繼續增大 或者縮小C值的範圍,AUC面積也只能夠在0.86上下進行變化了,調節C值不能夠讓模型的任何指標實現 質變。
如果我們追求平衡,也就是模型的各項指標都過得去,那SVM本身的結果就已經非常接近最 優結果了。調節閾值,調節參數C和調節class_weight都不一定有效果。但整體來看,我們的模型不是 一個糟糕的模型,但這個結果如果提交到kaggle參加比賽是絕對不足夠的。
顯然,還可以更加深入地探索模型,或者換別的方法來處理特徵,以達到AUC面積0.9以上,或是準確度或recall都提升 到90%以上。至於支持向量機對天氣預測的準確率高低要看人爲主觀的容忍度,也可能會有其他模型的調參使得該模型對天氣的預測優於支持向量機。