我怎么覺得自己就像小學生在寫青創日記……
知道了pickle是啥。pickle提供了一個簡單的持久化功能。可以將對象以文件的形式存放在磁盤上。
獲得了一些pickle文件,需要找出最快的回歸的方法。
有一個很厲害的人叫Tirthajyoti Sarkar,寫了一篇筆記,比較了八種常用的方法:
他的github上有代碼,我就跑了一遍試試。
結果也正如文中所寫,發現對於多元線性回歸,最快的方法就是
result = np.linalg.lstsq(A, y)
原理應當跟求廣義逆矩陣(MoorePenrose_inverse)是一樣的,詳情見官方文檔:https://numpy.org/doc/stable/reference/generated/numpy.linalg.lstsq.html
這個result返回的是個四元變量。所以也可以寫成
x, residuals, rank, s = np.linalg.lstsq(A, y)
x就是系數矩陣,residuals就要注意了,它是殘差之和!!所以只有一行。哎orz。如果要獲得每個殘差,就簡單計算一下,反正numpy算矩陣乘法快得很。
代碼是這樣的:
1 import pickle 2 import pandas as pd 3 import numpy as np 4 import time 5 from scipy import linspace, polyval, polyfit, sqrt, stats, randn, optimize 6 import statsmodels.api as sm 7 8 file1 = open('D:\實習\啞變量回歸數據\LF001.pkl','rb') #factor 9 #數據從20190121開始有效(第2690列) 10 file2 = open('D:\實習\啞變量回歸數據\sector.pkl','rb') #需要轉置,列名為股票代碼,行名為日期 11 temp= pickle.load(file1) 12 sector = pd.DataFrame(pickle.load(file2)) 13 sector = sector.iloc[:, 2690:] 14 factor = pd.DataFrame(temp.values.T, index=temp.columns, columns=temp.index) 15 factor = factor.iloc[:, 2690:] 16 sector.insert(sector.shape[1], 'temp', 1) #在右面新加一列為1 17 yx = pd.concat([factor, sector], axis=1, sort=False) # 列合並 18 d_yx = yx.dropna() # 刪掉有na的行 19 # 從323列再切成兩個表 20 # n_yx = d_yx.values 21 factor = d_yx.iloc[:, :322] 22 sector = d_yx.iloc[:, 323:] 23 df_dummies = pd.get_dummies(sector[20190121]) 24 sector = df_dummies 25 A = sector.values 26 y = factor.values 27 start = time.time() 28 for i in range(0, 500): 29 result = np.linalg.lstsq(A, y) 30 # x, residuals, rank, s = np.linalg.lstsq(A, y) 31 residuals = y - A.dot(result[0]) 32 end = time.time() 33 print(end-start)
前面數據處理比較周折。因為要用dropna丟掉nan值的數據,所以我是比較蠢的先把兩個表合成一個表,然后dropna完了再拆成兩個表。
pd.get_dummies特別好使,直接就就把行業轉成啞變量了。因為每一列日期都是一樣的,所以我就選了第一天的(sector[20190121])
有一個小技巧就是.values可以把dataframe轉成一個ndarray對象,然后就可以放進lstsq這個函數里用了!
殘差手算一下,用實際值-擬合值:
residuals = y - A.dot(result[0])
最后學到了一個方法。為了確定這個方法的效率,可以打開任務管理器,看性能
然后把程序循環個幾百次,看執行的時候八個線程是不是都是滿的。結果確實是,說明這個本身就是並行處理,效率很高。