1. 网站地图
  2. 设为首页
  3. 关于我们


大学生信息管理及就业预测系统的设计与实现

发布时间:2022-12-25 11:22
目录
第一章 绪论 1
1.1项目背景 1
1.1.1信息管理系统 1
1.1.2就业难度增大 1
1.1.3就业难度增大的形成原因 1
1.1.4就业现状 2
1.2现有技术的发展现状 3
1.2.1人工神经网络发展现状 3
1.2.2推荐系统发展现状 4
1.3本文的研究意义 5
第二章 需求分析与项目基础 7
2.1用户实际需求描述 7
2.2用户用例需求描述 8
2.2.1用户划分 8
2.2.2用户用例分析 8
2.3业务流程分析 9
2.4项目需求 9
2.4.1总体需求 9
2.4.2功能需求 11
2.5系统开发相关技术 13
2.5.1MySQL 13
2.5.2Java 14
2.5.3Python 16
第三章 系统总体设计 18
3.1系统总体架构 18
3.2数据库的架构 19
3.3数据流图 20
3.4就业推荐工作流程 20
第四章 信息管理模块的设计与实现 22
4.1引言 22
4.2前端页面的设计 23
4.3数据库设计 24
4.3.1数据库 ER 图 24
4.2.2数据仓库表设计 26
4.2.3数据字典 27
4.2.4类对象设计 30
4.2.5后端实现 33
第五章 就业推荐引擎的设计与实现 41
5.1引言 41
5.2数据预处理 42
5.2.1预处理的重要性 42
5.2.2预处理步骤 42
5.2.3第三方数据来源 43
5.2.4数据清洗举例 44
5.2.5特征工程举例 46
5.3推荐模型 53
5.3.1XGBoost 推荐模型 53
5.3.2Wide&Deep 模型 57
5.3.3模型融合 61
第六章 系统的设置与测试 63
6.1实验设计 63
6.2实验数据 64
6.3实验步骤 67
6.4实验结果 70
6.4.1信息模块实验结果 70
6.4.1推荐引擎实验结果 81
第七章 总结与展望 82
7.1总结 82
7.2展望 82
致谢 83
参考文献 84
第一章 绪论
1.1项目背景
1.1.1信息管理系统
信息管理系统作企业和高校不可缺少的工具之一,提供了科学、安全、高效 地信息管理功能。我们正处于一个信息过载的时代,每时每刻都有海量的数据产 生,而信息系统作为最基本的信息处理手段,广泛地应用于各种领域,为企业提 供了一种高效管理的手段。对于高校而言,学生信息的管理尤为重要,它可以帮 助高校统一、集中、高效地管理学生数据,并能快速地从数据中提取有用的信息, 以教学和就业为目的进行建模,最终实现最大化教育水平以及增加毕业生就业率。
1.1.2就业难度增大
匹配劳动力的需求和供给一直是一个很困难的问题。自2008 年以来,全球金 融危机加剧了中国应届大学毕业生就业压力。在需求方面,经济增长率下降伴随 着国内需求下降,其中劳动需求下降主要出现在制造业、出口导向型实体以及服 务部门。在供给方面,大学的数量因入学人数不断增加,中国的毕业生发展迅速。 自20 世纪90年代末以来的教育局统计显示,到 2009年中国的大学毕业生达到610 万人,2018 年更是达到了 820 万人,近半数求职者认为求职有难度,不可谓压力 不大。
1.1.3就业难度增大的形成原因
经济合作与发展组织已经强调了青年与整体失业率之间差距的大小,特别是 在一些欧洲国家。因此,联合国教科文组织的一份文件强调,虽然高等教育学生 人数增加,但必须更加重视毕业学生技能的质量及其与现实世界工作场所需求的 关系[15],这是为了应对未来的就业压力。近年来,中国的高等教育改革不断,高 等教育从“精英”到“大众化”,导致大学生人数迅速增加。此外,目前中国整体 就业形势严峻,受世界经济的影响,大学生就业状况低迷。同时,由于生产部门 的劳动力需求大幅减少,许多企业大量裁员和缩小规模,工厂破产增加了剩余劳 动力的社会压力,这个问题近年来尤为突出。另一方面,自 1999年中国高校扩招 以来,越来越多的大学毕业生以 23%的年均增长率加剧了就业状况[16,17,18,19,20]。中 国的地方大学作为中国高等教育体系的重要组成部分,在培养人才和解决毕业生 就业问题方面发挥着举足轻重的作用[21]。
1.1.4就业现状
2016年调查发现,87.5%的毕业生认为就业状况一般,只有 6.3%的毕业生认 为 2016 年的就业状况严重,这表明大多数毕业生的对于就业现状不了解。民营企 业,中小企业,二三线城市的毕业生需求明显增加,与此同时一线城市的大型央 企和跨国企业的毕业生需求趋于稳定。这一社会需求的现状与毕业生就业期望存 在明显差异。在制定正确的职业规划问题上,40%的毕业生认为对他们来说非常 必要,50%的毕业生认为帮助不明显,接近 10%的毕业生认为没有任何帮助。这 些数据表明,大多数毕业生即没有职业计划,也不了解就业前景,对自己的职业 未来大多处于被动式的接受。调查还发现,50%的毕业生希望在高校,科研单位 工作,25%的毕业生希望在国有企业工作,18.8%的毕业生希望在行政机关工作, 只有 6.3%的毕业生更喜欢外资企业或私营企业工作,近 80%的毕业生希望毕业时 的起薪是每月3000-4000 元。数据可以看出毕业生就业期望高度集中,然而,考虑 到企业在实际的岗位供给,可能近 50%的毕业生不能实现他们的就业期望。
面试准备的建议以及如何制作完美的简历并不足以让每个学生走上他们想要 的职业道路。英国大学的研究表明,大约三分之一的毕业生最终与离开大学后找 到的工作不匹配。这些不匹配的毕业生面临的前景较差,收入低于同龄人,他们 的职业生涯基本没有用到他们通过三到四年的学习所获得的知识和技能。这也说 明了传统的职业建议不起作用。
这样的不匹配是否因为学生参加了错误的课程?答案是否定的。根据UUK的 研究,几乎没有证据表明毕业生正在研究错误的科目,因为大多数科目都提供了 非常必备的学科知识和就业技能。学生所需要的是更好的职业建议,来帮助他们 定义自己的技能和属性,并了解这些建议如何匹配不同的职业选择。学生还需要 更多的建议帮助他们了解,进入某些行业与此对应的需要提高哪些技能。特别是 在那些研究方向较专一的专业,在没有亲戚朋友从事相关行业或社交网络也无法 提供可靠的建议时,更加需要一个可靠的职业推荐。
那么作为大学,如何才帮助毕业生,给他们提供相关建议呢?为了帮助毕业 生找到合适的工作,许多大学正在尝试新的方法,使他们的职业建议更容易和有 意义。在肯特大学,学生可以使用在线职业探索者服务,将他们的技能与职业选 择相匹配,并提供工作学习计划,为工作经验提供一个平台。邓迪大学的学生可 以在其学术工作的同时学习就业能力模块,包括在线和个人职业规划课程。同时, 玛丽女王的 QConsult 计划将学生转变为伦敦小企业和慈善机构迷用户咨询项目的 顾问。在诺威治艺术大学,他们正在为学生的职业生涯提供支持。他们开发了一 款名为 Profile 的职业纸牌游戏,为学生提供一副牌,其中一半描述技能和属性, 另一半描述需要不同策略来解决它们的工作场景。要求学生将技能卡与场景相匹 配,并考虑如何适用于他们,以及克服实际问题的最佳方法。这样能让学生们意 识到他们已经掌握的技能,以及他们在工作场所需要的技能。由于 Profile 穿着游 戏的衣服,无论背景如何,它都是一个公平竞争环境。同时,这是一项安全、受 规则约束的活动,允许进行一种充满困难的自我评估。借助政府资助支持技能开 发,他们的下一步是将个人资料转变为虚拟现实体验,为学生提供与工作场所的 VR 联系,而真正的访问受到成本、地理位置或工作经验放置竞争的限制。这是一 个关于高等教育中毕业生就业能力和物有所值的政策辩论:大学如何支持他们的 学生走向正确的职业生涯?什么样的成功才能算是大学的成功?
1.2现有技术的发展现状
由于本文涉及概念较多一我们使用到了 MySQL、Java web、神经网络、传统 机器学习模型,以及推荐系统的各种算法,我们将在本章着重介绍神经网络和推 荐系统的发展现状,随后在第2章介绍MySQL和Java Web,在第3章给出我们的 信息管理系统设计,并在第4章详细介绍更具体的模型。
1.2.1人工神经网络发展现状
人工神经网络(ANN)或连接系统是由构成动物大脑的生物神经网络启发得 到的计算系统[6]。神经网络不是算法而是机器学习算法的框架,它们协同工作并处 理复杂的数据输入。这些系统通过分析样本来学习执行任务,不需要使用任何特 定任务规则。例如,在图像识别中,神经网络可以识别有猫的图片——通过学习 那些已经别标记为“猫”和“没有猫”的图像,来识别其他图片中的猫。整个过 程没有任何关于猫的先验知识,例如,他们有毛皮,尾巴,胡须和猫状面孔。相 反,神经网络会自动从学习资料中找到它需要的特征。
人工神经网络是基于称为人工神经元的连接单元或节点的集合,这种结构可 以松散地模拟生物大脑中的神经元。我们都知道,生物的神经元会有信号传递, 一个神经元会传递信号给另一个神经元,收到信号的神经元还会发通知给其他的 神经元。人工神经元之间的连接处的信号通常是实数,并且每个人工神经元的输 出通过其输入之和的一些非线性函数来计算。人工神经元之间的连接叫做边。神 经元和边具有随着学习而更新的权重。权值可以增加或减少连接处信号的强度。 人工神经元可以有阈值,从而使得仅在聚合信号超过该阈值时才发送信号。人工 神经元可以聚集成层。不同的层可以对其输入执行不同类型的转换。信号可能在 多次遍历各层之后从第一层(输入层)传播到最后一层(输出层)。
一开始,科学家和研究者们是想要让人工神经网络能够模拟人多大脑来解决 很多复杂的问题。但是渐渐地,他们将注意力转移到执行特定任务,导致偏离生 物学。人工神经网络现在已经可以完成很多复杂的任务,并且应用于多个领域。 比如人脸识别、语音识别、机器翻译、医学图像识别等等。
由于人工神经网络具有复制和模拟非线性过程的能力,因此在各种学科中都 有许多应用。应用领域包括系统识别和控制,量子化学,游戏和决策,模式识别, 序列识别,医疗诊断,金融,数据挖掘,可视化,机器翻译,社交网络过滤和电 子邮件垃圾邮件过滤。
人工神经网络已被用于诊断癌症[7],包括肺癌,前列腺癌,结肠直肠癌,并仅 使用细胞形状信息将高侵袭性癌细胞系与侵入性较小的细胞系区分开来。
人工神经网络已被用于加速受自然灾害影响的基础设施的可靠性分析[8,9]。
人工神经网络也被用于建立地球科学中的黑箱模型:水文学[10,11],海洋模拟 和沿海工程[11,12],和地貌学[13]。
1.2.2推荐系统发展现状
作为高等学校,科学、高效地管理大学生信息是十分重要的。一个全面、高 效、功能强大的信息管理系统可以极大地帮助教学工作的开展,同时能代替传统 的文档管理模型。同时随着就业形势的不断变化,国家经济转型和国内产业结构 调整,新兴企业的需求量不断上升,传统企业的需求固话,对学生就业分析的预 测系统在高校就业工作中开始崭露头角,同时随着国外神经网络技术的飞速发展, 大数据和云计算的价值和作用开始体现出来。
推荐系统根据使用的推荐方法可以分为基于协同过滤的推荐(Collaborative filtering),和基于内容的推荐(Content-based filtering)<,
协同过滤的概念最初由提出 Goldberg 等人在[1]中提出。这一方法随后被 Resnick 等人在 [2] 中推广。协同过滤的核心思想是,喜欢相同物品的用户被认为 有相似的喜好,因此将相似用户喜好的其他物品推荐给对方(基于用户的协同过 滤)。同样地,被相同用户购买的物品可以视为相似物品,再根据用户喜好,将相 似物品推荐给用户(基于物品的协同过滤)。除了上述两种方式,还可以根据用户 的历史喜好训练模型,同时结合用户实时喜好进行预测,根据预测结果进行推荐 (基于模型的协同过滤)。
基于内容的推荐是目前使用最广的推荐方法之一。它的基本思想是,根据物 品的属性特征来寻找物品相似度,再由要用户历史偏好进行相似物品的推荐。内 容推荐的核心是对用户喜好进行建模。其中,用户的喜好从用户和物品的交互信 息中推断出。这里的物品一般多为文字类,比如邮件和网页。交互信息通常从一 些用户操作获取,比如下载、购买、授权或者打标签。
协同过滤和基于内容的推荐方法都有各自的优缺点。协同过滤相比基于内容 的推荐,只需要提取少量特征——用户对物品的显性打分和隐性打分。在活跃用 户多的情况下,协同过滤的推荐系统表现优异。但它的缺点也很明显:推荐效果 十分依赖用户偏好数据的多少。普通的中小企业缺少大量用户偏好数据,因而无 法获得较好的推荐效果。此外,协同过滤对物品和用户都存在冷启动问题。新加 入的物品缺少用户打分,而新注册的用户没有对任何物品进行打分,仅依靠协同 过滤的方法无法对新物品和新用户进行推荐。另外,用户对物品的打分矩阵通常 是一个非常大的稀疏矩阵,导致矩阵计算时间花费巨大,很难为用户提供实时推 荐。同时,协同过滤本身的算法优先推荐有大量用户打分的热门商品,因此它的 推荐缺少多样性和长尾效应[3]。一个好的推荐系统的推荐列表应该具有多样性, 这样商家可以在推荐热门商品的同时,也将一部分非热门商品推荐给用户,以此 获得更多利润。
基于内容的推荐则更多地考虑到了商品属性和用户属性,它能更好地对用户 偏好建模,提供更精确的推荐。同时,因为使用了商品和用户的特征,对新物品 和用户也可以进行准确地推荐。但该方法对物品和用户特征选取要求较高,其推 荐的效果很大程度上由模型好坏决定。此外,基于内容的推荐在寻找相似物品时 计算量较大,其搜索时间通常是0(九2)。
在实际的应用中,人们更多地选择混合型推荐方法。这类方法既结合了用户 对物品的历史偏好,同时加入了用户特征量和商品特征量,有效地解决了冷启动 问题,并且减少了相似匹配的计算量。但这类方法会比上述方法更为复杂,实现 的成本更高[4]。美国在线影片租赁商Netflix就使用了混合推荐系统,它通过协同 过滤比较相似用户的偏好,再利用基于内容的方法,根据电影的特征,推荐与用 户偏好电影的相似电影。
1.3 本文的研究意义
通过这个系统的开发和应用,可以为毕业生和企业提供更方便高效的服务; 能够帮助毕业生打破社会经验浅导致的壁垒,更容易找到适合自己的工作,实现 人生的价值和职业抱负;同时也能帮助企业找到更多契合需求的工作者,发展壮 大自身,提供更多的就业岗位,全面掌握求职人员信息与企业用人信息,切合实 际的提供人员配置,从而达到人员的供需平衡,提高人员工作匹配准确性,提高 工作效率,并使人力资源管理分析工作更具体。可以提高人力资源工作的有效性, 并在一定程度上解决社会就业问题。
第二章 需求分析与项目基础
分析高校毕业生对于信息管理及就业预测系统的实际需求,将用户需求总结 归纳梳理,然后建立需求分析模型。
2.1用户实际需求描述
大学生信息管理系及就业预测系统,其总体开发目标是为大学生就业提供切 实可靠的指导参考,实现缩小学生与企业之间的信息差,我们通过广泛的走访调 研与网络问卷,开展需求讨论会等形式,获取了各种类型用户的需求资料,并将 用户的需求总结归纳,其主要需求包括如下几个方面:
1.工作与专业相关度
2017届大学毕业生的第一份工作与学位所修专业相关匹配度为66%,和2016 届基本持平。其中,本科和高职高专院校 2017届毕业生的第一份工作与学位所修 专业相关匹配度分别为71%、 62%,均与 2016 届的近两年第一份工作与学位所修 专业相关匹配度(分别为70%、 62%)基本一致。在本科院校中,“双一流”院校 2017届毕业生的第一份工作与学位所修专业相关匹配度为 73%,非“双一流”本 科院校2017 届毕业生的第一份工作与学位所修专业相关匹配度为70%。综上,有 将近40%的是毕业生选择了与自己所学专业无关的工作,根据调查, 2017届本科 毕业生选择与专业无关工作的主要原因是“专业工作不符合自己的职业期待” (36%),其次是“迫于现实先就业再择业”(22%),这样的现象使得很多人学无 用武之地,大大浪费了社会的教育资源,进入就业岗位后需要从0基础学期,不 但增加了职工的贡献成本,也大大增加了企业负担,导致企业更青睐有相关经验 的技术人才,造成就业级差,不利于正常人员流动的形成,增加社会负担和企业 用工成本。
2.期待职业吻合度
2017届大学本科毕业生的第一份工作与其职业期待的吻合度为 49%,与2016 届期待职业吻合度变化不大,依旧处于低位。其中,本科和高职高专院校 2017届 毕业生的第一份工作与其职业期待吻合度分别为52%、 46%,均与 2016届变化不 大,平均甚至不足一半。在本科院校中,“双一流”院校 2017 届毕业生的第一份 工作与其职业期待的吻合度为48%,非“双一流”本科院校 2017届毕业生工作与 职业期待的吻合度为 53%,综上,近三年来各级毕业生的第一份工作与其职业期 待的吻合度均低于 50%,且无好转迹象,这大大影响了就业的稳定性,职工贡献 与忠诚度,企业与个人都将花费更多的成本在跳槽和挖人上。
3.真实可靠的薪资水平
现在社会生活压力不断增大,买房,买车,结婚生子都是大多数毕业生在就 业 2-3 年的重要规划,因此他们对职业的薪资水平都有较高期待,但是各种渠道的 信息真假难辨,其中不乏虚假夸大,甚至有诈骗传销,因此,与其专业对应行业, 或者是与其择业目标行业的真实薪资水平,对大学生来说,至关重要。
2.2用户用例需求描述
分析大学生信息管理及就业预测系统的使用者情况,将使用者抽象为若干类 型的参与者,同构归纳总结,构建每一类参与者的功能用例需求分析模型。运用 UML 用例图,实现参与者用例需求建模。
2.2.1用户划分
大学生信息管理及就业预测系统需求分析过程,需要根据系统用户情况,对 于每一类用户都开展有针对性的需求调研与分析。运用 UML 用例分析图对用户 功能需求进行建模分析,需要首先将使用者划分成为不同类型的用户。每一个用 户是对于某一类系统使用者的抽象。为了进行参与者划分,需要首先分析大学生 信息管理及就业预测系统使用者情况。
(1) 系统管理员
将负责管理整个学生系统的工作人员抽象为管理员,负责管理和维护 信息系统的日常运作。
( 2 ) 学生 即在校进行过注册的学生,主要对信息系统进行访问。
( 3 ) 教职工
学校的正式员教职工,主要对信息系统进行访问、编辑,通常会进行 添加、删除、上传文件等操作。
2.2.2用户用例分析
根据上一小节中的用户划分,创建了以下用例需求分析模型 系统管理员需求建模:负责对系统进行全面管理,功能用例需求有管理系统 中的组织信息、教师信息、学生信息、课程信息。
组织管理:组织指的是第三方企业,在本系统需要支持第三方上传招聘信息、 编辑招聘数据,同时还要管理已有的组织招聘信息。
教师管理:系统需要管理学校的教师信息,包括个人信息和岗位信息。还要 为教师提供查询、编辑的功能。
学生管理:管理学生的个人信息、学院和专业信息、选课信息。提供学生信 息的添加、编辑、删除功能。还要加入是否为毕业生的属性,为后面的预测分析 提供便利。
系统管理:对于不同用户进行权限管理,保证不同类型用户的权限符合这类 用户的岗位职责。
账号管理:管理不同类型用户的账号、密码,还要为用户提供注册、修改密 码的功能。
操作日志管理:系统日志是监控和处理异常的必要工具,因此要妥善保存系 统的日志,以便分析异常和制定策略。
2.3 业务流程分析
学校将学生信息输入管理系统中, 推荐系统根据数据库中学生信息和就业环 境信息对学生在当前就业形势中进行推荐,将为其提供最有可能录用的行业,最 恰当的公司以及最合适的薪资水平。以此引导应届生更好的找到适合自己的行业 和属于自己的事业,帮助求职者更好的认识社会现状和就业环境,提高学校就业 率,同时也可以为公司找到最适合的人才,缓解用工紧张的形势,提高企业效益 以及发展水平。
2.4项目需求
2.4.1总体需求
1.应届毕业生人数连年增长,屡创新高:
如下图所示,2016 年应届毕业生 765 万,创下当时毕业人数记录,但是没过 多久2017 年便达到了795 万人次,增长的脚步到此并未减缓,2018年应届毕业生 人数打到破天荒的820 万,就业压力前所未有。
 
 
图 3-1 2001~2008 年全国高校毕业生人数图
2.大量留学人员学成后选择回国就业
据中国留学回国就业蓝皮书统计,截止2015 年底,我国的留学生就已经超过 了四百万的留学生,每年增长率是 19.06%。而回国的人数累计超过两百多万,年 增长率为 22.46%。这个现象在 2016-2018 又有了新的进展,很多海归高学历人才 在国内就业薪资待遇偏低,就业面不断收窄,海归优势日渐模糊,导致每年大量 海归人才进入待业状态。
3.就业满意度不断下降
2017届大学毕业生的就业满意度为67%,比2016届(65%)高2个百分点。 其中,本科院校2017届毕业生的就业满意度为68%,比2016届(66%)高 2个百 分点;高职高专院校2017届毕业生的就业满意度为65%,比2016届(63%)高 2 个百分点。 2017 届本科毕业生对就业现状不满意的主要原因是“收入低”(64%)、 “发展空间不够”(54%)。
4.连续多年就业形势严峻造成往届生大量增加: 连续多年严峻的就业形势导致每年都有很多应届毕业生待业在家,处于无业
状态,然后再未来2-3 三年内进入就业市场择业,因此2018 年算是往届生,实际 就业人数可达1200-1300 万,长此以往,未来就业压力会越来越严峻,形成恶性循 环;
2016年毕业生半年后就业率
91.85%
91.80%
91.75%
> 91.70%
參 91.65% 91.60% 91.55% 91.50%
本科生 高职高专学院
坐标轴标题
 
