如何使用词袋使训练集和测试集大小相同

How do I make train and test set the same size using bag of words

我想用词袋来训练回归模型。但是,我不想在我的火车和测试集之间发生信息泄漏。所以,这意味着我需要在与测试集分开的训练集上创建一个词向量。我运行这个代码

def bow (tokens, data):
    tokens = tokens.apply(nltk.word_tokenize)
    cvec = CountVectorizer(min_df = .01, max_df = .95, ngram_range=(1,2), tokenizer=lambda doc:doc, lowercase=False)
    cvec.fit(tokens)
    cvec_counts = cvec.transform(tokens)
    cvec_counts_bow = cvec_counts.toarray()
    vocab = cvec.get_feature_names()
    bow_model = pd.DataFrame(cvec_counts_bow, columns=vocab)
    return bow_model

X_train = bow(train['clean_text'], train)
X_test = bow(test['clean_text'], test)

vocab = list(X_train.columns)

但我的数据框的形状是 X_train: (300, 730) 和 X_test (35, 1661) 我的测试集中有比我的训练集更多的独特词——因为训练集太小了——而且词不匹配。 X_train 中有些词不在 X_test 中,反之亦然。我想从 X_train 创建一个词汇列表,然后只保留 X_test 中的列,但这似乎不对。

如何将 X_train 中的词汇匹配到 X_test 中?

您似乎为训练集和测试集创建了不同的词汇。 您可以尝试从 bow 函数中移动下一个代码,并仅创建一个基于训练集的词汇。你也不需要使用 nltk.word_tokenize 因为 CountVectorizer 已经有了 tokenizer:

cvec = CountVectorizer(min_df = .01, max_df = .95, ngram_range=(1,2), lowercase=False)
cvec.fit(train['clean_text'])
vocab = cvec.get_feature_names() 
print(vocab)

然后更改弓函数:

def bow (tokens, vocab, cvec):
    cvec_counts = cvec.transform(tokens)
    cvec_counts_bow = cvec_counts.toarray()
    bow_model = pd.DataFrame(cvec_counts_bow, columns=vocab)
    return bow_model

X_train = bow(train['clean_text'], vocab, cvec)
X_test = bow(test['clean_text'], vocab, cvec)

或者看看我是怎么做到的。

首先,我只使用训练集创建词汇。此外,我只使用该组和其他组中更常见的词,例如 '<UNK>'.

您可以为此使用下一个代码:

 def create_vocab(all_tokens, vocab_size):   
     token_counts = Counter(all_tokens)   
     token_counts = token_counts.most_common()[:vocab_size]   
     vocab_list = ['<UNK>'] + [token for token, _ in token_counts]   
     return vocab_list

创建 vocab 之后,我将它用于词袋,如下所示:

 def bag_of_words(tokens, vocab_list):
     result = [0] * len(vocab_list)
     for t in tokens:
       if t not in vocab_list:
         t = '<UNK>'
     result[vocab_list.index(t)] += 1
     return result

使用此代码我创建了一个词袋,其中包括我的词汇表中的所有单词(仅使用训练集创建)和 '<UNK>' 不在我的词汇表中的单词的符号。

有一个示例,我如何 运行 此代码:

vocab_list = create_vocab(list(chain.from_iterable(tokens_train)), 5000)

bag_of_words_train = []
for token in tokens_train:
  bag_of_words_train.append(bag_of_words(token, vocab_list))

bag_of_words_test = []
for token in tokens_test:
  bag_of_words_test.append(bag_of_words(token, vocab_list))