Doc2Vec和分类 - 结果很差

问题描述 投票:2回答:3

我有6000个观测数据集;它的样本如下:

job_id      job_title                                           job_sector
30018141    Secondary Teaching Assistant                        Education
30006499    Legal Sales Assistant / Executive                   Sales
28661197    Private Client Practitioner                         Legal
28585608    Senior hydropower mechanical project manager        Engineering
28583146    Warehouse Stock Checker - Temp / Immediate Start    Transport & Logistics
28542478    Security Architect Contract                         IT & Telecoms

目标是根据职位预测每行的工作部门。

首先,我在job_title列上应用了一些预处理:

def preprocess(document):
    lemmatizer = WordNetLemmatizer()
    stemmer_1 = PorterStemmer()
    stemmer_2 = LancasterStemmer()
    stemmer_3 = SnowballStemmer(language='english')

    # Remove all the special characters
    document = re.sub(r'\W', ' ', document)

    # remove all single characters
    document = re.sub(r'\b[a-zA-Z]\b', ' ', document)

    # Substituting multiple spaces with single space
    document = re.sub(r' +', ' ', document, flags=re.I)

    # Converting to lowercase
    document = document.lower()

    # Tokenisation
    document = document.split()

    # Stemming
    document = [stemmer_3.stem(word) for word in document]

    document = ' '.join(document)

    return document

df_first = pd.read_csv('../data.csv', keep_default_na=True)

for index, row in df_first.iterrows():

    df_first.loc[index, 'job_title'] = preprocess(row['job_title'])

然后我用GensimDoc2Vec执行以下操作:

X = df_first.loc[:, 'job_title'].values
y = df_first.loc[:, 'job_sector'].values

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=0)

tagged_train = TaggedDocument(words=X_train.tolist(), tags=y_train.tolist())
tagged_train = list(tagged_train)

tagged_test = TaggedDocument(words=X_test.tolist(), tags=y_test.tolist())
tagged_test = list(tagged_test)

model = Doc2Vec(vector_size=5, min_count=2, epochs=30)

training_set = [TaggedDocument(sentence, tag) for sentence, tag in zip(X_train.tolist(), y_train.tolist())]

model.build_vocab(training_set)

model.train(training_set, total_examples=model.corpus_count, epochs=model.epochs)   

test_set = [TaggedDocument(sentence, tag) for sentence, tag in zip(X_test.tolist(), y_test.tolist())]

predictors_train = []
for sentence in X_train.tolist():

    sentence = sentence.split()
    predictor = model.infer_vector(doc_words=sentence, steps=20, alpha=0.01)

    predictors_train.append(predictor.tolist())

predictors_test = []
for sentence in X_test.tolist():

    sentence = sentence.split()
    predictor = model.infer_vector(doc_words=sentence, steps=20, alpha=0.025)

    predictors_test.append(predictor.tolist())

sv_classifier = SVC(kernel='linear', class_weight='balanced', decision_function_shape='ovr', random_state=0)
sv_classifier.fit(predictors_train, y_train)

score = sv_classifier.score(predictors_test, y_test)
print('accuracy: {}%'.format(round(score*100, 1)))

但是,我得到的结果是22%的准确性。

这让我很怀疑,特别是因为使用TfidfVectorizer而不是Doc2Vec(两者都使用相同的分类器),我的准确率达到88%(!)。

因此,我想我应该在如何应用Doc2VecGensim时做错了。

它是什么,我该如何解决?

或者它只是我的数据集相对较小,而更高级的方法,如字嵌入等需要更多的数据?

python classification gensim text-classification doc2vec
3个回答
3
投票

您没有提到数据集的大小 - 行,总单词,唯一单词或唯一类。 Doc2Vec最适合大量数据。大多数已发表的作品都训练了数万到数百万个文档,每个文档有数十到数千个单词。 (您的数据似乎每个文档只有3-5个字。)

此外,已发表的工作倾向于训练每个文档都具有唯一ID的数据。有时使用已知标签作为标签而不是唯一ID,或者除了唯一ID之外,有意义。但它不一定是更好的方法。通过使用已知标签作为唯一标签,您实际上每个标签只能训练一个doc-vector。 (它基本上类似于将具有相同标记的所有行连接到一个文档中。)

你在训练中使用的steps莫名其妙地比epochs更少 - 实际上这些是类似的值。在gensim的最新版本中,默认情况下,推理将使用与模型配置用于训练相同数量的推理时期。并且,在推理期间使用更多的时期比训练更常见。 (另外,你莫名其妙地使用不同的起始alpha值来推断分类器训练和分类器测试。)

但主要的问题是你可能选择微小的size=5 doc向量。而不是TfidfVectorizer,它将每行汇总为宽度等于唯一字数的矢量 - 可能是数百或数千个维度 - 您的Doc2Vec模型将每个文档概括为5个值。你基本上已经切割了Doc2Vec。这里的常用值为100-1000 - 但如果数据集很小,则可能需要更小的尺寸。

最后,词义化/词干化可能不是严格必要的,甚至可能是破坏性的。很多Word2Vec / Doc2Vec的工作并不打扰lemmatize / stem - 通常是因为有大量的数据,所有单词形式的出现很多。

这些步骤最有可能帮助处理较小的数据,通过确保较少的单词形式与相关的较长形式相结合,仍然可以从单词获得价值,否则这些单词将难以保留(或获得有用的向量)。

但我可以看到他们可能会为您的域名造成多种伤害。在这方面,ManagerManagement不会有完全相同的含义,但两者都可以源于manag。类似于SecuritySecurities都成为secur,换句话说。如果你能通过评估证明他们正在帮助我,我只会执行这些步骤。 (传递给TfidfVectorizer的词是被lemmatized / stemmed?)


0
投票

通常培训doc2vec / word2vec需要大量的通用数据(word2vec受过3百万维基百科文章的训练),因为它在doc2vec上表现不佳考虑尝试使用预先训练过的doc2vec参考this

或者您可以尝试使用word2vec并将其平均为整个文档,因为word2vec为每个单词提供向量。

让我知道这有什么帮助?


-1
投票

您使用的工具不适合分类。我建议你看看像char-rnn这样的东西。

https://pytorch.org/tutorials/intermediate/char_rnn_classification_tutorial.html

本教程适用于类似的问题,它对名称进行了分类。

© www.soinside.com 2019 - 2024. All rights reserved.