图 3-2 2016 年毕业生半年后就业率图
5.存在信息差:
一个是应届毕业生对社会现状不了解,不能正确的定位自我,过高的薪水要 求,不清楚自己适合的行业,以及对未来职业发展的规划不清晰,导致应届生在 招聘中丧失诸多机会;同时,企业也对应届生要求过高,企业制度以及文化封闭 导致外界难以了解真实现状,以及对自身定位过高引起企业无法找到对口人才。
6.国家经济转型: 跟随政策发展,才能更加找到个人在未来的发展方向; 综上,我们设计的学生信息管理系统既能够对学生信息进行存储管理,以便 以后进行大数据分析,同时推荐系统可以很好的给学生就业给予准确的指导方向, 消除企业和个人之间的信息差,提高就业率。
2.4.2功能需求
本系统从功能上可划分为信息管理模块和推荐引擎模块。我们首先将用户的 相关信息录入到信息管理模块中,而后经由一系列数据清洗,将清洗后的数据作 为推荐模块的输入,对用户进行个性化就业推荐。接下来我们对这两大模块进行 功能需求的分析。
2.4.2.1信息管理模块
用户登录
输入用户名和密码,验证后登录系统。
用户注册
用户输入新的用户名和密码注册并登陆到系统中
编辑个人信息
用户可以添加自己的照片、QQ号、手机号码等信息,并且显示在用户的个人 主页。
更改密码
用户可以方便地修改密码。
信息查询
根据用户的权限,为用户提供相应的可查询选项。学生用户的可查询包括成 绩查询、选课查询、考试时间,已选课程的学生名单。教师用户的查询包括班级 学生个人信息、学生成绩、任教课程信息等。管理员可以查询所有信息。
成绩管理 管理员和教师用户可以录入学生成绩,并且能够添加、修改和删除学生的成 绩记录,同时为不同用户提供相应权限下的查询功能。
课程管理
教师用户给和管理员可以对课程进行添加、修改和删除操作,同时为不同用 户提供相应权限下的查询功能。
考试管理 考试信息由管理员预添加,然后再有教师添加学生成绩。
2.4.2.2个性化推荐模块
数据清洗及特征工程
周期性地对所需信息系统中的数据进行数据清洗和特征工程,为个性化推荐 模块提供所需的数据源。
个性化推荐
周期性地对系统内的目标用户进行职位推荐。推荐模块默认为所有用户进行 个性化职位推荐,但是也可以根据需求对用户进行过滤。例如仅对即将毕业的学 生展示个性化职业推荐。
任务调度
定时执行推荐模块的运算模块,同时前端部分定时查询最新推荐模块的输出 数据。如果推荐模块任务调度失败,前端将展示一个预设的推荐结果作为兜底数 据。
2.5系统开发相关技术
2.5.1MySQL
MySQL是一个关系数据库管理系统(RDBMS)。其中,RDBMS表示R - DB- MS。DB代表Database,它是信息存储的存储库。数据库中的数据被组织成表, 每个表被组织成行和列。表中的每一行称为记录。记录可能包含多个(称为字段) 信息,表中的每个列称为字段。 MS 代表管理系统,该软件允许用户插入,检索, 修改或删除记录。R代表Relational,表示一种特殊类型的DBMS,它擅长将存储 在一个表中的信息与存储在另一个表中的信息相关联,方法是查找每个表中共有 的元素。关系DBMS具有高效存储和数据检索机制的优点,并在RDBMS设计过 程中使用规范化过程。数据库规范化过程超出了本文的范围,可以使用多个参考。
MySQL使用客户端/服务器体系结构运行,其中服务器在包含数据库的计算机 上运行,客户端通过网络连接到服务器。服务器操作系统通常是Linux (如Redhat 9.0 等)或 Windows 2000 操作系统。通常, Windows XP, Windows Server 2003, Red Hat Fedora Linux和Debian Linux等都支持MySQL。与任何其他客户端/服务 器应用程序一样,MySQL是一个多用户数据库系统,多个用户可以同时访问数据 库。MySQL服务器侦听通过网络传入的客户端请求,并根据这些请求访问数据库 内容并,将其提供给客户端。客户端是连接到数据库服务器并以预先指定的格式 发出查询的程序。MySQL与基于标准的SQL(SQL代表结构化查询语言)语言 兼容。客户端程序可以使用编程的方式联系服务器(或手动联系服务器。例如, 当用户通过telnet会话向MySQL服务器发出命令时,用户将通过在命令提示符下 手动键入命令向服务器发出请求。另一方面,如果在表单中输入了一些数据(比 如在互联网上购买某些商品的信用卡信息),并且使用服务器端程序处理表单,则 会以编程方式联系MySQL服务器。信用卡审批、会员订阅等通常都是这种情况。
MySQL具有以下特点
1.速度:服务器端程序运行的速度主要取决于服务器硬件。鉴于服务器硬件 是最佳的,MySQL运行速度非常快。它支持要求苛刻的应用程序的群集服
2.易用性:MySQL是一个高性能,相对简单的数据库系统。从一开始,MySQL 就通常从命令行进行配置、监控和管理。但也有几个MySQL图形界面可用:
MySQL管理员:该工具使管理员可以设置,评估和调整他们的MySQL数据 库服务器。这是为了取代 mysqladmin。
MySQL Query Browser:为数据库开发人员和操作员提供图形数据库操作界面。 它对于在单个用户界面中查看多个查询计划和结果集特别有用。
配置向导:管理员可以从预定义的最佳设置列表中进行选择,也可以创建自 己的设置。
MySQL 系统托盘:为基于 Windows 的管理员提供其 MySQL 实例的单一视图, 包括启动和停止其数据库服务器的能力。
3.成本:MySQL是免费的,并且是一个开源数据库。MySQL是LAMP (Linux, Apache, MySQL, PHP / Perl / Python)environment 的一部分,这是一个快速增长 的开源企业软件这是一个快速增长的开源企业软件栈。越来越多的公司使用LAMP 代替昂贵的专有软件堆栈,因为它具有较低的成本,同时有很好的可靠性和完善 的文档。
4.Query语言支持:MySQL理解基于标准的SQL (结构化查询语言)。
5.支持多个客户多同时接入服务器,同时单个客户端还可以同时访问多个数据 库。
6.用户可以通过联网来访问数据库,更可以与其他人共享数据。用户可以使用 ODBC驱动程序通过Windows程序实现连接。通过使用ODBC连接器到MySQL, 任何支持ODBC的客户端应用程序(例如,Microsoft Office,报表编写器,Visual Basic)都可以连接到MySQL。
7.兼容性/可移植性:MySQL可以在多种UNIX上运行,也可以运行在其他 非UNIX系统上,例如Windows和OS/2。MySQL从家用PC到高端服务器的硬 件,都可以运行。此外,MySQL可以安装在Windows XP,Windows Server 2003, Red Hat Fedora Linux, Debian Linux 等。
2.5.2Java
Java是自编程领域诞生以来最流行的编程语言之一。这种编程语言的使用超 越了信使。使用Java编程对于网络银行和金融科技应用来说非常普遍。与其他编 程语言相比, Java 在功能和安全环境方面绝对脱颖而出。 [22] 的报告中表明, Java 在所有网站和许多热门网站中的使用率不到0.1%,这些网站命名为Udemy.com, Gcalc.net,Dukascopy.com等。根据Oracle的说法,它是许多企业系统中使用最多 的运行时平台,其中包括97%的桌面。此外,超过30亿台设备以某种形式运行Java。 许多Web开发公司将Java用于其某些功能,Java服务器应用程序每天处理数千万 个请求。近年来,Java Web应用程序已成为明显的业务需求。这是因为Java的新 版本不断增强Web应用程序开发的可能性。随着对Web应用程序开发的需求增加, 企业正在寻求雇用 Java 开发公司。
1.可扩展性
Java编程语言可轻松扩展以用于Web应用程序开发。这是因为组件广泛可用。 如果用户计划横向或纵向扩展 Web 应用程序,该语言将适应用户的需求,尤其是 在商业逻辑和永久存储级别。
2.跨平台
使用Java编程,用户必须编写一次,然后在任何地方使用代码。它是Java最 重要的特性,也称为可移植性。Java是跨平台的,因为已编译的Java程序可以在 具有Java虚拟机(JVM)的所有平台上运行。业务中的实际场景是:首先,业务 所有者联系Java开发人员来开发程序。开发Web应用程序后,可以在任何设备和 任何操作系统中使用。它可以是用户自己的自主机器,可以叠加在任何操作系统 和任何硬件上。因此,企业主不再需要担心更改硬件或操作系统,然后面临纠正 现有软件不兼容性的麻烦和成本。与基于Windows的平台的编程语言相比,这是 Java 编程的一大优势。
3.内存管理
在Java编程中,所有Java对象都是活的,它们被称为“堆”在Web应用程 序启动时会创建堆,并且可以在执行时增加或减少堆。如果堆填满,则收集并消 除 垃圾,删除不再使用的对象,使得新对象有空间可以进入。
4.多线程
JavaWeb 应用程序可以同时管理多个用户的使用。可以通过为程序本内的每 个用户创建线程来完成,而不必在同一硬件上执行编程的多个副本。在此过程中, 将跟踪每个线程,直到作业结束。
以下是多线程的一些优点:
更少的故障:多线程服务器将始终保持响应,无论特定进程运行多长时间都 可以工作,而单线程服务器可能会停止响应并阻止其操作。
快速响应时间:即使应用程序被大量人员同时使用,用户命令也会在几秒钟 内完成。
多个操作:可以同时执行许多操作,并且用户的 Web 应用程序在执行此步骤 之前不会有太长的响应时间。
更好的性能:由于JAVA具有缓存存储和CPU资源的最佳使用,应用程序的 性能会更好。用户的网络应用程序将保持稳定并且无故障。
维护成本低:各种经济资源的使用使得它的维护成本很低。
5.预算友好
Java 是一种预算友好的语言,受到普遍欢迎。但是,对于许多企业而言,为 预算证明项目寻找可靠的Java开发公司也许很困难。
2.5.3Python
Python 是一种动态高级编程语言,设计它的宗旨是让代码更容易阅读,而设 计者使用缩进的机制来实现这一点。Python的动态类型的机制让程序员在编程的 时候不需要声明类型,十分地灵活。此外,python还会自动管理内存,也就是说, 程序员不需要再担心因为没有释放内存而导致内存溢出了,而且根本不需要主动 进行垃圾回收,省去了很多麻烦。Python解释器还可用于许多操作系统。
Python语言的多样化应用是功能组合的结果,这些功能使这种语言优于其他 语言。Python编程的一些优势包括:
1.语法简单
Python的语法简单,非程序员也可以快速上手。
2.可读性强
Python的语法清晰,让人很容易理解程序代码。Python被称作可执行的伪代 码,因为它的语法大多遵循程序员用来概括他们的想法的惯例,而没其他编程语 言那么冗长。因此,Python可用于原型化和测试代码。
3.高级语言
比起级语言,Python看起来更像一种可阅读的人类语言,让程序员可以更高 效、快速地进行编程。
4.面对对象编程
面向对象编程可以创建可重复使用的数据结构,减少需要重复执行的工作量。 编程语言通常定义具有命名空间的对象,如类或def,对象可以使用关键字编辑自 己,如this或self。大多数现代编程语言都是面向对象的,例如Java,C ++和C#, 或者支持 OOP 功能,例如 Perl 版本 5 及更高版本。此外,面向对象技术可用于几 乎所有非平凡软件的设计,并且几乎可以用任何编程或脚本语言实现。例如,许 多Linux内核功能是对象,它们通过指针实现自己的行为和数据构造封装,特别是 在 C 编程语言中指向函数的指针。
5.免费
Python是免费和开源的。Python Software Foundation分发预先制作的二进制 文件,这些二进制文件可以在所有主要操作系统CPython上免费使用。此外还可 以修改源代码,并按照CPython许可证的允许进行分发。
6.可跨平台运行
Python可在所有主要操作系统上运行,如Microsoft Windows, Linux和Mac OS X。
7.支持广泛
Python拥有一个活跃的支持社区,其中包含许多网站,邮件列表和USENET netnews 组,这些组吸引了大量知识渊博且有用的贡献。
8.安全性强
Python没有像其他基于C语言的指针,因此更加可靠。除此之外,错误永远 不会无声地传递,除非它们被明确地沉默。这使用户可以查看和读取程序崩溃的 原因以及纠正错误的位置。
9.有各种强大功能的内置库
Python有超过300个标准库模块,其中包含用于各种编程任务的模块和类。 例如,标准库包含能安全创建临时文件的模块,将文件映射到内存的模块,产生 和控制子进程的模块,压缩和解压缩文件和归档文件的模块,访问索引的DBM数 据库文件的模块, 连接各种图形用户界面的模块,如 TK 工具包和流行的 WxWindows多平台窗口系统,解析和维护CSV和“.cfg”或“.ini”配置文件的模 块,用于发送电子邮件的模块,获取和解析网页的模块等。例如,可以使用不到 十几行代码在Python中创建自定义Web服务器,当然也可以使用其中一个标准库。
10.可扩展性强 除了标准库之外,还有大量免费提供的附加模块,库,框架和工具包。很多大型 网站都采用了 python 来开发,比如亚马逊、 Facebook 等。还有很多软件也采用了 python作为脚本,比如理信息系统ArcGIS[14]。Python还是人工智能开发的主要 语言,现在几乎所有的人工智能机器学习工具包是基于 python 的。甚至还有一些 操作系统, AmigaOS 4、 FreeBSD 等,将 python 作为标准组件。
 
 
第三章 系统总体设计
本节将介绍大学生信息管理及就业预测系统的总体架构,数据库的架构和就业 推荐的工作流程。
3.1系统总体架构
前端网页
己选课程页 n 学生信息页 1 教师信息页 if 就业推荐页
 
ML模块
特征提取
传统ML
深度学习
 
图 3-1 整体架构图
我们的整个信息管理及就业推荐的系统架构如图 3-1 所示,本架构由数据层、 基础层、决策层以及前端网页组成。其中,数据层用于收集学生数据(包括个人 信息、选课记录、考试成绩、求职简历等)、岗位数据(招聘公司信息、招聘职业 信息、招聘要求等),以及就业数据(历年本校学生的就业数据),这几类数据将 作为后面应用的重要的数据源。
经过基础层的数据建模,决策层利用多种模型对数据进行清洗、特征提取、 模型计算以及评估。同时,我们设计实现了评估模块,该部分模块由离线评估和 在线评估组成。离线评估计算推荐结果的准确率、召回率等评价指标。在线评估 就是A/B test,但是A/Btest通常需要进行埋点和分流,才能得到测试结果。由于 我们目前的系统更偏向学术用途,其目的是为工业落地提供一个原始技术模型, A/B test对我们现在的系统来说实现起来比较不现实,所以我们并且有实现这部分 功能。然而,作为系统架构设计,这一部分却是十分重要的一环,因为在这里提 出。
最终输出的数据将直接读取和展示在前端的网页。
3.2数据库的架构
数据库担负起了系统的信息存储和信息收集功能,需要保证异常的时候,不 要丢失所有数据即可(丢失几个或几十个学生的信息属于可接受范围,可以后期 人工恢复)。对应的架构如下:
 
图 3-2 信息管理系统框架图
 
Nginx是一个轻量级的Web服务器,同类型的还有ApacheoNgnix相比Apache 要轻量级很多,而且并发性能力特别好,同时它还有负债均衡的优势。在我们的 架构图中,通过Nginx搭建Web服务器,再由服务器与Mysql数据库交互。此外, 我们还需要搭建一个数据库的主从备份,也就是保持多个数据库的状态同步,对 于某一个数据库的操作都应该自动备份到其它的数据库。这样做的原因一是为了 在主数据库遭到破坏时能有备份数据库,二是在数据请求太多的时候,可以将请 求分摊到其它备用数据库上面,提高效率。主从备份的实现思路是,主服务器每 次都将进行的操作写入一个日志中(通常是二进制),从服务器则读取这个日志, 并将日志中的操作执行一遍,这样就实现了主从备份的操作。
3.3数据流图
本系统采用自顶而下数据流设计:
 
图 3-3 数据流设计图
 
这里的前端指的是网页端,我们的整个系统是以网页的方式展示给用户的。 数据库存储了所有的学生、教师、课程的数据和就业推荐信息,它可以直接与前 端进行交互。最右边的推荐系统是一个后端计算模块,主要是从数据库提取数据 然后进行相应的机算,最终将计算后的结果存入数据库中,同时返回给前端。
3.4就业推荐工作流程
就业推荐的的工作流程主要由五个部分组成:数据源、预处理、特征工程、 模型、推荐过滤。
 
图 3-4 推荐引擎流程图
 
在介绍推荐引擎的工作流程以前,我们先介绍机器学习的大概流程。我们使 用的机器学习方法包括了模型训练和模型预测两个阶段。在模型训练阶段,我们 需要先从数据源中获取模型所需要的数据,然后对数据进行清洗和提取特征,接 着把处理过的特征作为输入,传入模型中。模型获得输入以后,会经过多次迭代, 迭代期间会更新模型的参数来以获得一组最佳的参数,把得到的这组最佳参数带 入我们的模型,就得到了一个训练以后的最优模型。而这整个迭代更新参数的过 程,称之为模型训练。在得到了一个训练后的模型之后,就需要进行模型预测阶 段。在预测阶段,我们仍然需要先从数据源获取所需的数据,然后同训练阶段时 一样,进行数据清洗和特征工程,把得到的特征输入到训练好的模型中,模型会 对数据进行计算,得到结果。这样就完成了整个模型训练和预测。
理解了上述过程以后,再回到开头的工作流程,就比较容易理解我们的推荐引 擎的工作流程被分为了训练部分和预测部分了。训练流程是:数据源抽数->数据清 洗->特征工程->模型训练->保存模型。预测流程是:数据源抽数->数据清洗->特征 工程->模型预测->推荐结果过滤->输出结果到前端。
第四章 信息管理模块的设计与实现
4.1引言
信息管理模块主要有两大功能:
1) 为学校提供日常的教学信息管理,例如成绩管理,课程管理等。
2) 通过教学信息的收集和企业信息的收集,作为后面介绍的推荐模块的数据 源。
我们采用Java编写系统前端用户界面,使用MySQL设计后端数据存储系统。
1.基本功能
• 登录
• 注册
• 信息查询
• 成绩管理
• 课程管理
• 就业推荐
2.性能
一般学校学生约 1~5 万人,学生信息管理系统访问频率不高,平均每天单个 学生的访问次数不到 1次,因此性能这部分要求并不复杂,存储使用常规的 MySQL 数据库既能胜任,缓存可以不用,Web服务器使用Nginx绰绰有余。
3.可扩展性 学生信息管理系统功能比较稳定,可扩展空间并不大,因此可扩展性也不复
杂。
4.高可用
学生信息管理系统即使宕机 2 小时,对学生管理工作影响并不大,因此可以 不用做负载均衡,更不用考虑异地多活这类复杂的方案。但是,如果学生的数据 全部丢失,修复是非常麻烦的,只能靠人工逐条修复,这个很难接受,因此需要 考虑存储高可靠,这里就有点复杂了。我们需要考虑多种异常情况:机器故障、 机房故障等。针对机器故障,我们需要设计MySQL的同机房主备方案;针对机房 故障,我们需要设计MySQL的跨机房同步方案。
5.成本
由于系统很简单,基本上几台服务器就能搞定,对于一所大学来说完全不是 问题,故无需关注太多。
4.2前端页面的设计
系统基本模块:
(一) 登陆: 登录界面主要设计能输入用户名、密码以及验证码的功能,同时还有一个用户 身份的选择。如果是学生登录,需要选择相应的学生用户身份,以此类推。这样 可以方便我们很快地进行查询匹配。
登录成功以后,则展示一个网站的主界面。这个界面主要可以分为右边的欢迎 栏,和左边的菜单栏。菜单栏显示了用户可操作的各功能,例如学生信息管理、 教师信息管理等。
(二) 系统设置: 设置系统配置,账号信息等。设置学校名称、教师通知和学生通知等信息。 同时还可以禁止教师和学生登录,这样的功能可以方便管理员对系统进行维护。
(三) 修改密码: 需要设置一个修改界面,设有原密码和两次新密码的输入。并设有提交按键 和重置按键。
(四) 学生管理 学生的信息管理功能主要由个人信息的添加、删除和修改组成。下图展示了 添加/修改学生Martin的个人信息的界面。如图所示,用户可以输入学生的学号、 姓名、性别、电话、年级和班级等信息。
(五) 教师管理: 教师的信息管理界面包括了个人信息的添加、删除和修改。教师信息需要编 辑的信息应该包括输入学号、姓名、性别等。
(六) 考试管理 教师应该能够管理考试名称、考试时间、考试对象。
(七) 成绩管理 教师应该能够上载在相应的考试科目后面上载学生的考试信息。
(八) 信息查询 除了上述的各种信息管理界面,我们还有设计了信息查询界面。查询的内容 包括学生信息、课程信息、成绩信息等、第五章将要介绍的就业推荐模块计算的 推荐就业职位。
4.3数据库设计
431数据库ER图
本小节将给出数据库的ER图。ER图也叫实体-联系图,我们用它来表达数据 库中实体的属性以及实体间的关联。这种图接近人类思考的方式,简单易懂,是 能让非技术人员也能看懂的图。 ER 图由实体、属性和关系三部分组成,其中用长 方形表示实体,椭圆形代表属性,而菱形作为关系。这三者之间用边相连。所谓 实体,就是数据模型中的对象,这里可以理解为我们数据库中的表。属性,顾名 思义就是实体具有的一些特性,通常实体包含至少一个属性。关系代表了实体间 的联系。
1•用户实体ER图
用户实体图很直观地表现了,在我们设计的数据库中,每个用户都拥有用户 名、密码以及用户类型这两种属性。其中类型可以试学生、教师或者管理员。
 
 
2•学生实体ER图
学生ER图包括了学生的ID、性别、年级、班级等属性。
 
 
家融址
岀生日期
学号
入学时间
性别
年级
所在院系
图 4-2 学生实体 ER 图
学生信息
备注
年级
班主任
专业
图 4-3 班级实体 ER 图
3.班级实体 E-R 图
班级ER图包括了等年级ID和年级名称。
班级
班级信息
4.实体关系 E-R 图
下面的实体关系图直观地表示了各个实体间的关系。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
姓名
性别
出生日期
职称
«««
管理员
年JS
姓名
姓名
.时安
性别
性别
民族
民族
出生年月
出生日期
教书
系别
成境
课程
年级
课程名
学生
老师
图 4-4 实体关系 ER 图
4.3.2 数据仓库表设计
为了便于信息系统的数据可以方便地被推荐模块使用,我们推荐建立数据仓
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
库,将数据进行建模,以便高效地维护和管理。数据库的主要作用是存储、管理 数据,存储的数据内容和存储形式则需要根据业务需求来设计。撰写本文时,我 们暂时无法获得学校内部数据源,本文使用到的数据均为外部数据,实验数据有 限,因而实现时并没有使用数据仓库。这里我们仍然给出数据仓库中 hive 表的设 计思路,将作为整个信息管理系统中不可或缺的部分,日后在项目真正落地时将 会用到该部分设计。通常,在数据仓库中使用较多的表结构为拉链表、全量表和 增量表。拉链表始终记录更新的数据,通过改变分区日期,让最新分区里的数据 始终包含更新过的数据以及没有更新过的数据。增量表是某日的增量数据,使用 该类表的方法是通过设置分区时间来有效地提取数据。全量表,顾名思义,包含 了以前的所有数据,使用该表的时设置分区为某一个日期,则提取的数据为该日 期及其以前的历史数据。通过分析第 2 章所述的需求,并结合上述各种表结构的 特点,我们认为可以使用拉链表作为存储和管理本系统的hive表结构。这是因为 拉链表不仅可以保存历史数据,同时也更节省空间。假设我们使用全量表来统计 每天的数据,那么每天都需要新增一个完整的全量数据,在数据量大的情况下, 这样做显然十分浪费空间。如果使用拉链表,则不需要增加全量数据,只需增加 每天更新过的数据,这样便达到了节省空间的目的。这样选择的前提是,数据量 大且每天改变的数据量较小,此时方能体现拉链表的优势。而我们的系统刚好符 合这样的业务需求,因此我们认为拉链表是不二选择。在具体实现时,我们可以 通过增加 begin_date 和 end_date 两个字段来实现链表的功能。其中, begin_date 表 示某条记录的生命周期开始时间,设置end_date= '4712-12-31'表示某条记录是 当前有效的。此外还可以额外加入dt字段,dt= '4712-12-31'也表示某条记录为 有效。
4.3.3数据字典
本小节主要给出信息管理系统中的字段设计。我们的管理系统由用户表、学 生表、教师表、课程表、年级表、班级表、年级-课程表、班级-课程-老师表、考 试表,以及考试成绩表组成。下面给出的数据字典中,每张表都给出了当前数据 表所含的字段、数据类型、是否主键、是否为空,以及备注说明。在关系型数据 库中,主键是用来唯一标识表中的一行,主键可以是一列或者多列的组合。外键 主要用来和其他表进行关联,某张表的外键代表了它是另一张表的主键。
 
