以預測股票漲跌案例入門基於SVM的機器學習


    SVM是Support Vector Machine的縮寫,中文叫支持向量機,通過它可以對樣本數據進行分類。以股票為例,SVM能根據若干特征樣本數據,把待預測的目標結果划分成“漲”和”跌”兩種,從而實現預測股票漲跌的效果。

1 通過簡單案例了解SVM的分類作用

    在Sklearn庫里,封裝了SVM分類的相關方法,也就是說,我們無需了解其中復雜的算法,即可用它實現基於SVM的分類。通過如下SimpleSVMDemo.py案例,我們來看下通過SVM庫實現分類的做法,以及相關方法的調用方式。    

1    #!/usr/bin/env python
2    #coding=utf-8
3    import numpy as np
4    import matplotlib.pyplot as plt
5    from sklearn import svm
6    #給出平面上的若干點
7    points = np.r_[[[-1,1],[1.5,1.5],[1.8,0.2],[0.8,0.7],[2.2,2.8],[2.5,3.5],[4,2]]]
8    #按0和1標記成兩類
9    typeName = [0,0,0,0,1,1,1]

    在第5行里,我們引入了基於SVM的庫。在第7行,我們定義了若干個點,並在第9行把這些點分成了兩類,比如[-1,1]點是第一類,而[4,2]是第二類。

    這里請注意,在第7行定義點的時候,是通過np.r_方法,把數據轉換成“列矩陣”,這樣做的目的是讓數據結構滿足fit方法的要求。     

10	#建立模型
11	svmTool = svm.SVC(kernel='linear')
12	svmTool.fit(points,typeName)  #傳入參數
13	#確立分類的直線
14	sample = svmTool.coef_[0] #系數
15	slope = -sample[0]/sample[1]  #斜率
16	lineX = np.arange(-2,5,1)#獲取-2到5,間距是1的若干數據
17	lineY = slope*lineX-(svmTool.intercept_[0])/sample[1]

  在第11行里,我們創建了基於SVM的對象,並指定該SVM模型采用比較常用的“線性核”來實現分類操作。

      在第14行,通過fit訓練樣本。這里fit方法和之前基於線性回歸案例中的fit方法是一樣的,只不過這里是基於線性核的相關算法,而之前是基於線性回歸的相關算法(比如最小二乘法)。訓練完成后,通過第14行和第15行的代碼,我們得到了能分隔兩類樣本的直線,包括直線的斜率和截距,並通過第16行和第17行的代碼設置了分隔線的若干個點。    

18	#畫出划分直線
19	plt.plot(lineX,lineY,color='blue',label='Classified Line')
20	plt.legend(loc='best') #繪制圖例
21	plt.scatter(points[:,0],points[:,1],c='R')
22	plt.show()

  計算完成后,我們通過第19行的plot方法繪制了分隔線,並在第21行通過scatter方法繪制所有的樣本點。由於points是“列矩陣”的數據結構,所以是用points[:,0]來獲取繪制點的 x坐標,用points[:,1]來獲取y坐標,最后是通過第22行的show方法繪制圖形。運行上述代碼,我們能看到如下圖13.8的效果,從中我們能看到,藍色的邊界線能有效地分隔兩類樣本。

    

    從這個例子中我們能看到,SVM的作用是,根據樣本,訓練出能划分不同種類數據的邊界線,由此實現“分類”的效果。而且,在根據訓練樣本確定好邊界線的參數后,還能根據其它沒有明確種類樣本,計算出它的種類,以此實現“預測”效果。 

2 數據標准化處理

    標准化(normalization)處理是將特征樣本按一定算法進行縮放,讓它們落在某個范圍比較小的區間,同時去掉單位限制,讓樣本數據轉換成無量綱的純數值。

    在用機器學習方法進行訓練時,一般需要進行標准化處理,原因是Sklearn等庫封裝的一些機器學習算法對樣本有一定的要求,如果有些特征值的數量級偏離大多數特征值的數量級,或者有特征值偏離正態分布,那么預測結果會不准確。

    需要說明的是,雖然在訓練前對樣本進行了標准化處理,改變了樣本值,但由於在標准化的過程中是用同一個算法對全部樣本進行轉換,屬於“數據優化”,不會對后繼的訓練起到不好的作用。

    這里我們是通過sklearn庫提供的preprocessing.scale方法實現標准化,該方法是讓特征值減去平均值然后除以標准差。通過如下ScaleDemo.py案例,我們實際用下preprocessing.scale方法。     

