Вот что я нашел в связи с вашим вопросом.В моем ответе используется подход dask
для распределенных вычислений, а также просто общая очистка вашего текущего подхода.
Я создал меньший поддельный набор данных с 1000 переменных, одна будет результатом, а две -быть baseterms
, так что на самом деле есть 997 переменных для прохождения.
import dask
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
#make some toy data for the case you showed
df_train = pd.DataFrame(np.random.randint(low=0,high=10,size=(10000, 1000)))
df_train.columns = ['var'+str(x) for x in df_train.columns]
baseterms = 'var1+var2'
VarsOut = df_train.columns[3:]
Базовая линия для вашего текущего кода (20 с + - 858 мс):
%%timeit
TStatsOut=pd.DataFrame()
for i in VarsOut:
xstrout='+'.join([baseterms,i])
fout='var0~'+xstrout
modout = smf.ols(fout, data=df_train).fit()
j=pd.DataFrame(modout.pvalues,index=[i],columns=['PValue'])
k=pd.DataFrame(modout.params,index=[i],columns=['Coeff'])
s=pd.concat([j, k], axis=1, join_axes=[j.index])
TStatsOut=TStatsOut.append(s)
Создана функция для удобства чтения, но возвращает вместо нее только pval и коэффициент регрессии для каждой проверяемой переменнойиз одной строки данных.
def testVar(i):
xstrout='+'.join([baseterms,i])
fout='var0~'+xstrout
modout = smf.ols(fout, data=df_train).fit()
pval=modout.pvalues[i]
coef=modout.params[i]
return pval, coef
Теперь работает с (14,1 с + - 982 мс)
%%timeit
pvals=[]
coefs=[]
for i in VarsOut:
pval, coef = testVar(i)
pvals.append(pval)
coefs.append(coef)
TStatsOut = pd.DataFrame(data={'PValue':pvals, 'Coeff':coefs},
index=VarsOut)[['PValue','Coeff']]
Использование Dask с задержкой для параллельной обработки.Имейте в виду, что каждое созданное отложенное задание также вызывает небольшие накладные расходы, поэтому иногда это может быть не выгодно, но будет зависеть от вашего точного набора данных и того, сколько времени занимает регрессия.Мой пример данных может быть слишком простым, чтобы показать какую-либо выгоду.
#define the same function as before, but tell dask how many outputs it has
@dask.delayed(nout=2)
def testVar(i):
xstrout='+'.join([baseterms,i])
fout='var0~'+xstrout
modout = smf.ols(fout, data=df_train).fit()
pval=modout.pvalues[i]
coef=modout.params[i]
return pval, coef
Теперь пропустите 997 переменных-кандидатов и создайте тот же кадр данных с задержкой dask.(18,6 с + - 588 мс)
%%timeit
pvals=[]
coefs=[]
for i in VarsOut:
pval, coef = dask.delayed(testVar)(i)
pvals.append(pval)
coefs.append(coef)
pvals, coefs = dask.compute(pvals,coefs)
TStatsOut = pd.DataFrame(data={'PValue':pvals, 'Coeff':coefs},
index=VarsOut)[['PValue','Coeff']]
Опять-таки, отсроченная работа создает дополнительные накладные расходы, поскольку создает задачи для отправки на многие процессоры, поэтому любой выигрыш в производительности будет зависеть от времени, которое ваши данные на самом деле занимаютрегрессии, а также сколько процессоров у вас есть.Dask можно масштабировать с одной рабочей станции до кластера рабочих станций.