表 4-1 系统用户表
系统用户表(user)
字段名 类型 是否主键 是否为空 说明
id int 主键值
account varchar(30) 否,不能重复,管 理员账号,教师 工号,或学生学 号 账号
password varchar(30) 密码
name varchar(20) 用户姓名
type tinyint 用户类型,默认 2(1 为管理员,2 为学生,3 为老 师)
 
 
表 4-2 学生表
学生表(student)
字段名 类型 是否主键 是否为空 说明
id int 主键值
number varchar(20) 学号
name varchar(20) 姓名
sex varchar(4) 性别
phone varchar(20) 电话
qq varchar(20) QQ
photo varchar(200) 照片路径
clazzid int 外键(班级 ID) 班级 ID
 
 
表 4-3 教师表
教师表(teacher)
字段名 类型 是否主键 是否为空 说明
id int 主键值
number varchar(20) 工号
name varchar(20) 姓名
sex varchar(4) 性别
phone varchar(20) 电话
qq varchar(20) QQ
photo varchar(200) 照片路径
 
 
表 4-4 课程表
课程表(course)
字段名 类型 是否主键 是否为空 说明
id int 主键值
name varchar(50) 课程名称
 
 
表 4-5 年级表
年级(grade)
字段名 类型 是否主键 是否为空 说明
id int 主键值
name varchar(50) 课程名称
 
 
表 4-6 班级表
班级(clazz)
字段名 类型 是否主键 是否为空 说明
id int 主键值
name varchar(50) 课程名称
gradeid int 外键(年级 ID) 年级 ID
 
 
表 4-7 年级-课程表
年级-课程(grade course)
字段名 类型 是否主键 是否为空 说明
id int 主键值
gradeid int 外键(年级 ID) 年级 ID
courseid int 外键(课程 ID) 课程 ID
 
 
表 4-8 班级 -课程-老师表
班级-课程-老师(clazz course teacher )
字段名 类型 是否主键 是否为空 说明
id int 主键值
clazzid int 外键(clazz. id) 班级 ID
courseid int 外键
(grade course.cid) 课程 ID
teacherid int 外键(teacher. id) 教师 ID
 
 
表 4-9 考试表
考试表(exam)
字段名 类型 是否主键 是否为空 说明
id int 主键值
name varchar(50) 考试名称
 
 
time Date 考试时间
remark varchar(200) 备注
type tinyint(1) 考试类型,默认 1(1 为年级统 考,2 为平时考 试)
gradeid int 外键(grade. id) 年级 ID
clazzid int 外键(clazz. id) 班级 ID
 
 
表 4-10 考试成绩表
考试成绩表(escore)
字段名 类型 是否主键 是否为空 说明
id int 主键值
examid int 外键(exam. id) 考试 ID
studentid int 外键(student. id) 学生 ID
clazzid int 外键(clazz. id) 班级 ID
courseid int 外键
(grade course.id) 课程 ID
score int 默认0 成绩
 
 
表 4-11 职位表
职位表(job)
字段名 类型 是否主键 是否为空 说明
id int 主键值
name varchar 职位名称
description longtext 职位描述
requirement longtext 职位要求
location longtext 职位地点
 
 
表 4-12 学生-推荐职位
考试成绩表(student job rec)
字段名 类型 是否主键 是否为空 说明
id int 主键值
studentid int 外键(student. id) 学生 ID
jobid int 外键(job. id) 职位 ID
studentnumber varchar 外键
(student.number) 学生学号
 
