Lesson 12.1 深度学习建模实验中数据集生成函数的创建与使用
Lesson 12.1 深度學習建模實驗中數據集生成函數的創建與使用
??為了方便后續練習的展開,我們嘗試自己創建一個數據生成器,用于自主生成一些符合某些條件、具備某些特性的數據集。相比于傳統的機器學習領域,深度學習的數據集往往更加復雜,大多數情況也無法把數據生成數據表來進行查看,在建模過程中,往往都是設計完模型結構后直接訓練模型,只能通過一些指標來觀測模型的效果,外加復雜神經網絡內部其實也是“黑箱”,因此我們基本只能控制流程、輸入數據、觀測結果,說是煉丹師也并不為過。不過在學習階段,尤其在學習優化算法的過程,我們還是希望能夠從更多角度觀測數據、觀測建模過程,這就需要我們自己動手,創建一些數據用于實驗的原材料,通過一些實驗深入了解模型原理,從“煉丹師”朝著“化學家”更進一步。
- 導入相關的包
以上均為此前用到的包,其他的新的包將在使用時再進行導入及介紹
一、回歸類數據集創建方法
1.手動生成數據
??回歸類模型的數據,特征和標簽都是連續型數值。
正常情況,應該是對于連續型數值標簽的預測,我們采用回歸類模型,此處因為先生成數據后進行建模,因此我們稱可用于回歸模型訓練的數據為回歸類模型數據,分類模型數據亦然。
- 數據生成
生成兩個特征、存在偏差,自變量和因變量存在線性關系的數據集
num_inputs = 2 # 兩個特征 num_examples = 1000 # 總共一千條數據然后嘗試通過線性方程,確定自變量和因變量的真實關系
torch.manual_seed(420) # 設置隨機數種子 #<torch._C.Generator at 0x25d6ababcd0> # 線性方程系數 w_true = torch.tensor([2., -1]).reshape(2, 1) b_true = torch.tensor(1.)# 特征和標簽取值 features = torch.randn(num_examples, num_inputs) labels_true = torch.mm(features, w_true) + b_true labels = labels_true + torch.randn(size = labels_true.shape) * 0.01此處設置所有的數據都是浮點型。
注意,此時labels_true和features滿足嚴格意義上的線性方程關系
y=2x1?x2+1y = 2x_1-x_2+1y=2x1??x2?+1
但我們實際使用的標簽labels,則是在labels_true的基礎上增添了一個擾動項,torch.randn(size = labels_true.shape) * 0.01,這其實也符合我們一般獲取數據的情況:真實客觀世界或許存在某個規律,但我們搜集到的數據往往會因為各種原因存在一定的誤差,無法完全描述真實世界的客觀規律,這其實也是模型誤差的來源之一(另一個誤差來源是模型本身捕獲規律的能力)。這其中,y=2x1?x2+1y=2x_1-x_2+1y=2x1??x2?+1相當于我們從上帝視角創建的數據真實服從的規律,而擾動項,則相當于人為創造的獲取數據時的誤差。
這種按照某種規律生成數據、又人為添加擾動項的創建數據的方法,也是數學領域創建數據的一般方法。
- 數據探索
不難看出,兩個特征和標簽都存在一定的線性關系,并且跟特征的系數絕對值有很大關系。當然,若要增加線性模型的建模難度,可以增加擾動項的數值比例,從而削弱線性關系。
當然,我們也能生成非線性關系的數據集,此處我們創建滿足y=x2+1y=x^2+1y=x2+1規律的數據集。
2.創建生成回歸類數據的函數
??為了方便后續使用,我們將上述過程封裝在一個函數內
- 定義創建函數
注:上述函數無法創建帶有交叉項的方程
- 測試函數性能
首先查看擾動項較小的時候的數據情況
# 設置隨機數種子 torch.manual_seed(420) # 擾動項取值為0.01 f, l = tensorGenReg(delta=0.01)f #tensor([[-0.0070, 0.5044, 1.0000], # [ 0.6704, -0.3829, 1.0000], # [ 0.0302, 0.3826, 1.0000], # ..., # [-0.9164, -0.6087, 1.0000], # [ 0.7815, 1.2865, 1.0000], # [ 1.4819, 1.1390, 1.0000]]) # 繪制圖像查看結果 plt.subplot(223) plt.scatter(f[:, 0], l) # 第一個特征和標簽的關系 plt.subplot(224) plt.scatter(f[:, 1], l) # 第二個特征和標簽的關系
然后查看擾動項較大時數據情況
當特征和標簽滿足二階關系時候數據表現
當只有一個特征時數據表現
二、分類數據集創建方法
??和回歸模型的數據不同,分類模型數據的標簽是離散值。
1.手動創建分類數據集
- 數據生成
在嘗試創建分類數據集之前,首先回顧torch.normal創建某種服從正態分布的隨機數的創建方法。
torch.randn(4, 2) #tensor([[ 1.4000, 0.3924], # [-0.0695, -1.7610], # [ 0.3227, 1.7285], # [-0.1107, -1.6273]]) torch.normal(4, 2, size=(10,2)) #tensor([[4.8092, 0.9773], # [4.4092, 3.3987], # [1.7446, 6.2281], # [3.0095, 4.2286], # [7.8873, 6.5354], # [3.9286, 4.0315], # [2.0309, 4.5259], # [3.6491, 0.7394], # [3.6549, 5.4767], # [8.5935, 3.0440]])接下來嘗試創建一個擁有兩個特征的三分類的數據集,每個類別包含500條數據,并且第一個類別的兩個特征都服從均值為4、標準差為2的正態分布,第二個類別的兩個特征都服從均值為-2、標準差為2的正態分布,第三個類別的兩個特征都服從均值為-6、標準差為2的正態分布,創建過程如下:
# 設置隨機數種子 torch.manual_seed(420) # 創建初始標記值 num_inputs = 2 num_examples = 500# 創建自變量簇 data0 = torch.normal(4, 2, size=(num_examples, num_inputs)) data1 = torch.normal(-2, 2, size=(num_examples, num_inputs)) data2 = torch.normal(-6, 2, size=(num_examples, num_inputs))# 創建標簽 label0 = torch.zeros(500) label1 = torch.ones(500) label2 = torch.full_like(label1, 2)# 合并生成最終數據 features = torch.cat((data0, data1, data2)).float() labels = torch.cat((label0, label1, label2)).long().reshape(-1, 1)此處需要注意:
-
normal函數的均值參數位、標準差參數位都允許輸入高維數組,從而最終輸出結果也是形狀相同的高維數組;
-
一般來說,約定俗成的方式,是針對多分類問題,類別標記從0開始依次遞增;
-
對于PyTorch來說,分類問題標簽要求是默認整型。
-
數據探索
能夠看出,類別彼此交叉情況較少,分類器在此數據集上會有不錯表現。當然,若要增加分類器的分類難度,可以將各類的均值壓縮,并增加方差,從而增加從二維圖像上來看彼此交錯的情況。
2.創建生成分類數據的函數
??同樣,我們將上述創建分類函數的過程封裝為一個函數。這里需要注意的是,我們希望找到一個變量可以控制數據整體離散程度,也就是后續建模的難以程度。這里我們規定,如果每個分類數據集中心點較近、且每個類別的點內部方差較大,則數據集整體離散程度較高,反之離散程度較低。在實際函數創建過程中,我們也希望能夠找到對應的參數能夠方便進行自主調節。
- 定義創建函數
??函數整體結構不復雜,且所使用的方法都是此前介紹過的tensor常用方法,唯一需要注意的是函數對于分布離散程度的控制。函數內部變量k是一個隨著均值增加和分類類別數量增加而增加的數值,且分類數量增加對k值增加影響是通過和1取平均后進行懲罰的結果。而i*mean_則是一個隨著i增加穩步增量的量,二者相減最終能獲得一個整體特征均勻分布在0附近的特征張量。
- 測試函數性能
在使用函數的過程中,離散度的第一個數值可以理解為簇的大概分布區間,第二個數值可以理解為每個簇的離散程度。
# 設置隨機數種子 torch.manual_seed(420) # 創建數據 f, l = tensorGenCla(deg_dispersion = [6, 2]) # 離散程度較小 f1, l1 = tensorGenCla(deg_dispersion = [6, 4]) # 離散程度較大# 繪制圖像查看 plt.subplot(121) plt.scatter(f[:, 0], f[:, 1], c = l) plt.subplot(122) plt.scatter(f1[:, 0], f1[:, 1], c = l1)三、創建小批量切分函數
??在深度學習建模過程中,梯度下降是最常用的求解目標函數的優化方法,而針對不同類型、擁有不同函數特性的目標函數,所使用的梯度下降算法也各有不同。目前為止,我們判斷小批量梯度下降(MBGD)是較為“普適”的優化算法,它既擁有隨機梯度下降(SGD)的能夠跨越局部最小值點的特性,同時又和批量梯度下降(BGD)一樣,擁有相對較快的收斂速度(雖然速度略慢與BGD)。而在小批量梯度下降過程中,我們需要對函數進行分批量的切分,因此,在手動實現各類深度學習基礎算法之前,我們需要定義數據集小批量切分的函數。
另外,后續講解的交叉驗證計算過程也需要對數據進行切分
shuffle過程:將原序列亂序排列
l = list(range(5)) l #[0, 1, 2, 3, 4] random.shuffle(l) l #[3, 2, 0, 1, 4]批量切分函數的目標就是根據設置的“批數”,將原數據集隨機均勻切分。可通過如下函數實現:
def data_iter(batch_size, features, labels):"""數據切分函數:param batch_size: 每個子數據集包含多少數據:param featurs: 輸入的特征張量:param labels:輸入的標簽張量:return l:包含batch_size個列表,每個列表切分后的特征和標簽所組成 """num_examples = len(features)indices = list(range(num_examples))random.shuffle(indices)l = []for i in range(0, num_examples, batch_size):j = torch.tensor(indices[i: min(i + batch_size, num_examples)])l.append([torch.index_select(features, 0, j), torch.index_select(labels, 0, j)])return lfor i in range(0, 5, 2):print(i) #0 #2 #4 # 設置隨機數種子 torch.manual_seed(420) # 生成二分類數據集 features, labels = tensorGenCla() features[:5] #tensor([[-4.0141, -2.9911], # [-2.6593, -4.7657], # [-3.9395, -3.2347], # [-5.0262, -2.5792], # [-0.3817, -3.1295]]) torch.tensor(l[0:2]) #tensor([3, 2]) torch.index_select(features, 0, torch.tensor(l[0:2])) #tensor([[-5.0262, -2.5792], # [-3.9395, -3.2347]]) labels #tensor([[0], # [0], # [0], # ..., # [2], # [2], # [2]]) l = data_iter(10, features, labels) l[0] # 查看切分后的第一個數據集 #[tensor([[ 0.7901, 2.4304], # [ 4.0788, 3.7885], # [-1.1552, -0.8829], # [ 1.3738, 2.3689], # [-2.1479, -6.6638], # [-2.5418, -7.9962], # [-1.0777, -0.7594], # [ 5.6215, 3.9071], # [ 3.5896, 3.3644], # [ 1.2458, 0.0179]]), # tensor([[1], # [2], # [1], # [1], # [0], # [0], # [1], # [2], # [2], # [1]])] plt.scatter(l[0][0][:, 0], l[0][0][:, 1], c = l[0][1])此處又使用了空列表用于存儲數據。在經典機器學習領域,我們經常使用空的列表來存儲經過處理之后的數據,這么做能讓我們非常清楚的看到數據的真實情況,但在深度學習領域,這么做卻不是常規操作。在深度學習領域,數據量往往非常大,甚至數據本身就是分布式存儲的,要調取數據進行完整的查看,一方面會耗費大量的存儲空間,另一方面也會消耗一定的算力,因此PyTorch的Dataset和DataLoader都是將數據進行迭代存儲或者映射存儲。關于數據生成器大的相關內容我們將在后續進行討論,此處由于我們是進行手動實驗,將處理完的數據完整的存在列表容器中則是為了方便調用查看,是一種更適合初學者的方法。
四、Python模塊編寫
根據此前介紹的課程安排,本節定義的函數將后續課程中將經常使用,因此需要將其封裝為一個模塊方便后續調用。封裝為模塊有以下幾種基本方法:
- 打開文本編輯器,將寫好并測試完成的函數寫入其中,并將文本的拓展名改寫為.py;
- 在spyder或者pycharm中復制相關函數,并保存為.py文件;
然后將文件保存在jupyter主目錄下,并取名為torchLearning,后續即可通過import torchLearning進行調用。如果是jupyterlab用戶,也可按照如下方式進行編寫:
Step 1.打開左側文件管理欄頁,點擊新建
Step 2.在新建目錄中,選擇Test File
Step 3.在打開的文本編輯器中輸入代碼
需要保存的函數有:
- tensorGenReg函數
- tensorGenCla函數
- data_iter函數
Step 4.保存退出,并將文件名改寫為torchLearning.py
然后即可在其他ipy文件中調用,具體調用方法見下一節內容。
總結
以上是生活随笔為你收集整理的Lesson 12.1 深度学习建模实验中数据集生成函数的创建与使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Lesson 11.1-11.5 梯度下
- 下一篇: Lesson 13.1 深度学习建模目标