随着互联网行业的快速发展、计算机硬件和软件能力的不断提升,大数据技术应运而生。大数据技术现已被应用到各行各业,各大互联网公司对大数据人才的需求也越来越多。如何引导相关从业人员正确的选择岗位,找到让自己满意的工作也就显得尤为重要。 本项目通过爬虫获取主流招聘网站大数据相关职位的招聘信息,对其进行数据挖掘和数据分析,探索大数据岗位的核心需求是什么,以及挖掘出不同城市、不同企业等对大数据岗位待遇的影响。旨在帮助求职者分析当前大数据行业的求职趋势。
同时,该项目还对各招聘信息的企业人才需求画像进行了建模,该模型能通过求职者的基本信息(渴望薪资、学历、工作经验等),生成可求职企业的基本画像。该功能可以帮助各招聘门户网站完善其求职搜索功能,在用户进行搜索后迅速缩小适合企业的范围,进行更加迅速有效的职位推荐。
通过爬虫爬取数据,从主流门户网站(智联招聘)上爬取大数据相关职位的招聘信息(包括职位地点、公司名称、公司性质、公司融资级别、职位空缺、薪资、福利、需求学历、需求工作经验等)。
智联招聘上大数据相关的招聘信息。
用scrapy-redis框架对智联招聘网站中的大数据相关职位进行了爬取。爬虫采用分布式双向爬取,分为master-slaver两端。master节点通过将需要爬取的url存放到redis缓存队列来调度各个slaver节点来爬取数据,slaver节点将爬取到的数据写入到数据库。爬虫架构如下图所示。
最终爬取到的数据共49248行,13列。
最终爬取到的数据共49248行,13列。
j_name
职位名称
c_name
公司名称
c_nature
公司性质
c_scale
公司规模
description
岗位描述(岗位要求)
w_place
工作地点
w_filed
职位类别
w_experience
要求的经验
education
要求的学历
s_min
最低工资
s_max
最高工资
vacancies
职位空缺
welfare
福利
数据预处理部分对爬虫爬到的数据进行去重,筛选,缺失值填补,概念分层,预处理后处理成合适的格式,方便进行数据挖掘。
在数据分析过程中,原始数据常常会有一些重复的记录,因此数据去重是必不可少的一个步骤。针对数据集,自定义去重规则,删除重复行并对数据进行整合。
针对所爬取的数据集,将职位名称(j_name
)和公司名称(c_name
)同时相同的定义为重复数据。采用pandas提供的drop_duplicate
方法对数据进行去重。
处理前数据量为49248行,13列;去重后数据量为39397行,13列。
实际数据是数据挖掘算法的输入,它受多个组件的影响。其中,噪声的存在是关键因素。噪声是不可避免的问题,它会影响数据挖掘应用程序中经常发生错误的数据收集和数据准备过程。噪声有两个主要来源:隐式错误由测量工具引入;以及批处理或专家在收集数据时引入的随机错误。
针对所爬取的数据集进行分析,可看出数据集中包含了许多非大数据相关职业的数据。我们采取自定义筛选规则,将不符合要求的数据筛选掉。主要对属性职位名称(j_name
)和职位类别(w_field
)进行筛选,筛选掉含有某些字段的数据(例如含有字段:软件测试
,销售
,运营
,商务
等),最后进行数据整合。
使用pandas数据包中自带函数,筛选掉含有特殊字段的数据,再筛选后的数据合并起来。
去噪前数据量为39397行,13列,去噪后数据量为19872行,13列。
针对去噪后数据集进行缺失值统计,其中没有分层的数值属性(s_min
,s_max
,vacancies
)中出现的非数字项(如"面议"
,"若干"
)视为缺失值。对于s_min
,s_max
这两列中包含一含有中文的项,其实为带单位的数值,处理后以正常的表现形式填入。最终统计结果如下:
属性 | 缺失值个数 |
---|---|
j_name | 0 |
c_name | 14 |
c_nature | 5933 |
c_scale | 5850 |
description | 5796 |
w_place | 0 |
w_field | 2 |
w_experience | 0 |
education | 0 |
s_min | 639 |
s_max | 639 |
vacancies | 5952 |
welfare | 7532 |
接下来需要分别对以上属性进行缺失值处理。
s_min
,s_max
,vacancies
对于这三个属性,首先将属性转换成float
类型,采用最高频率值填补缺失值。
c_name
由于c_name
的缺失值只有14个,在数据集中占比非常小,对于c_name
属性缺失的数据行直接删除。
description
对于description
属性缺失的数据行采用该行j_name
进行填补。
c_nature
,c_scale
,welfare
c_nature
,c_scale
,welfare
利用数据属性的相关性填补。即用拥有同一其它属性的行的这列的值填补,比如A公司的两条数据i1,i2。i1缺少福利描述,由于i2的公司和i1的公司相同,将i2的福利描述填入i1。若没有与缺失数据公司名相同的数据或者所有相同公司名的数据福利描述均为缺失,则将福利描述填入最高频率值。
缺失值处理前
bar.render_notebook()
缺失值处理后
bar.render_notebook()
缺失值处理前
bar.render_notebook()
缺失值处理后
bar.render_notebook()
bar.render_notebook()
bar.render_notebook()
首先对属性岗位描述(岗位要求)(description)进行粗粒度的分词,并将分词结果保存。在此调用腾讯TexSmart HTTP API进行粗粒度分词。
对分词后的description采用wordcloud工具包进行词云生成:
可以看出大数据岗位对于 分析、业务、大数据平台、团队能力、数据库操作等具有较高的需求。
对welfare采用wordcloud工具包进行词云生成:
可以看出大数据岗位均会提供 五险一金、节日福利、带薪年假、定期体检、绩效奖金等。
在此将对最低工资(s_min),最高工资(s_max),职位空缺进行概念属性分层。
对于最低工资与最高工资,我们都将其分为四层,分别为:
对于职位空缺,将其分为3层,分别为:
最终分层后的分布如下图所示:
grid.render_notebook()
我们可以从图中观察到,大多数企业对于最低薪资还是在6k-10k之间,而最高薪资在16k以上。而对于企业招聘而言,应聘者竞争压力较大,因为绝大多数企业的空缺职位都为1。
首先来了解一下,招聘大数据行业人才的企业的基本情况,了解这些有大数据需求的企业在公司性质、公司规模、地理这些维度的分布情况。
bar.render_notebook()
对于8979家对大数据有需求的企业,上图反应了其公司性质分布,我们可以从图中观察到,在大数据相关企业中,民营企业是最多的,这符合我国国情。另外对大数据有迫切需求的分别是股份制企业、上市公司、国企、合资公司等,每种企业数量均超过了300家,另外我们还可以观察到,下至社会团体,上至国家机关,对大数据都有需求。
pie.render_notebook()
在这8979家企业中,中型企业(100-499人)占了大多数,超过了4000家,小型企业(20-99人)和大型企业(1000-9999人)也占了不少的比重,将近达到3000家,另外可以观察到初创业(20人以下)和超大型企业(10000)也均对大数据有需求,公司数量均超过了200家。
m.render_notebook()
上图显示了这8979家企业的地理分布,可以观察到,在北京大数据公司数量最多,超过了2000家,上海等一些发达城市(成都、重庆)及沿海城市(深圳,杭州)的大数据公司也非常密集,均超过了80多家。整体来看,大数据公司的分布有着围绕着经济中心逐渐下降,从沿海到内地逐渐下降等趋势。
c = draw_heat(gp,gp.values.max())
c.render_notebook()
上图展示了不同性质和不同规模的企业,对大数据岗位给出的平均薪资(单位k/月),首先可以看见最高的竟然是一个20人以下的上市公司,这是因为20人以下的上市公司比较少,这家公司也比较特殊,并不具有非常明确的代表性,可以忽略这行数据。对于总体来看,其实可以发现不同性质对和不同规模的公司对大数据职位开出的薪资并没有相差太多,均在12k-15k左右,说明大数据需求是硬性需求,各种性质和规模的企业都不敢轻易忽视其地位。
对比不同性质的企业,港澳台公司给出的平均月薪资最高,为17k/月,其中最高的为港澳台的大型公司,给出平均月薪达到24k,最低的为社会团体,平均6k/月。
print("开出最高薪资(150k)的企业如下:")
data[data.s_max == data.s_max.max()].c_name
print("收入最高薪资(150k)的职业如下:")
data[data.s_max == data.s_max.max()].j_name
from mlxtend.frequent_patterns import apriori
frequent_items = apriori(c_s, min_support=0.05, use_colnames=True, max_len=4).sort_values(by='support', ascending=False)
frequent_items.head(10)
rules = get_rules(frequent_items)
rules.head(10)
导出的关联规则说明:
规则评价
下图给出了导出关联规则的置信度、支持度以及Lift的散点图。
s = draw_scatter(rules)
s.render_notebook()
vh = draw_heat(gp,2000)
vh.render_notebook()
在19748条招聘信息中,由于我国民营企业占了大多数,所以自然的民营企业对大数据行业的需求是最紧缺的,一共有35180职位空缺;上市公司和股份制企业对大数据人才的需求也非常迫切,职位空缺均超过了4000人;合资企业和国企招收大数据职位空缺将近3000人。
对于不同规模的企业,职位空缺并不是完全集中在超大型公司(10000人以上),而是更多的分布在中大型企业(100-9999人)中。
frequent_items = apriori(c_v, min_support=0.05, use_colnames=True, max_len=4).sort_values(by='support', ascending=False)
rules = get_rules(frequent_items)
rules.head(10)
导出的关联规则说明:
规则评价
下图给出了导出关联规则的置信度、支持度以及Lift的散点图。
sv = draw_scatter(rules)
sv.render_notebook()
bar.render_notebook()
对于8979家对大数据有需求的企业,上图反应了这些公司对人才工作经验方面的要求,可以发现多数公司要求有1-5年的工作经验,占到了公司总数的一半,也有大约20%的公司对工作经验没有限制,比较灵活,这可能包含校招或转岗的部分。
pie.render_notebook()
从图中我们看到,一半以上的大数据企业要求应聘者至少有本科学历,大约20%的企业要求至少大专学历,这表明企业对学历的要求是比较宽松的,推测是由于大数据行业比较注重实践能力,大多数对高学历没有硬性要求。
c = draw_heat(gp,gp.values.max())
c.render_notebook()
上图展示了不同工作经验及学历所对应的平均薪资(k/月),很明显,博士工作经验3-5年的薪资水平最高,硕士工作十年以上的薪资紧随其后,这表明虽然大多数公司对硕士、博士学历没有硬性要求,但是在同等工作经验条件下,拥有更高学历的人才所获得薪资也会更高。同时在工作经验方面,我们也能看到,工作十年以上的人才对应的平均薪资最高,其次是5-10年,3-5年,推测在大数据方向工作时间越久,专业技术能力越强,累积的经验越多,对于新任务也更容易上手,所以公司为这类人才提供更高的薪资。
print("最高薪资(150k)对应的工作经验及学历如下:")
data[data.s_max == data.s_max.max()][['w_experience','education']]
frequent_items = apriori(c_s, min_support=0.05, use_colnames=True, max_len=4).sort_values(by='support', ascending=False)
frequent_items.head(10)
rules = get_rules(frequent_items)
rules.head(10)
导出的关联规则说明:
规则评价
下图给出了导出关联规则的置信度、支持度以及Lift的散点图。
s = draw_scatter(rules)
s.render_notebook()
在3.2节中,我们已经看到了这些大数据企业的地理分布,呈现出围绕着经济中心逐渐下降,从沿海到内地逐渐下降等趋势。
从大数据岗位的招聘信息数量上来看,这些企业遍布全国208座城市,且不同城市对大数据人才的需求程度差异悬殊,需求量较大的城市能达到几千则招聘信息,如北京高达4797;而也有许多需求量小的城市,可能在数据集中只出现过1则。
print("大数据岗位招聘信息量Top30:")
data['w_place'].value_counts().head(30)
对比大数据岗位招聘信息发布量的前30座城市,再次印证了刚才的观点,即各城市间对大数据人才的需求程度差异非常大。北京遥遥领先,深圳紧随其后,其次是杭州、上海、广州,均在1000以上。其他二十几座城市的大数据人才招聘信息数分布在100-1000之间。
pie.render_notebook()
再来看一下各城市的大数据企业分布。从占比上来看,拥有大数据企业数量前十的城市,皆是一线城市和新一线城市,这也正照应了上述大数据岗位招聘信息数排名情况:大数据企业越多,对大数据人才的需求越大。
其中,北京的大数据企业最多,达到2000家,其次是深圳、杭州、广州。这是符合事实的,随着大数据国家战略的加速落地,大数据体量呈现爆发式增长,这些一线城市、新一线城市在大数据行业的发展上处于领先态势,急需招揽大量的大数据人才。正如我们所知道的,许多知名大数据企业正是坐落在上述城市。
m.render_notebook()
从地理分布上来看,各城市对于大数据岗位开出的平均薪资,与各城市大数据企业的地理分布趋势相似。沿海地区城市的薪资相对更高,内陆地区相对较低。
bar.render_notebook()
柱状图反映了各省的平均薪资排名。
北京、上海的大数据招聘岗位给出的平均薪资最高,为21k左右。
东北三省的平均薪资为7-8k,在各省份中处于较低水平。
从沿海省份到内陆,薪资水平逐渐降低,并呈现阶梯状分布。
c = draw_heat(gp,gp.values.max())
c.render_notebook()
上图所示为各省份不同性质的大数据企业,对大数据岗位给出的平均薪资(单位k/月)。从图中可以看出:
1.对于一些大数据发展较成熟的省份,如北京、上海、广东等,能够对大数据岗位开出的薪资明显较高,平均在22k,且基本覆盖各种性质的企业。
2.像江浙、福建、山东等沿海省份,依托沿海的优势,虽然薪资水平略低于一线城市,10-17k之间都有分布,但在各种企业间也基本都有所涉及。
3.广东、福建的港澳台公司贡献了当地较高的大数据岗位薪资,达到18k-20k,这说明当地与港澳台合作的大数据企业发展迅速,且对大数据人才的需求急切。
4.内陆省份一般都会有大数据发展突出的某种类型的企业,例如河南省的外商独资、甘肃省与陕西省的代表处、新疆维吾尔自治区的上市公司、西藏自治区的国企等,能够开出18k左右,甚至高达30k的月薪,可以说是当地大数据企业中的“领头羊”。
frequent_items = apriori(c_s, min_support=0.05, use_colnames=True, max_len=4).sort_values(by='support', ascending=False)
frequent_items.head(10)
rules = get_rules(frequent_items)
rules
导出的关联规则说明:
1.北京的民营企业通常对大数据行业岗位开出平均17k左右的薪资;
2.北京和深圳的大数据企业对招聘岗位一般能够给出17k左右的薪资;
3.在大数据人才需求量较大、大数据企业聚集的这几座城市中,即北京、深圳、上海、杭州,民营企业都占了较大比例,所开出的薪资范围广泛,从6k、7-10k、11-16k、17k都有涉及,可见民营企业在当地的大数据行业群体内占据了非常重要的位置;
规则评价
下图给出了导出关联规则的置信度、支持度以及Lift的散点图。
s = draw_scatter(rules)
s.render_notebook()
对各招聘信息的企业人才需求画像进行了建模,该模型能通过求职者的基本信息(渴望最低工资、最高工资、学历、工作经验、工作地点),生成可求职企业的基本画像(公司性质与公司规模)。该功能可以帮助各招聘门户网站完善其求职搜索功能,在用户进行搜索后迅速缩小适合企业的范围,进行更加迅速有效的职位推荐。
该问题的本质是多标签分类问题。Multi-Label Machine Learning(MLL算法)是指预测模型中存在多个y值,具体分为两类不同情况:
在本项目中,通过输入用户信息,预测公司的两个标签,为公司性质
与公司规模
。
根据多标签问题的复杂性,可以将问题分为两大类:
多标签问题的学习策略主要有三种,分别是一阶策略,二阶策略和高阶策略。
目前有很多关于多标签的学习算法,依据解决问题的角度,这些算法可以分为两大类:一是问题转换策略
,二是算法适应性策略
。
问题转换策略
是转化问题数据,使之使用现有算法,是一种将多标签的分类问题转换成为单标签模型构造的问题,然后将模型合并的一种方式。可分为:
算法适应性策略
是指针对某一特定的算法进行扩展,从而能够处理多标记数据,改进算法,适用数据。主要有:
Binary Relevance的核心思想是将多标签分类问题进行分解,将其转换为q个二元分类问题,其中每个二元分类器对应一个待预测的标签。
由于没有考虑标签之间的相关性,是一阶策略。
优点:
缺点:
构造二分类器的方法使用one-vs-rest的方式。可以直接使用如下接口实现,其中的基分类器可以使用任意sklearn中的预设分类器。 使用scikit-multilearn工具包进行策略及模型的构建与训练。例如:
# Decision Tree
classifier = BinaryRelevance(DecisionTreeClassifier())
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
precision_score(y_test, y_pred, average='micro')
Classifier Chains的核心思想是将多标签分类问题进行分解,将其转换成为一个二元分类器链的形式,其中链后的二元分类器的构建式在前面分类器预测结果的基础上的。在模型构建的时候,首先将标签顺序进行shuffle打乱排序操作,然后按照从头到尾分别构建每个标签对应的模型。
虽然还是作为二分类问题解决的,但以链式的方式随机考虑了多个标签的相关性,这是高阶策略。
优点:
缺点:
# Naive Bayes
classifier = ClassifierChain(GaussianNB())
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
precision_score(y_test, y_pred, average='micro')
Label Powerset的核心思想是将多标签学习转化为一个多类分类问题,每个不同的标签组合认为是一个不同的类。
考虑了多个标签之间的相关性,是高阶策略。
优点:
缺点
# SVM
classifier = LabelPowerset(SVC())
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
precision_score(y_test, y_pred, average='micro')
MLKNN的核心思想是对于每一个实例而言,先获取距离它最近的K个实例,然后使用这些实例的标签集合,通过最大后验概率(MAP)来判断这个实例的预测标签集合的值。
# MLKNN
classifier = MLkNN(k=10)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
precision_score(y_test, y_pred, average='micro')
由于传统的基于统计的方法最终准确率结果不佳,我们采用MLP神经网络模型进行训练和预测。
# create simple mlp
model = Sequential()
model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(class_no, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adagrad', metrics=['accuracy'])
# train
model.fit(X_train, y_train, epochs=10, verbose=2, validation_data=(X_test,y_test))
# evaluation
y_pred = model.predict(X_test)
model.evaluate(X_test, y_test)
为了获得统计上可信的结果,我们将实验重复20次并报告平均结果。
模型 | 准确率 |
---|---|
Binary Relevance | |
DT | 0.731 |
NB | 0.296 |
SVM | 0.810 |
RFC | 0.737 |
Classifier Chains | |
DT | 0.593 |
NB | 0.458 |
SVM | 0.602 |
RFC | 0.607 |
Label Powerset | |
DT | 0.612 |
NB | 0.358 |
SVM | 0.628 |
RFC | 0.610 |
Algorithm Adaptation | |
MLKNN | 0.752 |
Neural Network | |
MLP | 0.931 |
由以上结果,经过我们的分析,对比三种转换策略,Label Powerset与Classifier Chains的整体效果均不如Binary Relevance,原因可能是因为在当前应用场景下,对于y值即“公司性质”与“公司规模”,两者并不存在明显的依赖关系。
对比二元关联转换策略中的4种模型,即决策树、朴素贝叶斯、SVM、随机森林分类器的效果,首先由于朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好,所以无论何种转换策略,使用朴素贝叶斯模型分类的结果都不理想。 对于DT与RFC而言,由于我们的特征相对较少,所以随机森林相比决策树的提升效果并不明显。而SVM在这四种统计模型中则达到了最高的准确率,同样其运算时间也是最长的。
而对于算法适应性策略,MLKNN在我们的应用场景下,准确率也相对较高。
而模型结果最好的则是神经网络模型,我们仅采用了MLP效果就已经达到了0.931,对比其他模型得到了最优的效果。