量化軟件下載:赫茲量化中支持向量機(jī)如何應(yīng)用于交易
更高維度上文展示的二維空間的情形讓我們得以將支持向量機(jī)的處理過(guò)程可視化,然而它只能使用兩個(gè)輸入數(shù)據(jù)來(lái)對(duì)數(shù)據(jù)點(diǎn)分類。如果要使用更多的輸入數(shù)據(jù)呢?慶幸的是,支持向量機(jī)算法可以讓我們?cè)诟呔S度做同樣的事情,盡管在概念上更難解釋一些。 思考一下:你希望創(chuàng)建獲取 20 個(gè)輸入數(shù)據(jù)并且能夠使用這些輸入把任何數(shù)據(jù)點(diǎn)劃分為類型 1 或類型 2。要做到這一點(diǎn),支持向量機(jī)要將數(shù)據(jù)在 20 維空間建模,同時(shí)要用一個(gè)回歸算法找到一個(gè)將數(shù)據(jù)點(diǎn)區(qū)分為兩類的 19 維超平面。要對(duì)上述情形進(jìn)行可視化是極其困難的,因?yàn)槲覀兒茈y理解三維以上空間。不管怎樣,您只需知道它的工作原理與二維空間完全相同。
支持向量機(jī)的工作原理示例:這是 Schnick 嗎?
想象一個(gè)場(chǎng)景,您是一個(gè)研究人員,正在調(diào)查一種稀有的動(dòng)物叫做 Schnicks,該動(dòng)物只在北極深處出沒。由于這研究對(duì)象罕見,只有很少一部分被發(fā)現(xiàn)過(guò)(假設(shè)是 5000 只左右)。作為一個(gè)研究人員,您被這樣一個(gè)問(wèn)題所困惑:我怎么去認(rèn)定這是一個(gè) Schnick 呢?
您手頭上只有一些見過(guò)該動(dòng)物的其他研究員發(fā)表的論文。而這些研究論文中,作者對(duì)他們發(fā)現(xiàn)的 Schnicks 的某些特征進(jìn)行了描述,包括身高、體重、肢體數(shù)量等等。不過(guò)每一篇論文的特征描述都各不相同,而且沒有明顯的模式……
我們?nèi)绾斡眠@些數(shù)據(jù)來(lái)確定一只新的動(dòng)物是 schnick 呢?
支持向量機(jī)就有可能成為解決該問(wèn)題的方案之一。利用支持向量機(jī)區(qū)分?jǐn)?shù)據(jù)的模式,創(chuàng)建一個(gè)框架模型以區(qū)分動(dòng)物是 Schnick 還是非 Schnick。第一步就是創(chuàng)建一系列的數(shù)據(jù),用于訓(xùn)練你的支持向量機(jī)分辨 schnick。訓(xùn)練數(shù)據(jù)是一系列的輸入?yún)?shù),為支持向量機(jī)匹配輸出結(jié)果,以分析并從中提取模式。
因此,我們必須決定哪些輸入?yún)?shù)要用到,以及其數(shù)量。理論上說(shuō),我們可以獲取所希望數(shù)量的輸入?yún)?shù),然而這將經(jīng)常減緩訓(xùn)練的速度(參數(shù)越多,支持向量機(jī)提取模式的時(shí)間越長(zhǎng))。同時(shí),你希望選取在所有 schnick 中較為一致的輸入值。比如,動(dòng)物的身高或體重將是一個(gè)很好的輸入選擇,因?yàn)槟谕械?schnick 都在這些數(shù)值上保持相對(duì)一致。然而,平均年齡將不是個(gè)好選擇,因?yàn)槟?,所辨認(rèn)的動(dòng)物年齡可能差距非常大。
因此,以下的輸入?yún)?shù)是我們選擇的:
身高
體重
肢體數(shù)量
眼睛數(shù)量
前肢長(zhǎng)度
平均奔跑速度
交配鳴叫頻率
選擇了以上的輸入?yún)?shù),我們開始編譯熟練數(shù)據(jù)。有效的訓(xùn)練數(shù)據(jù)對(duì)于支持向量機(jī)來(lái)說(shuō)必須滿足以下特定條件:
數(shù)據(jù)必須包含 schnick 這一動(dòng)物的案例
數(shù)據(jù)必須包含非 schnick 動(dòng)物的案例
在這個(gè)案例中,我們獲得了科學(xué)家的研究論文,這些論文已經(jīng)成功地辨認(rèn)出 schnick 并列出了它的相關(guān)屬性。因此我們可以閱讀研究論文并提取每一輸入的數(shù)據(jù),然后對(duì)每一案例分配真或假的輸出結(jié)果。本例中的訓(xùn)練數(shù)據(jù)可能與下表類似。
訓(xùn)練采樣
身高 [mm]
體重 [kg]
N_legs
N_eyes
L_arm [mm]
av_speed [m/s]
f_call [Hz]
Schnick (true/false)
示例 1
1030
45
8
3
420
2.1
14000
TRUE
示例 2
1010
42
8
3
450
2.2
14000
TRUE
示例 3
900
40
7
6
600
6
13000
FALSE
示例 4
1050
43
9
4
400
2.4
12000
TRUE
示例 5
700
35
2
8
320
21
13500
FALSE
示例 6
1070
42
8
3
430
2.4
12000
TRUE
示例 7
1100
40
8
3
430
2.1
11000
TRUE
示例 N
...
...
...
...
...
...
...
...
表 1. schnick 數(shù)據(jù)例表
一旦我們收集了所有的訓(xùn)練輸入和輸出數(shù)據(jù),我們就可以用它訓(xùn)練我們的支持向量機(jī)。在訓(xùn)練過(guò)程中,支持向量機(jī)會(huì)創(chuàng)建一個(gè)七維模型,用以將各種訓(xùn)練示例分類為 ture 或 false。支持向量機(jī)會(huì)不斷創(chuàng)建,直到獲得精確表示訓(xùn)練數(shù)據(jù)(在指定誤差容許范圍之內(nèi))的模型。一旦這項(xiàng)訓(xùn)練結(jié)束,該模型就可以用來(lái)處理新的數(shù)據(jù)點(diǎn),按照 true 或 false 歸類。
支持向量機(jī)到底工作了嗎?
借助 Schnick 案例,我寫了一個(gè)腳本,測(cè)試支持向量機(jī)實(shí)際上是如何很好地處理新的 schnick 的。為了完成這個(gè)測(cè)試,我使用了“支持向量機(jī)學(xué)習(xí)工具”函數(shù)庫(kù)(可以在“應(yīng)用市場(chǎng)”中下載)。
為了針對(duì)這個(gè)案例有效建模,我們首先決定哪些是 Schnick 的實(shí)際屬性。我假定的這些屬性已經(jīng)列在了下表中。如果一只動(dòng)物滿足以下所有標(biāo)準(zhǔn),那么它就是 Schnick……
參數(shù)
下限
上限
身高 [mm]
1000
1100
體重 [kg]
40
50
N_legs
8
10
N_eyes
3
4
L_arm [mm]
400
450
av_speed [m/s]
2
2.5
f_call [Hz]
11000
15000
表 2. 定義 schnick 的參數(shù)匯總
現(xiàn)在我們定義了 Schnick,我們可以用這種定義來(lái)試驗(yàn)支持向量機(jī)。第一步是創(chuàng)建一個(gè)函數(shù):能獲取指定動(dòng)物的 7 個(gè)輸入,然后返回是否為 schnick 的動(dòng)物實(shí)際分類結(jié)果。這個(gè)函數(shù)將用來(lái)生成支持向量機(jī)的訓(xùn)練數(shù)據(jù),同時(shí)在結(jié)束的時(shí)候評(píng)估支持向量機(jī)的性能。可以用以下的函數(shù)完成:
//+------------------------------------------------------------------+ //| This function takes the observation properties of the observed //| animal and based on the criteria we have chosen, returns true/false whether it is a schnick //+------------------------------------------------------------------+ bool isItASchnick(double height,double weight,double N_legs,double N_eyes,double L_arm,double av_speed,double f_call) ?{ ? if(height ? < 1000 ?|| height ? > 1100) ?return(false); ? // If the height is outside the parameters > return(false) ? if(weight ? < 40 ? ?|| weight ? > 50) ? ?return(false); ? // If the weight is outside the parameters > return(false) ? if(N_legs ? < 8 ? ? || N_legs ? > 10) ? ?return(false); ? // If the N_Legs is outside the parameters > return(false) ? if(N_eyes ? < 3 ? ? || N_eyes ? > 4) ? ? return(false); ? // If the N_eyes is outside the parameters > return(false) ? if(L_arm ? ?< 400 ? || L_arm ? ?> 450) ? return(false); ? // If the L_arm ?is outside the parameters > return(false) ? if(av_speed < 2 ? ? || av_speed > 2.5) ? return(false); ? // If the av_speed is outside the parameters > return(false) ? if(f_call ? < 11000 || f_call ? > 15000) return(false); ? // If the f_call is outside the parameters > return(false) ? return(true); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // Otherwise > return(true) ?}
下一步就是創(chuàng)建一個(gè)可生成訓(xùn)練輸入和輸出的函數(shù)。本例中的輸入,將通過(guò)在 7 個(gè)輸入值的各自設(shè)置范圍內(nèi)創(chuàng)建隨機(jī)數(shù)字的方式生成。然后針對(duì)每組隨機(jī)生成的輸入,再使用上面的 isItASchnick() 函數(shù)生成希望的輸出結(jié)果。這在下述函數(shù)中完成:
//+------------------------------------------------------------------+ //| This function takes an empty double array and an empty boolean array, //| and generates the inputs/outputs to be used for training the SVM //+------------------------------------------------------------------+ void genTrainingData(double &inputs[],bool &outputs[],int N) ?{ ? double in[]; ? ? ? ? ? ? ? ? ? ?// Creates an empty double array to be used for temporarily storing the inputs generated ? ArrayResize(in,N_Inputs); ? ? ? // Resize the in[] array to N_Inputs ? ArrayResize(inputs,N*N_Inputs); // Resize the inputs[] array to have a size of N*N_Inputs ? ArrayResize(outputs,N); ? ? ? ? // Resize the outputs[] array to have a size of N ? for(int i=0;i<N;i++) ? ? { ? ? ?in[0]= ? ?randBetween(980,1120); ? ? ?// Random input generated for height ? ? ?in[1]= ? ?randBetween(38,52); ? ? ? ? // Random input generated for weight ? ? ?in[2]= ? ?randBetween(7,11); ? ? ? ? ?// Random input generated for N_legs ? ? ?in[3]= ? ?randBetween(3,4.2); ? ? ? ? // Random input generated for N_eyes ? ? ?in[4]= ? ?randBetween(380,450); ? ? ? // Random input generated for L_arms ? ? ?in[5]= ? ?randBetween(2,2.6); ? ? ? ? // Random input generated for av_speed ? ? ?in[6]= ? ?randBetween(10500,15500); ? // Random input generated for f_call ? ? ?ArrayCopy(inputs,in,i*N_Inputs,0,N_Inputs); ? ? ? ? ? ? ? ? ? ? ? ? // Copy the new random inputs generated into the training input array ? ? ?outputs[i]=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]); // Assess the random inputs and determine if it is a schnick ? ? } ?} //+------------------------------------------------------------------+ //| This function is used to create a random value between t1 and t2 //+------------------------------------------------------------------+ double randBetween(double t1,double t2) ?{ ? return((t2-t1)*((double)MathRand()/(double)32767)+t1); ?}
我們現(xiàn)在有了一系列的輸入和輸出參數(shù),現(xiàn)在到了利用“應(yīng)用市場(chǎng)”的“支持向量機(jī)學(xué)習(xí)工具”創(chuàng)建支持向量機(jī)的時(shí)候了。只要新的支持向量機(jī)創(chuàng)建好,就必須要將訓(xùn)練輸入輸出參數(shù)傳遞給它,并執(zhí)行訓(xùn)練。
void OnStart() ?{ ? double inputs[]; ? ? ? ? ? ? ?// Empty double array to be used for creating training inputs ? bool ? outputs[]; ? ? ? ? ? ? // Empty bool array to be used for creating training inputs ? int ? ?N_TrainingPoints=5000; // Defines the number of training samples to be generated ? int ? ?N_TestPoints=5000; ? ? // Defines the number of samples to be used when testing ? genTrainingData(inputs,outputs,N_TrainingPoints); //Generates the inputs and outputs to be used for training the SVM ? int handle1=initSVMachine(); ? ? ? ? ? ? // Initializes a new support vector machine and returns a handle ? setInputs(handle1,inputs,7); ? ? ? ? ? ? // Passes the inputs (without errors) to the support vector machine ? setOutputs(handle1,outputs); ? ? ? ? ? ? // Passes the outputs (without errors) to the support vector machine ? setParameter(handle1,OP_TOLERANCE,0.05); // Sets the error tolerance parameter to <5% ? training(handle1); ? ? ? ? ? ? ? ? ? ? ? // Trains the support vector machine using the inputs/outputs passed ?}
現(xiàn)在,我們有了一個(gè)支持向量機(jī)并完成了良好的訓(xùn)練,它可以成功分辨 Schnick 了。為了確認(rèn)這一點(diǎn),我們可以測(cè)試最終支持向量機(jī),讓它對(duì)新的數(shù)據(jù)點(diǎn)進(jìn)行分類。首先可以生成隨機(jī)輸入,然后使用 isItASchnick() 函數(shù)來(lái)判斷這些輸入是否對(duì)應(yīng)實(shí)際的 Schnick,然后使用支持向量機(jī)去劃分輸入,并判斷所預(yù)測(cè)的結(jié)果是否與實(shí)際結(jié)果相符。這在下述函數(shù)中完成: