2016-12-16 44 views
0

我想在数据库中的数据项目中使用scikit-learn Pipelines的FeatureUnion功能。我在如何构建我正在做的事情方面遇到了一些基本问题。Sci-Kit通过不同的行数学习FeatureUnion

我从数据库中的两个不同表创建两个功能。我有一个fetch_x1,fetch_x2方法来从数据库表中获取感兴趣的数据作为pandas DataFrames。我将这两个DataFrames打包成一个数据框字典。在每个变压器中,我解压缩感兴趣的DataFrame并对其进行操作。我有点关注这个post的模式。

我的代码如下:

class Feature1Extractor(TransformerMixin): 

    def transform(self, dictionary_of_dataframes): 
     df = dictionary_of_dataframes['feature1_raw_data'] 
     x = df.groupby('user_id').count()['x1'] 
     return df 

class Feature2Extractor(TransformerMixin): 

    def transform(self, dictionary_of_dataframes): 
     df = dictionary_of_dataframes['feature2'] 
     x = df.groupby('user_id').sum()['x2'] 
     return x 

pipeline = Pipeline([ 
    ('union', FeatureUnion(
     transformer_list=[ 
      ('feature1', Feature1Extractor()), 
      ('feature2', Feature2Extractor())])), 
    ('null', None) 
]) 

pipeline.transform(dictionary_of_dataframes) 

我遇到另一个更基本的问题 - 改造后说出来的每个管道的两个特征矩阵有不同数量的行的。因此,FeatureUnion结束时的简单堆叠失败如下:

ValueError: all the input array dimensions except for the concatenation axis must match exactly 

这是我拥有的数据的基础。 feature1表中不存在多个user_id,类似地,feature2表中没有多个user_id。这是数据的基础 - 如果用户在feature1表中没有数据,他/她从未在应用中使用该功能,例如没有数据=没有参与该功能。为了让这个例子明确,这里的两个DF的正在传递到每个变压器的例子:

DF(为特征1)

user_id, x1, timestamp 
1, 'click', 1/1/2016 
1, 'click', 1/2/2016 
2, 'click', 1/2/2016 

DF(为特征2)

user_id, x2, timestamp 
2, 12.3, 1/2/2016 
3, 14,5, 1/4/2016 

注特征1的DataFrame没有用户3,特征2的DataFrame没有用户1.当我没有使用管道时,我会在最终的合并数据框上做一个外连接,然后fillna(0),例如

merged_df = pd.merge(df1, df1, how='outer', left_on=['user_id'], right_on=['user_id']) 
final_df = merged_df.fillna(0) 

但是似乎没有任何方法可以使用FeatureUnion方法来实现此目的。我似乎没有想到在Pipeline框架中有一个干净的解决方法......我必须运行单独的管道,对它们进行转换,在pandas中执行外连接和fillna,然后将完成的功能矩阵运行到下游建模管道?有没有更好的办法?展望社区寻求帮助。

注:我不知道user_ids之前。我根据时间戳范围查询表格,而不是user_id。查询本身告诉我应该在训练(或测试)中设置哪些用户。

+0

很难跟随你的要求。给我们一些示例数据或一个小的输入/输出,以便我们可以验证您遇到的问题。我不确定为什么你不能填充一个数据集,使其具有与其他数据行相同的行数(用“None”或其他填充),然后执行FeatureUnion – mwm314

+0

您是对的,我将编辑适当的......我不知道所有的user_ids在手之前 - 这就是为什么我正在做一个外连接......我不想单独跟踪这个。我将以一个很好的例子来编辑这个以更加专注。 –

回答

0

为什么不建立自己的基于熊猫的工会? 这样的事情......(我没有测试过,只是看到了这个想法)

class DataMerging(BaseEstimator): 

    def __init__(self): 
     return self 

    def fit(self, x, y=None): 
     return self 

    def transform(self, dfs): 
     df1, df2 = dfs 
     merged_df = pd.merge(df1, df2, how='outer', left_on=['user_id'], right_on=['user_id']).fillna(0) 
     return merged_df.values #(return shape (n_features, n_samples)) 


pipeline = Pipeline([ 
    ('union', DataMerging, 
    ('other thing', ...) 
])   

pipeline.fit(df1, df2) 
+0

好吧,这很有趣 - 但我不完全理解这是如何适应管道描述...此外,我应该继承FeatureUnion? –