期貨量化軟件:赫茲量化系統(tǒng)神經(jīng)網(wǎng)輕松學(xué)習(xí)之關(guān)注機(jī)制
在之前的文章中,我們已經(jīng)測試了組織規(guī)劃神經(jīng)網(wǎng)絡(luò)的各種選項(xiàng)。 其中包括借鑒來的圖像處理算法的卷積網(wǎng)絡(luò)[ 3 ],以及遞歸神經(jīng)網(wǎng)絡(luò)[ 4 ],這些神經(jīng)網(wǎng)絡(luò)不僅處理重要的數(shù)值序列,還有它們在源數(shù)據(jù)集合中的位置。
全連接和卷積神經(jīng)網(wǎng)絡(luò)具有固定的輸入序列大小。 遞歸神經(jīng)網(wǎng)絡(luò)通過轉(zhuǎn)移先前迭代中的隱藏狀態(tài),可稍微擴(kuò)展所分析序列。 但是它們的有效性也隨著序列的遞增而降低。 在 2014 年,出于機(jī)器翻譯的目的,第一次提出了關(guān)注機(jī)制。 該機(jī)制的目的在于判定并高亮顯示與目標(biāo)翻譯詞最相關(guān)的源句子(上下文)的區(qū)塊。 這種直觀的方法極大地提高了神經(jīng)網(wǎng)絡(luò)翻譯文本的質(zhì)量。
1. 關(guān)注機(jī)制
分析燭條品種圖表時,我們定義了趨勢和傾向,并判定出它們的交易范圍。 這意味著,我們從總體圖中選擇一些對象,然后將注意力集中在這些對象上。 我們知曉對象會影響未來的價格行為。 為了實(shí)現(xiàn)這種方法,早在 2014 年,開發(fā)人員就提出了第一種算法,該算法可以分析輸入和輸出序列元素[8] 之間的依賴性,并高亮顯示。 所提議的算法稱為“泛關(guān)注機(jī)制”。 最初提議將其用在遞歸網(wǎng)絡(luò)機(jī)器翻譯模型之中,以便解決長句子翻譯中的長期記憶問題。 這種方式大大改善了之前研究的基于 LSTM 模塊[ 4 ] 的遞歸神經(jīng)網(wǎng)絡(luò)的結(jié)果。
采用遞歸網(wǎng)絡(luò)的經(jīng)典機(jī)器翻譯模型由兩個模塊組成:編碼器和解碼器。 第一個模塊將源語言中的輸入序列編碼為上下文向量,第二個模塊將結(jié)果上下文解碼為目標(biāo)語言中的單詞序列。 當(dāng)輸入序列的長度遞增時,第一個單詞對最終句子上下文的影響會遞減。 后果就是,翻譯品質(zhì)下降。 采用 LSTM 模塊略微增加了模型的效能,但它們?nèi)匀挥邢蕖?/p>
. 升級卷積層
我們從自關(guān)注算法的第一個動作開始 — 計(jì)算 Query、Key 和 Value 向量。 輸入一個數(shù)據(jù)矩陣,其內(nèi)包含所分析序列每根柱線特征。 逐根提取燭條的特征,然后將它們乘以權(quán)重矩陣,從而得到一個向量。 在我看來,這類似于文章[ 3 ] 中研究的卷積層。 然而,在這種情況下,輸出不是數(shù)字,而是固定大小的向量。 為了解決這一難題,我們升級負(fù)責(zé)神經(jīng)網(wǎng)絡(luò)卷積層操作的 CNeuronConvOCL 類。 加入 iWindowOut 變量來存儲輸出向量的尺寸。 在類方法中實(shí)現(xiàn)相應(yīng)的修改。
class CNeuronConvOCL ? ?: ?public CNeuronProofOCL ?{ protected: ? uint ? ? ? ? ? ? ?iWindowOut; //--- ? CBufferDouble ? ? *WeightsConv; ? CBufferDouble ? ? *DeltaWeightsConv; ? CBufferDouble ? ? *FirstMomentumConv; ? CBufferDouble ? ? *SecondMomentumConv; //--- ? virtual bool ? ? ?feedForward(CNeuronBaseOCL *NeuronOCL); ? virtual bool ? ? ?updateInputWeights(CNeuronBaseOCL *NeuronOCL); public: ? ? ? ? ? ? ? ? ? ? CNeuronConvOCL(void) : ? iWindowOut(1) { ?activation=LReLU; ? } ? ? ? ? ? ? ? ? ? ?~CNeuronConvOCL(void); ? virtual bool ? ? ?Init(uint numOutputs,uint myIndex,COpenCLMy *open_cl,uint window, uint step, uint window_out, uint units_count, ENUM_OPTIMIZATION optimization_type); //--- ? virtual bool ? ? ?SetGradientIndex(int index) ? { ?return Gradient.BufferSet(index); ? } ? //--- ? virtual bool ? ? ?calcInputGradients(CNeuronBaseOCL *NeuronOCL); ? virtual int ? ? ? Type(void) ? const ? { ?return defNeuronConvOCL; ? } ? //--- methods for working with files ? virtual bool ? ? ?Save(int const file_handle); ? virtual bool ? ? ?Load(int const file_handle); ?};
在 OpenCL 內(nèi)核 FeedForwardConv 之中,添加一個獲取輸出矢量尺寸的參數(shù)。 另外,在卷積層輸出之處,在通用向量中添加輸出向量已處理片段的偏移量計(jì)算,并實(shí)現(xiàn)額外的循環(huán)遍歷輸出層元素。
__kernel void FeedForwardConv(__global double *matrix_w, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?__global double *matrix_i, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?__global double *matrix_o, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int inputs, int step, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int window_in, int window_out, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?uint activation) ?{ ? int i=get_global_id(0); ? int w_in=window_in; ? int w_out=window_out; ? double sum=0.0; ? double4 inp, weight; ? int shift_out=w_out*i; ? int shift_in=step*i; ? for(int out=0;out<w_out;out++) ? ? { ? ? ?int shift=(w_in+1)*out; ? ? ?int stop=(w_in<=(inputs-shift_in) ? w_in : (inputs-shift_in)); ? ? ?for(int k=0; k<=stop; k=k+4) ? ? ? ?{ ? ? ? ? switch(stop-k) ? ? ? ? ? { ? ? ? ? ? ?case 0: ? ? ? ? ? ? ?inp=(double4)(1,0,0,0); ? ? ? ? ? ? ?weight=(double4)(matrix_w[shift+k],0,0,0); ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 1: ? ? ? ? ? ? ?inp=(double4)(matrix_i[shift_in+k],1,0,0); ? ? ? ? ? ? ?weight=(double4)(matrix_w[shift+k],matrix_w[shift+k+1],0,0); ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 2: ? ? ? ? ? ? ?inp=(double4)(matrix_i[shift_in+k],matrix_i[shift_in+k+1],1,0); ? ? ? ? ? ? ?weight=(double4)(matrix_w[shift+k],matrix_w[shift+k+1],matrix_w[shift+k+2],0); ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 3: ? ? ? ? ? ? ?inp=(double4)(matrix_i[shift_in+k],matrix_i[shift_in+k+1],matrix_i[shift_in+k+2],1); ? ? ? ? ? ? ?weight=(double4)(matrix_w[shift+k],matrix_w[shift+k+1],matrix_w[shift+k+2],matrix_w[shift+k+3]); ? ? ? ? ? ? ?break; ? ? ? ? ? ?default: ? ? ? ? ? ? ?inp=(double4)(matrix_i[shift_in+k],matrix_i[shift_in+k+1],matrix_i[shift_in+k+2],matrix_i[shift_in+k+3]); ? ? ? ? ? ? ?weight=(double4)(matrix_w[shift+k],matrix_w[shift+k+1],matrix_w[shift+k+2],matrix_w[shift+k+3]); ? ? ? ? ? ? ?break; ? ? ? ? ? } ? ? ? ? sum+=dot(inp,weight); ? ? ? ?} ? ? ?switch(activation) ? ? ? ?{ ? ? ? ? case 0: ? ? ? ? ? sum=tanh(sum); ? ? ? ? ? break; ? ? ? ? case 1: ? ? ? ? ? sum=1/(1+exp(-clamp(sum,-50.0,50.0))); ? ? ? ? ? break; ? ? ? ? case 2: ? ? ? ? ? if(sum<0) ? ? ? ? ? ? ?sum*=0.01; ? ? ? ? ? break; ? ? ? ? default: ? ? ? ? ? break; ? ? ? ?} ? ? ?matrix_o[out+shift_out]=sum; ? ? } ?}