4.3.4类对象设计
本小节介绍系统中Java实现的类对象。设计如下Java类主要是为了使用Java
对数据库进行操作。为了实现Java对数据库的操作,我们需要使用JDBC(Java Database Connectivity)类来进行Java数据库连接并对数据库进行操作。同时,我 们会用到DBUtils来简化一些数据库的操作,例如直接将结果变成我们需要的Java 数据类型,甚至直接写sql语句进行数据库操作等等。
针对上一小节所设计的多张表,我们设计了七个类:用户、学生、教师、年 级、班级、课程、成绩,每个类都有它们对应表中的字段,并且其数据类型也设 计为对应的类型。
表 4-13 系统用户类
系统用户(user)
字段 类型 注释
id int ID
account String 账号(学生和老师的学号即为账号)
password String 密码
type int 账号类型(1为管理员,2为学生,3
为老师)
 
 
表 4-14 职位类
职位(Job)
字段 类型 注释
id int ID
name String 职位名称
description String 职位描述
requirement String 职位要求
location String 职位地点
 
 
表 4-15 学生类
学生(Student)
字段 类型 注释
id int ID
number String 学号
name String 姓名
sex String 性别
phone String 电话
qq String QQ
photo String 照片路径
clazz Clazz 学生所在班级
 
 
表 4-16 老师类
老师(Teacher)
字段 类型 注释
id int ID
number String 工号
name String 姓名
sex String 性别
phone String 电话
qq String QQ
photo String 照片路径
courseList List<Course> 所选课程集合
 
 
表 4-17 课程类
课程(Course)
字段 类型 注释
id int ID值
name String 课程名称
 
 
表 4-18 年级类
年级(Grade)
字段 类型 注释
id int ID 值
name String 年级名称
clazzList List<Clazz > 该年级下的班级
courseList List<Course> 该年级的课程集合
studentList List<Student> 该年级下的学生集合
 
 
表 4-19 班级类
班级(Clazz)
字段 类型 注释
id int ID
name String 班级名称
grade Grade 年级
studentList List<Student> 班级的学生集合
 
 
表 4-20 考试类
考试(Exam)
字段 类型 注释
id int ID
name String 考试名称
time Date 考试时间
remark String 备注
grade Grade 年级
clazz Clazz
type int 考试类型,默认1(1为期中考试,2
为期末考试)
 
 
表 4-21 考试成绩类
考试成绩(EScore)
字段 类型 注释
id int 记录的 id 值
exam Exam 考试
clazz Clazz 班级
course Course 课程
student Student 学生
score int 该门课程的成绩
 
4.3.5后端实现
我们的后端系统采用的是MVC(Model View Controller)的架构模式,它是目 前主流的软件设计方法,这里简单介绍一下它的思想。MVC包含三个部分,模型、 视图和控制器。其中,控制器部分会转发请求并处理请求,视图部分负责图形界 面的设计,模型部分主要用来实现算法以及数据库的设计。 MVC 模式对应到 Java Web里,则是:View层由JSP、HTML编写,(JSP是Java服务器页面,这种文件 可以在HTML文件中插入Java程序,用来在服务器端执行,实现动态网页。HTML 就是超文本标记语言,用来创建网页的。)Controller层主要编写的是接受View层 请求的 Servlet。 Servlet 是 Java 的一个类,用来处理请求和发送响应的,现在的动 态页面都是基于Servlet技术实现。Model层主要需要编写DAO层、Bean层以及 Service层。DAO (Data Access Object)层是指数据访问层,用来对数据库中的表 进行操作,例如对某个表进行删除、添加、查找等。Bean层的主要功能是将指定 的 Bean 集合成一个包,以方便管理大量的 Bean。 Java 中的 Bean 其实是一种可以 复用的Java类,一般用它实现一些基本的功能。接下来,我们将对三个模块的实 现进行详细介绍。
我们的View层实现主要是编写JSP文件,实现网页设计。前面说到了,JSP 主要的功能是HTML中嵌入JAVA代码以实现动态页面,以下是我们实现登录界 面的核心代码。
<script type="text/javascript">
$(function(){
//点击图片切换验证码
$("#vcodeImg").click(function(){ this.src="LoginServlet?method=GetVcode&t="+new Date().getTime();
});
//登录
$("#submitBtn").click(function(){
if($("#radio-2").attr("checked") &&
"${systemInfo.forbidStudent}" == 1){
$.messager.alert("New Message", "Failed to login", "warning");
return;
}
if($("#radio-3").attr("checked") &&
"${systemInfo.forbidTeacher}" == 1){
$.messager.alert("New Message", "Failed to login", "warning");
return;
}
var data = $("#form").serialize();
$.ajax({
type: "post",
url: "LoginServlet?method=Login",
data: data,
dataType: "text", //返回数据类型
success: function (msg){
if("vcodeError" == msg){
$.messager.alert("New Message", "Code Error!",
 
$("#vcodeImg") .click();//切换验证码
$("input[name='vcode']") .val("");//清空验证码 输入框
} else if("loginError" == msg){
$.messager.alert("New Message", "Account or Password error!", "warning");
$("#vcodeImg") .click();//切换验证码
$("input[name= 'vcode']") .val("");//清空验证码 输入框
} else if("admin" == msg){ window.location.href = "SystemServlet?method=toAdminView";
} else if("student" == msg){ window.location.href = "SystemServlet?method=toStudentView";
} else if("teacher" == msg){ window.location.href = "SystemServlet?method=toTeacherView";
} }
});
});
//设置复选框
$(".skin-minimal input").iCheck({ radioClass: 'iradio-blue', increaseArea: '25%'
});
})
接下来我们在Controller层实现Servlet类,来接受View层请求。我们定义并
实现了以下几个Servlet类。
>| Jj ClazzServletjava
>JT] CourseServlet.java
>,Jj ExamServletjava
>』GradeServletjava
>,£] JobServlet.java
>[J] LoginServlet.java
>]T] PhotoServlet.java
>{JJ ScoreServletjava
>Stu dentServI et.java
>jf] SystemServlet.java
>JT] TeacherServletjava
图 4-5 Servlet 中定义的类
以学生Servlet类StudentServlet为例,在这个类中,通过创建一个学生的service 类的对象作为属性,可以直接调用服务层定义的功能,下面介绍service层会详细 介绍。Servlet层主要还是对我们在view层定义的request作出响应实现的一些功能。 例如,以下是一个跳转学生个人信息页面的StudentServlet中的方法。
/**
*转到个人信息页,加载个人信息
*@param request
*@param response
*@throws IOException
*@throws ServletException
*/
private void toPersonal(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = (User) request.getSession().getAttribute("user");
Student student = service.getStudent(user.getAccount()); request.getSession().setAttribute("userDetail", student);
request.getRequestDispatcher("/WEB-INF/view/student/studentPe rsonal.jsp").forward(request, response);
}
Model 层包括 Bean 层、 DAO 层和 service 层。我们先介绍 Bean 层的实现。我 们在Bean层里实现数据模型类,这对应在我们的系统就是职位类Job、班级类Clazz、 课程类Course>学生类Student、教师类Teacher,以下是我们在Bean层中定义的 所有类的列表。
>[J] Clazz.java
>[J] Course.java
>[T| Courseltem.java
>国 EScore.java
>[T] Exam.java
>① Grade.java
>Job.java
>[T| Page.java
>]Tj Student.java
>[7] System I nfo.java
>|7| Teacher.java
>囚 Userjava
图 4-6 Bean 层中设计的类
Bean里面的每个类都有对应的属性和方法。以Student类为例,我们定义的 Student类的属性有姓名、ID、学号、性别、电话、年级、班级等。Student的方法 有获取和设置学生的班级号、ID、姓名、成绩等。下图是Student类的属性以及部 分方法的代码截选。
public class Student {
private int id;
private String number;
private String name;
private String sex;
private String phone;
private String qq;
private Clazz clazz;
private int clazzid;
private Grade grade;
private int gradeid;
private List<EScore> scoreList;
private String[] course = new String[]{};
public int get【d() { return id;
}
public void setId(int id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
 
接下来介绍 DAO 层的设计和实现。我们在 DAO 层声明接口类,然后再同一
层里实现这个接口类的类,接着再重写接口里的方法,也就是对表格的操作方法
下图中左边是我们定义的所有DAO接口类,右边是我们的接口实现。
 
图 4-7 DAO 层设计的类和接口
以学生接口举例,下面的代码实现了 Student类接口的。
public class StudentDaoImpl extends BaseDaoImpl implements StudentDaoInter {
public List<Student> getStudentList(String sql, List<Object> param) {
//数据集合
List<Student> list = new LinkedList<>();
try {
//获取数据库连接
Connection conn = MysqlTool.getConnection();
//预编译
PreparedStatement ps = conn.prepareStatement(sql);
//设置参数
if(param != null && param.size() > 0){ for(int i = 0;i < param.size();i++){ ps.setObject(i+1, param.get(i));
}
}
//执行sq l语句
ResultSet rs = ps.executeQuery();
//获取元数据
ResultSetMetaData meta = rs.getMetaData(); //遍历结果集
while(rs.next()){
//创建对象
Student stu = new Student();
//遍历每个字段
for(int i=1;i <= meta.getColumnCount();i++){ String field = meta.getColumnName(i); BeanUtils.setProperty(stu, field, rs.getObject(field));
}
//查询班级
Clazz clazz = (Clazz) getObject(Clazz.class, "SELECT
*FROM clazz WHERE id=?", new Object[]{stu.getClazzid()});
//查询年级
Grade grade = (Grade) getObject(Grade.class, "SELECT
*FROM grade WHERE id=?", new Object[]{stu.getGradeid()});
//添加
stu.setClazz(clazz);
stu.setGrade(grade);
//添加到集合
list.add(stu);
}
//关闭连接
MysqlTool. closeConnection();
MysqlTool.close(ps);
MysqlTool.close(rs);
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
MVC框架中的Model部分的最后一层是service层,其实就是对DAO层的一 次封装,主要用来实现业务逻辑。我们的 service 层包含了以下几个类,用来实现 每个类(实体)的更高级的复杂操作。这里依旧用Student类来举例,我们先打开 如下列表。
>JT] ClazzService.java
>j Jj CourseService.java
>]Tj ExamService.java
>{lj GradeService.java
>[T| JobService.java
>[jj PhotoService.java
>[T] ScoreService.java
>[jj StudentService.java
>{T| SystemService.java
>JT] TeacherService.java
图 4-9 Service 层中设计的所有类
然后找到service层对应的Student类定义为StudentService。通过在 StudentService 里直接设置 DAO 层的 StudentDaoInter 接口为私有属性, 就能在 service类中调用DAO层里面实现的各种基础操作,从而实现更高级的业务逻辑。 下面的代码实现了在service层中对学生信息进行修改的操作。
public class StudentService { private StudentDaoInter dao; public StudentService(){ dao = new StudentDaoImpl();
}
/**
*修改学生信息
*@param student
*/
public void editStudent(Student student){
String sql = "";
List<Object> params = new LinkedList<>(); params.add(student.getName()); params.add(student.getSex()); params.add(student.getPhone()); params.add(student.getQq());
if(student.getGrade() == null || student.getClazz() == null){ sql = "UPDATE student SET name=?, sex=?, phone=?, qq=?
WHERE number=?";
} else {
sql = "UPDATE student SET name=?, sex=?, phone=?, qq=?, clazzid=?, gradeid=? WHERE number=?";
params.add(student.getClazzid());
params.add(student.getGradeid());
} params.add(student.getNumber());
//更新学生信息
dao.update(sql, params);
//修改系统用户名
dao.update("UPDATE user SET name=? WHERE account=?", new Object[]{student.getName(), student.getNumber()});
}
}
第五章 就业推荐引擎的设计与实现
5.1引言
本章介绍整个信息推荐系统的推荐引擎。我们的职业推荐引擎总的来说有两 大类数据,一类是学生的数据,比如学生的个人信息、专业信息以及学科成绩等; 另一类是各企业的招聘信息。第一类学生数据我们可以直接从信息管理系统中获 得,而对于另一类招聘信息我们有两种方案来获得。第一种方案是,我们为招聘 数据再创建几张表,设计的逻辑和方法与第三章中所述的信息系统是一样的,然 后开发一个 web 端,放在学校的服务器上,并利用运营的手段鼓励各企业将其招 聘信息录入到系统中,这样我们就能收集到第三方招聘数据了。第二种方案是, 找一家大规模招聘网站,让他们为我们提供接口,从而直接读取招聘网站的招聘 数据。
下面我们对两种方案的可行性稍作分析。对于第一种方案,考虑到每年会有 诸多企业来到高校进行校园招聘,鼓励他们将招聘信息提前录入到设计好的系统 中是完全可行的,理由有两点:首先这样做对他们没有任何风险,同时又能为他 们的照片提供精准筛选,实则为一个双赢的方案。需要说明的是,我们的推荐引 擎虽然直接目标是大学生,但是我们的推荐结果稍作处理就能为企业推荐合适的 候选人。第二种方案需要和招聘网站进行合作,希望他们能提供招聘数据的接口, 同时,可以将我们的推荐模块接口提供给招聘网站,为他们提供推荐引擎的运算 功能。这其实就相当于我们成为了一个平台,把我们的模型接口提供给别人。总 的来说,我们认为这两种方案都具有一定的可行性,其中方案一的可行性更大一 些,因为涉及的风险更小。
如上所述,我们的推荐引擎的一部分数据源来自于学生信息管理系统,另一 部分数据源来自企业。这就使得大学生的职业推荐需要依赖于信息管理系统,因 为推荐引所需的数据是直接从已搭建好的信息管理系统中提取的。这样一定程度 节省了开发成本,也更便于维护。如果没有信息管理系统的建立,就无法收集到 推荐系统所需要的数据,也就无法进行个性化推荐了。同时,推荐系统扩展了信 息管理系统的功能,为信息管理系统中的数据进行数据挖掘,提供精准推荐,使 得整个信息管理系统具有更高效、更强大的功能,真正达到科学、高效、准确地 人事管理和信息管理。
对于获得招聘数据的问题,从上面所提出的两种方案中我们能看出,两种方 案涉及的实现方法都是不一样的,而我们工作的核心是展示这种信息管理系统和
推荐引擎相结合的模式,因此我们选择对上述获取招聘数据的方案不作实现。
5.2数据预处理
在 3.4 节中,我们介绍了本推荐引擎的工作流程。首先从第四章我们介绍并搭 建的数据库中进行抽数,然后我们就需要对抽取出来的数据进行预处理。数据预 处理主要包含两个步骤——数据清洗和特征工程。在训练模型之前,我们首先要 对用户和招聘职位的数据进行清洗和特征选择,然后才能将这两个预处理过的特 征用于后面的推荐模型的训练和测试。本小节将详细介绍数据预处理。我们将首 先介绍预处理的重要性,然后给出预处理的步骤,再分别对预处理中的两个主要 部分——数据清洗和特征工程,进行详细的介绍。
5.2.1预处理的重要性
在机器学习的工作流程中,数据预处理是不可缺少的重要环节。这是因为机 器学习对数据非常依赖,而数据质量的好坏直接决定了机器学习模型的最终预测 表现。所以预处理的主要目的是,确保用来训练机器学习模型的数据要足够好。 所谓足够好,一是要适合我们所选择的模型,二是要尽可能少的包含噪声数据。 下面介绍预处理的基本步骤。
5.2.2预处理步骤
1.数据清洗
a)提取有用的数据 从数据库或者系统日志中取得的数据,很可能有很多非正规的格式。 比如职位的描述,这些文字很可能是从网页文件中提取的,通常会含 有各种Tag,像是<p> Software Developer </p>这样的,文字会嵌套 在Tag里面。因此我们需要使用一些工具来去除这些Tag,得到干净 的文字。
b)填补缺省值 无论是从数据库中抽取的数据,或者使用现成的数据集,我们经常会 发现有些项的数据是没有的。缺少数据的原因有多种,比如在收集用 户信息时,有些用户选择不填某些项的数据,这些都是经常会遇到的 情况。那么一旦遇到缺失的数据,我们就需要处理它们。通常有两种 方法,一是直接去掉这一组缺失的数据,比如某个用户没有填入姓名 和性别,那我们就直接把这个用户的数据整个去掉不使用它。第二种 方法是,给缺失数据的项填入默认值,通常的做法是填入 0或者 1。
2.特征工程
a)类别数据处理 我们的数据中经常会有些表示类别的数据,比如“男”、“女”,或者“中 国”、“美国”。这样的文字信息,机器是无法理解的,因此我们需要对 他们进行一定的转换。我们通常称这种转换为编码。
b)连续数据处理 连续数据就是一些取值为实数的数据,比如年龄、身高、体重。虽然 机器可以直接“理解”这类数据,但是通常为了让机器能更好地理解 他们,我们会将连续数据进行一些分类处理。我们在 4.2.3中进行了 详细介绍。
c)划分训练集和测试集 对于一个完整的数据集,我们需要将它分为两个部分,一部分用来训 练模型,称为训练集。另一部分用来测试模型的表现,称为测试集。 拆分的规则是,要保证绝大部分的数据都用来训练模型,少部分的数 据用来测试。通常的做法是,选取 80%的数据用来训练,剩余的 20% 的数据用来测试。
d)归一化处理 我们需要将每种特征都进行归一化处理,将这类数值通过数学函数, 映射到一个固定的区间,通常映射到[0,1]或[1,1]。这样做的目的, 是为了避免,某一类特征由于具有的数值比较大,而其他类的特征数 值比较小,从而导致机器学习模型只专注于这类特征,而把其他数值 小的特征忽略了。
5.2.3第三方数据来源
由于我们的系统并没有真正上线使用,所以无法收集我们系统产生的历史用 户行为数据以及职位数据。因此我们选择其他现有的数据集进行设计和实验,以 此证明我们设计的推荐系统是合理、高效、可行的。我们使用了[5]中的数据集, 它是一个发布在 Kaggle 上的关于职位推荐的竞赛的数据集。这个数据集刚好符合 我们系统的要求:它包含了要用户的个人数据、用户的历史职位申请数据,以及 招聘职位的数据。唯一遗憾的是,这个数据集缺少了用户的学科成绩这一项数据, 好在我们所使用的数据集中,用户数据里包含了学历和专业。我们认为,这两项 数据一定程度能代替缺少的数据,达到类似的效果。
 
在这个数据集中,用户特征数据包括了所在地、教育程度、专业、管理经验、 工作历史等。职位特征包括职位名称、岗位描述、要求、发布时间、结束时间等。 下面,我们针对该数据集,根据上面列出的步骤,对预处理中的两大部分——数 据清洗和特征工程,分别进行详细介绍。
5.2.4数据清洗举例
•清理数据格式并提取可用数据
我们的数据集中,需要进行清洗的主要是职位数据的职位描述Description和 职位要求Requirement。下图是未经清洗的职位描述和职位要求。
Description
<p>Security Clearance Required:&nbsp: Top Secr...
<strong>NO Corp, to Corp『esumes&nbsp:are bein...
<b> <b> P/T HUMAN RESOURCES ASSISTANT</b> <...
CITY BEV ERAGES Come to work for the best in th...
I make sure every part of their day is magica...
<b> <b>aon SALON.-'SPA COORDINATOR ...
<b> <b>SUPERINTENDENT</b> </b> aZZaDZ Cen...
<b> <b>ELECTRONIC PRE-PRESS PROFESSIONAL…
<b> </b> Wn <b> <b>UTILITY LINE TRUCK...
 
 
为了清洗这些文字,我们需要进行几个步骤:
 
1)去掉 HTML Tags
2)所有单词转换为小写
3)句子分词
4)去掉标点和停止词。
5)词形还原。
我们使用了 NLTK包进行上述处理。NLTK的全名是Natural Language Toolkit, 它是一个用来处理自然语言的python包,也是现在主流的自然语言处理工具。
以下是文字数据处理的核心代码。
def clean_text(self, rawtext):
ii ii ii
clean input raw text process steps: 1・ remove HTML tags 2・ tokenize words 3・ remove punctuation 4・ lowercase words 5・ stem words
extracted_text = self.parser.extract(rawtext)
tokens = word_tokenize(extracted_text)
lower_tokens = [word・lower() for word in tokens if word not in self・stop_words]
stemmed_tokens = [self・stemmer・stem(word) for word in tokens] return stemmed_tokens
处理完的职位描述如下图所示,我们给出了其中三个清洗后的描述句子特征。 职位要求的文字处理也是类似的,这里就不再赘述了。
description 1
hr interview orlando web resume strong speaking year benef讥 question skill source experience os resource customer assistant sentinel servic e human fax description 2
florida business route time career opportunity orlando beverage salary busch industrial distributor qualified competitive work delivery pers on benefit full best self advancement apply clean source drive license airport class product candidate sentinel eeo facility following dfwp premier city cdl motivated park posse crown come anheuser driver description 3
turning visit housekeeping opportunity information recreation orlando beverage for magical life entertainment steward custodial look enchant ed show guest hotel apply take food realty dream beloved sure job every alike source part waltdisneyworld member cast pride class driver av ail able nowhiring drawing divers 讥 y many sentinel wait world there currently quick creativ 讥 y from that service disney bus make online perfo rmer today theme role park culinary lifeguard eoe day bring resort spectacular character find
图 5-3 清洗后的职位描述特征图
•填补缺失值
填补缺失值的最好的方法是使用 Pandas。 Pandas 是一个 python 工具包,它自 己将数据以表格的形式存储在它独有的DataFrame数据结构中,从而得以高效地 处理数。这里,我们使用了 Pandas包中的填补缺失值的函数,对于每一列特征,
它会自动填补缺失值为我们设定的值。我们这里设定填补缺失值为 0。 下面两个图是我们从样本在选取的一个例子,以此来展示填补缺失值的前后 效果。第一张图是没有填补缺失值的样本,我们可以看到, ID 为555的用户的 TotalYearsExperience中有一个NaN,这就代表该用户的这项数据没有。
UserID Tota I Yea r&Ex perien ce Man aged Others
0 554 4.0 No
1 555 NaN No
2 589 26.0 Yes
3 640 34.0 No
4 644 4.0 No
5 645 13.0 No
图 5-4 带有缺失数据的用户数据样本图
 
