我正在尝试从劳工统计局O * NET数据库中搜索技能的文本工作描述。
职位描述可能会说:
=====
“具有在Java,SQL和git方面具有丰富经验的软件工程师。需要2年以上行业经验。具有计算机科学或相关领域的学士学位者优先。”
=====
这里的相关O * NET技能是:
=====
“ Oracle Java”,“结构化查询语言SQL”和“ git”。
=====
我使用此示例是因为(在大多数情况下)仅存在部分匹配项,即描述中不包含'Oracle Java',而是'java'。
我已经尝试在python中使用各种字符串匹配库,例如FuzzyWuzzy,以达到一定效果。但是,由于我要将2个单词与一个段落进行比较,因此编辑距离通常非常低。我正在苦苦挣扎的地方是在给定一定的匹配度量阈值的情况下知道如何量化一项技能。
我敢肯定,Glassdoor,Google和其他公司已经解决了类似的问题,所以我确定确实存在解决方案。我真的可以使用一些建设性的建议。有什么想法吗?
我目前在职位描述中搜索约100-200个技能的策略是使用模糊模糊过程将职位描述分解成与特定技能长度相同的ngram,提取最佳匹配并记下该分数。完成所有技能后,我会记录相似度得分> 80的技能并返回给用户。
我遇到的两个大问题是:速度慢了一点,因为我搜索了太多的ngram,并且第二次仍然有很多较差的匹配项通过。
对于上下文,我曾经尝试匹配数千种技能。但是通过使用ML模型,我能够显着减少相关技能的数量。这个数字仍然很高。
from nltk import ngrams
from nltk.corpus import stopwords
from nltk import word_tokenize
from fuzzywuzzy import process, fuzz
def clean(text, include_stopwords=True):
nopunc = [char.lower() for char in text if char not in string.punctuation]
# Join the characters again to form the string.
nopunc = ''.join(nopunc)
if include_stopwords == True:
nopunc = [word.lower() for word in nopunc.split()]
else:
nopunc = [word.lower() for word in nopunc.split() if word.lower() not in
stopwords.words('english')]
return nopunc
def grams(description, skills):
lens = []
for skill in skills:
if len(clean(skill)) not in lens:
lens.append(len(clean(skill)))
gram_dict = {}
for num in lens:
if num > 1:
gram_dict[num] = list(ngrams(clean(description, include_stopwords=False), num))
else:
gram_dict[1] = clean(description, include_stopwords=False)
gram_dict2 = {i:[] for i in gram_dict.keys()}
for k,v in gram_dict.items():
if k >1:
for i in v:
phrase = ' '.join(i)
gram_dict2[k].append(phrase)
for skill in skills:
if len(clean(skill)) == 1:
gram_dict2[1] = clean(skill)
return gram_dict2
def skill_count(description, skills):
import operator
gram_dict = grams(description, skills)
count = {skill:0 for skill in skills}
for skill in skills:
count[skill] = process.extract(skill, gram_dict[len(clean(skill))])
new_count = {skill:0 for skill in count.keys()}
for k, v in count.items():
for a,b in v:
new_count[k] = b
break
sorted_count = sorted(new_count.items(), key= operator.itemgetter(1),reverse=True)
return [a for a,b in sorted_count if b > 80]
无错误信息。我真的很好奇如何更好,更快,更严格地做到这一点。