如何从分类变量创建交互设计矩阵?

时间:2014-05-06 14:26:19

标签: python pandas scikit-learn

我来自主要在R工作的统计建模/机器学习,并希望提高我的Python技能。我想知道在python中创建分类交互(任意程度)的设计矩阵的最佳方法。

玩具示例:

import pandas as pd
from urllib import urlopen
page = urlopen("http://www.shatterline.com/MachineLearning/data/tennis_anyone.csv")
df = pd.read_csv(page)
df.head(n=5)

enter image description here

让我们说我们想要创建Outlook,Temp和Humidity之间的交互。有没有一种有效的方法来做到这一点?我可以在熊猫中手动做这样的事情:

OutTempFact=pd.Series(pd.factorize(pd.lib.fast_zip([df.Outlook.values, df.Temperature.values]))[0],name='OutTemp')
OutHumFact=pd.Series(pd.factorize(pd.lib.fast_zip([df.Outlook.values, df.Humidity.values]))[0],name='OutHum')
TempHumFact=pd.Series(pd.factorize(pd.lib.fast_zip([df.Temperature.values, df.Humidity.values]))[0],name='TempHum')

IntFacts=pd.concat([OutTempFact,OutHumFact,TempHumFact],axis=1)
IntFacts.head(n=5)

enter image description here

然后我可以将其传递给scikit-learn one-hot编码器,但是可能有更好的,更少手动的方式来创建分类变量之间的交互,而无需逐步完成每个组合。

import sklearn as sk
enc = sk.preprocessing.OneHotEncoder()
IntFacts_OH=enc.fit_transform(IntFacts)
IntFacts_OH.todense()

2 个答案:

答案 0 :(得分:3)

如果您使用设计矩阵上的OneHotEncoder来获得单热设计矩阵,那么交互只不过是列之间的乘法。如果X_1hot是您的热门设计矩阵,其中样本是行,那么对于二阶交互,您可以编写

X_2nd_order = (X_1hot[:, np.newaxis, :] * X_1hot[:, :, np.newaxis]).reshape(len(X_1hot), -1)

会有重复的互动,它也会包含原始功能。

任意顺序会使你的设计矩阵爆炸。如果你真的想这样做,那么你应该研究使用多项式内核进行内核化,这样可以轻松地进入任意度数。

使用您提供的数据框,我们可以按照以下步骤操作。首先,从数据框中构建单热设计的手动方法:

import numpy as np
indicators = []
state_names = []
for column_name in df.columns:
    column = df[column_name].values
    one_hot = (column[:, np.newaxis] == np.unique(column)).astype(float)
    indicators.append(one_hot)
    state_names = state_names + ["%s__%s" % (column_name, state) for state in np.unique(column)]

X_1hot = np.hstack(indicators)

然后将列名存储在state_names中,指标矩阵为X_1hot。然后我们计算二阶特征

X_2nd_order = (X_1hot[:, np.newaxis, :] * X_1hot[:, :, np.newaxis]).reshape(len(X_1hot), -1)

为了知道二阶矩阵的列的名称,我们像这样构造它们

from itertools import product
one_hot_interaction_names = ["%s___%s" % (column1, column2) 
                             for column1, column2 in product(state_names, state_names)]

答案 1 :(得分:2)

现在遇到一个类似的问题,想要一种简单的方法来整合来自文献的基线OLS模型的特定交互以与ML appraches进行比较,我遇到了 patsy http://patsy.readthedocs.io/en/latest/overview.html )和这个scikit-learn integration patsylearn https://github.com/amueller/patsylearn)。

下面,如何将交互变量传递给模型:

from patsylearn import PatsyModel
model = PatsyModel(sk.linear_model.LinearRegression(), "Play-Tennis ~ C(Outlook):C(Temperature) + C(Outlook):C(Humidity) + C(Outlook):C(Wind)")

注意,在这个公式中你不需要OneHotEncoder(),因为公式中的C告诉Patsy解释器这些是分类变量,它们是一个热门编码的你!但请在他们的文档中详细了解它(http://patsy.readthedocs.io/en/latest/categorical-coding.html)。

或者,您也可以使用我更喜欢的PatsyTransformer,因为它可以轻松集成到scikit-learn Pipelines中:

from patsylearn import PatsyTransformer
transformer = PatsyTransformer("C(Outlook):C(Temperature) + C(Outlook):C(Humidity) + C(Outlook):C(Wind)")