【玩點有趣的】這幾篇SVM介紹是從0到1慢慢學會支持向量機,將是滿滿的乾貨,都是我親自寫的,可以隨我一起從頭瞭解SVM,並在短期內能使用SVM做到想要的分類或者預測~我也將附上自己基礎訓練的完整代碼,可以直接跑,建議同我一樣初學者們,自己從頭到尾打一遍,找找手感,代碼不能光看看,實踐出真知!
回顧一下,上上篇,我們建立和比較了線性分類器和非線性分類器,比較了多元線性核函數和線性核函數,解決了類型數量不平衡問題,上篇,我們使用SVC做了簡單的分類,話不多說,今天我們開始SVR做迴歸預測,原理篇和實戰基礎一 請參見上幾篇博客,我們循序漸進慢慢貼近真實情景!解決生活問題
估算交通流量
首先做一個比較有趣的應用,我們使用了SVR來預測:在洛杉磯棒球隊進行主場比賽期間,體育場周邊馬路通過的汽車數量
如圖:
這裏一萬七千條記錄數據,分別表示:星期,時間,對手球隊名,比賽是否正在進行,通過汽車的數量
【完整代碼】上代碼:
import numpy as np
from sklearn import preprocessing
from sklearn.svm import SVR
input_file = 'traffic_data.txt'
X = []
count = 0
with open(input_file, 'r') as f:
for line in f.readlines():
data = line[:-1].split(',')
X.append(data)
X = np.array(X)
label_encoder = []
X_encoded = np.empty(X.shape)
for i, item in enumerate(X[0]):
if item.isdigit():
X_encoded[:, i] = X[:, i]
else:
label_encoder.append(preprocessing.LabelEncoder())
X_encoded[:, i] = label_encoder[-1].fit_transform(X[:, i])
X = X_encoded[:, :-1].astype(int)
y = X_encoded[:, -1].astype(int)
params = {'kernel': 'rbf', 'C': 10.0, 'epsilon': 0.2}
regressor = SVR(**params)
regressor.fit(X, y)
import sklearn.metrics as sm
y_pred = regressor.predict(X)
print("Mean absolute error =", round(sm.mean_absolute_error(y, y_pred), 2))
print('mean squared error=',round(sm.mean_squared_error(y, y_pred),2))
print('median absolute error=',round(sm.median_absolute_error(y, y_pred),2))
print('explained variance score=',round(sm.explained_variance_score(y, y_pred),2))
print('R2 score=',round(sm.r2_score(y, y_pred),2))
input_data = ['Tuesday', '13:35', 'San Francisco', 'yes']
input_data_encoded = [-1] * len(input_data)
count = 0
for i, item in enumerate(input_data):
if item.isdigit():
input_data_encoded[i] = int(input_data[i])
else:
input_data_encoded[i] = int(label_encoder[count].transform([input_data[i]]))
count = count + 1
input_data_encoded = np.array(input_data_encoded)
print("Predicted traffic:", int(regressor.predict([input_data_encoded])[0]))
解說一下:
X = []
count = 0
with open(input_file, 'r') as f:
for line in f.readlines():
data = line[:-1].split(',')
X.append(data)
X = np.array(X)
使用文件操作逐行讀取並使用spilt通過逗號分割得出最後一列的數據(汽車通行量)append進到數組X中,構成我們的初始數據, 再通過sklearn.preprocessing.LabelEncoder()進行標準化標籤,將標籤值統一轉換成range(標籤值個數-1)範圍內 ,最後使用fit_transform(X[:, i])進行fit和transform轉換成計算機可讀的數字(矩陣)形式:
【數據預處理】代碼如下
label_encoder = []
X_encoded = np.empty(X.shape)
for i, item in enumerate(X[0]):
if item.isdigit():
X_encoded[:, i] = X[:, i]
else:
label_encoder.append(preprocessing.LabelEncoder())
X_encoded[:, i] = label_encoder[-1].fit_transform(X[:, i])
print('標準化操作(數據預處理)\n', X_encoded)
X = X_encoded[:, :-1].astype(int)
y = X_encoded[:, -1].astype(int)
print('影響結果的各個維度:\n', X)
print('Label:\n', y)
看看結果:
可以看出:每行每列,帶有英文的字符也被清洗成了數字,這其中是有邏輯含義的,可以用過查看源碼明白。同樣的也可以通過Pandas實現上述操作。然後我們使用切片操作分割出label和X
後續就是使用SVR構建預測器,然後“餵它數據”:
params = {'kernel': 'rbf', 'C': 10.0, 'epsilon': 0.2}
regressor = SVR(**params)
regressor.fit(X, y)
import sklearn.metrics as sm
y_pred = regressor.predict(X)
print("Mean absolute error =", round(sm.mean_absolute_error(y, y_pred), 2))
print('mean squared error=',round(sm.mean_squared_error(y, y_pred),2))
print('median absolute error=',round(sm.median_absolute_error(y, y_pred),2))
print('explained variance score=',round(sm.explained_variance_score(y, y_pred),2))
print('R2 score=',round(sm.r2_score(y, y_pred),2))
input_data = ['Tuesday', '13:35', 'San Francisco', 'yes']
input_data_encoded = [-1] * len(input_data)
count = 0
for i, item in enumerate(input_data):
if item.isdigit():
input_data_encoded[i] = int(input_data[i])
else:
input_data_encoded[i] = int(label_encoder[count].transform([input_data[i]]))
count = count + 1
input_data_encoded = np.array(input_data_encoded)
print("Predicted traffic:", int(regressor.predict([input_data_encoded])[0]))
最後我們直接看結果
這是這個情況下的預測汽車數量,[‘Tuesday’, ‘13:35’, ‘San Francisco’, ‘yes’] Predicted traffic =29
[‘Thursday’, ‘23:10’, ‘Arizona’, ‘no’]下: Predicted traffic =14
我們來看一下這幾個判別情況:
Mean absolute error =7.28
mean squared error= 106.94
median absolute error= 4.91
explained variance score= 0.47
R2 score= 0.47
介紹一下:
建立迴歸器後,需要建立評價迴歸器擬合效果的指標模型。
平均誤差(mean absolute error):這是給定數據集的所有數據點的絕對誤差平均值
均方誤差(mean squared error):給定數據集的所有數據點的誤差的平方的平均值,最流行
中位數絕對誤差(mean absolute error):給定數據集的所有數據點的誤差的中位數,可以消除異常值的干擾
解釋方差分(explained variance score):用於衡量我們的模型對數據集波動的解釋能力,如果得分爲1.0,表明我們的模型是完美的。
R方得分(R2 score):讀作R方,指確定性相關係數,用於衡量模型對未知樣本預測的效果,最好的得分爲1.0,值也可以是負數。
通常情況下,儘量保證均方誤差最低,而且解釋方差分最高。
可以看到,我們使用的這個SVR迴歸器不是那麼完美,甚至誤差有一些。
昨天也跟朋友有提高過:
機器學習算法和平常的數據結構與算法的區別:通俗的說,前者注重accuracy,recall,precision,F1_score,後者注重時間複雜度和空間複雜度,
那麼我們的SVR迴歸器的這個誤差當然是難以容忍的,我們來分析一下原因:
一:參數誤差:沒有通過網格搜索或者k折交叉驗證,貝葉斯優化調整超參數,svr的參數誤差很大,不同的參數,差別十萬八千里。
二:原始數據標準化過程:transform問題,或者未歸一化,
三:SVR容易欠擬合
這些都是待改進問題。
下面我們比較一下常用的迴歸與分類算法:
(資料來源百度,後期我們會把常用的算法介紹,並且實戰(實戰是理論的體現,兩者結合纔會綻放絢麗光芒))
一、樸素貝葉斯
- 優點:小規模表現好,適合分類任務,適合增量訓練。
- 缺點:對輸入形式敏感(數值型可以考慮二分?),很多時候要拉普拉斯平滑。
二、決策樹
- 優點:計算簡單,可解釋型強,能處理缺失值,不相關特徵,能多分類。可以設計爲迴歸模型。
- 缺點:過擬合問題(預剪枝、後剪枝)。RF可以解決一些,因爲對數據樣本的bagging加上對特徵的隨機選擇(比如選 n**0.5個特徵)引入了隨機,減小了過擬合。
三、logistic
- 優點:實現簡單,速度快,存儲小。
- 缺點:容易欠擬合,只能二分類(改進,1v1,1v多,多v多),對outlier比較敏感,不支持非線性劃分。
四、線性擬合(LSM/Ridge/Lasso)
- 優點:實現簡單,計算簡單(close form,閉式解)。
- 缺點:不能擬合非線性數據。
五、kNN
- 優點:思路簡單(近朱者赤),理論成熟,可分類可迴歸,可非線性,對outlier不敏感。
- 缺點:計算量大,樣本不平衡,大內存開銷。
- 注:其實是免訓練的模型。也算優點吧。
六、SVM
- 優點:可用於線性/非線性(核:高斯核、多項式核、字符串核、RBF、Logistic核),可以用於迴歸SVR,低泛化誤差,易解釋性,抗數據擾動(outlier),存儲小(支持向量)。
- 缺點:需要手動選參數,選核函數,原始的SVM是二分類。
七、Adaboost
- 優點:低泛化誤差,易實現,準確率高,參數少,多分類。降低偏差bias(預測與實際的差)。
- 缺點:對outlier敏感(因爲會調誤分類權重),不能並行。
- 注:和GBM(GBRT/GBDT)都是boosting,不同在於權重調整一個根據誤分類數據,一個根據梯度。
八、Random Forest
- 優點:處理高維數據不用做特徵選擇;能給出特徵重要比;oob,使用無偏估計,泛化能力強;樹之間獨立,可並行,因而訓練快;不平衡數據可以平衡誤差;一部分特徵遺失仍然可以有精確度。不用剪枝。減低方差variance(數據擾動產生的不同結果)。
- 缺點:在某些噪音較大的分類或者回歸問題上過擬合;對於不同取值的屬性的數據,取值劃分較多的屬性會對RF產生更大的影響,導致權值不可信。
九、xgboost
- 基分類器除CART外還支持線性分類器,相當於LR、Ridge。
- GBDT用一階,xgboost用一階和二階進行梯度優化。
- 代價函數裏有L1和L2正則,控制複雜度減小過擬合。
- shrinkage可以設置學習速率。
- 借鑑了RF的列抽樣(選一些特徵),引入隨機(深度學習的dropout也是引入了隨機),降低過擬合,減少計算。
- 缺失值的樣本也可以自動學習分裂方向。
- 支持並行,不是tree粒度的,而是特徵粒度的。
- 可並行的近似直方圖算法,高效生成候選的分割點。
十、k-means(屬於EM思想)
-
優點:簡單快速,團狀效果好,O(nkt),通常局部收斂
-
缺點:需要指定k,初始值敏感,需要指定距離定義/中心定義,數據形狀敏感(比如密度形狀的用DBSCAN,比如流形學習),對outlier敏感。
下一期我們先做一個真實項目實戰,後續我們遇到SVM問題,再繼續補充
這是我們的SVM第四期文章了,已經大致明白了他的原理和基本用法,我們使用了sklearn對SVM的封裝,也使用了numpy對SVM的復現,還可以使用libsvm和opencv對svm的封裝。接下來我們結合計算機視覺做有趣的實驗,先賣個關子(關注博主,下期繼續),上圖!
這是幫朋友做的畢業設計,其中有一些bug需要修復,一些問題,需要優化,並且,代碼不是我寫的,朋友給我的。我幫助他跑起來,並且現在開始幫助他修改,優化代碼,學C++,推薦算法去了,關注博主,敬請期待!
上海第二工業大學智能科學與技術大二 周小夏(CV調包俠)