周志华《机器学习》习题3.4——用UCI数据集比较10折交叉验证法和留一法
1.題目
選擇兩個 UCI 數據集,比較 10 折交叉驗證法和留一法所估計出的對率回歸的錯誤率。(本文就對一個UCI數據集用兩種評估方法實現了,畢竟再對另一個數據集的實現方法是一樣的)
2.下載UCI數據集
導入數據集的方法有很多,可以直接從官網下載數據集文件,也從keras庫里直接導入,本文使用第一種方法。
首先,進入UCI官網:https://archive.ics.uci.edu/ml/
在UCI主頁下的 Most Popular Data Sets 能看見由很多常用數據集,包含最常用的鳶(yuan)尾花、酒、車等等,本文就使用最經典的鳶尾花了。
點擊IRIS圖標進入鳶尾花數據集頁面:
這里表格包含了一些比較重要的信息:
同時,下方包含了對屬性和類別的說明。
像該數據集,用于分類任務,包含150條數據,每條數據含有4個屬性,不存在數據缺失,擁有3個類別(也就是多分類任務)。
確認數據集是我們想要的后,點擊Data Folder進入數據的文件目錄。
然后,點擊iris.data下載該數據集文件。
打開下載后的文件,可以看到,每條數據(對應每朵花)占一行,每行包含用逗號隔開的4個數字和1個字符串,每個數字對應一朵花的對應屬性值,字符串表示該條數據屬于的類別。
3.實現思路
3.1 評估方法
本題需要實現兩種評估算法,分別為10折交叉驗證和留一法。
首先,對于10折交叉驗證,其思想是將數據集劃分為10份(劃幾份就是幾折),然后任取1份做測試集,另取9份做訓練集,根據排列組合可知有10種取法,然后,對于每種取法,對學習器(本文使用對率回歸模型)進行訓練,然后用測試集測試,10輪后能得到10個正確率(注意每輪訓練都是重新訓練,也就是說,一共要訓練和測試10次),最后將10個正確率取平均值當作最后該模型的正確率。
然后,對于留一法,簡單來說就是m折交叉認證(m等于數據實例數),對于該數據集就是150折交叉驗證,每輪留1個做測試集,其余149個做訓練集,最后會得到150個準確率(當然,不是100%就是0%),然后取平均值作為模型正確率。
3.2 多分類方法
對于線性模型,多分類任務一般使用拆分策略,即將任務差分為多個二分類任務,拆分策略包括一對一(OvO)、一對多(OvR)和多對多(MvM)。本文將會使用OvR實現多分類。
這里講一下OvO,該策略會將任務中的多個類別兩兩組合,然后對于每個組合,將其看作一個二分類任務(例如本題有3個類,有3種組合方法,需要訓練三個二分類學習器),訓練完成后,在預測時,只需要將測試實例輸入到這些二分類學習器中,最后統計哪個類別結果多即可。
OvR則是將任務中的多個類別按照“一個類是正類,其余類都是負類”的規則劃分,例如本例中包含三個花的類別:Iris-setosa、Iris-versicolor、Iris-virginica,先將Iris-setosa視為正例,然后將Iris-versicolor、Iris-virginica視為反例,這樣就會形成一個二分類學習器,然后同理能一共得到三個二分類學習器,在預測時,只需要將測試實例分別輸入到三個學習器中,觀察三個學習器的結果,然后看哪個學習器輸出正例,則認為該實例屬于對應類別。而對于MvM,由于這里只有3個類別,使用MvM也會退化成OvR,所以無需使用了。
4. python實現
(1)讀取數據集
將數據集文件按照行依次讀取,每行按逗號分割,然后將用于表示類別的字符串轉換為數字(三個類對應數字1,2,3)。
(2) 二分類實現
實現多分類學習器前,先要實現二分類學習器,本文使用對率回歸模型,對對率回歸的損失函數進行梯度下降,其中對率回歸的損失函數為:
l(β)=∑i=1m[?yiβTx^i+ln?(eβTx^i+1)]\boldsymbol{l{}}(\boldsymbol{\beta}) = \sum_{i=1}^{m}[-y_{i}\beta^{T}\widehat{x}_{i}+\ln(e^{\beta^{T}\widehat{x}_{i}}+1)]l(β)=i=1∑m?[?yi?βTxi?+ln(eβTxi?+1)]
梯度下降公式為:
βt+1=βt?s?l(β)?β\boldsymbol{\beta} ^{t+1}=\boldsymbol{\beta} ^{t}-s\frac{\partial \boldsymbol{l{}}(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} βt+1=βt?s?β?l(β)?
按照上述公式實現梯度下降即可。然后說一下超參數,這里對beta設置初始值為全1,d表示收斂的界限,就是當beta在下降過程中如果不超過0.01則表示已經收斂,就不用繼續下降了,alpha表示步長(對應公式的s),n表示最大下降次數。這些值設置可以相對隨意,然后經過測試可以找到一個比較好的參數,本文就測試了6、7次,按照最高正確率選出的參數。
(3)三分類學習器
二分類實現完,就可以實現三分類了,主要就是把y,也就是標簽處理一下,這里第一個循環用于將1類看為正類,2、3類分為反類,以此類推,第二個循環是,2正,1、3反,第三個循環是,3正,1,2反。
(4)10折交叉驗證
這里為了實現每折數據的類別比例都是1:1:1,將數據集先按照類別分開,然后在各自打亂,最后再分成10部分,取9部分訓練1部分測試。
(5)留一法
留一法與上面交叉驗證一樣,區別在于只留一個進行測試,所以要進行150次訓練測試,運行時間會長一些。
(6)其他函數
# sigmoid函數 def sigmoid(x):if x<-500:x = -500return 1 / (1 + math.exp(-x))# 判斷兩個浮點是是否相同 def float_equal(a, b):delta = a-bif delta > -1e-5 and delta < 1e-5:return Trueelse:return False# 預測 def predict(beta, x):y = 0for i in range(len(x)):y += x[i] * beta[i]y += beta[len(x)]return sigmoid(y)# 測試 def test(beta1, beta2, beta3, test_x, test_y):right = 0for i in range(len(test_x)):y1 = predict(beta1, test_x[i])y2 = predict(beta2, test_x[i])y3 = predict(beta3, test_x[i])if y1 >= 0.5 and test_y[i] == 1:right += 1elif y2 >= 0.5 and test_y[i] == 2:right += 1elif y3 >= 0.5 and test_y[i] == 3:right += 1r_rate = right/len(test_x)print("測試樣例總數:", len(test_x))print("通過樣例數:", right)print("正確率為:", r_rate)return r_rate(7)主程序
if __name__ == "__main__":x,y = read_uci("./iris.data")cv10_devide_test(x, y)cv1_devide_test(x, y)7. 結果
10折交叉驗證結果:
留一法運行結果:
10折交叉驗證準確率是86%,留一法是84%,但不代表交叉驗證要好,因為在測試運行過程中,該程序的準確率是有浮動的,比如說前幾次交叉驗證會經常出現81%左右的結果,由于留一法需要運行時間比較長,我就只運行了一次。
所以如果要想得到嚴謹的比較結果,就可以多運行幾個結果,然后再進行比較。
總結
以上是生活随笔為你收集整理的周志华《机器学习》习题3.4——用UCI数据集比较10折交叉验证法和留一法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NAT(网络地址转换)技术与代理服务器原
- 下一篇: 联通沃商店游戏中心接入规范(2014新版