文章目錄
- 前言
- 數據集
- 怎么理解數據
- 數據對齊
- 為什么偏偏是這樣對齊?
前言
在神經網絡中,我們往往會根據數據集構建訓練集、測試集,有時會有驗證集。但是,在構建完成后,如果直接將這些數據直接扔進模型訓練,輸入輸出上可能會對不上。
例如,如果我的數據集是 111 條 111 維數組作為 xxx,111 條 111 維數組作為 yyy,測試集也是等長度的 111 條 111 維數組,這個時候完全不需要在意輸入輸出問題。但如果數據集是 mmm 條 111 維數組,每條數組長度為 lil_ili?(1≤i≤m1\le i\le m1≤i≤m 且 iii 為整數),而且 mmm 個 lil_ili? 均不相等,最終結果卻需要為每個 xxx 生成一個 y^\hat{y}y^?,這就明顯對不上。
因此,在這種情況下,xxx 與 yyy 的長度需要額外的修整。該怎么做呢?
數據集
為了更好地說明這個例子,我們首先得找到一些數據集。我們其實可以直接使用最粗暴的方法:自己構建。
就舉一個最簡單的例子吧,我們要找一找sin
與cos
的曲線關系。這樣的話,神經網絡傳入的維度就非常講究。
總之,我們先構建數據集。比如說:
我們截取x∈[0,75]x\in[0, 75]x∈[0,75],并且把步長調整為0.10.10.1,這樣每條數據就有750750750個步長。
然后,我們令y=sin?(x)y=\sin(x)y=sin(x),z=cos?(2x)+0.3z=\cos(2x)+0.3z=cos(2x)+0.3。
就像這樣:
import numpy as npBATCH_MAX:int = 50
TRAIN_SIZE:int = int(BATCH_MAX * 0.6)
VALID_SIZE:int = int(BATCH_MAX * 0.2)x:np.array = np.arange(0, 75, 0.1, dtype = np.float64)
SAMPLE_SIZE:int = x.shape[0]y:np.array = np.array(np.array([np.sin(x + item) + 0.03 * np.random.normal(0, 1, size = SAMPLE_SIZE) for item in range(BATCH_MAX)]).tolist()
)
z:np.array = np.array(np.array([np.cos(2 * (x + item)) + 0.3 + 0.03 * np.random.normal(0, 1, size = SAMPLE_SIZE) for item in range(BATCH_MAX)]).tolist()
)
似乎很簡單。
我們來試著畫一下,看看長什么樣:
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocatorPLOT_SAMPLE:int = 3
plt.figure(figsize = (18, 10))for i in range(1, PLOT_SAMPLE + 1):location = 310 + iplt.subplot(location)plt.title(f'sample{i}')plt.gca().xaxis.set_major_locator(MultipleLocator(5))plt.xlim(0, 80)plt.plot(x, y[i], label = 'sin')plt.plot(x, z[i], label = 'cos')plt.legend(loc = 'best')plt.grid(linestyle = '--')
plt.show()
可以看到效果是這樣的:
看上去很完美。
怎么理解數據
這種數據其實相對來說比較好理解。主要場景就是:
我從很長兩段采樣中取了若干段等長的數據,兩段采樣控制了時間序列是等同的。
雖然在這段數據中確實沒有體現出時間的概念?(′???)?
其中,采樣的序列片段之間,存在一定的聯系。
我們先假裝不知道這兩段之間是什么聯系,總之就是看上去是有億點點關聯(′・ω・`)
既然理解了數據,接下來我們就對齊一下。
數據對齊
我們訓練的時候往往需要將兩條曲線放在一起才算找規律。但是,我們找到規律之后,要運用規律,只能輸入一條曲線。畢竟,我們的根本任務是用一條曲線預測另外一條曲線,而不是又來兩條曲線繼續訓練。
那么,更大的問題是,我們具體而言要怎么對齊?
時間片和時間片對齊?看著不太靠譜,因為我們是用一整段數據去預測另一整段數據,而不是截取其中的若干個時間片,然后預測下一個時間片。
其實非常可笑的是,由于三角函數的周期性非常有特點,也就是波峰波谷呈現出極強的一致性,甚至沒有極大值和最大值不同的問題,所以用時間片分析算是一種誤打誤撞。
為了讓你看出有多誤打誤撞,下一篇文章會講。這里只留下一個截圖:
是不是很可笑?
數組和數組對齊?看著確實是這個道理。
試試?
也就是說,每次只需要塞進去一條yyy和一條zzz就好了對吧。
怎么配呢?
其實如果翻看tensorflow
的文檔,就會發現,其實每一個常見的神經網絡方法都有一個注釋:
Input shape:N-D tensor with shape: `(batch_size, ..., input_dim)`.The most common situation would bea 2D input with shape `(batch_size, input_dim)`.
那這可太棒了!
既然我們每條數據都有750750750對yyy和zzz,那也就是說其中有一個數據就是750750750。同時,由于我們最終的目標是找到z=f(y)z=f(y)z=f(y),所以另一個數字就是111。
哪怕我真的完全不懂神經網絡橫是什么豎是什么,這個二維的東西,最多試222次也就出來了。于是,最終目標也就是構建一個輸入750750750、輸出111的神經網絡。
為什么偏偏是這樣對齊?
當然,光是嘗試成功了可不太行。我們得知道為什么是(750,1)(750,1)(750,1)。
首先,我們需要知道,無論是tensorflow
還是pytorch
,都有一個習慣性的寫法,那就是將輸入整理為(n_samples, n_features)
的矩陣。
別問為什么,因為這個為什么甚至能追溯到鍵盤為什么是WASD
塞在一起,就是一個習慣問題。
那么,在接受這個習慣之后,我們應該怎么理解這個矩陣?
我們還是拿這個例子說明。首先,字面意思理解的話,前面是樣本數,后面是特征數。樣本數還好理解,有多少就是多少。對于一個序列片段,我們有750750750對yyy和zzz,那么樣本數就是750750750。
那,特征數是多少?
我們常說,主成分分析的時候,把眾多特征減少為主要特征,并構建映射關系,說的實際上就是將x1x_1x1?、x2x_2x2?、…\ldots…、xnx_nxn?篩除大部分沒啥用的,最后只留下少數幾個。這里的xxx就是特征。
那么,對應到我們現在這里,特征是什么呢?是xxx嘛?當然不是,因為我們的目標是找到z=f(y)z=f(y)z=f(y),而不是找到z=f(x)z=f(x)z=f(x)。所以實際意義上的特征有且只有111個,即yyy。
所以才是(750,1)(750,1)(750,1)。
當然啦,這個案例比較簡單,每個yyy都有且只有一個唯一對應的zzz。如果這里的yyy是多維的呢?比如說,他是nnn張長aaa寬bbb的圖像,兩個維度的數據應該如何配置輸入輸出?
其實也是一樣的。最終也就只有特征數是最關鍵的,所以,最終就是:(n,a,b)(n,a,b)(n,a,b)。
當然啦,我知道后面還有很多內容,但一篇的篇幅有限,我們慢慢來。