1	#!/usr/bin/env python
2	#coding=utf-8
3	from sklearn import preprocessing
4	import numpy as np
5	
6	origVal = np.array([[10,5,3],
7	                   [8,6,12],
8	                   [14,7,15]])
9	#計算均值
10	avgOrig = origVal.mean(axis=0)
11	#計算標准差
12	stdOrig=origVal.std(axis=0)
13	#減去均值,除以標准差
14	print((origVal-avgOrig)/stdOrig)
15	scaledVal=preprocessing.scale(origVal)
16	#直接輸出preprocessing.scale后的結果
17	print(scaledVal)

  在第6行里,我們初始化了一個長寬各為3的矩陣,在第10行,通過mean方法計算了該矩陣的均值,在第12行則通過std方法計算標准差。

      第14行是用原始值減去均值,再除以標准差,在第17行,是直接輸出preprocessing.scale的結果。第14行和第17行的輸出結果相同,均是下值,從中我們驗證了標准化的具體做法。    

1	[[-0.26726124 -1.22474487 -1.37281295]
2	 [-1.06904497  0.          0.39223227]
3	 [ 1.33630621  1.22474487  0.98058068]]

   

3 預測股票漲跌

    在之前的案例中,我們用基於SVM的方法,通過一維直線來分類二維的點。據此可以進一步推論:通過基於SVM的方法,我們還可以分類具有多個特征值的樣本。

    比如可以通過開盤價、收盤價、最高價、最低價和成交量等特征值,用SVM的算法訓練出這些特征值和股票“漲“和“跌“的關系,即通過特征值划分指定股票“漲”和“跌”的邊界,這樣的話,一旦輸入其它的股票特征數據,即可預測出對應的漲跌情況。在如下的PredictStockBySVM.py案例中,我們給出了基於SVM預測股票漲跌的功能。     

1	#!/usr/bin/env python
2	#coding=utf-8
3	import pandas as pd 
4	from sklearn import svm,preprocessing
5	import matplotlib.pyplot as plt
6	origDf=pd.read_csv('D:/stockData/ch13/6035052018-09-012019-05-31.csv',encoding='gbk')
7	df=origDf[['Close', 'Low','Open' ,'Vol','Date']]
8	#diff列表示本日和上日收盤價的差
9	df['diff'] = df["Close"]-df["Close"].shift(1)
10	df['diff'].fillna(0, inplace = True)
11	#up列表示本日是否上漲,1表示漲,0表示跌
12	df['up'] = df['diff']   
13	df['up'][df['diff']>0] = 1
14	df['up'][df['diff']<=0] = 0
15	#預測值暫且初始化為0
16	df['predictForUp'] = 0

  第6行里,我們從指定文件讀取了包含股票信息的csv文件,該csv格式的文件其實是從網絡數據接口獲取得到的,具體做法可以參考前面博文。

    從第9行里,我們設置了df的diff列為本日收盤價和前日收盤價的差值,通過第12行到第14行的代碼,我們設置了up列的值,具體是,如果當日股票上漲,即本日收盤價大於前日收盤價,則up值是1,反之如果當日股票下跌,up值則為0。

    在第16行里,我們在df對象里新建了表示預測結果的predictForUp列,該列的值暫且都設置為0,在后繼的代碼里,將根據預測結果填充這列的值。    

17	#目標值是真實的漲跌情況
18	target = df['up']
19	length=len(df)
20	trainNum=int(length*0.8)
21	predictNum=length-trainNum
22	#選擇指定列作為特征列
23	feature=df[['Close', 'High', 'Low','Open' ,'Volume']]
24	#標准化處理特征值
25	feature=preprocessing.scale(feature)

  在第18行里,我們設置訓練目標值是表示漲跌情況的up列,在第20行,設置了訓練集的數量是總量的80%,在第23行則設置了訓練的特征值,請注意這里去掉了日期這個不相關的列,而且,在第25行,對特征值進行了標准化處理。    

26	#訓練集的特征值和目標值
27	featureTrain=feature[1:trainNum-1]
28	targetTrain=target[1:trainNum-1]
29	svmTool = svm.SVC(kernel='liner')
30	svmTool.fit(featureTrain,targetTrain)

  在第27行和第28行里,我們通過截取指定行的方式,得到了特征值和目標值的訓練集,在第26行里,以線性核的方式創建了SVM分類器對象svmTool。

     在第30行里,通過fit方法,用特征值和目標值的訓練集訓練svmTool分類對象。從上文里我們已經看到,訓練所用的特征值是開盤收盤價、最高最低價和成交量,訓練所用的目標值是描述漲跌情況的up列。在訓練完成后,svmTool對象中就包含了能划分股票漲跌的相關參數。

