Poe*_*dit 3 python classification gensim text-classification doc2vec
我有一个包含 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
Run Code Online (Sandbox Code Playgroud)
目标是根据职位预测每一行的职位部门。
首先,我对该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'])
Run Code Online (Sandbox Code Playgroud)
然后我使用Gensimand执行以下操作Doc2Vec:
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)))
Run Code Online (Sandbox Code Playgroud)
但是,我得到的结果是 22% 的准确率。
这让我很怀疑,特别是因为通过使用TfidfVectorizer而不是Doc2Vec(两者都具有相同的分类器)然后我获得了 88% 的准确度(!)。
因此,我想我必须在我如何应用做错了什么Doc2Vec的Gensim。
它是什么,我该如何解决?
或者仅仅是因为我的数据集相对较小而更高级的方法(例如词嵌入等)需要更多的数据?
您没有提及数据集的大小 - 行数、总字数、唯一字数或唯一类别。Doc2Vec 最适合处理大量数据。大多数已发表的作品训练了数万到数百万个文档,每个文档包含数十到数千个单词。(您的数据似乎每个文档只有 3-5 个字。)
此外,已发布的工作倾向于对每个文档都有唯一 ID 的数据进行训练。有时使用已知标签作为标签代替唯一 ID 或作为唯一 ID 的补充是有意义的。但这不一定是更好的方法。通过使用已知标签作为唯一的标签,您实际上只为每个标签训练了一个文档向量。(它本质上类似于将具有相同标签的所有行连接到一个文档中。)
你莫名其妙地steps在推理中使用的比epochs在训练中少——而实际上这些是类似的值。在 的最新版本中gensim,推理将默认使用与模型配置用于训练的推理时期数相同的数量。而且,在推理过程中使用比训练更多的时期更为常见。(此外,您莫名其妙地使用不同的起始值alpha进行分类器训练和分类器测试的推理。)
但主要问题可能是您选择了微小的size=5文档向量。而不是TfidfVectorizer,它将每一行总结为宽度等于唯一字数的向量——可能是数百或数千个维度——您的Doc2Vec模型将每个文档总结为 5 个值。你基本上已经切除了Doc2Vec. 这里的通常值是 100-1000——尽管如果数据集很小,可能需要更小的尺寸。
最后,词形还原/词干提取可能不是绝对必要的,甚至可能是破坏性的。很多Word2Vec/Doc2Vec工作不会费心去词形还原 / 词干 - 通常是因为有大量数据,所有单词形式都有很多外观。
这些步骤最有可能帮助处理较小的数据,通过确保将较罕见的词形式与相关的较长形式结合起来,仍然可以从原本太稀有而无法保留的词中获得价值(或获得有用的向量)。
但是我可以看到它们可能会损害您的域的多种方式。Manager并且Management在这种情况下不会有完全相同的含义,但都可以归结为manag. 类似于 forSecurity和Securitiesboth Being secur,以及其他词。如果您可以通过评估证明它们有帮助,我只会执行这些步骤。(这些词是否传递给TfidfVectorizer被词形化/词干化?)
| 归档时间: |
|
| 查看次数: |
3728 次 |
| 最近记录: |