将其他数据合并到我的 TFIDF 数组

Combine additional data to my TFIDF array

我正在尝试使用 scikit-learn 创建文本分类模型。起初,我只使用文本的 tfidf 数组作为特征。我的数据集的结构如下所示(数据集存储在名为 df 的 pandas 数据框中):

>>>df.head(2)

       id_1    id_2    id_3    target    text
       11      454     320     197       some text here
       15      440     111     205       text goes here too

>>>df.info()

    Data columns (total 5 columns):
     #   Column    Non-Null Count   Dtype 
    ---  ------    --------------   ----- 
     0   id_1      500 non-null     uint16
     1   id_2      500 non-null     uint16
     2   id_3      500 non-null     uint16
     3   target    500 non-null     uint16
     4   text      500 non-null     object

因此,我拆分了 train/test 数据集并继续创建 tfidf 向量并转换数据以进行训练和测试。

X_train, X_test, y_train, y_test = train_test_split(df['text'], df['target'], random_state=0)

vectorizer = TfidfVectorizer(max_features=500, decode_error="ignore", ngram_range=(1, 2))
vectorizer.fit(X_train)

X_train_tfidf = vectorizer.transform(X_train)
X_test_tfidf  = vectorizer.transform(X_test)

到目前为止,代码显然工作正常。但是,需要改进算法,包括另一个功能。对于此改进,我想将 id_1 列添加到我的特征中(它可能是我们 ML 模型的重要信息)。因此,除了我的 tfidf 矩阵之外,我还想添加此列 (id_1) 和我的新功能,以便我可以将其作为参数传递来训练模型。

我尝试过的:

X_train, X_test, y_train, y_test = train_test_split(df['text'], df['target'], random_state=0)

vectorizer = TfidfVectorizer(max_features=500, decode_error="ignore", ngram_range=(1, 2))
vectorizer.fit(X_train)

X_train_tfidf = vectorizer.transform(X_train)
X_test_tfidf  = vectorizer.transform(X_test)

X_train_all_features = pd.concat([pd.DataFrame(X_train_tfidf.toarray()), df['id_1']], axis = 1)

所以,我的结构形状是

>>>print(X_train_tfidf.shape)

(37, 500) # as expected (I'm loading 50 lines, so this is about 75%)

>>>print(X_train_all_features.shape)

(50, 501) # n of columns is expected, but not the lines, because the df[id_1] was not splited in train_test_split function

简而言之,我想传递给我的 ML 算法,如下图所示 - 我的 tfidf 向量和我的 id_1 特征:

我觉得我遗漏了一些非常基本的东西,但即使进行了所有研究,我仍然能够令人满意地解决我的问题。老实说,我迷失在问题的那一部分,我不知道如何从这里发展

理想情况下,您希望先添加新列,然后再进行拆分。如果出于某种原因这不合适,我建议如下:

您需要 X_train_tfidf 中的观察索引,以便能够从 df['id_1'] 中获得相应的值,因此不能简单地连接整个 df['id_1'] 列到 X_train_tfidf。尝试替换

X_train_all_features = pd.concat([pd.DataFrame(X_train_tfidf.toarray()), df['id_1']], axis = 1)

通过以下代码:

X_train_all_features = X_train_tfidf.copy()
X_train_all_features['id_1'] = df.loc[X_train_tfidf.index.values, 'id_1']

让我知道这是否有效。

你的 df 有 50 行,X_train_tfidf 37,pd.concat() returns 数据帧有 50 行,剩下的 13 行用 NaN 填充。

您将特征的所有值都添加到训练 tf-idf 中,这不是您想要的。

添加新列时不要搞乱train/val拆分,我建议在原始数据帧的索引上进行拆分

idx_train, idx_test = train_test_split(df.index, random_state=0)
X_train, y_train = df.loc[idx_train, 'text'],  df.loc[idx_train, 'target']
# same for test

然后您可以添加 "id1" 功能:

X_train_all_features = pd.concat([pd.DataFrame(X_train_tfidf.toarray()), df.loc[idx_train, 'id_1']], axis = 1)

更新 我看不出将稀疏矩阵转换为 pandas 数据帧的原因。使用足够大的数据集会非常慢。相反,将您的特征添加到矩阵中,以便稍后在下游算法中使用它。

from scipy.sparse import hstack 
X_train_tfidf = hstack([X_train_tfidf, df.loc[idx_train, 'id1'].values.reshape(-1, 1)])

检查尺寸

X_train_tfidf.shape # should be (37, 501)