首先是构造分类训练、测试集,使用Google Scholar的作者标签数据(访问网页https://ericdongyx.github.io/metapath2vec/m2v.html,下载其中的label.zip文件),通过作者名,将作者ID与标签连接起来。详细代码如下:
CsvSourceBatchOp author_name_label = new CsvSourceBatchOp() .setFilePath(DATA_DIR + "googlescholar.8area.author.label.txt") .setSchemaStr("author_labeled string, label int") .setFieldDelimiter(" "); BatchOperator author_id_label = new JoinBatchOp() .setJoinPredicate("author = author_labeled") .setSelectClause("author_id, label") .linkFrom(id_author, author_name_label);
随后,将关联起来的作者ID、标签数据进行训练集和预测集划分,具体代码如下,划分结果分别保存到文件AUTHOR_LABEL_TRAIN和AUTHOR_LABEL_TEST。
Utils.splitTrainTestIfNotExist( author_id_label, DATA_DIR + AUTHOR_LABEL_TRAIN, DATA_DIR + AUTHOR_LABEL_TEST, 0.8 );
在执行分类前,还要将作者ID与其对应的Embedding向量关联起来,这个向量将作为分类特征。Alink中常用两种方式进行关联,一种是用Join方法,通过组建实现;另一种是使用组件,从Embedding模型表中查找对应向量。这里我们对于训练集和测试集分别使用了这两种方法,具体代码如下:
BatchOperator author_train = new JoinBatchOp() .setJoinPredicate("author_id = node") .setSelectClause("author_id, vec, label") .linkFrom( graph_embedding, new AkSourceBatchOp().setFilePath(DATA_DIR + AUTHOR_LABEL_TRAIN) ); BatchOperator author_test = new LookupBatchOp() .setSelectedCols("author_id") .setOutputCols("vec") .linkFrom( graph_embedding, new AkSourceBatchOp().setFilePath(DATA_DIR + AUTHOR_LABEL_TEST) );
注意:在批式处理场景,这两个组件的效果是一样的;但是如果需要部署到线上服务或者在流式场景中使用,Lookup都有对应的组件可以使用。
基于前面准备好的训练集和测试集,可以开始分类实验,这里选择了两个常用风分类器:Softmax与KnnClassifier,并对预测结果进行评估,便于了解当前场景下,不同分类器的效果,及不用Embedding算法对分类结果的影响。
new Softmax() .setVectorCol("vec") .setLabelCol("label") .setPredictionCol("pred") .fit(author_train) .transform(author_test) .link( new EvalMultiClassBatchOp() .setLabelCol("label") .setPredictionCol("pred") .lazyPrintMetrics("[ Using Softmax ]") ); new KnnClassifier() .setVectorCol("vec") .setLabelCol("label") .setPredictionCol("pred") .fit(author_train) .transform(author_test) .link( new EvalMultiClassBatchOp() .setLabelCol("label") .setPredictionCol("pred") .lazyPrintMetrics("[ Using KnnClassifier ]") );
最后,构造完整的实验流程如下面代码所示,其中的classifyWithEmbedding()方法包装前面的Embedding向量关联及模型训练评估的流程。
for (String embedding_model_file : new String[] {DEEPWALK_EMBEDDING, NODE2VEC_EMBEDDING, METAPATH2VEC_EMBEDDING} ) { System.out.println("\n\n< " + embedding_model_file + " >\n"); classifyWithEmbedding( new AkSourceBatchOp().setFilePath(DATA_DIR + embedding_model_file) ); }
运行结果汇总如下,我们看到KnnClassifier的分类效果比Softmax更好;Softmax在DeepWalk Embedding上效果较好;KnnClassifier在Node2Vec Embedding上效果较好。注意,是在当前参数的条件下,如果调整Embedding训练参数或者分类器训练参数,结果会不一样的。
Softmax | KnnClassifier | |
DeepWalk | Accuracy:0.5306 Kappa:0.2438 | Accuracy:0.5593 Kappa:0.3651 |
Node2Vec | Accuracy:0.5229 Kappa:0.2294 | Accuracy:0.5603 Kappa:0.3662 |
MetaPath2Vec | Accuracy:0.524 Kappa:0.2324 | Accuracy:0.5419 Kappa:0.3284 |