31	predictedIndex=trainNum
32	#逐行預測測試集
33	while predictedIndex<length:
34	    testFeature=feature[predictedIndex:predictedIndex+1]            
35	    predictForUp=svmTool.predict(testFeature)    
36	    df.ix[predictedIndex,'predictForUp']=predictForUp    
37	    predictedIndex = predictedIndex+1

    在第33行的while循環里,我們通過predictedIndex索引值,依次遍歷測試集。

    在遍歷過程中,通過第35行的predict方法,用訓練好的svmTool分類器,逐行預測測試集中的股票漲跌情況,並在第36行里,把預測結果設置到df對象的predictForUp列中。      

38	#該對象只包含預測數據,即只包含測試集
39	dfWithPredicted = df[trainNum:length]
40	#開始繪圖,創建兩個子圖
41	figure = plt.figure()
42	#創建子圖     
43	(axClose, axUpOrDown) = figure.subplots(2, sharex=True)
44	dfWithPredicted['Close'].plot(ax=axClose)
45	dfWithPredicted['predictForUp'].plot(ax=axUpOrDown,color="red", label='Predicted Data')
46	dfWithPredicted['up'].plot(ax=axUpOrDown,color="blue",label='Real Data')
47	plt.legend(loc='best') #繪制圖例
48	#設置x軸坐標標簽和旋轉角度
49	major_index=dfWithPredicted.index[dfWithPredicted.index%2==0]
50	major_xtics=dfWithPredicted['Date'][dfWithPredicted.index%2==0]
51	plt.xticks(major_index,major_xtics)
52	plt.setp(plt.gca().get_xticklabels(), rotation=30) 
53	plt.title("通過SVM預測603505的漲跌情況")
54	plt.rcParams['font.sans-serif']=['SimHei']
55	plt.show()

  由於在之前的代碼里,我們只設置測試集的predictForUp列,並沒有設置訓練集的該列數據,所以在第39行里,用切片的手段,把測試集數據放置到dfWithPredicted對象中,請注意這里切片的起始和結束值是測試集的起始和結束索引值。至此完成了數據准備工作,在之后的代碼里,我們將用matplotlib庫開始繪圖。

    在第43行里,我們通過subplots方法設置了兩個子圖,並通過sharex=True讓這兩個子圖的x軸具有相同的刻度和標簽。在第44行代碼里,在axClose子圖中,我們用plot方法繪制了收盤價的走勢。在第45行代碼里,在axUpOrDown子圖中,我們繪制了預測到的漲跌情況,而在第46行里,還是在axUpOrDown子圖里,繪制了這些天的股票真實的漲跌情況。

    在第49行到第52行的代碼里,我們設置了x標簽的文字以及旋轉角度,這樣做的目的是讓標簽文字看上去不至於太密集。在第53行里,我們設置了中文標題,由於要顯示中文,所以需要第54行的代碼,最后在55行通過show方法展示了圖片。運行上述代碼,能看到如下圖所示的效果。

    

    其中上圖展示了收盤價,下圖的藍色線條表示真實的漲跌情況,0表示跌,1表示上漲,而紅色則表示預測后的結果。

4 結論

     對比一下,雖有偏差,但大體相符。綜上所述,本案例是數學角度,演示了通過SVM分類的做法,包括如果划分特征值和目標值,如何對樣本數據進行標准化處理,如何用訓練數據訓練SVM,還有如何用訓練后的結果預測分類結果。 

5 總結和版權說明

    本文是給程序員加財商系列,之前還有兩篇博文

 
    
    本文的內容即將出書,在出版的書里,是用股票案例和大家講述Python入門時的知識點,敬請期待
    

    有不少網友轉載和想要轉載我的博文,本人感到十分榮幸,這也是本人不斷寫博文的動力。關於本文的版權有如下統一的說明,抱歉就不逐一回復了。

    1 本文可轉載,無需告知,轉載時請用鏈接的方式,給出原文出處,別簡單地通過文本方式給出,同時寫明原作者是hsm_computer。

    2 在轉載時,請原文轉載 ,謝絕洗稿。否則本人保留追究法律責任的權利。

 

 


免責聲明!

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



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