第二周:python實現線性回歸(啞變量回歸)的高效方法


我怎么覺得自己就像小學生在寫青創日記……

知道了pickle是啥。pickle提供了一個簡單的持久化功能。可以將對象以文件的形式存放在磁盤上。

獲得了一些pickle文件,需要找出最快的回歸的方法。

有一個很厲害的人叫Tirthajyoti Sarkar,寫了一篇筆記,比較了八種常用的方法:

https://www.freecodecamp.org/news/data-science-with-python-8-ways-to-do-linear-regression-and-measure-their-speed-b5577d75f8b/

他的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])

最后學到了一個方法。為了確定這個方法的效率,可以打開任務管理器,看性能

 

 然后把程序循環個幾百次,看執行的時候八個線程是不是都是滿的。結果確實是,說明這個本身就是並行處理,效率很高。


免責聲明!

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



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