1.環境搭建以及前置條件
- 1.前置環境:
- 1.mac
- 2.pycharm
- 3.python3
- 4.Anaconda
- 2.環境搭建:
- 3.前置知識:numpy、python、SciPy基礎學習, 教程
2.SVM知識了解
假設我們有一個訓練圖檔集10000*3072,也就是10000張像素為3072的圖檔,有一個測試圖檔集的圖檔100*3072,測試和訓練圖檔集總共的圖檔類型有10種(這裡圖檔類型指的是圖檔内容的類型,如:圖檔内容為貓、狗等)。我們将某一張訓練圖檔命名為Tn,将一張測試圖檔命名為Cm,将一個圖檔的類型命名為La。
1.SVM是什麼
- 1.我們定義一個函數為f(Cm,W)=W*Cm,在這裡W為一個3072*10的矩陣。最終這個函數的結果是一個大小為10的數組,這裡數組中的每個數字就是Cm這張圖檔在每個La下的得分,分數最高的La就表示我們預測這張測試圖檔是這種圖檔類型。
- 2.從1中我們可以知道要讓我們的預測準确率高,那麼W就需要找準。我們有很多方法來尋找一個好的W
- 1.随機法:不斷随機生成W,然後計算準确率,最終試出符合要求的W,但是很明顯這種方式效率很低
- 2.SVM:我們可以先随機初始化一個W,此時可以算出準确率為z1。此時我們可以嘗試小幅度修改(整體加一個數或者減一個數)W中的某一行資料,然後再計算準确率z2。如果z1小于z2,那麼表示我們修改對了,可以繼續這樣修改,否則我們需要往反方向修改。以上就是SVM的基本思想。如果把尋找一個最佳的W比作在一座山中尋找最低點的話,那麼SVM就是不斷嘗試沿着下降的路向前走,一直走到山谷最低點。
2.SVM具體實作
我們在1中說了SVM算法的基本思想,但是我們也可以從中發現一些問題。1.每次要通過計算最終的準确率才能知道目前的W是否變好了,這樣效率太低了。2.修改W的時候我們隻是在嘗試,如果能知道目前具體的下降趨勢是不是速度就更快了呢?接下來的一節我們就會解決上面的問題。
- 1.損失函數:為了解決上面說到的第一個問題,我們就定義了一個損失函數來評價目前的W的好壞。
-
1.公式:
損失函數
- 2.解釋:
- 1.我們都知道f(Cm,W)的結果會是一個大小為10的數組,這個數組的下标表示的是La數組中某個圖檔類型的下标,那麼我們就可以将這個數組比作:在W下Tm這張訓練圖檔,在每個圖檔類型下面的得分。我們這裡講這個得分數組設為S[10]
- 2.我們都知道每個Tn都會有一個正确的圖檔類型La我們設為LaM,那麼此時對于Tn我們就有衡量這個W是否标準的方法了,用每個S減去LaM(除了LaM本身)再加上一個x(這裡的x是一個自定義的數字,可以是1,2等等,這個x是一個門檻值,表示LaM的分數到底超過其他S多少才算可以接受),最後将每個的結果求和這樣就可以得出一個數字Ls。這裡的Ls就是Tn對于W的評價,Ls越大就表示,對于Tn來說這個W越不好,還有一個限制是0<=Ls,當Ls小于0的時候表示這個W對Tn來說已經夠好了,是以小于0的Ls都算作0,到這裡就是圖檔中公式Li的解釋
- 3.我們在上面算出了一個Tn對于W的評價Ls,但是光有這一個樣本太少了,我們需要讓很多的Tn對W進行評價得出大量的Ls,然後去平均值,此時就能得出目前圖檔訓練集對于這個W的評價,到這就是圖檔中公式L的解釋。
-
4.我們能看見公式中最後還有一個直接定義的項,這個一項被稱為正則項。大家可以想想,我們前面擷取的評價LsM是基于訓練圖檔集的,但是我們正在需要進行預測的是測試圖檔集。那麼此時就會有個問題我們的W隻對訓練圖檔集的預測正确率高,對測試圖檔集的預測正确率很低,這個現象就被稱為————過拟合,那麼我們如何解決這個問題呢?這就要正則項出馬了
正則化公式
,這幾個公式就是常用的正則項,我們直接拿來使用就好了。
-
- 2.優化函數:為了解決上面提出的第二個問題,我們可以定義一個優化函數,來不斷的根據趨勢優化我們的W
-
1.我們首先需要擷取到目前W朝着好的方向前進的趨勢,這裡就要用上前面定義的損失函數了,因為損失函數是關于Wj和Wi的函數,也就是說這兩個參數影響着損失函數的走向,而損失函數的結果就表示目前W的好壞程度。如果你知道偏導數的話就可以知道算出損失函數對于Wj和Wi的偏導數dW就是的W目前的趨勢。是以便有了這個公式:
dw
-
2.我們得到了dW之後,優化的公式就出來了,我們需要不斷更改W使得損失函數的結果向0靠近,是以優化函數是這樣的:
優化函數
,注意這裡還有一個參數learning_rate被稱為學習率,這個學習率就表示我們在通往山谷的路上邁的步子有多的大,如果太大的話就越過山谷到另一邊山坡去了,如果太小我們下降的又太慢,是以這是一個超參數,需要我們多試試找到最優結果。
-
- 3.随機梯度下降法:我們現在已經有了優化函數和損失函數,但是我們會發現每一次進行W優化的時候,都要周遊一整個圖檔訓練集,這樣效率就會很低,是以我們可以每次訓練取一小部分,圖檔訓練集,然後進行訓練,這樣的話效率就會比較高。一般來說,取的數字都是2的幂
2.SVM代碼實作
1.我的項目
- 1.先上一個github吧,會持續更新直到把cs231n課程學習完: cs231n
-
2.我的項目目錄:
項目目錄
2.代碼分析
全局代碼1
全局代碼2
- 1.建議結合github代碼食用,前面6行就不說了,我在上一篇部落格中分析過,就是導入子產品,然後從檔案中讀取資料: cs231n之KNN算法 ,隻要看裡面的第二節代碼解析的前兩個小結就行了。
- 2.定義了:
- 1.num_training:全體訓練集數量(num_dev會從其中抽取一定數量的圖檔用于訓練,減少訓練時間)
- 2.num_validation:驗證集數量(在不同的學習率和正則參數下使用該驗證集擷取最高的正确率,最終找到最好的學習率和正則參數)
- 3.num_test:測試集數量(在擷取到最好的學習率和正則參數之後,測試最終的正确率)
- 4.num_dev:随機訓練集數量(用于實作随機化梯度下降的)。
- 3.接下來三行是從訓練資料x_train和y_train中擷取驗證集資料
- 4.接下來三行是從訓練資料x_train和y_train中擷取全體訓練集資料
- 5.接下來三行是從num_training中随機選取随機訓練集資料
- 6.接下來四行表示:将x_train,x_val,x_test,x_dev這些n*32*32*3的圖檔集,轉化成n*3072的矩陣。簡單來說就是将每張圖檔拉伸成一維的矩陣,友善後面進行資料處理。
- 7.接下來五行表示:将x_train,x_val,x_test,x_dev這些圖檔集進行去均值處理,簡單來說就是計算出x_train全體圖檔的均值,然後讓其他圖檔集的每張圖檔邱減去這個均值。這樣的好處是統一量綱,和歸一化操作類似,隻是沒有再除以方差而已
- 8.接下來兩行定義了一系列學習率和正則參數,在後面會使用兩層循環找到最高正确率下的學習率和正則參數。
- 9.接下來三行定義了:每個學習率和正則參數下的正确率鍵值對results,最高的正确率best_val,最高正确率下的SVM對象後面可以之間對測試集進行預測。
- 10.進入了兩層循環,被循環測參數分别是學習率和正則參數
-
1.在某個學習率和正則參數下,我們建立了一個SVM對象,然後将學習率和正則參數、訓練集x_train和y_train、W需要疊代的次數num_iters,傳入訓練方法中。
訓練代碼
- 1.我們進入了訓練W的代碼中,先是擷取了訓練集圖檔數量num_train,圖檔種類數量num_classes。然後随機初始化了W。
- 2.定義一個loss_history用于儲存每次疊代的損失值
- 3.進入一個循環,被循環的參數是num_iters,也就是前面說的W需要疊代的次數
- 1.從訓練集x_train和y_train中再取出batch_size數量的資料集,再次減少訓練時間。
-
2.将再次減少的訓練集X_batch和y_batch還有正則參數reg傳入loss()方法中以擷取損失值loss和W的趨勢grad,也就是dW。
計算loss
- 1.有兩種方式來計算損失值loss和W的趨勢dW,我這裡選擇簡單的方式。
- 2.先定義了一個與W同矩陣大小的dW,擷取了訓練集圖檔數量和圖檔種類數量num_train和num_classes
- 3.初始化loss為0
- 4.進入循環,循環參數是訓練集圖檔數量num_train
- 1.計算目前W和目前訓練圖檔X[i]在各個圖檔種類下的分數scores
- 2.獲得目前訓練圖檔X[i]真實圖檔種類的分數correct_class_score
- 3.進入循環,循環參數是圖檔種類數量num_classes
- 1.如果目前的圖檔種類j,就是目前訓練圖檔X[i]真實的圖檔種類y[i],那麼由前面損失函數的定義可知,我們不需要繼續執行
- 2.如果1不成立,我們就能計算出對于目前訓練圖檔X[i],在圖檔種類j下的損失分量margin。
- 3.由前面損失函數的定義可知loss隻需要大于0的margin,是以如果margin小于0,那麼就當0處理,接下來就沒必要繼續了。
-
4.如果margin大于0,那麼為loss加上margin,并且給dW[,j]和dw[,y[i]]都加上公式:
求偏導
對Wj和Wyi求過偏導數之後的X[i]和-X[i]
- 5.退出兩層循環,此時計算出了全部訓練圖檔的dW和loss之和,是以dW和loss需要除以num_train,再為loss和dW加上正則項。
- 6.傳回dW和loss
- 3.獲得了loss和W的趨勢grad,也就是dW之後,将本次loss儲存在了loss_history中
-
4.根據公式:
,對W進行優化
- 5.這樣一直循環直至疊代次數num_iters完成
- 4.W的循環疊代結束之後,傳回上一層
- 2.在目前學習率和正則參數下,将W訓練完畢之後,分别使用x_train和x_val來進行預測并算出準确率train_accuracy和val_accuracy。
- 3.一直循環上面的操作,直至找到最大的正确率下的best_svm和best_val,并将曆次的train_accuracy,val_accuracy儲存在results中。
- 4.結束兩層循環
-
- 11.輸出10中曆次循環的train_accuracy,val_accuracy與學習率和正則參數
- 12.使用上面找到的最佳的best_svm來預測測試集x_test得到了測試集的準确率test_accuracy并輸出
- 13.擷取最佳的best_svm中的W,将其重新轉化為n*32*32*3,然後以圖檔形式輸出。
3.結果
-
1.訓練過程中在不同學習率和正則參數下訓練好模型後,驗證集和訓練集進行預測的準确率:
結果1
-
2.最終測試集的準确率:
結果2
-
3.W最終學習成的圖檔:可以看出車子的圖檔還是有一點大概的模型存在的。
結果3
4.不同損失函數的SoftMax算法
我們前面做的了Svm算法就是不斷根據損失函數對于Wi和Wj這兩個分量的偏導數來優化W的算法。這裡的損失函數定義了W的好壞,如果我們換一個損失函數的定義方式,會不會有不一樣的結果呢?我們接下來要講的就是另一種損失函數的算法SoftMax
-
1.損失函數:
softmax損失函數
- 1.解釋:這裡的Li公式我們隻要看Log裡面的東西就好了,這裡的j表示某一個圖檔種類,yi表示該訓練圖檔的真實種類,是以裡面的東西就很好了解了,即該訓練圖檔真實種類的分數在總的分數中的占比。最後Log内部算出的會是一個百分比,是以使用Log将其轉化一下。
- 2.當然最終的損失函數L,還需要算所有Li的均值
-
2.損失函數的梯度,這裡就是對Wj和Wyi算偏導:
softmax偏導
- 3.以上就是SoftMax和Svm的全部不同,是以隻需要更換一下公式的代碼就可以了。
我的部落格即将搬運同步至騰訊雲+社群,邀請大家一同入駐:
https://cloud.tencent.com/developer/support-plan?invite_code=pe24xbp4axut