利用spark进行机器学习时模型序列化存储到hive解决方案

机器学习模型的训练和预测经常是在不同的时间点进行,在工程实现中,一般训练和预测都是在不同的子工程里面进行,训练子工程训练模型后存储到hive,之后预测子工程项目再将模型重hive中load出来进行预测 1.模型存储到hive存储很简单,将要存储的模型调用如下spark的序列化方法def serialize(spark: SparkSession)序列化后再转换拼装成sql,然后执行 spark.sql(insertSQL)即可,如下 case class ModleToHive(modelBizType: String, data: String) def save(modelUID: String): Unit = { val instance = ModleToHive( modelUID, modelBizType, model.serialize(spark) ) val instDf = Seq(instance).toDF() instDf.createOrReplaceTempView("model") var sqlString = s"insert into modelTable select modelUID as modelUID, modelBizType as modelBizType, data as saved_model" sqlString = sqlString + " from model " spark.sql(sqlString).collect()这样模型就存储到hive了 2.从hive仓库load模型并反序列化 val sqlString = s"select saved_model from modelTable where modelUID=modelUID " val modelHexBinary = spark.sql(sqlString).first() val ser = new KryoSerializer(sparkConf).newInstance() val byteBuffer = ByteBuffer.wrap(DatatypeConverter.parseHexBinary(modelHexBinary.getString(0))) ser.deserialize[T](byteBuffer)这样模型就又反序列化出来了,可用于预测了 ...

June 9, 2019 · 1 min · jiezi

mongodb的model名称细节

最近研究api设计,顺便研究了下mongodb,教程没有仔细看过,所以使用过程中也遇到了一些诡异的现象。 比如我使用中发现,我创建的模型名称,在对应数据库的collections内的名称不一致。我很纳闷,比如我创建的如下: const PersonModel = Mongoose.model("person", { firstname: String, lastname: String});当我将一条数据写入后,用工具Robo 3T发现,名称居然变成了people。 后来查了相关资料,原来mongodb有自己的一套规则,详细的规则,比如我这条:mongoose/lib/utils.js。当然这个是历史版本的例子了。关于这个现象,最新文档中也指出: The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural version of your model name. For example, if you use const MyModel = mongoose.model('Ticket', mySchema);Then Mongoose will create the model for your tickets collection, not your ticket collection. 一般情况他会创建一个复数的model,这种person算特殊的了。所以你写得model不一定在查询的时候会一样,即便不一样也不要惊讶哦~

May 22, 2019 · 1 min · jiezi

Laravel-队列-database-驱动今天刚学习了队列记录下笔记

刚学习了laravel队列,把笔记记一下。 1.第一步配置(.env)QUEUE_CONNECTION=database2.database 驱动设置第一步:生成 jobs 数据迁移表 php artisan queue:table效果如下:第二步: 创建jobs表,执行迁移命令 php artisan migrate效果如下: 3.模拟数据第一步: 进入 thinker php artisan thinker第二步:创建数据 (thinker命令) factory(App\User::class,10)->create();// 创建10个用户打开users表 就能看到 创建的10 个新用户 4.创建 Jobs及编写第一步:创建 php artisan make:job Email此时能在 app 目录下生成个 Jobs 文件夹 及我们创建的 Email.php文件 效果如下: 第二步:编写Email.php <?phpnamespace App\Jobs;use App\User;use Illuminate\Bus\Queueable;use Illuminate\Queue\SerializesModels;use Illuminate\Queue\InteractsWithQueue;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Bus\Dispatchable;use Illuminate\Support\Facades\Log;class Email implements ShouldQueue{ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; //定义 public $user; /** * Create a new job instance. * * * @return void */ public function __construct(User $user) { //赋值 $this->user = $user; } /** * Execute the job. * * @return void */ public function handle() { //打印日记 Log::info('发送的邮件是:'.$this->user->email); }}6. 创建控制器,分发任务第一步:创建Usercontroller控制器 ...

May 15, 2019 · 1 min · jiezi

使用-seed-命令创建模拟数据学习笔记

在开发环境中,我们经常会使用 “模拟数据” 来测试我们应用,在laravel 中 提供了 ”数据填充“来帮助我们实现这个需求。我们现在就来用这个功能来创建 20个用户... 1.使用 artisan 命令生成 用户表1.1 打开新创建的laravel项目 database/migrations目录 下可以发现 两个文件 一个是创建用户表的,一个是创建确认密码表的(图中没看到是因为我删除了) 1.2 我们可以打开这个文件瞧瞧 (根据实际情况修改,这里我就不修改了) <?phpuse Illuminate\Support\Facades\Schema;use Illuminate\Database\Schema\Blueprint;use Illuminate\Database\Migrations\Migration;class CreateUsersTable extends Migration{ /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); }}1.3 执行 artisan 命令 生成表 ...

May 15, 2019 · 2 min · jiezi

