W2VTransformer:只用一个单词作为输入?



以下可重现脚本用于计算 Word2Vec 分类器的准确性,并在 gensim 中使用W2VTransformer包装器:

import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from gensim.sklearn_api import W2VTransformer
from gensim.utils import simple_preprocess
# Load synthetic data
data = pd.read_csv('https://pastebin.com/raw/EPCmabvN')
data = data.head(10)
# Set random seed
np.random.seed(0)
# Tokenize text
X_train = data.apply(lambda r: simple_preprocess(r['text'], min_len=2), axis=1)
# Get labels
y_train = data.label
train_input = [x[0] for x in X_train]
# Train W2V Model
model = W2VTransformer(size=10, min_count=1)
model.fit(X_train)
clf = LogisticRegression(penalty='l2', C=0.1)
clf.fit(model.transform(train_input), y_train)
text_w2v = Pipeline(
[('features', model),
('classifier', clf)])
score = text_w2v.score(train_input, y_train)
score
0.800000000000000004

这个脚本的问题在于它train_input = [x[0] for x in X_train]时起作用,这基本上总是第一个单词。 一旦更改为train_input = X_train(或train_input简单地替换为X_train),脚本将返回:

值错误: 无法将大小为 10 的数组调整为形状 (10,10)

如何解决此问题,即分类器如何处理多个单词的输入?

编辑:

显然,与D2V相比,W2V包装器不能与可变长度的列车输入一起使用。这是一个有效的D2V版本:

import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score, classification_report
from sklearn.pipeline import Pipeline
from gensim.utils import simple_preprocess, lemmatize
from gensim.sklearn_api import D2VTransformer
data = pd.read_csv('https://pastebin.com/raw/bSGWiBfs')
np.random.seed(0)
X_train = data.apply(lambda r: simple_preprocess(r['text'], min_len=2), axis=1)
y_train = data.label
model = D2VTransformer(dm=1, size=50, min_count=2, iter=10, seed=0)
model.fit(X_train)
clf = LogisticRegression(penalty='l2', C=0.1, random_state=0)
clf.fit(model.transform(X_train), y_train)
pipeline = Pipeline([
('vec', model),
('clf', clf)
])
y_pred = pipeline.predict(X_train)
score = accuracy_score(y_train,y_pred)
print(score)

从技术上讲,这不是一个答案,但不能写在注释中,所以就在这里。这里有多个问题:

  • LogisticRegression类(以及大多数其他scikit-learn模型)使用2D数据(n_samples, n_features)

    这意味着它需要一个一维数组的集合(每行(样本一个),其中数组的元素包含特征值)。

    在数据中,单个单词将是一维数组,这意味着单个句子(样本)将是二维数组。这意味着完整的数据(此处的句子集合)将是二维数组的集合。即使如此,由于每个句子可以具有不同数量的单词,因此无法将其组合成单个3-D数组。

  • 其次,gensim 中的W2VTransformer看起来像一个 scikit-learn 兼容类,但事实并非如此。它试图遵循"scikit-learn API约定"来定义方法fit()fit_transform()transform()。它们与scikit-learnPipeline不兼容

    您可以看到fit()fit_transform()的输入参数要求是不同的。

    • fit()

      X(str 的迭代对象可迭代对象)– 输入语料库。

      X 可以只是标记列表的列表,但对于较大的语料库,请考虑直接从 磁盘/网络。参见 word2vec 中的 BrownCorpus、Text8Corpus 或 LineSentence 模块,用于此类示例。

    • fit_transform()

      X (形状 [n_samples, n_features] 的 numpy 数组)– 训练集。

如果你想使用scikit-learn,那么你需要有2-D形状。您需要"以某种方式合并"单个句子的词向量,以形成该句子的一维数组。这意味着你需要通过执行以下操作来形成一种句子向量:

  • 单个单词的总和
  • 单个单词的平均值
  • 基于频率、TF-IDF 等对单个单词进行加权平均。
  • 使用其他技术,如Sent2Vec,Paragraph2Vec,Doc2VEC等。

注意:- 我现在注意到你正在根据D2VTransformer做这件事。如果你想使用sklearn,这应该是正确的方法。

该问题中的问题是这一行(因为该问题现已删除):

X_train = vectorizer.fit_transform(X_train)

在这里,您用已经计算的词向量覆盖原始X_train(单词列表列表),因此会出现错误。

或者,您可以使用其他工具/库(keras,tensorflow),它们允许可变大小的顺序输入。例如,可以在此处将 LSTM 配置为采用变量输入和结束标记来标记句子结尾(示例)。

更新

在上面给出的解决方案中,您可以替换以下行:

model = D2VTransformer(dm=1, size=50, min_count=2, iter=10, seed=0)
model.fit(X_train)
clf = LogisticRegression(penalty='l2', C=0.1, random_state=0)
clf.fit(model.transform(X_train), y_train)
pipeline = Pipeline([
('vec', model),
('clf', clf)
])
y_pred = pipeline.predict(X_train)

pipeline = Pipeline([
('vec', model),
('clf', clf)
])
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_train)

无需单独拟合和转换,因为pipeline.fit()会自动执行此操作。

相关内容

  • 没有找到相关文章

最新更新