具有混合数据类型(文本、数字、分类)的 Python scikit-learn 分类

Posted

技术标签:

【中文标题】具有混合数据类型(文本、数字、分类)的 Python scikit-learn 分类【英文标题】:Python scikit-learn classification with mixed data types (text, numerical, categorical) 【发布时间】:2019-04-01 01:50:47 【问题描述】:

我正在尝试使用 Pandas 和 scikit-learn 在 Python 中执行分类。我的数据集包含文本变量、数值变量和分类变量的混合体。

假设我的数据集如下所示:

Project Cost        Project Category        Project Description       Project Outcome
12392.2             ABC                     This is a description     Fully Funded
493992.4            DEF                     Stack Overflow rocks      Expired

我需要预测变量Project Outcome。这是我所做的(假设df 包含我的数据集):

    我将类别Project CategoryProject Outcome 转换为数值

    df['Project Category'] = df['Project Category'].factorize()[0]
    df['Project Outcome'] = df['Project Outcome'].factorize()[0]
    

数据集现在看起来像这样:

Project Cost        Project Category        Project Description       Project Outcome
12392.2             0                       This is a description     0
493992.4            1                       Stack Overflow rocks      1

    然后我使用TF-IDF处理文本列

    tfidf_vectorizer = TfidfVectorizer()
    df['Project Description'] = tfidf_vectorizer.fit_transform(df['Project Description'])
    

数据集现在看起来像这样:

Project Cost        Project Category        Project Description       Project Outcome
12392.2             0                       (0, 249)\t0.17070240732941433\n (0, 304)\t0..     0
493992.4            1                       (0, 249)\t0.17070240732941433\n (0, 304)\t0..     1

    所以既然所有变量现在都是数值,我想我最好开始训练我的模型

    X = df.drop(columns=['Project Outcome'], axis=1)
    y = df['Project Outcome']
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
    model = MultinomialNB()
    model.fit(X_train, y_train)
    

但我在尝试执行model.fit 时收到错误ValueError: setting an array element with a sequence.。当我打印X_train 时,我注意到Project Description 出于某种原因被NaN 替换了。

对此有任何帮助吗?有没有一种使用具有各种数据类型的变量进行分类的好方法?谢谢。

【问题讨论】:

你能不能在所有转换之前尝试做df.isnull().sum().sum() 如果这就是您的意思,则没有缺失值,它们在上述步骤之前已从数据集中删除。 【参考方案1】:

替换这个

df['Project Description'] = tfidf_vectorizer.fit_transform(df['Project Description'])

df['Project Description'] = tfidf_vectorizer.fit_transform(df['Project Description']).toarray()

你也可以使用:tfidf_vectorizer.fit_transform(df['Project Description']).todense()

此外,您不应简单地将类别转换为数字。例如,如果您将 A、B 和 C 转换为 0,1 和 2。它们被视为 2>1>0,因此 C>B>A 通常不是这种情况,因为 A 与 B 和 C 不同。对于你可以使用 One-Hot-Encoding(在 Pandas 中你可以使用 'get_dummies')。您可以将以下代码用于所有分类特征。

#df has all not categorical features
featurelist_categorical = ['Project Category', 'Feature A',
           'Feature B']

for i,j in zip(featurelist_categorical, ['Project Category','A','B']):
  df = pd.concat([df, pd.get_dummies(data[i],prefix=j)], axis=1)

特征前缀不是必需的,但在多个分类特征的情况下会特别帮助您。

此外,如果您出于某种原因不想将功能拆分为数字,则可以使用 H2O.ai。使用 H2O,您可以直接将分类变量作为文本输入模型。

【讨论】:

【参考方案2】:

问题出现在第 2 步,tfidf_vectorizer.fit_transform(df['Project Description']),因为 tfidf_vectorizer.fit_transform returns a sparse matrix,然后以压缩形式存储在 df['Project Description'] 列中。您希望将结果保留为模型训练和测试的稀疏(或不太理想的密集)矩阵。这是以密集形式准备数据的示例代码

import pandas as pd
import numpy as np
df = pd.DataFrame('project_category': [1,2,1], 
                   'project_description': ['This is a description','*** rocks', 'Another description'])

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf_vectorizer = TfidfVectorizer()
X_tfidf = tfidf_vectorizer.fit_transform(df['project_description']).toarray()
X_all_data_tfidf = np.hstack((df['project_category'].values.reshape(len(df['project_category']),1), X_train_tfidf))

我们在“project_category”中添加的最后一行,如果您想将其作为一个特征包含在您的模型中。

【讨论】:

以上是关于具有混合数据类型(文本、数字、分类)的 Python scikit-learn 分类的主要内容,如果未能解决你的问题,请参考以下文章

在具有不同字段的现有混合数字和字符串文本文件上写入

文本类型自变量到数字类型火花朴素贝叶斯

c# 解决读取Excel混合文本类型,数据读取失败的解决方法

选择分类算法对名义数据和数字数据的混合进行分类?

随机森林的混合预测器类型

使用混合数字和分类数据进行无监督异常检测