目錄
系列文章
目錄
前言 :
作業二 真的很難 。而且會出現訓練集沒辦法過擬合的情況 也就是訓練集准確度沒辦法到百分之百 數據太多了 。 向實驗室申請了一台服務器來跑這個作業,最后在kaggle上 pub達到了strong pri沒有 哭了 試了好久都不太行。
但還是試着寫寫思路吧。git地址 和kaggle網址
項目:
我的習慣 一般會把一個小項目做成下面的幾個模塊 這樣非常的清晰
第一個就是數據模塊 , 這部分的作用是讀入數據。 接口輸入是數據地址 返回的是各種loader
第二個是模型模塊 。沒啥好說的 ,就是創造模型。接口輸入是特征數和分類數(分類任務), 出口是模型。
第三個是訓練模塊 。 這一部分要傳入訓練集 驗證集 和超參數。步驟就是 梯度歸0 模型前向過程得到預測結果 預測和標簽比得到loss loss回傳。模型更新。還有一些記錄。 訓練過后有一個驗證過程 , 讓模型在驗證集上跑 ,最后得到驗證集准確率。
第四個是驗證模塊。一般負責從模型和測試數據出發,得到想要驗證的數據 。
第五個是main函數 。 整合各個模塊 進行數據模型的傳遞。
我覺得模塊化是非常有必要的 ,我一直想做一個萬能模塊。特別是數據部分,后來發現,想多了,面對每一個項目 總是免不了微調。大家可以逐漸形成自己的模塊。
一: 數據 :
看到 數據一段編碼好了的 聲音片段 。 每一段是39長度的向量。 然后會給出前后五段的 數據 也就是我們有11*39 = 429 維度的一個特征 根據這個特征去做分類 。 有多少類呢 ?有39類 。數據被放在一個.npy的numpy文件中 。跟上次一樣, 先創建一個讀數據的dataset
把x,y讀進來 把y轉為int型
dataset 是非常基礎的 init負責把數據讀進來 getitem 負責在訪問數據集時返回數據 我們返回的是float類型的特征數據 和longtensor的標簽 len負責返回長度 。。 用這個文件做數據很簡單。直接放完整代碼 。 這部分被我放在model.utils 中的data里
二: 模型
很基礎的一個模型 就是fc+relu+dropout 我不知道怎么樣去改出來一個好模型 只是感覺 都差不多。
這部分被我放在model.utils 中的model里
三 : 訓練和評估
這部分和之前幾乎一樣 。我就不放代碼了 可以去git下
四:main函數和訓練過程
超參和模型設置 以及創造loader
創造優化器和loss 然后訓練
1 訓練過程中 會發現訓練集的准確率比測試集還高。 這是因為我們有drop過程。
2 驗證准確度會與drop率有關 大家不要迷信准確率。 最后我上面這個模型驗證准確在百分之88.5左右就上不去了 。我是訓練了 1000個epoch。
3 換了好幾個優化器 換了好幾個lr 最后結果總是上不去, 然后上傳到kaggle 上 得到的分數是 0.741
五 后處理 。
很早就得到了這個結果 卻差別人一大截。 然后在網上找到了一個大佬做的視頻。
然后跟着大佬的思路 (抄他的代碼),把結果提了兩個點。 然后我來盡量講一下這個思路 。 實在是太難了 。這個思路就是HMM, hmm是什么 大家可以參考這里。記得跟着這個鏈接里的算一次。就算沒看懂,也要把他是怎么算出結果的。用手把步驟寫出來、下面我盡量帶大家理解我的想法。好吧 我也不確定我的想法對。
其實hmm感覺上是什么呢 ? 就感覺是天下大勢和小家之勢的相互關系。 天下有大勢,當你實力強時,你就可以不完全被大勢挾裹,但是如果你實力微弱,就會被卷入其中。
后處理的代碼如下。這串代碼非常的難看懂。一定要仔細調試並與上面的例子結合起來看。
1 加載訓練標簽。
2 統計轉移矩陣。 trains_table[i,j]位置的元素 表示在所有標簽里,從i到j的個數。統計后,在每行進行歸一化, 就得到從當現在的標簽是i 他下一個是其他標簽各個的概率。
3:得到發射矩陣。 這就是小家小勢了 。也就是模型預測的置信度多高。如果你模型預測一個結果的置信度是0.99 那么相信天下大勢也很難影響你。test_ln_softmax有451552行 每行都是每一類的預測概率。
4:將他們log化 這里應該是為了乘起來快一點。 大家都知道 log的加就相等於數字相乘。反正我們只是比較相對大小。所以這里log后可以用加法代替乘法。
5: 定義路徑和初始狀態。
6: 計算過程 開始計算了 。
這一句相當於上面例子里的這一段。前一個是y0的概率然后乘以從y0轉到yi的概率 再乘以現在這個表現為yi的概率。 我們就得到了在前一個表現為y0的情況下,這個表現為yi的概率。 我們會得到39個。我們來細看 這一句到底是怎么算的。
laststate 就是前面一天 表現為yi的概率 。 長度是39 代表了每一類。但是這里有 reshape(39,1) 就表示變成了39行。 transtabnle是一個39乘以39的矩陣。這兩個矩陣相加,就要對latestate進行行擴充。 下面的0 就表示 預測值為0的概率。
再看 下面兩個的相加 我們知道 其實就是相乘 tran的每個位置i,j都是i到j的概率。那么 相加之后的矩陣意思就是 如果上一天是yi 今天表現為yj的概率。
test_ln_softmax[i] 是一個1*39長的向量 他每個位置意思是不管天下大勢 我表現為 y?的概率 。由於他要和39*39的矩陣相加 所以他也要擴充。
所以這三個矩陣相加 i,j位置的值 就表示 綜合了天下大勢和小家局勢。 后 前一天是i今天是j的概率。
取列的最大值。 那么固定的是j的值 如果j=0 就是意思找 昨天預測值是多少時 今天能得到0的概率最高。 此時那個概率的值時多少。 但找齊每一列后 current_state(1,39) 中每一個值的意思就變成了 這天得到預測值j的概率是多大。(我們把最大的那個,選擇相信他。)
列最大值所在行是哪一行。 這個就是位置了。 第j個位置的數字表明 昨天取預測值track【j】時, 今天得到預測值j的概率最大。 也就是統計一個路徑。
更新狀態。也就是把今天概率看成上一天的概率,看下一天。
track 是一個 長451551 寬39的矩陣。 有45萬行 表示45萬天 然后有39 列 第j表示 昨天取預測值track【j】時, 今天得到預測值j的概率最大。
我們選擇最后一天的那個數字 帶入。 這個數字 就是最后一天的發射值。比如這個值是38(正常大家得到的值應該是25) 我們就要去找 38位的值 發現這一位上還是38 那么意思就是 昨天取38時 今天取38的概率最大。 所以預測值里就要加入38 但這里我們是倒序加入,最后要反過來。
到這里 發現38位上寫的 7 說明上天是7 今天取38概率最大。然后找到上天的7 繼續這個步驟 。
也就是說 按照track這條路去走 是最有可能的 。 所以就取這條路提交。 得到最后的結果。hmm后會比正常提交提高兩個百分點左右。
而hmm那個晴天陰天的例子 用第一天的轉移用 上面的 代碼大概就是 下面這樣
import numpy as np a = np.array([0.06,0.24]) b = np.array([[0.7,0.3],[0.4,0.6]]) c = np.array([0.4,0.3]) print(a.reshape(2,1)*b*c)