GIT - 代码分支管理模型之二

书接上文在前一篇文章GIT 代码分支管理模型之一中,我们一起了解了一种叫做“成功的代码分支管理模型”。在这种模型中,我们确实可以很灵活地应对各种场景下的代码分支管理。理想总是那么美好,而现实偏偏那么蛋疼!要用好这种代码分支管理模型,需要全体开发人员对于GIT有比较深入的了解,比如merge, rebase,而且在每一次GIT的操作的时候要很清楚地知道自己正在开发的功能属于哪个分支的。对于同时开发多个功能点的同事来说,比如同时在开发一个下一版本的功能,以及进行产品线上细微改动的同事来说,确实要非常小心,稍不留神就容易怼错分支。历史背景在我们公司刚开始推行GIT的时候,领导下的指令是要让大家把精力全放在功能开发上,对于GIT只需要知道pull 跟push就可以了,经过一段历史时期的挣扎磨合,无形中我们形成了下面这种分支管理模型,称之为 “简单但啰嗦的分支管理模型"简单但啰嗦的分支管理模型主心骨这个模型主要有两种分支,一种叫DEV,一种叫REL。每一种后面都附加有对应版本号,比如DEV1.0, REL1.0RELx.0每个版本开始开发之前,都会从上一个版本的REL分支创建出一个新的REL分支,比如REL2.0是从REL1.0创建出来。当然第一个版本REL1.0就是从master分支创建出来的。这样就确保了每一个版本都是从上一个版本最新代码创建出来的。RELx.0神圣职责是作为每一个大版本发布的分支,并且是用来部署测试环境,准产品线以及产品线的分支。一般开发人员没有权限直接往RELx.0上面提交代码,只能从对应的DEV分支提交代码,再由集成人员合并到上面去。DEVx.0DEVx.0是与RELx.0对应的开发分支,所有开发人员默认都有权限往这个分支上提交代码。这也是开发人员所需要知道的分支,只需要从这上面pull最新的代码,然后把本地commit的代码push到上面去就可以了。小版本怎么办?在相当长的一段历史时期中,基本稳定在一个版本一个月左右。但有时会遇到有些小功能着急着上,等不及一个月上一次,所以就有了对应RELx.x以及DEVx.x (x > 0). 比如刚发布了REL3.0,这时有VIP客户需要上一个功能,改动不至于很大,但是也等不及下个月再上,于是我们就从REL3.0上面衍生出一条REL3.1的分支。按照之前的规则, REL分支是不允许直接修改代码的,所有对应的我们会创建DEV3.1的分支,给开发人员在上面进行开发。在这个过程中,下一版本4.0其实一直在同步进行开发的,但是这时REL4.0以及DEV4.0的分支上是没有DEV3.1的新功能的,所有在3.1的新功能上线之后,需要由持续集成人员DEV3.1的代码合并到DEV4.0上面去 (为什么不是直接REL3.1到REL4.0呢? 技术上是可行的,但是这样的话,REL4.0需要反向将代码合并会DEV4.0去,比较别扭),持续集成环境会自动将DEV4.0的新代码合并到REL4.0上面去,这样到时发布4.0的时候,才不会丢失了3.1新增的功能没bug的系统是不完整的有bug怎么办?不管是大版本还是小版本,总有可能产品线上有bug需要hotfix。在上次介绍的成功代码分支模型中,可以通过hotfix的分支进行代码修复。但在这个简单模型中,就不会新建hotfix的分支,而是在最新以上线的分支上进行修改。比如当前产品线上是REL3.0的代码,REL4.0是下一个大版本,REL3.1是准备上线的小版本,而这时产品上客户报了Level 1的case,按照SLA需要在三天内修复,我们是等不及REL3.1下周末上的,更不可能等REL4.0到下个月,所有我们要上到3.0的分支上:已上线的REL3.0以及对应的DEV3.0在上线之后就全被锁掉了,所以这时我们要找代码集成人员进行解锁然后在DEV3.0的分支上进行代码修复,直到测试通过后,合并代码分支到REL3.0进行紧急上线简单但啰嗦简单这种模型中,大部分开发人眼只需要记住版本的DEVx.x就可以了,其它REL什么的都可以不用管,不懂也没关系的。啰嗦每一个新版本开发前,管理人员都要新建对应的DEV分支,然后开发人员checkout对应分支进行开发。这样一来,一个版本,无论大小,都需要对应有两条分支,整个代码库看起来就有很多很多的分支,略显啰嗦。there is no free lunch!利弊关系上面已经做了一些简单的介绍,这种模型适合在项目比较大,团队人数较多的情况下使用,好处是开发人员不需要对GIT有过深的理解,只需会简单的pull / push,其它都由分支管理以及对应的权限管理搞定;其缺点也明显,就是整个代码库会有好多好多的分支,看起来比较啰嗦。

January 25, 2019 · 1 min · jiezi