下图是我们对ID为555的用户填补了缺失值以后的结果。可以看到,通过填 补缺失值为 0,该用户的 TotalYearsExperience 的值从 NaN 变为了 0。
UserID Total Yea rs Ex perien ce ManagedOthers
0 554 4.0 No
1 555 0.0 No
2 589 26.0 Yes
3 640 34.0 No
4 644 4.0 No
5 645 13.0 No
图 5-5 带有缺失数据的用户数据样本图
 
5.2.5特征工程举例
经过5.2.4节中的数据清洗后,我们已经有了相对干净的数据了。但正如我们 前文所说,仅仅是干净的数据并不能让我们的推荐模型学习到重要的、有意义的 信息。因此,我们需要一些方法来从干净的数据中提取有意义的特征,这些方法 统称为特征工程。
在介绍具体方法前,我们简要地介绍一下机器学习中的数据特征。
顾名思义,数据特征是从数据中提取的,能代表其某一属性的值。比如图像 的特征就有图像的边、角、灰度值等,这些特征都很好地代表了图像的某些特性, 并且我们可以使用这些特性来对不同的图像进行区分,这也是为什么需要从样本
数据中首先获取特征的主要原因。
特征从类型上来分类,分为连续特征(Continuous Features)和类别特征 (Categorical Features)。连续特征的值均为连续的实数,比如在我们的用户数据中, 工作年限和管理过的人数这两种数据,它们的取值是无限的,因此我们可以把他 们作为连续特征。相对地,类别特征通常是一些有限的取值,例如用户数据中的 专业、国家、州和城市,职位数据中的职位所在国家、州和城市,它们可取的值 都是有限的,所以我们将它们视为类别特征。
下面我们分别介绍如何处理这两类特征。
• 类别型数据处理 处理类别型数据的初衷是让机器充分理解某个特征表示的某一类别的东西, 而不是单纯的数值。而类别型数据又可以简单地分为两大类:数值型和非数值型。 我们的数据集中,数值型类别特征有用户ID、职位ID,非数值型类别特征有用户 和职位所在的国家、州、城市,用户的专业等。
类别特征的转换有两步:1. 对该类别数据的所有取值编号;2. 对 1中的编号 进行独热编码( one-hot encoding)。
首先对每种类别值进行编号。我们拿用户数据中的学历水平(DegreeType)作 为例子来说明。首先,整个数据集中, DegreeType 数据的所有取值有六种: Associate's, Bachelor's, High School, Master's, PhD, Vocationalo 那么这六个值 对应了从 0到 5的整数编号。
有了编号以后,我们进行one-hot encodingo one-hot encoding简单来说就是用 一个比特表示一个状态,而比特的总数等于该特征所有可能取到的值的个数。那 么我们的DegreeType数据经过one-hot encoding后,就成为了下面的数据。
DegreeType DegreeTypeO DegreeTypel DegreeType_2 DegreeType_3 DegreeType_4 DegreeType_5
0 Associate's 1.0 0.0 0.0 0.0 0.0 0.0
1 Bachelor's 0.0 1.0 0.0 0.0 0.0 0.0
2 High School 0.0 0.0 1.0 0.0 0.0 0.0
3 Master's 0.0 0.0 0.0 1.0 0.0 0.0
4 PhD 0.0 0.0 0.0 0.0 1.0 0.0
5 Vocational 0.0 0.0 0.0 0.0 0.0 1.0
图 5-6 职位数的独热编码结果图
 
进行one-hot coding的原因是为了避免因为由数值编号的类别特征带来的额外 的信息。在我们的例子中,假如直接将第一步得到的编码0到 5的整数作为特征 用来训练模型,那么就会有"Associate's"小于"Bachelor's",”High School”小于 "Master's”这样的关系。并且还会有"PhD”到"Master's”的距离小于"PhD" 到“Associate's”的距离。这样的信息显然不是我们想要的,因为学历这个特征只 是为了说明样本是属于某一个类别。所以我们采用one-hot encoding来编码,把一 个学历类型的编号扩展成了六列的,当某一列为1而其他列为 0,就表示样本属于 为 1 的这一类代表的类别。
• 连续数据处理 接下来介绍数值型类别特征。数值型类别特征大致分为两种,一种是它的数 值代表的是某种编号,比如上文中的学历类型这个例子,如果我们的数据一开始 不是学历类型,而是给出的学历类型的编号,这样的特征我们也把它视为类别特 征。
另一种数值型类别特征是通过转换连续特征得到的。例如用户数据中的工作 年限这个连续特征,我们可以对不同的年数进行划分。这里划分区间为 0至5 年, 5 年至 10 年,10 年至 15 年,则转换后的特征如下图。
TotalYearsExperience (0,5] (5,10] (10,15]
0 10.0 0.0 1.0 0.0
1 8.0 0.0 1.0 0.0
2 11.0 0.0 0.0 1.0
3 3.0 1.0 0.0 0.0
4 9.0 0.0 1.0 0.0
图 5-7 对连续特征分类后的特征编码图
 
