利用pytorch進行機器學習(7)—— 處理多維特征的輸入


(一)數據集的認識

對於回歸任務,我們輸出的結果是一個實數集,而對於分類任務來說,我們輸出的結果是屬於一個離散的集合,接下來我們觀察一個關於糖尿病的數據集,我們把這樣的一個表,數據庫中叫做關系圖,每一行是一個樣本,在數據庫里叫做記錄,每一列是一個特征,在數據庫中叫字段,其中輸入為X,輸出為Y。

 

 

 這樣的數據我們在sk-learn中也可以找到類似的數據,如果安裝了Anaconda,我們可以在lib下的site-packages中找到相關的數據集,里面用的文件擴展名為gz,用解壓縮文件即可打開,是一個csv文件,里面的文件名為x與y,表示了輸入與輸出。csv文件面對的數據是用逗號來做分隔符,而excel文件面對的數據是用空格或者table做分隔符,所以不同的文件用excel打開不一定都是對齊的。在我們本次用到的數據中,輸入的維度是八維,而輸出的維度是一維的。

 

 

 (二)模型的計算

對於n維的數據,我們要計算他的y_hat,那么他每個維度都有一個權重,每個權重與相應的特征值相乘進行加和得到響應的計算值,再將該計算值帶入logistic函數中計算

 

 

 對於Mini-Batch的樣本,由於pytorch提供的函數是向量函數,計算這些輸入的話,我們可以將其裝變為矩陣之間的計算,利用GPU的並行性計算的能力得到輸出,因為如果我們用for循環來寫里面的計算,會相當麻煩。對應的,我們在實際代碼中,Linear類需要修改下參數,輸入為8維,輸出1維

 

 

 由於矩陣乘法其實是一個空間轉換,M x N矩陣可以看成是一個m維的向量映射到n維空間的變換函數,在我們要做的線性變換中有可能不是線性的,我們可能要通過多次的變換來實現非線性,所以我們可以用多個logistic函數的線性變換層首尾相連,中間每一層記得加上一個激活函數,這樣可以讓每一次的空間壓縮都引入一個非線性,這樣我們就可以通過調整線性變換,來去擬合真正想要的空間變換。

 

 

 因為我們想要找的是一個8維空間到1維空間的非線性的空間變換,我們可以將8維先變為6維,再把6維降為1維,也可以先把8維往高維度變化例如24維,再往低維度變化,變化的層數和維度決定了網絡的復雜程度,但具體這些值(維度,層數等)取什么好,這就是一個超參數的搜索問題,一般來說里面的層數越多,中間的神經元越多,那我們可以對非線性變換的學習能力就越強。但學習能力越強也不一定是件好事,因為它可能會把輸入樣本的噪音也學習進去,但不同的數據他們的噪聲是可能不相同的。我們需要的是學習數據本身的能力,從而保證他的泛化能力最好。這一般要通過超參數搜索的方式來嘗試誰實現的比較好。

(三)pytorch代碼解析

1. loadtxt函數中delimiter是分隔符參數,這里由於為csv文件所以用 “ , ” 作為分隔符,用numpy讀取的時候要指定數據類型,用float32的原因是神經網絡中經常用32位,因為一般GPU如2080或者1080他們只支持32位的浮點數運算,只有在比較貴的顯卡如英偉達特斯拉系列顯卡他支持64位,但對於神經網絡來說,32位的浮點數足夠用了。

2. 對於x_data和y_data,由於輸入和輸出特征是放在一起的,所以讀取的時候,x_data取前八列,y_data取最后一列,由於我們要輸出的數據是一個向量形式,所以要加 "[ ]"

補充:關於列表和數組的關系

列表:是python中的一種數據結構,列表中每個元素的大小可以不同,因而不支持一次性讀取一列這樣的操作,但可以支持索引操作

數組:在python中並不存在這樣的數據結構,但是可以通過numpy中的函數numpy.array() 把列表轉為數組,這樣就可以將原來的列表表示為一個矩陣,也可以使用分片操作了。樣例代碼中

3. 注意torch.nn.Sigmoid()是一個模塊,繼承自Module,而且這個模塊沒有什么參數,所以我們只要一個實例化self.sigmoid就可以了,而torch.nn.Function.sigmoid()是一個函數。在使用的時候我們應該把torch.nn.Sigmoid看做是一層來調用。

4. 在定義forward函數的時候,由於我們每層的輸出都是下一層的輸入,如果我們把每一層的輸出定義成多個變量,那么可能我們后續再寫代碼的時候出現問題很難發現具體是哪一層出了錯,很不方便,所以我們不如把所有的變量都設為一個x,這樣在命名上就不用有所考慮。

5. 雖然我們前面講了Mini-Batch風格,但我們這個例子中並沒有利用Mni-Batch來實現而是把所有的數據都扔進去了。

6. 激活函數有的連續有的不連續,比如ReLU這個就不連續,softplus長得很像ReLU, 但它的激活函數是連續的。還要注意的一點是,ReLU這個函數的輸出是[0,1],后續的損失函數計算會涉及到求ln 0,所以我們在算最后的y_hat的時候,forward中的最后一個激活函數應該改為sigmoid,這樣算出的就是[0,1]之間,比較光滑的。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM