根据职位说明使用机器学习来检索相关简历

我们使用平均词嵌入(AWE)模型基于职业描述来检索相关的CV。我们在这提供了一个循序渐进的指南,通过使用西班牙语的文件(简历)训练,将已训练的领域词嵌入与预先训练好嵌入结合起来。我们还使用主要成分分析(PCA)作为一种缩减技术,用于将类似的维度用于单词嵌入结果。

架构描述

信息检索(IR)模型是由一个索引语料库和评分或排序功能所组成的。IR系统的主要目标是根据用户请求检索相关文档或网页。在检索过程中,评分功能根据检索到的文档与用户查询的相关性来对检索到的文档进行排序。诸如像BM25和语言模型这样的经典IR模型都是基于bag-of-words(BOW)索引方案。BOW模型有两个主要弱点:它们丢失了出现单词的上下文,而且也忽略了它的语义。潜在语义索引Latent semantic indexing(LSI)是一种用于处理这个问题的技术,但是当文档数量增加时,索引处理计算量将变得很大。最标准的解决这个问题的方法就是训练单词或语句嵌入到语料库中或者使用预训练的语料库。

字嵌入(WE)是从神经网络模型获得的术语的分布式表示。这些连续的表示近期已经被用于不同的自然语言处理任务中。平均词嵌入(AWE)是一种比较受欢迎的表示长文本序列的技术,它不仅仅是表示一个术语。

在我们的例子中,我们需要一组简历,但由于工作的描述是事先未知的,我们需要提供一个基于无监督学习方法的解决方案。因此,词嵌入的使用似乎是我们实验的一个很好的起点。

下图是架构的定义。

步骤1:训练域词嵌入(已训WEs)

作为第一步,我们从四个已知的职业(Java工程师,测试工程师Tester,人力资本管理SAP HCM和销售与分销SAP SD)中构建一个平均的简历文档,使得四个职业简历文档数量相当。由于简历是用不同格式和不同风格和词汇编写的,所以我们决定只使用名词和动词,以便从简历中获得重要和相关的信息。建立语料库后,我们将他传输给Word2vec,并设定以下参数:窗口大小为5,最小字数为3,维数为200. CBOW默认使用的就是Word2vec模型。

我们在Linux Ubuntu 16.04 LTS上使用Python 3.6.1和64位的Anaconda 。为了安装多个库,pip必须按如下所示运行install命令:

pip install gensim
pip install pattern3
pip install textract
pip install numpy
pip install scipy
pip install sklearn 
pip install pickle

在安装了所有需要的软件包之后,我们创建一个函数来从特定的文件夹中检索所有的CV,读取它们(使用textract),将它们解析(使用模式3),最后创建嵌入字(使用gensim)。负责从简历(PDF,TXT,DOC,DOCX)中提取文本的python函数定义如下:

from gensim.models import Word2Vec, KeyedVectors
from pattern3 import es
import textract
from os import listdir
rom os.path import isfile, join
import numpy as np
from scipy import spatial
from sklearn import decomposition
import matplotlib.pyplot as plt
import pickle
def read_All_CV(filename):
text = textract.process(filename)
return text.decode('utf-8')
#Next, we define a function to parse the documents (CVs) and save the word embeddings as follows:
def preprocess_training_data1(dir_cvs, dir_model_name):   
dircvs = [join(dir_cvs, f) for f in listdir(dir_cvs) if isfile(join(dir_cvs, f))]
alltext = ' '  
for cv in dircvs:
    yd = read_All_CV(cv)
    alltext += yd + " "   
    alltext = alltext.lower()
    vector = []
    for sentence in es.parsetree(alltext, tokenize=True, lemmata=True, tags=True):
        temp = []
        for chunk in sentence.chunks:
            for word in chunk.words:                            
                 if word.tag == 'NN' or word.tag == 'VB':
                    temp.append(word.lemma)
                    vector.append(temp)
                    global model
                    model = Word2Vec(vector, size=200, window=5, min_count=3, workers=4)
                    model.save(dir_model_name)

一旦所有的嵌入被保存进 dir_model_name,我们已经完成了将单词嵌入设置到全局变量模型的任务,我们可以使用PCA技术来减少预训练词嵌入的维度。

第2步:下载并减少预训练字嵌入(Pretrained PCA WEs)

在我们下载西班牙预训练词并嵌入后,我们观察到这些向量共有300个维度,我们提出的领域训练的嵌入有200个维度。于是我们决定将300维矢量缩减为200维,然后用两个词嵌入空间来构建混合空间。以下函数负责减少预先训练的词嵌入的维度:

def reduce_dimensions_WE(dir_we_SWE, dir_pca_we_SWE):
m1 = KeyedVectors.load_word2vec_format(dir_we_SWE ,binary=True)
model1 = {}
# normalize vectors
for string in m1.wv.vocab:
model1[string]=m1.wv[string] / np.linalg.norm(m1.wv[string])
# reduce dimensionality
pca = decomposition.PCA(n_components=200)
pca.fit(np.array(list(model1.values())))
model1=pca.transform(np.array(list(model1.values())))
i = 0
for key, value in model1.items():
    model1[key] = model1[i] / np.linalg.norm(model1[i])
    i = i + 1
    with open(dir_pca_we_SWE, 'wb') as handle:
    pickle.dump(model1, handle, protocol=pickle.HIGHEST_PROTOCOL)
    return model1

一旦获得了简化矢量,我们可以使用混合词嵌入和AWE来执行检索任务,以计算简历(CV)和查询(职业描述)的均值向量。

步骤3:构建混合词嵌入空间并检索相关简历(CV)

我们展示了一个在实验室中开发的服务,我们实际上加载了两个嵌入空间,当请求到来时,这个潜入空间必须被选择使用。例如,如果用户公布了一个职位名称“Java”,我们将会加载训练的嵌入空间。当输入另一个未知的配置文件,例如说“Cobol Analyst”时,则使用预先训练的词嵌入。另外,对于每个CV和职位请求,计算其平均字嵌入向量。最后,我们只是检索与职位描述要求相匹配的前三名的简历。以下Python函数负责这个处理块:

model1 = Word2Vec.load(join(APP_STATIC, "word2vec/ourModel"))
with open(join(APP_STATIC, 'word2vec/reduced_pca.pickle'), 'rb') as f:
model2 = pickle.load(f)
@app.route('/find/', methods=['GET'])
def find():  
data = request.args.get('value')
w2v = []
aux = data.lower().split(" ")[0:5]
sel = len(set(['java','sap','tester','prueba','hcm','sd','pruebas','testing']).intersection(aux))
val = False
if sel > 0:
   model = model1
   val = True
else:
   model = model2
   if val:
      data = data.lower()
      for sentence in es.parsetree(data, tokenize=True, lemmata=True, tags=True):
          for chunk in sentence.chunks:
              for word in chunk.words:
                  if val:
                     if word.lemma in model.wv.vocab:
                        w2v.append(model.wv[word.lemma])
                     else:
                          if word.lemma.lower() in model.wv.vocab:
                           w2v.append(model.wv[word.lemma.lower()])
                     else:
                           if word.string in model.keys():
                              w2v.append(model[word.string])
                     else:
                           if word.string.lower() in model.keys():
                              w2v.append(model[word.string.lower()])
                              Q_w2v = np.mean(w2v, axis=0)
                              # Example of document represented by average of each document term vectors.
                              dircvs = APP_STATIC + "/cvs_dir"
                              dircvsd = [join(dircvs, f) for f in listdir(dircvs) if isfile(join(dircvs, f))]
                              D_w2v = []
                              for cv in dircvsd:
                                  yd = textract.process(cv).decode('utf-8')
                                  w2v = []
                              for sentence in es.parsetree(yd.lower(), tokenize=True, lemmata=True, tags=True):
                              for chunk in sentence.chunks:
                              for word in chunk.words:
                                 if val:
                                 if word.lemma in model.wv.vocab:
                                    w2v.append(model.wv[word.lemma])
                                 else:
                                 if word.lemma.lower() in model.wv.vocab:
                                    w2v.append(model.wv[word.lemma.lower()])
                                 else:
                                 if word.string in model.keys():
                                    w2v.append(model[word.string])
                                 else:
                                 if word.string.lower() in model.keys():
                                    w2v.append(model[word.string.lower()])
                                    D_w2v.append((np.mean(w2v, axis=0),cv))
                                    # Make the retrieval using cosine similarity between query and document vectors.
                                    retrieval = []
                                 for i in range(len(D_w2v)):
                                     retrieval.append((1 - spatial.distance.cosine(Q_w2v, D_w2v[i][0]),D_w2v[i][1]))
                                     retrieval.sort(reverse=True)
                                     ret_data = {"cv1":url_for('static', filename="test/"+retrieval[0][1][retrieval[0][1].rfind('/')+1:]), "score1": str(round(retrieval[0][0], 4)), "cv2":url_for('static', filename="test/"+retrieval[1][1][retrieval[1][1].rfind('/')+1:]), "score2": str(round(retrieval[1][0], 4)),"cv3":url_for('static', filename="test/"+retrieval[2][1][retrieval[2][1].rfind('/')+1:]), "score3": str(round(retrieval[2][0], 4))   }
                              return jsonify(ret_data)

本文的版权归 KX_WEN 所有,如需转载请联系作者。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏专知

【AlphaGo Zero 核心技术-深度强化学习教程代码实战04】Agent类和SARSA算法实现

【导读】Google DeepMind在Nature上发表最新论文,介绍了迄今最强最新的版本AlphaGo Zero,不使用人类先验知识,使用纯强化学习,将价值...

31940
来自专栏石瞳禅的互联网实验室

【TensorFlow实战——笔记】第2章:TensorFlow和其他深度学习框架的对比

可以看到各大主流框架基本都支持Python,目前Python在科学计算和数据挖掘领域可以说是独领风骚。虽然有来自R、Julia等语言的竞争压力,但是Python...

13310
来自专栏新智元

3D实时换脸又有新进展!中科院博士生提出改进版本,每张图推理只需0.27毫秒

2018年4月,针对如何解决所有姿势范围内的面部替换,中科院自动化所的研究人员发表了一篇论文,提出了3D实时解决方法。

11140
来自专栏人工智能头条

通过Amazon Machine Learning建立一个数值回归模型

18150
来自专栏专知

【AlphaGo Zero 核心技术-深度强化学习教程代码实战03】编写通用的格子世界环境类

【导读】Google DeepMind在Nature上发表最新论文,介绍了迄今最强最新的版本AlphaGo Zero,不使用人类先验知识,使用纯强化学习,将价值...

31440
来自专栏机器学习算法与Python学习

干货 | 数据挖掘知识点整理

关键字全网搜索最新排名 【机器学习算法】:排名第一 【机器学习】:排名第二 【Python】:排名第三 【算法】:排名第四 1. 数据、信息和知识是广义数据表...

34170
来自专栏新智元

【李飞飞团队最新研究】神经任务编程NTP,具有强大泛化能力的机器人学习框架

【新智元导读】斯坦福大学计算机视觉实验室李飞飞团队的最新研究提出一个新的机器人学习框架:神经任务编程(NTP),在机械臂的物品堆叠、分拣和桌面清理三类任务中,证...

39380
来自专栏新智元

谷歌开源JPEG压缩算法,比同类方法性能优越35%

【新智元导读】 谷歌最近开源了一个JPEG图像压缩编码器,比同类方法压缩要小35%。 在互联网上,速度意味着一切。一个通用的规则是:文件越小,载入的速度会越快...

42850
来自专栏AI科技评论

ICML论文 | Facebook分享机器学习研究开源平台代码

正在美国纽约举行的国际机器大会(ICML)上,我们很难忽略 Facebook 研究科学家们的身影——他们呈现三篇论文、主导四场研讨会、并主讲两场教程。其中包括 ...

395110
来自专栏机器之心

资源 | 一个基于PyTorch的目标检测工具箱,商汤联合港中文开源mmdetection

项目地址:https://github.com/open-mmlab/mmdetection

84920

扫码关注云+社区

领取腾讯云代金券