• 划分训练集和测试集
我们将80%的数据作为训练集,将 20%的数据作为测试集。
推荐系统的模型将在训练集中进行训练。训练好的模型会在测试集中进行预 测,将它得到的测试结果与测试集中已知的标准结果进行对比,通过计算我们规 定好的评测指标,来评测模型的效果。
• 归一化处理
上面几个步骤处理完的数据还不是最终用于训练的数据,我们还需要进行归 一化处理。简单地说,就是把数值映射到一个比较小的区间,一般是映射到(0,1) 或者(1,1)。这样做的原因主要有两点。一是我们不希望不同特征会因为某一种特征 的取值范围较大,导致这种特征对模型的影响大于了其他特征。第二个原因是, 归一化以后的数据,会缩短模型的整个学习过程,这是因为机器学习的模型通常 会使用梯度下降(gradient descent)来进行参数更新,特征值的大小会影响梯度的 计算。
• 特征降维
我们在实际进行工程实现的时候,还需要对特征进行降维。特征降维的意思 很容易理解,就是降低特征维度。
这里说一下为什么要降维。假设我们有十万个招聘职位,有一百万个用户, 那么采用我们之前介绍的one-hot coding来编码职位ID和用户ID以后,就会分别 得到一个十万维的职位 ID 向量,和一百万维的用户 ID 向量。最后再加上其它的 一些特征向量,得到的特征向量的总维数就有一百一十万以上了。对于这样的高 维数据,一般的计算机都没有足够的内存可以计算,因此需要对特征进行降维。 降维的方法有多种,我们选择目前使用最多的 PCA(Principal ComponentAnalysis), 主成分分析,来进行降维。PCA可以将一系列相关联的变量转换成一系列无关联 的变量,转换后的维度远小于原始的维度。PCA的步骤包括数据中心化、求出协 方差矩阵、对协方差矩阵求特征向量和特征值、取最大的 K 个特征值所对应的特 征向量、最后将样本投影到特征向量上。我们在实现时,选择使用 scikit-learn 包 中的TruncatedSVD函数,而不是PCA函数。TruncatedSVD函数使用了 SVD[24] 的降维方法,它的算法与PCA类似,但是可以高效地处理大量的样本,非常适合 处理稀疏矩阵。以下是核心代码。
def fit(self, df, dim=100, dtype= 'numerical'):
if dtype == 'numerical':
self.onehot_enc = OneHotEncoder(handle_unknown='ignore')
self・svd_enc = TruncatedSVD(
n_components=100, n_iter=7, random_state=42)
X = self・onehot_enc・fit_transform(
df.values・ravel())・ reshape(-1,1)
self・onehot_enc・fit(X)
else:
self・label_enc = LabelEncoder()
self・onehot_enc = OneHotEncoder(handle_unknown='ignore')
self・svd_enc = TruncatedSVD(
n_components=dim, n_iter=7, random_state=42)
X_int = self・label_enc・fit_transform(
df.values・ravel())・ reshape(-1,1)
X_onehot = self・onehot_enc・fit_transform(X_int)
self・onehot_enc・fit(X)
return self・label_enc, self・onehot_enc, self・svd_enc
def transform(self, df, dtype='numerical'):
ii ii ii
dtype is numerical or string
ii ii ii
col = df・columns・tolist()[0]
if dtype == 'numerical':
t ry:
X = self.onehot_enc・transform(
df.values・ravel()・ reshape(-1,1))
except:
df = df・ replace({-999:0, -999・0:0・0})
df = df[df[col]>=0]
X = self・onehot_enc・transform(
df.values・ravel()・ reshape(-1,1))
encoded_feat = self・svd_enc・fit_transform(X)
else:
X_int = self・label_enc.transform(
df・ values ・ ravel())
X_onhot = self・onehot_enc・transform(X_int ・ reshape(-1,1)) encoded_feat = self・svd_enc・fit_transform(X_onhot) return encoded_feat
•文字特征提取
在我们的数据集中,涉及文字的特征有招聘职位Title、职位描述和职位要求。 接下里我们将这些文字特征转化成在数值特征,这样才能让机器学习模型学习到 正确的信息。
对于处理自然语言,目前主流的做法是将一个单词转换为一个向量,我们叫 word2vec,词向量。它的基本原理是,通过机器学习模型将一个单词映射成一个 固定长度的数值向量。关于word2vec的更多细节可以参考[23],本论文就不对此 展开了。Word2vec的实现有很多,最常用的是工具库是gensim、Google的Glove, 以及Facebook的Fasttext。我们选择使用gensim的word2vec实现,来训练我们自 己的词向量。gensim是一个第三方开源python工具包,它可以无监督式地从语料 库中学习得到词向量。我们需要准备好自己的语料库,设置好参数,再将语料库 作为输入传入gensim的函数,就可以通过训练得到词向量。这里的语料库指的是 文字集合,对应到我们的数据集中,语料库就是经过5.2.3 节中的文字清洗后的职 位描述和职位要求。
以下是训练词向量的代码。我们实现了一个Word2Vec的类,在它的初始化 」nit_函数中实例化了 gensim中的word2vec类,用来作为我们需要训练的词向量 模型。训练词向量模型的核心代码是train_model这个函数。train_model函数接受 两个输入,trian_corpus和outfile。变量train_corpus是我们的语料库,outfile是模 型需要保存到的文件名。Mysentences是我们实现的一个生成器,用来快速处理语 料库中的句子。代码中调用了 build_vocab方法,它实现的是提取语料库中的重要 的单词。调用trian方法,进行词向量模型训练,这个方法结束后,self.model就是 已经训练完的模型了,可以直接使用这个模型来转换我们数据集中的文字特征。
以下是训练词向量的核心代码。
class Word2Vec:
def _init_(self, logger, size, modelfile=None):
self・logger = logger
if not modelfile or (not os.path.exists(modelfile)):
self.model = gensim.models・Word2Vec(
size=size,
window=5,
min_count=2,
workers=8,
iter=50,
hs=0,
negative=10,
sample=1e-4,)
self・outdir = modelfile
else:
self.model = gensim.models・Word2Vec・load(modelfile)
self・outdir = modelfile
self.dim = size
self・stop_words = stopwords・words('english')
self・tokenizer = RegexpTokenizer(r'\w+')
self.lmtzr = WordNetLemmatizer()
def train_model(self, train_corpus, outfile=None):
if self・logger:
self・logger・info("build vocab")
sentences = MySentences(train_corpus, self・logger, 'list')
self.model・ build_vocab(sentences)
if self・logger:
self・logger・info("done")
self・logger・info("train model")
self.model.train(sentences,
total_examples=self.model・ corpus_count,
epochs=self.model・iter)
if outfile or self・model!=None:
if outfile:
self.model・ save(outfile)
output_file = outfile
else:
self.model・ save(self・outdir)
output_file = self・outdir
if self・logger:
self・logger・info("model saved to %s"%output_file)
需要明确的是,我们最终得到的是词向量并不是整个语料库中的所有单词, 而是经过TF-IDF算法[25]筛选后的重要单词。TF-IDF算法除了筛选出重要单词, 还会计算出每个单词的权值,这个权值表示了每个单词在预料库中的重要程度。
以下通过计算TF-IDF获取单词权值的函数。这个函数的输入df_set还是我们 的语料库。我们使用了 sklearn 工具包中的 TfidfVectorizer 类,这个类高效实现了 计算TF-IDF的算法。通过实例化TfidfVectorizer,再调用它的fit_transform方法, 我们就能得到单词的权值,该权值储存在vectorizer.idf_里。以下是计算单词权值 核心代码
def calculate_word_weights(df_set, out_model_file=None):
sentences = MySentences(
df_set, logger=None, out_format='string')
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer・fit_transform(sentences)
feature_weights = dict(
zip(vectorizer・get_feature_names(),
vectorizer・idf_))
dict_to_json(feature_weights, out_model_file)
我们做文字特征提取的主要目的是,用向量的方式表示数据集中的职位描述 和职位要求这两个特征。因此,我们将这段文字中的重要单词的词向量,乘以它 对应的权值,再对所有的向量求和,这样就得到了这段文字的向量。这种方法可 以简单地理解为词向量的加权求和。
用 python 实现从词向量到句/段落向量的代码如下。该函数有两个入参, sentence 和 weights。 sentence 是一个包含某一段文字的所有重要单词的 list,(list 是python中的一个常用数据结构)weights是整个语料库中提取的重要单词的权值。 我们训练得到的词向量是300维,通过该函数得到的某段文字的向量也是 300维。 下面是生成句子和段落向量的核心代码。
def infer_with_weighted_sum(self, sentence, weights):
if not isinstance(sentence, str):
vecs = [np.zeros((1, self.dim))]
else:
vecs =[]
clean_words = self・clean_text(sentence)
for word in clean_words:
t ry:
word_vec = self・model[word]
wt = weights[word]
vecs・ append(wt*word_vec)
except:
vecs.append(np・zeros((1, self.dim)))
if len(vecs) == 0:
vecs = [np.zeros((1, self.dim))]
return sum(vecs)・flatten()
5.3推荐模型
将 4.2.5 中的特征工程得到的特征数据拼接起来,就是我们最后输入到模型的 数据了。这个输入的数据是一个MxN的矩阵,其中M是样本的数量,N是特征 的数量,我们的样本数M有一百多万,特征数量N有一千多。我们的推荐模型会 将矩阵作为一个整体进行计算。
我们的推荐模型可以简单地理解为分类器,而分类器的作用就是对输入样本 进行分类预测,给出输入样本属于每一个分类的概率。具体来说,我们的一个输 入样本是一个用户的个人数据特征和一个职位特征拼接在一起的向量,而推荐模 型的任务就是分析计算这个输入向量,最终输出两个概率值,其中一个概率表示 用户会对这个职位感兴趣,另一个概率表示用户不会对这个职位感兴趣,并且保 证这两个概率之和为1。但如果逐条地对每一个样本进行计算,效率明显就会很低, 因此我们会直接把输入的矩阵作为整体进行计算。
经过大量地调研和学习,我们选择了两种最适合用于工程中的推荐模型——
XGBoost 和 Wide&Deep。
XGBoost[31]是一个基于梯度步进决策树的算法工具库,近几年非常受研究者 和工程师的青睐。根据我们的调研,现在工业界基本都在使用XGBoost进行数据 挖掘或者推荐计算,可以说XGBoost是不二选择。
Wide&Deep也是最近很热门的一个用于推荐的模型。它是Google在2016提 出来的一个既简单又效果好的深度学习模型。目前国内很多知名企业都在使用以 Wide&Deep 为原型的深度学习模型,因此我们认为它是搭建个性化推荐引擎的首 选。
为了更进一步提高推荐模型的精准度,我们还使用了一种融合算法, AdaBoost, 将上面提到的两种模型相融合。融合算法是机器学习中的一个热门领域,尤其在 数据挖掘和工程实现中用得很多。使用融合算法的初衷是将多个弱分类器结合起 来,以得到更好的分类结果。这在工程上的意义就很大了,在工程上我们往往会 因为计算成本和硬件成本的限制,不选择使用复杂的模型,而选择稍微简单一点 的模型,但同时又希望达到一个很好的效果,这个时候就需要融合算法来提升效 果。由此可见,融合算法在推荐系统中是必不可少的一部分。
下面我们对XGBoost、Wide&Deep,以及AdaBoost的原理和实现分别进行介绍。
5.3.1XGBoost 推荐模型
本节将对XGBoost (Extreme Gradient Boost),进行详细介绍。我们先简单介 绍XGBoost中的算法原理和算法步骤,随后会给出我们的实现代码。
XGBoost是基于梯度步进决策树的模型实现工具库。决策树(Decision Tree) 决策树是一个机器学习中的预测模型,树种的节点表示某个对象,每个分叉路径 代表某个可能的属性值,每个叶节点对应从根节点到叶节点的所有对象的值。每 个决策树可以依靠对源数据库的分割进行数据测试。这个过程可以递归式的对树 进行修剪。 当不能再进行分割或一个单独的类可以被应用于某一分支时,递归过 程就完成了。
在XGBoost模型中,为了训练决策树,它使用了迭代增加的训练方法。核心 思想是,我们每次训练的树都是由上一次训练的树加上本次训练的树,可以理解 为每一步训练都会对上一步的训练结果进行修正,把修正结果作为一部分加入到 这一步的训练中。这个过程用数学表示如下, obj 是我们定义的目标函数。
obj 二勺(y,,£")) + *(f) (5-1)
i=1 i=1
y(0) = 0 (5-2)
y(1)= f (x,) + f2 (兀)=f2 (xj (5-3)
y()=工力(xJ = yl:T+ ft (xJ (5-4)
k=1
每一步中加入的新树可以表示为:
objj)=立(y,, y(T ) + f Q (fi ) = EZ(y,‘ + ft (xi)) + Q (ft) + constant (5-5 )
i =1 i =1 i =1
接下来定义正则化项。首先,我们定义Q(力)的复杂度。定义f (x)如下:
ft(x) = Wq(x), w e RT, q: Rd T {1,2,...,T} (5-6)
其中 w 是叶子节点的值的向量, q 是将每个数据赋给相应叶子节点的函数, T 是叶子的数量。复杂度则表示为:
of =YT +势塞M (5-7)
有了 4-5中的目标函数以后,XGBoost使用了优化算法对目标函数进行优化。 最常用的优化算法是梯度下降,它的核心是最小化机器学习模型的目标函数,而 这个目标函数中的参数就是模型的参数。换句话说,使用优化算法得到目标函数 最小值时所对应的参数,就是模型的最优参数解。它的具体方式是,在每次迭代 的时候,对参数中的每个变量,按照目标函数在这个变量梯度的反方向,更新对 应的参数值。
梯度下降仅仅是一个最基础的算法,但它计算量太大,因此实际使用的优化 算法都是在此基础上进行改进的算法,比如 GD、 SGD、 Momentum、 RMSprop、 Adam 等[27-30],这些改进的优化算法通常比梯度下降的计算速度快很多,且经过 精调参数后,也能达到相当的效果。
由于XGBoost没有公布所使用的优化算法,我们在这里不对XGBoost的优化 算法进行介绍。另外,因为XGBoost是一个工具包,它已经将所有的算法实现封 装得很好了,所以我们在使用它实现推荐模型的时候只需要根据它的要求设计好 输入的数据,然后再通过多次试验,选出最适合我们数据集的超参。超参是指那 些不包含在模型里的参数,这些参数无法通过训练模型得到,通常只能由经验法 则和多次试验获得一个最好的取值。XGBoost本身可调的超参非常多,我们无法 对每一个参数都进行多次试验来调整数值,所以我们只选择几个关键的参数来进 行调参,其它参数均取它们的默认值。我们选取的需要调整的超参有学习率,迭 代次数、树的总数。学习率是指在优化算法中,每一次沿梯度方向更新的步长。 迭代次数就是训练中总共需要迭代多少次。树的总数就是XGBoost算法中,需要 创建的子树的数目。
有了以上的基础理论,下面将介绍利用XGBoost模型对经过数据预处理后的 输入训练样本矩阵进行训练和预测的详细步骤。 首先我们实现了 一个 GradientBoostedTree 类。这个类主要实现了 XGBoost 模型中的训练和预测功能。 然后我们将对输入训练样本矩阵,进行数据类型转换。调用set_Dmatrix方法,将 其转换成 XGBoost 中的 DMatrix 类型。接着再调用 train 方法,对转换后的 Dmatrix 类型的训练样本数据进行训练,得到一个XGBoost中的model实例。接下来再在 预测阶段,直接调用model的predict方法,即可求得用户对每个职位感兴趣的概 率。最后根据求得的概率进行排序,选出每个用户最感兴趣的 N 个职位作为推荐 结果。obj函数在XGBoost模型中代表一个优化的目标,用于评判XGBoost运行 状态。模型训练的目的就是使obj函数达到最小化。当obj函数达到最小化的时候, 对应的参数就是模型运行的最佳参数。而优化过程就是在模型的训练过程,在不 断的迭代里面进行最小化。以下为XGBoost模型的核心代码:
class GradientBoostedTree:
ii ii ii
Gradient boosted tree
ii ii ii
def _init_(self, params=None, num_rounds=None, outdir=None):
self.model = None
self・num_rounds = num_rounds
self.params = params
self・dtrain = None
self.dtest = None
self・outdir = outdir
def fit(self, X, Y, weight):
self・dtrain = xgb・Dmatrix(X, Y, weight)
self・train()
def train(self, tok=None, callbacks=None, watchlist=None): scores = {} saved_model_fname = None if not watchlist:
watchlist = [(self・dtrain, 'train'),
(self.dtest, 'test')]
self.model = xgb・train(self.params,
self・dtrain,
self・num_rounds,
watchlist,
early_stopping_rounds=10,
evals_result=scores,
callbacks=callbacks, verbose_eval=500)
if self・outdir:
maxdepth = self・params['max_depth']
eta = self・params['eta']
paramstr = f"{maxdepth}_{eta}"
saved_model_fname = os.path・join(
self・outdir, f"{tok}_{self・num_rounds}_{paramstr}・model") self・ model・ save_model(saved_model_fname)
return saved_model_fname, scores
def cv(self, watchlist=None, callbacks=None, customobj=None):
ii ii ii
Training with early stopping return best iteration
ii ii ii
if not customobj:
cv = xgb・cv(self.params,
self・dtrain,
self・num_rounds,
nfold=10,
early_stopping_rounds=5,
callbacks=callbacks)
else:
from utils import logregobj, evalerror
cv = xgb・cv(self.params,
self・dtrain,
self・num_rounds,
nfold=10,
callbacks=callbacks,
obj=logregobj, feval=evalerror, early_stopping_rounds=5,
verbose_eval=1)
return cv
def predict(self, dtest=None, ntree_limit=0): if dtest:
return self.model・predict( dtest, ntree_limit=ntree_limit) else:
return self.model・predict( self.dtest, ntree_limit=ntree_limit)
def load_model(self, fname):
self.model = xgb.Booster({'nthread':4}) self.model・load_model(fname)
5.3.2 Wide&Deep 模型
本节是对 Wide&Deep 模型的详细介绍。我们同样先介绍 Wide&Deep 的模型, 然后给出具体的实现代码。
Wide&Deep模型是由Google在2016年提出的深度神经网络模型,后被工 业界大量采用,大量实验和案例都证明了这个模型的表现力较好。我们都知道, 对于大规模稀疏数据的回归和分类问题,通常采用非线性特征变换的广义线性模 型,我们称之为 wide 模型。在 wide 模型中,通过交叉积的方式,能高效且具可解 释地对交互特征进行记忆。但这种方法的缺点是需要大量的特征工程。与之相反 地,deep模型通过从稀疏的特征中学习到低纬度的密集embedding,可以生成人们 无法轻易发现的特征组合。Embedding相比于one hot encoding实现了更加简洁的 数据关系,降低训练所需要的数据量。不过deep模型的缺点是,当用户和推荐内 容交互较少的时候,deep模型就会很容易过度生成,并且推荐出不相关的内容。 Wide& Deep 模型则结合了两种模型,取长补短:通过联合训练线性模型和深度 模型,将线性模型的记忆优势和深度模型的生成优势结合。
Wide部分实则是一个线性模型。令y为预测结果,x=[xi,%2,…,也]是我们的 输入特征,维度为d和w = [wi,w2,^,wj为模型的参数,b是模型的bias。我们的 特征输入集包含了原始的特征以及变换后的特征。其中,最重要的特征变换就是 交叉积变换了,定义如下:
d
札(x)=盯兀% cki g{0,1} (5-8)
i=1
于其中,当布尔变量Ck为1,则第i个特征是变换加的一部分,反之为0。
Deep部分是一个前置神经网络。对于categorical特征,我们的输入是特征字 符串。我们先将每个高维度的稀疏特征转换为低纬度的密集实数向量,也就是我 们说的embedding向量。Embedding向量的维度通常在0(10)到0(100)之间。 Embedding这里采取随机初始化,在训练的过程中通过最小化损失函数来得到我们 想要的 embedding 值。
这里得到的 embedding 紧接着就被传入下一层隐藏层。隐藏层的计算公式如 下:
a(l+1) = f(W(l)a(l) +b(l)) (5-9)
1代表当前的层数,f为激活函数,我们这里采取的是ReLUs。a)是激活函数, 於)是bias,W)是I层的的权值。我们的模型预测公式则表示为:
P ( Y = 1|x ) = o( WWide [x, 0 ( X )] + 心3 + b ) (5-10)
其中Y是0或者1,o(•)是sigmoid函数,0(x)是特征x的交叉积,b是bias。 wwde是wide模型的权值,wdieep是deep模型的权值。完整的模型图如下:
 
 
图 5-8 模型图
接下来我们详细介绍是实现wide & deep模型的核心代码。
首先给出公式 5-8 的实现,如下所示。它的本质是对两种特征值的组合的一个
编码。
def val2id(df, cols):
Helper function to index categorical
columns before embedding
val_types= dict()
for c in cols:
val_types[c] = df[c]・unique()
val_to_idx = dict()
for k,v in val_types・items():
val_to_idx[k] = {o:i for i,o in enumerate(val_types[k])}
unique_vals = dict()
for c in cols:
unique_vals[c] = df[c]・nunique()
return df, unique_vals
下面给出的deep函数针4-16模型图中右半边结构部分的深模型,定义了它的 输入数据的结构。除了直接传入Deep模型的特征,还通过上面所展示val2id函 数得到交叉特征,将其作为输入传到Deep模型中。
def deep(df_train, df_test, embedding_cols, cont_cols, method):
"""构建Deep模型的输入"""
df_train['IS_TRAIN'] = 1
df_test['IS_TRAIN'] = 0
df_deep = pd・concat([df_train, df_test])
df_deep = df_deep・reset_index(drop=True) embedding_cols = \
[col for col in df_train if 'sku_property_feat' in col] + \ embedding_cols
cont_cols = \
[col for col in df_train if 'sku_property_feat' in col] + \ cont_cols
df_deep, unique_vals = val2idx(df_deep, embedding_cols)
train = df_deep[df_deep・IS_TRAIN==1]・drop('IS_TRAIN', axis=1)
test = df_deep[df_deep・IS_TRAIN==0]・drop('IS_TRAIN', axis=1) embeddings_tensors =[]
n_factors = 8
reg = 1e-3
for ec in embedding_cols:
if isinstance(ec,str):
layer_name = ec + '_inp'
else:
layer_name = str(ec) + '_inp'
t_inp, t_build = embedding_input(
layer_name, unique_vals[ec], n_factors, reg)
embeddings_tensor・append((t_inp, t_build))
del(t_inp, t_build)
continuous_tensors =[]
for cc in cont_cols:
if isinstance(cc, str):
layer_name = cc + '_in'
else:
layer_name = str(cc) + '_in
t_inp, t_build = continuous_input(layer_name)
continuous_tensors・append((t_inp, t_build))
del (t_inp, t_build)
X_train = [train[c] for c in deep_cols]
X_test = [test[c] for c in deep_cols]
inp_layer = [et[0] for et in embedding_tensors]
inp_layer += [ct[0] for et in continuous_tensors]
inp_embed = [et[1] for et in embedding_tensors]
inp_embed = [ct[1] for et in continuous_tensors]
return X_train, X_test, inp_embed, inp_layer
接下来给出Wide模型以及合并Deep和Wide模型的实现代码。Wide模型本 质上是一个线性模型,构建的时候只需要一层 Dense 层就行了。此外,我们还给 Deep模型额外增加了 attention层。Attention层可以理解为对上一层的每个输出节 点求一个权值,将求得的权值与节点相乘,输出到下一层中。最后,我们将两个 子模型相连接,并且加上一层全连层,再用一个so仕max输出分类结果。我们最终 得到的结果就是预测输入用户对于输入职位感兴趣的概率。
def wide_deep(df_train, df_test, y_train, \
y_test, embedding_cols, cont_cols, method):
"""Wide & Deep 模型"""
embedding_dim = 8
#归一化特征值
scaler = MinMaxScaler()
X_test_wide = scaler・fit_transform(df_test.values)
X_train_deep, X_test_deep, deep_inp_embed, deep_inp_layer = \ deep(df_train, df_test, embedding_cols, cont_cols, method)
X_tr_wd = [X_train_wide] + X_train_deep
X_te_wd = [X_test_wide] + X_test_deep
Y_tr_wd = np.array(y_train)・reshape(-1,1)
Y_te_wd = np.array(y_test)・reshape(-1,1)
acitvation, loss, metrics = fit_params[method]
if metrics: metrics = [metrics]
#构建Wide模型
w = Input(shape=(X_train_wide・shape[1],)),dtye='float32',name='wide')
#构建Deep模型
list_of_attention =[]
for i, em_input in enumerate(deep_inp_embed):
if em_input.shape[2] == embedding_dim:
inp_dim = embedding_dim
else:
inp_dim = 1
# 构建 Attention
attention.distribution = Dense(inp_dim,activation='sotware',
name='attention.vec_'+str(i))(em_input) attention_output = merge(
[em_input,attention_distribution,output_shape=inp_dim,
name='attention.mul_'+str(i),mode='mul'])
list_of_attention.append(attention_output)
d = merge(list_of_attention, mode='concat')
d = Flatten()(d)
d = BatchNormaliztion()(d)
 
d = Dense(100, activation='relu',
kernel_regularizer=l1_l2(
l1=0・01,l2=0・02))(d)
d = Dense(50, activation='relu', name='deep')(d)
#合并Wide与Deep两部分,加一层全量层,做一个分类输岀
wd_inp = concatenate([w, d])
wd_out = Dense(Y_tr_wd ・shape[1],activation=activation,
name='wide_deep')(wd_inp)
wide_deep = Model(inputs=[w]+deep_inp_layer,outputs=wd_out)
wide_deep・compile(optimizer=Adam(lr=0・0001),loss=loss,metrics=metrics) wide_deep・fit(X_tr_wd, Y_tr_wd, epochs=5, batch_size=1000, shuffle=True) results = wide_deep・evaluate(X_te_wd, Y_te_wd)
return wide_deep
5.3.3模型融合
有了 XGBoost与Wide&Deep模型后,紧接着需要融合算法将他们结合,来提 高最终的预测准确率。
模型融合的算法有多种,我们选择使用AdaBoost算法。AdaBoost是Adaptive Boost的缩写,中文叫自适应增强,是机器学习中的一种模型融合算法。所谓模型 融合,就是将多个模型以某种形式结合在一起,来提高最终的表现。模型融合算 法有很多种,这里着重介绍AdaBoost的算法。Adaboost的算法如下图所示。简单 来说,Adaboost求的是若干个模型的线下叠加,而我们同通过下面的算法得到这 个线下关系式的各项系数。
1.Initialize the observation weights = 1/7V, i = 1, 2,..., TV.
2.For m =: 1 to M:
(a)Fit a classifier Gm(x) to the training data using weights w,
(b)Compute
 
 
(c)Compute am = log((l 一 errm)/errm).
(d)Set ~ * I(s 弄 Gm(①彳))], 2 = 1,2,・・・,N*
 
这个算法中的w是一个向量,我们把它作为训练集中每个样本的权值,并设 它的初始值为样1/N,其中N为样本的总数。M表示已训练完成的总的模型个数。
(a)步骤中,将样本x与w相乘得到的结果作为输入,传入当前迭代中的模型 进行训练。(b)步骤是让(a)中训练得到的模型进行一次预测,并计算出错误率 errmo (b)步骤中的公式的分母部分是在对当前的样本的权值向量w求和,分子 部分是求出被错误预测的样板的权值和,最终求得当前的错误率errm。(c)步骤 是在计算当前模型在线性融合中的系数它是根据上一步求得的错误率errm来 计算的。(d)步骤是在更新样本的权值向量w,这个公式其实是在让被预测错误 的样本的权值增加,我们需要用这种方法让后面的模型专注于修正前面预测错误 的样本。迭代结束后,我们最终融合的模型就是每个模型乘以迭代中求出的对应a 系数的加和。
以下是AdaBoost实现的python代码。第20行到第22行是算法中错误率的实 现。23行是算法中Qm的实现。24行是算法的(d)步实现,也就是通过求得的Qm来 更新每个样本的权值的实现。
def adaboost_clf(Y_train, X_train, Y_test, X_test, clfs):
n_train, n_test = len(X_train), len(X_test)
w = np.ones(n_train) / n_train
pred_train, pred_test = [np・zeros(n_train), np・zeros(n_test)]
for clf in clfs:
X_train = np.multiply(X_train,w)
clf・fit(X_train, Y_train)
pred_train_i = clf.predict(X_train)
pred_test_i = clf.predict(X_test)
miss = [int(x) for x in (pred_train_i != Y_train)]
miss2 = [x if x==1 else -1 for x in miss]
err_m = np・dot(w,miss) / sum(w)
alpha_m = 0・5 * np.log((1-err_m) / float(err_m))
w = np.multiply(w, np・exp([float(x) * alpha_m for x in miss2]))
pred_train = [sum(x) for x in zip(pred_train,
[x * alpha_m for x in pred_train_i])]
pred_test = [sum(x) for x in zip(pred_test,
[x * alpha_m for x in pred_test_i])]
return alpha_m
第六章 系统的设置与测试
本章介绍整个系统的实验设计、使用的实验数据、实验的详细步骤,以及展 示最终的结果。我们的测试主要分为两大部分,一是数据库在Java Web中的功能 测试,另一个部分是推荐引擎的性能测试以及在JavaWeb中的功能测试。
6.1实验设计
实验目的 本实验目的主要为测试信息管理模块的功能以及推荐模块的性能。
实验对象
我们的实验目的是信息管理模块和离线推荐计算模块。
评测方法
测试管理模块功能的方法较为直接,这里不再多做说明。测试推荐引擎的方 法是离线评估多组模型的方法,这里稍作说明。对于推荐系统的评估,一般分为 离线评估和在线评估。离线评估是指,在已有的数据集中对模型训练并预测评估。 之所以称之为离线,是因为使用的数据集是历史数据,并不是实时的数据和反馈。 使用离线评估的好处是,它不需要真实的用户参与,而且数据集可以很容易得到, 能快速地计算,并且方便测试大量不同算法。但离线评估的不足也很明显,那就 是它只针对了历史的数据,并不能真实、完整地反映用户对推荐系统的真实反馈。 相对地,在线评估就是指,在模型上线以后,通过分流的方法来收集用户对于推 荐系统的反馈。当然,用户的反馈被分为了显示反馈和隐式反馈。显示反馈就是 用户对推荐内容的直接评分,比如给一组推荐结果设置满意和不满两个选项让用 户进行选择,这样得到的评价结果就是显式反馈。但这种通过显式反馈的方法收 集到的数据会很少,因为大部分用户不会进行这样的打分,尤其是在电商网站, 或者像我们这样的职位推荐网站,因此能收集到的绝大部分都是隐式反馈。比如, 我们设置两个前端界面,一个前端界面展示一组不是推荐引擎给出的结果,另一 个界面展示一组推荐引擎给出的推荐结果,然后将用户分流,对一部分用户展示 有推荐的界面,对另一部分用户展示没有使用推荐引擎的界面,最后我们通过埋 点来获取页面上展示的职位的点击率,从而达到在线评价的效果。这样通过分流 展示不同界面的方法也称之为A/B test。由于我们在撰写论文时没有条件进行在 线评价,所以在本论文中只给出了离线评价的结果。我们会在后续加入在线评估 的环节,进行A/B test,得到一个真实的用户反馈。
评测指标 (推荐计算模块)
 
评测指标我们使用了准确率、召回率。需要说明的是,我们的离线实验是给 用户推荐一个最适合该用户的N个职位的推荐列表,这种称为TopN推荐。下面 给出每一个评测指标的计算公式。
设R(u)是基于用户u在训练集上的行为u给出的top N推荐结果,T(u)是用户
在测试集上的行为列表。推荐结果的准确率为:
 
推荐结果的召回率为:
 
 
 
6.2实验数据
本实验使用了 Kaggle Job Recommendation Challenge[5]的数据集。该数据集包 含了时长13周的用户申请简历以及发布的职位信息。其中,用户的申请简历被分 为了 7 组,每一组代表了 13天的窗口时间。其中,每个窗口的前 9天作为训练集, 后四天为测试集。
每个发布的职位都被分配到一个窗口,并且其概率与该窗口中站点上的活动 时间成正比。每个用户被分配到一个窗口,其概率与他们在窗口中对他们所提交 的职位申请数成正比。
我们需要预测用户在该窗口的测试期会申请哪些职位。
Data Layout
Window 1 Window 3 Window 7
 
 
13 weeks split into 7 windows
图 6-1 数据集窗口分布图
 
Assigning Users to Windows
Userl
Activity >
Period Activity
Period
Training lest
Window 1 Training 沧久
Window 2
 
图 6-1 用户申请分布图
用户的历史申请数据内容如下图,图中展示了历史申请数据中的五个数据样 本。可以看到,历史申请数据包含了五个维度的数据,分别是用户ID,窗口 ID, 数据类型Split,申请日期ApplicationDate,和职位ID。这里的窗口 ID对应上述的 七个窗口 ;数据类型Split的取值有Train和Test两种,分别代表了对应样本属于 训练集或测试集。
UserID WindowID Split ApplicationDate JoblD
0 47 1 Train 2012-04-04 15:56:23.537 169528
1 47 1 Train 2012-04-06 01:03:00.003 284009
2 47 1 Train 2012-04-05 02:40:27.753 2121
3 47 1 Train 2012-04-05 02:37:02.673 848187
4 47 1 Train 2012-04-05 22:44:06.653 733748
 
图 6-2 用户历史申请数据示意图
用户的个人数据包括了用户ID、窗口 ID、所在城市、州、邮编、学历、专业、 毕业日期、有过几份工作、工作经验(年)、目前是否在职、有无管理经验、管理 过多少人。
 
 
WorkHistoryCount
TotalYears Experience
CurrentlyEmployed ManagedOthers
 
GraduationDate
 
Man agedHowMany
图 6-3
用户个人信息数据示意图
职位数据包括了职位ID、窗口 ID、职位名称、岗位职责描述、岗位要求、职
位所在的城市、州、国家、邮编、职位可申请的起始日期。
JoblD WindowID
Title
Description
Security
Engin eer/Tech nical
Lead
<p>Security Clearance
Required:&nbsp; Top Seer...
SAP Business Analyst
/WM
<strong>NO Corp, to Corp resumes^nbsp;a「e bein...
P/T HUMAN
RESOURCES
ASSISTANT
<b> <b> P/T HUMAN RESOURCES ASSISTANT</b> <...
Route Delivery Drivers
CITY BEVERAGES Come to work for the best in th...
Housekeepi ng
I make sure every part of their day is magica...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Requireme nts City State Country Zip5 StartDate En dDate
<p>SKILL SET </p>\r<p>&nbsp; </p>\r<p>Network Se... Washington DC US 20531 2012-03-07
13:17:01.643 2012-04
06
23:59:59
<p><b>WHAT YOU NEED: </b></p>\r<p>Four year co... Charlotte NC US 28217 2012-03-21
02:03:44.137 2012-04
20
23:59:59
Please refer to the Job
Description to view th... Winter Park FL US 32792 2012-03-02
16:36:55.447 2012-04
01
23:59:59
Please refer to the Job
Description to view th... Orlando FL US NaN 2012-03-03
09:01:10.077 2012-04
02
23:59:59
Please refer to the Job
Description to view th... Orlando FL US NaN 2012-03-03
09:01:11.88 2012-04
02
23:59:59
图 6-4 职位信息示意图
 
6.3实验步骤
实验步骤总体分为两个部分,首先我们测试的是信息模块的功能,接着测试推 荐模块的性能表现。
信息模块功能测试步骤如下:
1.登录功能测试
2.管理员功能测试
> 主页展示
>设置系统全局信息
>查看及编辑考试信息
>查看及编辑教师信息
>查看及编辑学生信息
>查看及编辑教师信息
>查看及编辑年级信息
>查看及编辑班级信息
>查看及编辑课程信息
>查看所有职位信息
3.教师功能测试
> 主页展示
>查看及添加考试和成绩
>查看教师通讯录
 
>查看及编辑个人信息
4.学生功能测试
> 主页展示
>查看考试及成绩信息
>查看同班同学通讯录
>查看及编辑个人信息
>查看推荐职位信息
>查看所有职位信息
推荐模块性能测试步骤如下:
1.数据预处理,包括清洗数据,特征工程。(参考 4.2 节)
2.将 80%的数据集作为训练集,20%的数据集测试集
3.在训练样本集上训练 XGBoost 模型并调参
4.在训练样本集上训练 Wide&Deep 模型并调参
5.用 AdaBoost 融合 2、3 中的两个模型
6.4 中的模型以及前文2、3 中的模型分别在测试集上进行预测
7.分析结果
数据预处理部分我们在 4.2节已经做了详细的介绍,这里稍作重复。首先,我 们将连续特征进行归一化处理,同时对所有的类别特征进行one-hot encoding,再 对文字特征进行 word2vec 转化。其中, word2vec 转化是指,在我们数据集上收集 得到一个语料库,在这个语料库上训练一个神经网络模型,这个模型会将一句文 字转化成一个固定长度的向量。有了 word2vec模型以后,我们就可以将数据集中 的文字类特征,也就是职业数据中的的Title、描述、要求三类特征,分别转化成 三个固定长度的向量。此外,在进行one-hot encoding的时候,我们还做了一个降 维,减小了输入数据的维度,使得运算更快效率跟高。
有了处理好的输入特征以后,我们将特征分别用来训练上述的两种模型。在 训练每种模型的时候,除了模型自身训练得到的参数以外,还有非训练的参数, 我们称之为超参。这些超参需要我们通过多次实验,找出最优参数值。这个通过 多次实验寻找最优超参的过程,我们称之为调参。为了进行调参,我们需要用 K-fold 交叉验证的方法。这里对K-fold交叉验证进行简单的介绍。
交叉验证是一种重采样程序,用于评估有限数据样本的机器学习模型。该过 程有一个名为k的参数,它指的是给定数据样本要拆分的组数。因此,该过程通 常称为k折交叉验证。K-fold交叉验证的步骤如下。
1.随机混洗数据集。
2.将数据集拆分为k个组
3.对于每个独特的群体:
a 将该组作为保留或测试数据集
b 将剩余的组作为训练数据集
c 在训练集上拟合模型并在测试集上进行评估
d 保留评估分数并丢弃模型
4.使用模型评估分数样本总结模型的技能 使用这种算法以后,样本中的每个观察结果都被分配给一个单独的组,并在
该过程的持续时间内保留在该组中,从而每个样本都有机会在保持集 1中使用并 用于训练模型 k-1 次。这里我们结合数据和实际表现,选择了 K=5 进行交叉验证。
以下是实现交叉验证的核心代码。
def cv(self, watchlist=None, callbacks=None, customobj=None):
ii ii ii
交叉训练
II II II
if not customobj:
cv = xgb・cv(self.params,
self・dtrain,
self・num_rounds,
nfold=10,
early_stopping_rounds=5,
callbacks=callbacks)
else:
from utils import logregobj, evalerror
cv = xgb・cv(self.params,
self・dtrain,
self・num_rounds,
nfold=10,
callbacks=callbacks, obj=logregobj, feval=evalerror, early_stopping_rounds=5, verbose_eval=1)
return cv
经过交叉验证以后得到每个模型的最佳参数以及超参。然后我们使用 5.3.3 节 中的AdaBoost算法,将两个模型进行融合,得到一个融合的模型。最后,我们分 别让目前所得到的所有模型在预测集上进行预测,得到各自的最终结果。
 
6.4实验结果
6.4.1信息模块实验结果
1. 登录功能
 
图 6-5 登录界面图
 
该页面中,完成了通过输入用户名、密码、验证码以及选择相应的身份(学 生、老师或管理员)以登录到网站系统中的功能。
2. 管理员功能
• 首页展示
 
图 6-6 管理员登录后首页界面图
 
图6-6为管理员成功登录后的首页。左边的Navigation Menue是导航栏,上面
分别有五个可下拉的菜单,分别是Exam Managements (考试及成绩管理),Student Managemen(t 学生管理), Teacher Managemen(t 教师管理), General Info Management (其他信息管理),System (系统设置)。
• 设置系统全局信息
点击System栏后展开下拉菜单,选择Settings后右侧显示系统设置的界面。
Reset g Reset Password
University Name:
Prohibited Teacher
Log in
Prohibited Student
Log in
Teacher Notification:
该界面提供了五个主要设置项,分别是修改学校名称(University Name),是 否禁止教师用户登录(Prohibit Teacher Login),是否禁止学生用户登录(Prohibit Student Login),给教师的首页通知(Teacher Notification),以及给学生的首页通知 (Student Notification) o此外,该界面的左上角分别实现了 Reset (重置所有输入 框内容)功能和Reset Password (重置管理员密码)功能。重置所有修改的功过于 简单,这里不再展示。下图是点击Reset Password按钮后弹出的窗口界面。弹出的 窗口中需要输入旧的密码的两次输入新设置的密码,填好后点提交。随后会弹出 设置成功并强制跳转到登录界面重新登录的对话框。
 
图 6-8 重置密码编辑界面
 
图 6-9 密码重置成功界面
•查看及编辑考试信息
选择左侧Navigation Menu中第一栏Exam Management (考试管理),再选择 下拉菜单中的Exam List,右侧显示所有考试信息表格。界面截图如下。
Information Management System
Navigation Menu Welcome!三 Exam List >;
Exam Management ;Exams List
;z Exam List $Add §「emove || Caculate Grade: v Class:
 
(Exam Name Exam Date Exam Type Grade ofExarr i Class of Exam Subject of Exam Comments
1 0 midterm 2019-03-27 Midterm Exam Fourth Year Class 2 Computer Science II Computer Science II Midterm
2 midterm 2019-03-27 Midterm Exam Fourth Year Class 1 Computer Science II Computer Science II Midterm
3 [」m就erm 2019-03-27 Midterm Exam Third Year Class 2 Computer Science I Computer Science I Midterm
4 U midtenn 2019-03-27 Midterm Exam Third Year Class 1 Computer Science I Computer Science I Midterm
5 U midterm 2019-03-27 Midterm Exam Second Year Class 2 Calculus II Calculus II Midterm
6 Q midtenn 2019-03-27 Midterm Exam Second Year Class 1 Calculus II Calculus II Midterm
7 1」m就erm 2019-03-27 Midterm Exam First Year Class 2 Calculus I Calculus I Midterm
8 midterm
2019-03-27 Midterm Exam First Year Class 1 Calculus I Calculus I Midterm
9 final 2019-05-04 Final Exam Fourth Year Class 2 Software Engineering II Software Engineering II Final
10 final 2019-05-04 Final Exam Fourth Year Class 1 Software Engineering II Software Engineering II Final
 
图 6-10 考试管理界面
 
在该界面中,我们展示了当前所有考试的信息,包括考试名称、时间、科目 名字、年级、班级。
同时,我们加入了工具栏,以实现对考试信息的增添、删除和修改。 下图是点击 Add 按钮后弹出的添加考试的窗口。
 
图 6-11 添加考试科目界面
 
 
我们添加了名为 Wireless Security 的考试,点击添加提交结果以后,系统会自 动为所选年级的所有班级添加该门考试。
• 查看及编辑学生信息
选择左侧Navigation Menu中第二栏Student Management (学生管理),再选择 下拉菜单中的StudentList,右侧显示所有学生信息表格。界面截图如下
 
图 6-12 学生信息编辑界面
该界面展示了学生信息,并且有添加、修改和删除的功能。添加和删除的界 面与之前的类似,之里直接给出更新学生信息的窗口。
• 查看及编辑教师信息
选择左侧Navigation Menu中第三栏Teacher Management (教师管理),再选择 下拉菜单中的Teacher List,右侧显示所有教师信息表格。界面截图如下。篇幅有 限,这里不再重复贴出类似的编辑窗口界面。
 
图 6-13 教师信息编辑界面
 
• 查看及编辑年级、班级、课程、职位信息
选择左侧 Navigation Menu 中第四栏 General Info Managemen(t 其他信息管理), 下拉菜单中有Grade List (年级列表)、Class List (班级列表)、Course List (课程 列表)以及Job List (职位列表)。下面以最复杂的Job List (职位列表)图举例展 示。
由于我们的职位数据文字内容较多,一个页面只够显示一个职位的信息,所 以我们用了两张截图来分别展示表格中前两个职位的内容。
 
 
 
 
图 6-14 职位信息编辑界面
 
 
图 6-15 职位信息编辑界面
3. 教师功能
• 首页展示
 
r cd o* I i riwix info” x +
V- - Q! Q kx«<IK< >->i ^ ^ ,
Information Management System
Z«av2«*U。" M«2<bu
I «>M<-hnw*nt MAnxQ«*«rw*mt tea<=K«r I nfo
Sy^Ccru Mdfidvctaidil
Welcome to Information Management System
News:
Please upload grade ASAP.
图 6-16 教师登录后界面
• 查看及添加考试和成绩
 
 
 
 
 
 
 
 
 
 
 
 
图 6-17 考试编辑界面 (1)
以下是点击添加按钮后弹出的添加窗口界面。
 
 
图 6-18 考试编辑界面 (2)
点击 enter score 按钮以后的添加/修改学生考试成绩的窗口界面
 
 
图 6-19 成绩编辑界面
• 查看及编辑个人信息
 
 
图 6-20 教师个人信息编辑界面
4. 学生功能
• 首页展示
 
 
 
 
 
 
图 6-21 学生登录后界面
•查看考试及成绩信息
图 6-22 学生成绩查看界面
• 查看及编辑个人信息
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
图 6-23 学生个人信息编辑界面
 
• 查看推荐职位信息 同样,由于我们的职位数据文字内容较多,一个页面只够显示一个职位的信 息,所以我们用了两张截图来分别展示表格中前两个推荐的职位的内容。
 
 
图 6-23 就业信息推荐界面(1)
图 6-24 就业信息推荐界面(2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6.4.2推荐引擎实验结果
图 4-13 为训练和测试的损失函数曲线。红色为训练集的 loss ,蓝色为测试集, 可loss。可以看到,我们的模型能够很快地收敛并且达到一个不错的效果。最终, 我们的模型在训练集上能达到90%的准确率,在测试集上达到了 88%的准确率。
表 6-1 实验数据表
模型 Precision Recall
GBDT 0.886 0.7126
Wide 0.921 0.7265
Deep 0.913 0.7221
Wide & Deep 0.981 0.7280
Ensembled 0.987 0.782
 
 
learning curve
0.5
 
0.0
0 25 50 75 100 125 150 175 200
iteration
 
图 6-25 训练和测试的损失函数曲线图
第七章 总结与展望
7.1总结
随着电子化数据管理系统在各级高校的普及,这部分数据对于就业领域是极 具价值的,本论文因地制宜,使用当下火热的人工智能技术来对传统的数据管理 系统进行数据分析,在测试集上的可以得到就业情况预测准确率达 90%的试验结 果,可以说是非常令人振奋的,这进一步论证了使用人工智能技术进行数据分析 和预测在就业领域的使用价值和应用前景。
7.2展望
文虽然程序模型在测试数据集上效果良好,但是因为样本量不足,模型没有 办法进一步完善,如果将来应用到现实中可以使用更大的样本进行训练来调整参 数,同时可以根据需求进一步细分参数,可以得到更加精细的预测结果使得系统 更加可用。
致谢
在完成该论文之时,我要由衷的感谢给予我关心、支持和帮助的各位导师、 和同学。
其中,首先要感谢我的导师李瑞教授。在李老师耐心细致的指导下,使我能 利用研究生三年所学的基础知识制定毕业论文的课题方向,并顺利的通过了开题 报告。在课题方向确定后,从资料查询,到论文撰写,再到最后的论文成型,我 遇到很多的疑惑和困难。李老师花费了很多宝贵的时间和精力与我答疑解惑,给 予我许多的启迪和自信,使我在研究生学习上受益匪浅。同时,李老师严谨的治 学态度,开拓进取的精神和高度的责任心都使我受益终生。
同时我还要向李先进教授级高工表示感谢,在论文撰写过程中,多次在百忙 中挤出时间对我精心指导,对各类问题不厌其烦给我指正和解惑。
在此我再次向所有关心我、支持我、帮助我的老师、亲友、同学表示衷心的 感谢!
参考文献
[1]Goldberg, D., Nichols, D., Oki, B.M., Terry, D.: Using collaborative filtering to weave an information Tapestry. Commun. ACM 35(12), 61—70 (1992)
[2]Resnick, P., Iacovou, N., Suchak, M., Bergstrom, P., Riedl, J.: GroupLens: an open architecture for collaborative filtering of netnews. In: Proceedings of the 1994 ACMconference on Computer supported cooperative work, pp. 175-186 (1994)
[3]Anderson, Chris. "The Long Tail" Wired, October 2004.
[4]"Kernel-Mapping Recommender system algorithms". Information Sciences. 208: 81-104. doi: 10.1016/j.ins.2012.04.012
[5]https://www.kaggle.com/c/job-recommendation/data
[6]"Artificial Neural Networks as Models of Neural Information Processing | Frontiers Research Topic". Retrieved 2018-02-20.
[7]Ganesan, N. "Application of Neural Networks in Diagnosing Cancer Disease Using Demographic Data" (PDF). International Journal of ComputerApplications.
[8]Nabian, Mohammad Amin; Meidani, Hadi (2017-08-28). "Deep Learning for Accelerated Reliability Analysis of Infrastructure Networks". Computer-Aided Civil and Infrastructure Engineering. 33 (6): 443-458. arXiv:1708.08551.doi:10.1111/mice.12359
[9]Nabian, Mohammad Amin; Meidani, Hadi (2018). "Accelerating Stochastic Assessment of Post-Earthquake Transportation Network Connectivity via Machine-Learning-Based Surrogates". Transportation Research Board 97th Annual Meeting.
[10]null null (2000-04-01). "Artificial Neural Networks in Hydrology. I: Preliminary Concepts".
Journal of Hydrologic Engineering. 5 (2): 115-123. CiteSeerX 10.1.1.127.3861.
doi:10.1061/(ASCE)1084-0699(2000)5:2(115)
[11]null null (2000-04-01). "Artificial Neural Networks in Hydrology. II: Hydrologic Applications".
Journal of Hydrologic Engineering. 5 (2): 124-137.
doi:10.1061/(ASCE)1084-0699(2000)5:2(124)
[12]Peres, D. J.; Iuppa, C.; Cavallaro, L.; Cancelliere, A.; Foti, E. (2015-10-01). "Significant wave height record extension by neural networks and reanalysis wind data". Ocean Modelling. 94: 128-140. Bibcode:2015OcMod..94..128P. doi:10.1016/j.ocemod.2015.08.002
[13]Dwarakish, G. S.; Rakshith, Shetty; Natesan, Usha (2013). "Review on Applications of Neural Network in Coastal Engineering". Artificial Intelligent Systems and Machine Learning. 5 (7):
324-331.
[14]Ermini, Leonardo; Catani, Filippo; Casagli, Nicola (2005-03-01). "Artificial Neural Networks applied to landslide susceptibility assessment". Geomorphology. Geomorphological hazard and human impact in mountain environments. 66 (1): 327-343.
[15]UNESCO (2012) Education and Skills for Inclusive and Sustainable Development beyond 2015
[16]Qu, X.F., Zhang, J. and Wang, Y. (2015) A Study on College Graduates Employment Situation. Brand, 4, 154.
[17]Zhou, Y. (2015) A Study on the Employment View Problems and Countermeasures of College Students. Brand, 1, 176.
[18]Chen, X.M. (2014) The Research on University Students' Employment under the Multidimensional Perspective. China Electric Power Education, 2, 227-229.
[19]Ai, L.R. (2015) Study on Undergraduates Employment Ideological Education Practice. Creative Education, 6, 309-314.
[20]Dai, L.T. and Xiao, R. (2016) The Influence of Social Comparison on Job Performance. Open Journal of Social Sciences, 4, 147-151.
[21]Wang, D.J., Zhu, Q.X. and Lin, Y. (2013) Study on the Problems Existing in the Employment Education for College Students in China's Independent Colleges and Corresponding Countermeasures. Creative Education, 4, 470-473.
[22]Usage of Java for websites report https://w3techs.com/technologies/- details/cp-javaruntime/all/all
[23]Mikolov, Tomas, et al. "Distributed representations of words and phrases and their compositionality." Advances in neural information processing systems. 2013.
[24]De Lathauwer, Lieven, Bart De Moor, and Joos Vandewalle. "A multilinear singular value decomposition." SIAM journal on MatrixAnalysis and Applications 21.4 (2000): 1253-1278.
[25]Rajaraman, Anand, and Jeffrey David Ullman. Mining of massive datasets. Cambridge University Press, 2011.
[26]Kiefer, Jack, and Jacob Wolfowitz. "Stochastic estimation of the maximum of a regression function." The Annals of Mathematical Statistics 23.3 (1952): 462-466.
[27]Robbins, Herbert, and Sutton Monro. "A stochastic approximation method." The annals of mathematical statistics(1951): 400-407.
[28]Qian, Ning. "On the momentum term in gradient descent learning algorithms." Neural networks 12.1 (1999): 145-151.
[29]Tieleman, Tijmen, and Geoffrey Hinton. "Lecture 6.5-rmsprop: Divide the gradient by a running average of its recent magnitude." COURSERA: Neural networks for machine learning 4.2 (2012): 26-31.
[30]Kingma, Diederik P., and Jimmy Ba. "Adam: A method for stochastic optimization." arXiv preprint arXiv:1412.6980(2014).
[31]Chen, Tianqi, and Carlos Guestrin. "Xgboost: A scalable tree boosting system." Proceedings of the 22nd acm sigkdd international conference on knowledge discovery and data mining. ACM, 2016.
【本文地址:https://www.xueshulunwenwang.com//guanlilei/gongshangguanli/xixinguanli/5852.html

上一篇:运营公路隧道土建结构定期检查病害信息 管理系统研究

下一篇:基于MVC和ExtJS的高校学生信息管理系统的 设计与实现

相关标签: